diff --git a/Toolbox/Contents.m b/Toolbox/Contents.m new file mode 100644 index 0000000..9ae761e --- /dev/null +++ b/Toolbox/Contents.m @@ -0,0 +1,238 @@ +% GSW Oceanographic Toolbox +% Version 3.01 (R2011a) 15-May-2011 +% +% documentation set +% gsw_front_page - front page to the GSW Oceanographic Toolbox +% gsw_check_functions - checks that all the GSW functions work correctly +% gsw_demo - demonstrates many GSW functions and features +% +% Practical Salinity (SP), PSS-78 +% gsw_SP_from_C - Practical Salinity from conductivity, C (inc. for SP < 2) +% gsw_C_from_SP - conductivity, C, from Practical Salinity (inc. for SP < 2) +% gsw_SP_from_R - Practical Salinity from conductivity ratio, R (inc. for SP < 2) +% gsw_R_from_SP - conductivity ratio, R, from Practical Salinity (inc. for SP < 2) +% gsw_SP_salinometer - Practical Salinity from a laboratory salinometer (inc. for SP < 2) +% +% Absolute Salinity (SA), Preformed Salinity (Sstar) and Conservative Temperature (CT) +% gsw_SA_from_SP - Absolute Salinity from Practical Salinity +% gsw_Sstar_from_SP - Preformed Salinity from Practical Salinity +% gsw_CT_from_t - Conservative Temperature from in-situ temperature +% +% Absolute Salinity - Conservative Temperature plotting function +% gsw_SA_CT_plot - function to plot Absolute Salinity - Conservative Temperature +% profiles on the SA-CT diagram, including the freezing line +% and selected potential density contours +% +% other conversions between temperatures, salinities, pressure and height +% gsw_deltaSA_from_SP - Absolute Salinity Anomaly from Practical Salinity +% gsw_SA_Sstar_from_SP - Absolute Salinity & Preformed Salinity from Practical Salinity +% gsw_SR_from_SP - Reference Salinity from Practical Salinity +% gsw_SP_from_SR - Practical Salinity from Reference Salinity +% gsw_SP_from_SA - Practical Salinity from Absolute Salinity +% gsw_Sstar_from_SA - Preformed Salinity from Absolute Salinity +% gsw_SA_from_Sstar - Absolute Salinity from Preformed Salinity +% gsw_SP_from_Sstar - Practical Salinity from Preformed Salinity +% gsw_pt_from_CT - potential temperature from Conservative Temperature +% gsw_t_from_CT - in-situ temperature from Conservative Temperature +% gsw_CT_from_pt - Conservative Temperature from potential temperature +% gsw_pot_enthalpy_from_pt - potential enthalpy from potential temperature +% gsw_pt0_from_t - potential temperature with a reference pressure of zero dbar +% gsw_pt_from_t - potential temperature +% gsw_t90_from_t48 - ITS-90 temperature from IPTS-48 temperature +% gsw_t90_from_t68 - ITS-90 temperature from IPTS-68 temperature +% gsw_z_from_p - height from pressure +% gsw_p_from_z - pressure from height +% gsw_depth_from_z - depth from height +% gsw_z_from_depth - height from depth +% gsw_Abs_Pressure_from_p - Absolute Pressure,P, from pressure, p +% gsw_p_from_Abs_Pressure - pressure, p, from Absolute Pressure, P +% gsw_entropy_from_CT - entropy from Conservative Temperature +% gsw_CT_from_entropy - Conservative Temperature from entropy +% gsw_entropy_from_pt - entropy from potential temperature +% gsw_pt_from_entropy - potential temperature from entropy +% gsw_molality_from_SA - molality of seawater +% gsw_ionic_strength_from_SA - ionic strength of seawater +% +% density and enthalpy, based on the 48-term expression for density +% (The functions in this group ending in "_CT" may also be called without "_CT".) +% gsw_rho_CT - in-situ density from CT, and potential density +% gsw_alpha_CT - thermal expansion coefficient with respect to CT +% gsw_beta_CT - saline contraction coefficient at constant CT +% gsw_rho_alpha_beta_CT - in-situ density, thermal expansion & saline contraction coefficients +% gsw_specvol_CT - specific volume +% gsw_specvol_anom_CT - specific volume anomaly +% gsw_sigma0_CT - sigma0 from CT with reference pressure of 0 dbar +% gsw_sigma1_CT - sigma1 from CT with reference pressure of 1000 dbar +% gsw_sigma2_CT - sigma2 from CT with reference pressure of 2000 dbar +% gsw_sigma3_CT - sigma3 from CT with reference pressure of 3000 dbar +% gsw_sigma4_CT - sigma4 from CT with reference pressure of 4000 dbar +% gsw_sound_speed_CT - sound speed (approximate, with r.m.s. error of 0.067 m/s) +% gsw_internal_energy_CT - internal energy +% gsw_enthalpy_CT - enthalpy +% gsw_enthalpy_diff_CT - difference of enthalpy between two pressures +% gsw_dynamic_enthalpy_CT - dynamic enthalpy +% gsw_SA_from_rho_CT - Absolute Salinity from density & CT +% gsw_CT_from_rho - Conservative Temperature from density +% gsw_CT_maxdensity - Conservative Temperature of maximum density of seawater +% +% water column properties, based on the 48-term expression for density +% gsw_Nsquared - buoyancy (Brunt-Vaisala) frequency squared (N^2) +% gsw_Turner_Rsubrho - Turner angle & Rsubrho +% gsw_IPV_vs_fNsquared_ratio - ratio of the vertical gradient of potential density +% (with reference pressure, p_ref), to the vertical gradient +% of locally-referenced potential density +% +% neutral and non-linear properties, based on the 48-term expression for density +% gsw_cabbeling - cabbeling coefficient +% gsw_thermobaric - thermobaric coefficient +% gsw_isopycnal_slope_ratio - ratio of the slopes of isopycnals on the SA-CT diagram +% for p & p_ref +% gsw_isopycnal_vs_ntp_CT_ratio - ratio of the gradient of Conservative Temperature +% in a potential density surface to that in the neutral +% tangent plane +% gsw_ntp_pt_vs_CT_ratio - ratio of gradients of potential temperature & +% Conservative Temperature in a neutral tangent plane +% (i.e. in a locally-referenced potential density surface) +% +% geostrophic streamfunctions, based on the 48-term expression for density +% gsw_geo_strf_dyn_height - dynamic height anomaly +% gsw_geo_strf_dyn_height_pc - dynamic height anomaly for piecewise constant profiles +% gsw_geo_strf_isopycnal - approximate isopycnal geostrophic streamfunction +% gsw_geof_str_isopycnal_pc - approximate isopycnal geostrophic streamfunction for +% piecewise constant profiles +% gsw_geo_strf_Montgomery - Montgomery geostrophic streamfunction +% gsw_geo_strf_Cunningham - Cunningham geostrophic streamfunction +% +% geostrophic velocity +% gsw_geostrophic_velocity - geostrophic velocity +% +% derivatives of enthalpy, entropy, CT and pt +% gsw_CT_first_derivatives - first derivatives of Conservative Temperature +% gsw_CT_second_derivatives - second derivatives of Conservative Temperature +% gsw_enthalpy_first_derivatives - first derivatives of enthalpy +% gsw_enthalpy_second_derivatives - second derivatives of enthalpy +% gsw_entropy_first_derivatives - first derivatives of entropy +% gsw_entropy_second_derivatives - second derivatives of entropy +% gsw_pt_first_derivatives - first derivatives of potential temperature +% gsw_pt_second_derivatives - second derivatives of potential temperature +% +% freezing temperatures +% gsw_CT_freezing - Conservative Temperature freezing temperature of seawater +% gsw_t_freezing - in-situ freezing temperature of seawater +% gsw_brineSA_CT - Absolute Salinity of seawater at the freezing point (for given CT) +% gsw_brineSA_t - Absolute Salinity of seawater at the freezing point (for given t) +% +% isobaric melting enthalpy and isobaric evaporation enthalpy +% gsw_latentheat_melting - latent heat of melting of ice into seawater (isobaric melting enthalpy) +% gsw_latentheat_evap_CT - latent heat of evaporation of water from seawater (isobaric +% evaporation enthalpy) with CT as input temperature +% gsw_latentheat_evap_t - latent heat of evaporation of water from seawater (isobaric +% evaporation enthalpy) with in-situ temperature, t, as input +% +% Planet Earth properties +% gsw_f - Coriolis parameter +% gsw_grav - gravitational acceleration +% gsw_distance - spherical earth distance between points in the ocean +% +% steric height +% gsw_steric_height - dynamic height anomaly divided by 9.7963 m s^-2 +% +% TEOS-10 constants +% gsw_T0 - Celcius zero point; 273.15 K +% gsw_P0 - one standard atmosphere; 101 325 Pa +% gsw_SS0 - Standard Ocean Reference Salinity; 35.165 04 g/kg +% gsw_uPS - unit conversion factor for salinities; (35.165 04/35) g/kg +% gsw_cp0 - the "specific heat" for use with CT; 3991.867 957 119 63 (J/kg)/K +% gsw_C3515 - conductivity of SSW at SP=35, t_68=15, p=0; 42.9140 mS/cm +% gsw_SonCl - ratio of SP to Chlorinity; 1.80655 (g/kg)^-1 +% gsw_valence_factor - valence factor of sea salt; 1.2452898 +% gsw_atomic_weight - mole-weighted atomic weight of sea salt; 31.4038218... g/mol +% +% density and enthalpy in terms of CT, based on the exact Gibbs function +% gsw_rho_CT_exact - in-situ density from CT, and potential density from CT +% gsw_alpha_CT_exact - thermal expansion coefficient with respect to CT +% gsw_beta_CT_exact - saline contraction coefficientat constant CT +% gsw_rho_alpha_beta_CT_exact - in-situ density, thermal expansion & saline contraction +% coefficient from CT +% gsw_specvol_CT_exact - specific volume from CT +% gsw_specvol_anom_CT_exact - specific volume anomaly from CT +% gsw_sigma0_CT_exact - sigma0 from CT with reference pressure of 0 dbar +% gsw_sigma1_CT_exact - sigma1 from CT with reference pressure of 1000 dbar +% gsw_sigma2_CT_exact - sigma2 from CT with reference pressure of 2000 dbar +% gsw_sigma3_CT_exact - sigma3 from CT with reference pressure of 3000 dbar +% gsw_sigma4_CT_exact - sigma4 from CT with reference pressure of 4000 dbar +% gsw_sound_speed_CT_exact - sound speed +% gsw_internal_energy_CT_exact - internal energy +% gsw_enthalpy_CT_exact - enthalpy from CT +% gsw_enthalpy_diff_CT_exact - difference of enthalpy from CT between two pressures +% gsw_dynamic_enthalpy_CT_exact - dynamic enthalpy from CT +% gsw_SA_from_rho_CT_exact - Absolute Salinity from Density & CT +% gsw_CT_from_rho_exact - Conservative Temperature from density +% gsw_CT_maxdensity_exact - Conservative Temperature of maximum density of seawater +% +% basic thermodynamic properties in terms of in-situ t, based on the exact Gibbs function +% gsw_rho_t_exact - in-situ density +% gsw_pot_rho_t_exact - potential density +% gsw_sigma0_pt0_exact - sigma0 from pt0 with reference pressure of 0 dbar +% gsw_alpha_wrt_CT_t_exact - thermal expansion coefficient with respect to +% Conservative Temperature. +% gsw_alpha_wrt_pt_t_exact - thermal expansion coefficient with respect to +% potential temperature +% gsw_alpha_wrt_t_exact - thermal expansion coefficient with respect to +% in-situ temperature +% gsw_beta_const_CT_t_exact - saline contraction coefficient at constant +% Conservative Temperature. +% gsw_beta_const_pt_t_exact - saline contraction coefficient at constant +% potential temperature +% gsw_beta_const_t_exact - saline contraction coefficient at constant +% in-situ temperature +% gsw_specvol_t_exact - specific volume +% gsw_specvol_anom_t_exact - specific volume anomaly +% gsw_sound_speed_t_exact - sound speed +% gsw_kappa_t_exact - isentropic compressibility +% gsw_kappa_const_t_exact - isothermal compressibility +% gsw_internal_energy_t_exact - internal energy +% gsw_enthalpy_t_exact - enthalpy +% gsw_dynamic_enthalpy_t_exact - dynamic enthalpy +% gsw_SA_from_rho_t_exact - Absolute Salinity from density +% gsw_t_from_rho_exact - in-situ temperature from density +% gsw_t_maxdensity_exact - in-situ temperature of maximum density of seawater +% gsw_entropy_t_exact - entropy +% gsw_cp_t_exact - isobaric heat capacity +% gsw_isochoric_heat_cap_t_exact - isochoric heat capacity +% gsw_chem_potential_relative_t_exact - relative chemical potential +% gsw_chem_potential_water_t_exact - chemical potential of water in seawater +% gsw_chem_potential_salt_t_exact - chemical potential of salt in seawater +% gsw_Helmholtz_energy_t_exact - Helmholtz energy +% gsw_adiabatic_lapse_rate_t_exact - adiabatic lapse rate +% gsw_osmotic_coefficient_t_exact - osmotic coefficient of seawater +% gsw_osmotic_pressure_t_exact - osmotic pressure of seawater +% +% Library functions of the GSW toolbox (internal functions; not intended to be called by users) +% (The GSW functions above call the following library functions.) +% gsw_gibbs - the TEOS-10 Gibbs function and its derivatives +% gsw_SAAR - Absolute Salinity Anomaly Ratio (excluding the Baltic Sea) +% gsw_Fdelta - ratio of Absolute to Preformed Salinity, minus 1 +% gsw_delta_SA_ref - Absolute Salinity Anomaly ref. value (excluding the Baltic Sea) +% gsw_SA_from_SP_Baltic - Calculates Absolute Salinity in the Baltic Sea +% gsw_SP_from_SA_Baltic - Calculates Practical Salinity in the Baltic Sea +% gsw_infunnel - "oceanographic funnel" check for the 25-term equation +% gsw_entropy_part - entropy minus the terms that are a function of only SA +% gsw_entropy_part_zerop - entropy_part evaluated at 0 dbar +% gsw_interp_ref_cast - linearly interpolates the reference cast +% gsw_interp_SA_CT - linearly interpolates (SA,CT,p) to the desired p +% gsw_gibbs_pt0_pt0 - gibbs(0,2,0,SA,t,0) +% gsw_specvol_SSO_0_p - specvol_CT(35.16504,0,p) +% gsw_enthalpy_SSO_0_p - enthalpy_CT(35.16504,0,p) +% gsw_Hill_ratio_at_SP2 - Hill ratio at a Practical Salinity of 2 +% +% The GSW data set. +% gsw_data_v3_0 - contains +% (1) the global data set of Absolute Salinity Anomaly Ratio, +% (2) the global data set of Absolute Salinity Anomaly Ref., +% (3) a reference cast (for the isopycnal streamfunction), +% (4) two reference casts that are used by gsw_demo +% (5) three vertical profiles of (SP, t, p) at known long & lat, plus +% the outputs of all the GSW functions for these 3 profiles, and +% the required accuracy of all these outputs. +% \ No newline at end of file diff --git a/Toolbox/gsw_Abs_Pressure_from_p.m b/Toolbox/gsw_Abs_Pressure_from_p.m new file mode 100644 index 0000000..3dd7250 --- /dev/null +++ b/Toolbox/gsw_Abs_Pressure_from_p.m @@ -0,0 +1,43 @@ +function Absolute_Pressure = gsw_Abs_Pressure_from_p(p) + +% gsw_Abs_Pressure_from_p Absolute Pressure +%========================================================================== +% +% USAGE: +% Absolute_Pressure = gsw_Abs_Pressure_from_p(p) +% +% DESCRIPTION: +% Calculates Absolute Pressure from sea pressure. Note that Absolute +% Pressure is in Pa NOT dbar. +% +% INPUT: +% p = sea pressure [ dbar ] +% +% OUTPUT: +% Absolute_Pressure = Absolute Pressure [ Pa ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. +% See Eqn. (2.2.1) of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +if ~(nargin == 1) + error('gsw_Abs_Pressure_from_p: Requires one input') +end + +db2Pa = 1e4; + +Absolute_Pressure = p*db2Pa + 101325; + +end diff --git a/Toolbox/gsw_C3515.m b/Toolbox/gsw_C3515.m new file mode 100644 index 0000000..627c762 --- /dev/null +++ b/Toolbox/gsw_C3515.m @@ -0,0 +1,37 @@ +function C3515 = gsw_C3515 + +% gsw_C3515 Conductivity of SSW at SP=35,t_68=15,p=0 +%========================================================================== +% +% USAGE: +% C3515 = gsw_C3515 +% +% DESCRIPTION: +% This function provides the present estimate of Conductivity, C, of +% Standard Seawater (SSW) at (SP=35, t_68=15, p=0) which is +% 42.9140 mS/cm (=4.29140 S/m) (Culkin and Smith, 1980; UNESCO, 1983). +% +% OUTPUT: +% C3515 = Conductivity at (SP=35, t_68=15, p=0) [ mS/cm ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% Culkin and Smith, 1980: Determination of the Concentration of Potassium +% Chloride Solution Having the Same Electrical Conductivity, at 15C and +% Infinite Frequency, as Standard Seawater of Salinity 35.0000 +% (Chlorinity 19.37394), IEEE J. Oceanic Eng, 5, 22-23. +% +% Unesco, 1983: Algorithms for computation of fundamental properties of +% seawater. Unesco Technical Papers in Marine Science, 44, 53 pp. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +C3515 = 42.9140; + +end diff --git a/Toolbox/gsw_CT_first_derivatives.m b/Toolbox/gsw_CT_first_derivatives.m index 5a516c8..6d19da3 100644 --- a/Toolbox/gsw_CT_first_derivatives.m +++ b/Toolbox/gsw_CT_first_derivatives.m @@ -25,29 +25,23 @@ % CT_SA = The derivative of Conservative Temperature with respect to % Absolute Salinity at constant potential temperature % (the regular potential temperature which has reference -% sea pressure of 0 dbar). The CT_SA output has units of: -% [ K/(g/kg)] +% sea pressure of 0 dbar). +% The CT_SA output has units of: [ K/(g/kg)] % CT_pt = The derivative of Conservative Temperature with respect to % potential temperature (the regular one with pr = 0 dbar) % at constant SA. CT_pt is dimensionless. [ unitless ] % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (11th April 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of % seawater - 2010: Calculation and use of thermodynamic properties. % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. -% See Eqns. (A.12.3) and (A.12.9a,b) of this TEOS-10 Manual. -% -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% See Eqns. (A.12.3a,b) and (A.15.8) of this TEOS-10 Manual. % % This software is available from http://www.TEOS-10.org % @@ -73,8 +67,8 @@ end if ms == 1 - SA = SA'; - pt = pt'; + SA = SA.'; + pt = pt.'; transposed = 1; else transposed = 0; @@ -86,19 +80,46 @@ cp0 = 3991.86795711963; % from Eqn. 3.3.3 of IOC et al. (2010). n0 = 0; -n1 = 1; n2 = 2; pr0 = zeros(size(SA)); abs_pt = 273.15 + pt; -CT_SA = (gsw_gibbs(n1,n0,n0,SA,pt,pr0) -... - abs_pt.*gsw_gibbs(n1,n1,n0,SA,pt,pr0))./cp0; - CT_pt = - (abs_pt.*gsw_gibbs(n0,n2,n0,SA,pt,pr0))./cp0; +%-------------------------------------------------------------------------- + +sfac = 0.0248826675584615; % sfac = 1/(40*(35.16504/35)). +x2 = sfac.*SA; +x = sqrt(x2); +y_pt = 0.025*pt; + +g_SA_T_mod = 1187.3715515697959 + ... + x.*(-1480.222530425046 + x.*(2175.341332000392 + x.*(-980.14153344888 + 220.542973797483.*x) + ... + y_pt.*(-548.4580073635929 + y_pt.*(592.4012338275047 + y_pt.*(-274.2361238716608 + 49.9394019139016.*y_pt)))) + ... + y_pt.*(-258.3988055868252 + y_pt.*(-90.2046337756875 + y_pt.*10.50720794170734))) + ... + y_pt.*(3520.125411988816 + y_pt.*(-1351.605895580406 + ... + y_pt.*(731.4083582010072 + y_pt.*(-216.60324087531103 + 25.56203650166196.*y_pt)))); +g_SA_T_mod = 0.5*sfac*0.025*g_SA_T_mod; + +g_SA_mod = 8645.36753595126 + ... + x.*(-7296.43987145382 + x.*(8103.20462414788 + ... + y_pt.*(2175.341332000392 + y_pt.*(-274.2290036817964 + ... + y_pt.*(197.4670779425016 + y_pt.*(-68.5590309679152 + 9.98788038278032.*y_pt)))) + ... + x.*(-5458.34205214835 - 980.14153344888.*y_pt + ... + x.*(2247.60742726704 - 340.1237483177863.*x + 220.542973797483.*y_pt))) + ... + y_pt.*(-1480.222530425046 + ... + y_pt.*(-129.1994027934126 + ... + y_pt.*(-30.0682112585625 + y_pt.*(2.626801985426835 ))))) + ... + y_pt.*(1187.3715515697959 + ... + y_pt.*(1760.062705994408 + y_pt.*(-450.535298526802 + ... + y_pt.*(182.8520895502518 + y_pt.*(-43.3206481750622 + 4.26033941694366.*y_pt))))); +g_SA_mod = 0.5*sfac*g_SA_mod; + +CT_SA = (g_SA_mod - abs_pt.*g_SA_T_mod)./cp0; + if transposed - CT_SA = CT_SA'; - CT_pt = CT_pt'; + CT_SA = CT_SA.'; + CT_pt = CT_pt.'; end end diff --git a/Toolbox/gsw_CT_freezing.m b/Toolbox/gsw_CT_freezing.m new file mode 100644 index 0000000..ecdda10 --- /dev/null +++ b/Toolbox/gsw_CT_freezing.m @@ -0,0 +1,177 @@ +function CT_freezing = gsw_CT_freezing(SA,p,saturation_fraction) + +% gsw_CT_freezing Conservative Temperature at which seawater freezes +%========================================================================== +% +% USAGE: +% CT_freezing = gsw_CT_freezing(SA,p,saturation_fraction) +% +% DESCRIPTION: +% Calculates the Conservative Temperature at which seawater freezes. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% OPTIONAL: +% saturation_fraction = the saturation fraction of dissolved air in +% seawater +% (i.e., saturation_fraction must be between 0 and 1, and the default +% is 1, completely saturated) +% +% p & saturation_fraction (if provided) may have dimensions 1x1 or Mx1 or +% 1xN or MxN, where SA is MxN. +% +% OUTPUT: +% CT_freezing = Conservative Temperature at freezing of seawater [ deg C ] +% That is, the freezing temperature expressed in +% terms of Conservative Temperature (ITS-90). +% +% AUTHOR: +% Trevor McDougall, Paul Barker and Rainer Feistal [ help@teos-10.org ] +% +% VERSION NUMBER: 3.0 (4th November, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. +% See sections 3.33 and 3.34 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2 | nargin == 3) + error('gsw_CT_freezing: Requires either two or three inputs') +end %if + +if ~exist('saturation_fraction','var') + saturation_fraction = 1; +end + +if (saturation_fraction < 0 | saturation_fraction > 1) + error('gsw_CT_freezing: saturation_fraction MUST be between zero and one.') +end + +[ms,ns] = size(SA); +[mp,np] = size(p); +[map,nap] = size(saturation_fraction); + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_CT_freezing: Inputs array dimensions arguments do not agree') +end %if + +if (map == 1) & (nap == 1) % saturation_fraction scalar + saturation_fraction = saturation_fraction*ones(size(SA)); % fill to size of SA +elseif (ns == nap) & (map == 1) % saturation_fraction is row vector, + saturation_fraction = saturation_fraction(ones(1,ms), :); % copy down each column. +elseif (ms == map) & (nap == 1) % saturation_fraction is column vector, + saturation_fraction = saturation_fraction(:,ones(1,ns)); % copy across each row. +elseif (ns == map) & (nap == 1) % saturation_fraction is a transposed row vector, + saturation_fraction = saturation_fraction.'; % transposed then + saturation_fraction = saturation_fraction(ones(1,ms), :); % copy down each column. +elseif (ms == map) & (ns == nap) + % ok +else + error('gsw_CT_freezing: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + p = p.'; + saturation_fraction = saturation_fraction.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + error(' gsw_CT_freezing: SA must be non-negative!') +end + +c0 = 0.017947064327968736; +% +c1 = -6.076099099929818; +c2 = 4.883198653547851; +c3 = -11.88081601230542; +c4 = 13.34658511480257; +c5 = -8.722761043208607; +c6 = 2.082038908808201; +% +c7 = -7.389420998107497; +c8 = -2.110913185058476; +c9 = 0.2295491578006229; +% +c10 = -0.9891538123307282; +c11 = -0.08987150128406496; +c12 = 0.3831132432071728; +c13 = 1.054318231187074; +c14 = 1.065556599652796; +c15 = -0.7997496801694032; +c16 = 0.3850133554097069; +c17 = -2.078616693017569; +c18 = 0.8756340772729538; +c19 = -2.079022768390933; +c20 = 1.596435439942262; +c21 = 0.1338002171109174; +c22 = 1.242891021876471; + +SA_r = SA.*1e-2; +x = sqrt(SA_r); +p_r = p.*1e-4; + +CT_freezing = c0 ... + + SA_r.*(c1 + x.*(c2 + x.*(c3 + x.*(c4 + x.*(c5 + c6.*x))))) ... + + p_r.*(c7 + p_r.*(c8 + c9.*p_r)) ... + + SA_r.*p_r.*(c10 + p_r.*(c12 + p_r.*(c15 + c21.*SA_r)) + SA_r.*(c13 + c17.*p_r + c19.*SA_r) ... + + x.*(c11 + p_r.*(c14 + c18.*p_r) + SA_r.*(c16 + c20.*p_r + c22.*SA_r))); + +% The error of this fit ranges between -5e-4 K and 6e-4 K when compared +% with the Conservative Temperature calculated from the exact in-situ +% freezing temperature which is found by a Newton-Raphson iteration of the +% equality of the chemical potentials of water in seawater and in ice. +% (Note that the in-situ freezing temperature can be found by this exact +% method using the function sea_ice_freezingtemperature_si in the SIA +% library). + +% Adjust for the effects of dissolved air +a = 0.014289763856964; % Note that a = 0.502500117621/35.16504. +b = 0.057000649899720; +CT_freezing = CT_freezing ... + - saturation_fraction.*(1e-3).*(2.4 - a.*SA).*(1 + b.*(1 - SA./35.16504)); + +[Iout_of_range] = find(p > 10000 | SA > 120 | ... + p + SA.*71.428571428571402 > 13571.42857142857); +if ~isempty(Iout_of_range) + CT_freezing(Iout_of_range) = NaN; +end + +if transposed + CT_freezing = CT_freezing.'; +end + +end \ No newline at end of file diff --git a/Toolbox/gsw_CT_from_entropy.m b/Toolbox/gsw_CT_from_entropy.m index 8146271..c8c7959 100644 --- a/Toolbox/gsw_CT_from_entropy.m +++ b/Toolbox/gsw_CT_from_entropy.m @@ -11,18 +11,18 @@ % Calculates Conservative Temperature with entropy as an input variable. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% entropy = specific entropy [ deg C ] +% SA = Absolute Salinity [ g/kg ] +% entropy = specific entropy [ deg C ] % % SA & entropy need to have the same dimensions. % % OUTPUT: -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % % AUTHOR: -% Trevor McDougall and Paul Barker. [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker. [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (13th October, 2010) +% VERSION NUMBER: 3.0 (3rd March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -51,8 +51,8 @@ end %if if ms == 1 - SA = SA'; - entropy = entropy'; + SA = SA.'; + entropy = entropy.'; transposed = 1; else transposed = 0; @@ -72,7 +72,7 @@ CT = gsw_CT_from_pt(SA,pt); if transposed - CT = CT'; + CT = CT.'; end end diff --git a/Toolbox/gsw_CT_from_pt.m b/Toolbox/gsw_CT_from_pt.m index cc7c906..bdd1632 100644 --- a/Toolbox/gsw_CT_from_pt.m +++ b/Toolbox/gsw_CT_from_pt.m @@ -17,12 +17,13 @@ % SA & pt need to have the same dimensions. % % OUTPUT: -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (5th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -51,8 +52,8 @@ end if ms == 1 - SA = SA'; - pt = pt'; + SA = SA.'; + pt = pt.'; transposed = 1; else transposed = 0; @@ -113,7 +114,7 @@ CT = pot_enthalpy./cp0; if transposed - CT = CT'; + CT = CT.'; end end diff --git a/Toolbox/gsw_CT_from_rho.m b/Toolbox/gsw_CT_from_rho.m new file mode 100644 index 0000000..a9c8383 --- /dev/null +++ b/Toolbox/gsw_CT_from_rho.m @@ -0,0 +1,248 @@ +function [CT,CT_multiple] = gsw_CT_from_rho(rho,SA,p) + +% gsw_CT_from_rho Conservative Temperature from density +% (48-term equation) +% ========================================================================= +% +% USAGE: +% [CT,CT_multiple] = gsw_CT_from_rho(rho,SA,p) +% +% DESCRIPTION: +% Calculates the Conservative Temperature of a seawater sample, for given +% values of its density, Absolute Salinity and sea pressure (in dbar), +% using the computationally-efficient 48-term expression for density in +% terms of SA, CT and p (McDougall et al., 2011) +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% rho = density of a seawater sample (e.g. 1026 kg/m^3) [ kg/m^3 ] +% Note. This input has not had 1000 kg/m^3 subtracted from it. +% That is, it is 'density', not 'density anomaly'. +% SA = Absolute Salinity [ g/kg ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% rho & SA need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where rho & SA are MxN. +% +% OUTPUT: +% CT = Conservative Temperature (ITS-90) [ deg C ] +% CT_multiple = Conservative Temperature (ITS-90) [ deg C ] +% Note that at low salinities, in brackish water, there are two possible +% Conservative Temperatures for a single density. This programme will +% output both valid solutions. To see this second solution the user +% must call the programme with two outputs (i.e. [CT,CT_multiple]), if +% there is only one possible solution and the programme has been +% called with two outputs the second variable will be set to NaN. +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (21th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin==3) + error('gsw_CT_from_rho: Requires three inputs') +end %if + +[md,nd] = size(rho); +[ms,ns] = size(SA); +[mp,np] = size(p); + +if (ms ~= md | ns ~= nd) + error('gsw_CT_from_rho: rho and SA must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of rho + p = p*ones(size(rho)); +elseif (nd == np) & (mp == 1) % p is row vector, + p = p(ones(1,md), :); % copy down each column. +elseif (md == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,nd)); % copy across each row. +elseif (nd == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,md), :); % copy down each column. +elseif (md == mp) & (nd == np) + % ok +else + error('gsw_CT_from_rho: Inputs array dimensions arguments do not agree') +end %if + +if md == 1 + rho = rho.'; + SA = SA.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% alpha_limit is the positive value of the thermal expansion coefficient +% which is used at the freezing temperature to distinguish between +% I_salty and I_fresh. +alpha_limit = 1e-5; + +% rec_half_rho_TT is a constant representing the reciprocal of half the +% second derivative of density with respect to temperature near the +% temperature of maximum density. +rec_half_rho_TT = -110.0; + +CT = nan(size(SA)); +CT_multiple = nan(size(SA)); + +[I_SA_p] = find(SA<0 | SA>42 | p <-1.5 | p>12000); +if ~isempty(I_SA_p) + SA(I_SA_p) = NaN; +end + +rho_40 = gsw_rho_CT(SA,40*ones(size(SA)),p); +[I_rho_light] = find((rho - rho_40) < 0); +if ~isempty(I_rho_light) + SA(I_rho_light) = NaN; +end + +CT_max_rho = gsw_CT_maxdensity(SA,p); +rho_max = gsw_rho(SA,CT_max_rho,p); +rho_extreme = rho_max; +CT_freezing = gsw_CT_freezing(SA,p); % this assumes that the seawater is always saturated with air +rho_freezing = gsw_rho(SA,CT_freezing,p); +[I_fr_gr_max] = find((CT_freezing - CT_max_rho) > 0); +rho_extreme(I_fr_gr_max) = rho_freezing(I_fr_gr_max); +[I_rho_dense] = find(rho > rho_extreme); +if ~isempty(I_rho_dense) + SA(I_rho_dense) = NaN; +end + +[I_bad] = find(isnan(SA.*p.*rho)); +if ~isempty (I_bad) + SA(I_bad) = NaN; +end + +alpha_freezing = gsw_alpha(SA,CT_freezing,p); +[I_salty] = find(alpha_freezing > alpha_limit); + +if ~isempty(I_salty) + CT_diff = 40*ones(size(I_salty)) - CT_freezing(I_salty); + + top = rho_40(I_salty) - rho_freezing(I_salty) ... + + rho_freezing(I_salty).*alpha_freezing(I_salty).*CT_diff; + a = top./(CT_diff.*CT_diff); + b = - rho_freezing(I_salty).*alpha_freezing(I_salty); + c = rho_freezing(I_salty) - rho(I_salty); + sqrt_disc = sqrt(b.*b - 4*a.*c); + % the value of t(I_salty) here is the initial guess at CT in the range + % of I_salty. + CT(I_salty) = CT_freezing(I_salty) + 0.5*(-b - sqrt_disc)./a; +end + +[I_fresh] = find(alpha_freezing <= alpha_limit); +if ~isempty(I_fresh) + CT_diff = 40*ones(size(I_fresh)) - CT_max_rho(I_fresh); + factor = (rho_max(I_fresh) - rho(I_fresh))./ ... + (rho_max(I_fresh) - rho_40(I_fresh)); + delta_CT = CT_diff.*sqrt(factor); + + [I_fresh_NR] = find(delta_CT > 5); + if ~isempty(I_fresh_NR) + CT(I_fresh(I_fresh_NR)) = CT_max_rho(I_fresh(I_fresh_NR)) + delta_CT(I_fresh_NR); + end + + [I_quad] = find(delta_CT <= 5); + if ~isempty(I_quad) + CT_a = nan(size(SA)); + % set the initial value of the quadratic solution routes. + CT_a(I_fresh(I_quad)) = CT_max_rho(I_fresh(I_quad)) + ... + sqrt(rec_half_rho_TT*(rho(I_fresh(I_quad)) - rho_max(I_fresh(I_quad)))); + for Number_of_iterations = 1:7 + CT_old = CT_a; + rho_old = gsw_rho(SA,CT_old,p); + factorqa = (rho_max - rho)./(rho_max - rho_old); + CT_a = CT_max_rho + (CT_old - CT_max_rho).*sqrt(factorqa); + end + [Ifrozen] = find(CT_freezing - CT_a < 0); + if ~isempty(Ifrozen) + CT_a(Ifrozen) = NaN; + end + + CT_b = nan(size(SA)); + % set the initial value of the quadratic solution roots. + CT_b(I_fresh(I_quad)) = CT_max_rho(I_fresh(I_quad)) - ... + sqrt(rec_half_rho_TT*(rho(I_fresh(I_quad)) - rho_max(I_fresh(I_quad)))); + for Number_of_iterations = 1:7 + CT_old = CT_b; + rho_old = gsw_rho(SA,CT_old,p); + factorqb = (rho_max - rho)./(rho_max - rho_old); + CT_b = CT_max_rho + (CT_old - CT_max_rho).*sqrt(factorqb); + end +% After seven iterations of this quadratic iterative procedure, +% the error in rho is no larger than 4.6x10^-13 kg/m^3. + [Ifrozen] = find(CT_freezing - CT_b < 0); + if ~isempty(Ifrozen) + CT_b(Ifrozen) = NaN; + end + end +end + +% begin the modified Newton-Raphson iterative method, which will only +% operate on non-NaN CT data. + +v_lab = ones(size(rho))./rho; +v_CT = gsw_specvol(SA,CT,p).*gsw_alpha(SA,CT,p); + +for Number_of_iterations = 1:3 + CT_old = CT; + delta_v = gsw_specvol(SA,CT_old,p) - v_lab; + CT = CT_old - delta_v./v_CT ; % this is half way through the modified N-R method + CT_mean = 0.5*(CT + CT_old); + v_CT = gsw_specvol(SA,CT_mean,p).*gsw_alpha(SA,CT_mean,p); + CT = CT_old - delta_v./v_CT ; +end + +if exist('t_a','var') + [I_quad] = find(~isnan(CT_a)); + if ~isempty(I_quad) + CT(I_quad) = CT_a(I_quad); + end +end +if exist('t_b','var') + [I_quad] = find(~isnan(CT_b)); + if ~isempty(I_quad) + CT_multiple(I_quad) = CT_b(I_quad); + end +end +% After three iterations of this modified Newton-Raphson iteration, +% the error in rho is no larger than 1.6x10^-12 kg/m^3. + +if transposed + CT = CT.'; + CT_multiple = CT_multiple.'; +end + +end diff --git a/Toolbox/gsw_CT_from_rho_exact.m b/Toolbox/gsw_CT_from_rho_exact.m new file mode 100644 index 0000000..112294f --- /dev/null +++ b/Toolbox/gsw_CT_from_rho_exact.m @@ -0,0 +1,103 @@ +function [CT,CT_multiple] = gsw_CT_from_rho_exact(rho,SA,p) + +% gsw_t_from_rho_exact in situ temperature from density +% ========================================================================= +% +% USAGE: +% [t,t_multiple] = gsw_t_from_rho_exact(rho,SA,p) +% +% DESCRIPTION: +% Calculates the in-situ temperature of a seawater sample, for given +% values of its density, Absolute Salinity and sea pressure (in dbar). +% +% INPUT: +% rho = density of a seawater sample (e.g. 1026 kg/m^3) [ kg/m^3 ] +% Note. This input has not had 1000 kg/m^3 subtracted from it. +% That is, it is 'density', not 'density anomaly'. +% SA = Absolute Salinity [ g/kg ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% rho & SA need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where rho & SA are MxN. +% +% OUTPUT: +% t = in-situ temperature [ deg C ] +% t_multiple = in-situ temperature [ deg C ] +% Note that at low salinities, in brackish water, there are two possible +% temperatures for a single density. This programme will output both +% valid solutions. To see this second solution the user must call the +% programme with two outputs (i.e. [t,t_multiple]), if there is only +% one possible solution and the programme has been called with two +% outputs the second variable will be set to NaN. +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (21th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin==3) + error('gsw_t_from_rho_exact: Requires three inputs') +end %if + +[md,nd] = size(rho); +[ms,ns] = size(SA); +[mp,np] = size(p); + +if (ms ~= md | ns ~= nd) + error('gsw_t_from_rho_exact: rho and SA must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of rho + p = p*ones(size(rho)); +elseif (nd == np) & (mp == 1) % p is row vector, + p = p(ones(1,md), :); % copy down each column. +elseif (md == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,nd)); % copy across each row. +elseif (nd == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,md), :); % copy down each column. +elseif (md == mp) & (nd == np) + % ok +else + error('gsw_t_from_rho_exact: Inputs array dimensions arguments do not agree') +end %if + +if md == 1 + rho = rho.'; + SA = SA.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +[t,t_multiple] = gsw_t_from_rho_exact(rho,SA,p); + +CT = gsw_CT_from_t(SA,t,p); +CT_multiple = gsw_CT_from_t(SA,t_multiple,p); + +if transposed + CT = CT.'; + CT_multiple = CT_multiple.'; +end + +end diff --git a/Toolbox/gsw_CT_from_t.m b/Toolbox/gsw_CT_from_t.m index 8092f53..a2ae047 100644 --- a/Toolbox/gsw_CT_from_t.m +++ b/Toolbox/gsw_CT_from_t.m @@ -14,18 +14,19 @@ % SA = Absolute Salinity [ g/kg ] % t = in-situ temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (27th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -60,16 +61,28 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms),:); % copy down each column. elseif (ms == mp) & (ns == np) % ok else error('gsw_CT_from_t: Inputs array dimensions arguments do not agree') end %if +[Iout_of_range] = find(p < 100 & (t > 80 | t < -12)); +if (~isempty(Iout_of_range)) + t(Iout_of_range) = NaN; +end +[Iout_of_range] = find(p >= 100 & (t > 40 | t < -12)); +if (~isempty(Iout_of_range)) + t(Iout_of_range) = NaN; +end + if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -83,7 +96,7 @@ CT = gsw_CT_from_pt(SA,pt0); if transposed - CT = CT'; + CT = CT.'; end end diff --git a/Toolbox/gsw_CT_maxdensity.m b/Toolbox/gsw_CT_maxdensity.m new file mode 100644 index 0000000..74d93f5 --- /dev/null +++ b/Toolbox/gsw_CT_maxdensity.m @@ -0,0 +1,123 @@ +function CT_maxdensity = gsw_CT_maxdensity(SA,p) + +% gsw_CT_maxdensity Conservative Temperature of maximum +% density of seawater (48-term equation) +% ========================================================================= +% +% USAGE: +% CT_maxdensity = gsw_CT_maxdensity(SA,p) +% +% DESCRIPTION: +% Calculates the Conservative Temperature of maximum density of seawater. +% This function returns the Conservative temperature at which the density +% of seawater is a maximum, at given Absolute Salinity, SA, and sea +% pressure, p (in dbar). This function uses the computationally-efficient +% 48-term expression for density in terms of SA, CT and p (McDougall et +% al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA is MxN. +% +% OUTPUT: +% CT_maxdensity = Conservative Temperature at which [ deg C ] +% the density of seawater is a maximum for +% given Absolute Salinity and pressure. +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (3rd April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 3.42 of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_CT_maxdensity: Requires two inputs') +end %if + +[ms,ns] = size(SA); +[mp,np] = size(p); + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_CT_maxdensity: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% n0 = 0; +% n1 = 1; + +dCT = 0.001; % the Conservative Temperature increment. + +CT = 3.978 - 0.22072*SA; % the initial guess of CT. + +dalpha_dCT = 1.1e-5; % the initial guess for d(alpha)_dCT. + +for Number_of_iterations = 1:3 + CT_old = CT; + alpha = gsw_alpha(SA,CT_old,p); + CT = CT_old - alpha./dalpha_dCT; % this is half way through the modified method + CT_mean = 0.5*(CT + CT_old); + dalpha_dCT = (gsw_alpha(SA,CT_mean + dCT,p) ... + - gsw_alpha(SA,CT_mean - dCT,p))./(dCT + dCT); + CT = CT_old - alpha./dalpha_dCT; +end + +% After three iterations of this modified Newton-Raphson iteration, the +% error in CT_maxdensity is typically no larger than 1x10^-15 degress C. + +CT_maxdensity = CT; + +if transposed + CT_maxdensity = CT_maxdensity.'; +end + +end diff --git a/Toolbox/gsw_CT_maxdensity_exact.m b/Toolbox/gsw_CT_maxdensity_exact.m new file mode 100644 index 0000000..256f29d --- /dev/null +++ b/Toolbox/gsw_CT_maxdensity_exact.m @@ -0,0 +1,89 @@ +function CT_maxdensity_exact = gsw_CT_maxdensity_exact(SA,p) + +% gsw_CT_maxdensity_exact Conservative Temperature of maximum +% density of seawater +% ========================================================================= +% +% USAGE: +% CT_maxdensity_exact = gsw_CT_maxdensity_exact(SA,p) +% +% DESCRIPTION: +% Calculates the Conservative Temperature of maximum density of seawater. +% This function returns the Conservative temperature at which the density +% of seawater is a maximum, at given Absolute Salinity, SA, and sea +% pressure, p (in dbar). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA is MxN. +% +% OUTPUT: +% CT_maxdensity_exact = Conservative Temperature at which [ deg C ] +% the density of seawater is a maximum for +% given Absolute Salinity and pressure. +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (3rd April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 3.42 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_CT_maxdensity_exact: Requires two inputs') +end %if + +[ms,ns] = size(SA); +[mp,np] = size(p); + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_CT_maxdensity_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +t_maxdensity_exact = gsw_t_maxdensity_exact(SA,p); +CT_maxdensity_exact = gsw_CT_from_t(SA,t_maxdensity_exact,p); + +if transposed + CT_maxdensity_exact = CT_maxdensity_exact.'; +end + +end diff --git a/Toolbox/gsw_CT_second_derivatives.m b/Toolbox/gsw_CT_second_derivatives.m index 2047580..04d2365 100644 --- a/Toolbox/gsw_CT_second_derivatives.m +++ b/Toolbox/gsw_CT_second_derivatives.m @@ -1,7 +1,7 @@ function [CT_SA_SA, CT_SA_pt, CT_pt_pt] = gsw_CT_second_derivatives(SA,pt) -% gsw_CT_second_derivatives second derivatives of Conservative -% Temperature +% gsw_CT_second_derivatives second derivatives of +% Conservative Temperature %========================================================================== % % USAGE: @@ -10,10 +10,10 @@ % DESCRIPTION: % Calculates the following three, second-order derivatives of Conservative % Temperature -% (1) CT_SA_SA, the second derivative with respect to Absolute Salinity at -% constant potential temperature (with pr = 0 dbar), +% (1) CT_SA_SA, the second derivative with respect to Absolute Salinity +% at constant potential temperature (with p_ref = 0 dbar), % (2) CT_SA_pt, the derivative with respect to potential temperature -% (the regular potential temperature which is referenced to 0 dbar) +% (the regular potential temperature which is referenced to 0 dbar) % and Absolute Salinity, and % (3) CT_pt_pt, the second derivative with respect to potential % temperature (the regular potential temperature which is referenced @@ -21,7 +21,8 @@ % % INPUT: % SA = Absolute Salinity [ g/kg ] -% pt = potential temperature (ITS-90) [ deg C ] +% pt = potential temperature (ITS-90) [ deg C ] +% (whose reference pressure is 0 dbar) % % SA & pt need to have the same dimensions. % @@ -30,20 +31,21 @@ % respect to Absolute Salinity at constant potential % temperature (the regular potential temperature which % has reference sea pressure of 0 dbar). -% The CT_SA_SA output has units of: [ K/((g/kg)^2) ] +% CT_SA_SA has units of: [ K/((g/kg)^2) ] % CT_SA_pt = The derivative of Conservative Temperature with % respect to potential temperature (the regular one with -% pr = 0 dbar) and Absolute Salinity. -% CT_SA_pt has units of: [ (g/kg)^-1 ] +% p_ref = 0 dbar) and Absolute Salinity. +% CT_SA_pt has units of: [ 1/(g/kg) ] % CT_pt_pt = The second derivative of Conservative Temperature with % respect to potential temperature (the regular one with -% pr = 0 dbar) at constant SA. -% CT_pt_pt has units of: [ K^-1 ] +% p_ref = 0 dbar) at constant SA. +% CT_pt_pt has units of: [ 1/K ] % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -52,11 +54,10 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. % See appendix A.12 of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % This software is available from http://www.TEOS-10.org % @@ -78,12 +79,12 @@ [mt,nt] = size(pt); if (mt ~= ms | nt ~= ns) - error('gsw_CT_second_derivatives: SA and pt must have same dimensions') + error('gsw_CT_second_derivatives: SA and pt must have same dimensions') end if ms == 1 - SA = SA'; - pt = pt'; + SA = SA.'; + pt = pt.'; transposed = 1; else transposed = 0; @@ -125,9 +126,9 @@ CT_pt_pt = (CT_pt_u - CT_pt_l)./(pt_u - pt_l); if transposed - CT_SA_SA = CT_SA_SA'; - CT_SA_pt = CT_SA_pt'; - CT_pt_pt = CT_pt_pt'; + CT_SA_SA = CT_SA_SA.'; + CT_SA_pt = CT_SA_pt.'; + CT_pt_pt = CT_pt_pt.'; end end diff --git a/Toolbox/gsw_C_from_SP.m b/Toolbox/gsw_C_from_SP.m new file mode 100644 index 0000000..fe658e8 --- /dev/null +++ b/Toolbox/gsw_C_from_SP.m @@ -0,0 +1,413 @@ +function C = gsw_C_from_SP(SP,t,p) + +% gsw_C_from_SP conductivity from SP +%========================================================================== +% +% USAGE: +% C = gsw_C_from_SP(SP,t,p) +% +% DESCRIPTION: +% Calculates conductivity, C, from (SP,t,p) using PSS-78 in the range +% 2 < SP < 42. If the input Practical Salinity is less than 2 then a +% modified form of the Hill et al. (1986) fomula is used for Practical +% Salinity. The modification of the Hill et al. (1986) expression is to +% ensure that it is exactly consistent with PSS-78 at SP = 2. +% +% The conductivity ratio returned by this function is consistent with the +% input value of Practical Salinity, SP, to 2x10^-14 psu over the full +% range of input parameters (from pure fresh water up to SP = 42 psu). +% This error of 2x10^-14 psu is machine precision at typical seawater +% salinities. This accuracy is achieved by having four different +% polynomials for the starting value of Rtx (the square root of Rt) in +% four different ranges of SP, and by using one and a half iterations of +% a computationally efficient modified Newton-Raphson technique to find +% the root of the equation. +% +% Note that strictly speaking PSS-78 (Unesco, 1983) defines Practical +% Salinity in terms of the conductivity ratio, R, without actually +% specifying the value of C(35,15,0) (which we currently take to be +% 42.9140 mS/cm). +% +% INPUT: +% SP = Practical Salinity (PSS-78) [ unitless ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SP & t need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SP & t are MxN. +% +% OUTPUT: +% C = conductivity [ mS/cm ] +% +% AUTHOR: +% Trevor McDougall, Paul Barker and Rich Pawlowicz [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (1st April, 2011) +% +% REFERENCES: +% Hill, K.D., T.M. Dauphinee and D.J. Woods, 1986: The extension of the +% Practical Salinity Scale 1978 to low salinities. IEEE J. Oceanic Eng., +% OE-11, 1, 109 - 112. +% +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See appendix E of this TEOS-10 Manual. +% +% Unesco, 1983: Algorithms for computation of fundamental properties of +% seawater. Unesco Technical Papers in Marine Science, 44, 53 pp. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_C_from_SP: Must have 3 input arguments') +end %if + +% These few lines ensure that SP is non-negative. +[I_neg_SP] = find(SP < 0); +if ~isempty(I_neg_SP) + error('gsw_C_from_SP: SP must be non-negative!') +end + +[ms,ns] = size(SP); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_C_from_SP: SP and t must have same dimensions') +end + +if (mp == 1) & (np == 1) % p is a scalar, + p = p*ones(ms,ns); % Fill to size of SP. +elseif (np == ns) & (mp == 1) % p is row vector, + p = p(ones(1,ms),:); % copy down each column. +elseif (mp == ms) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (np == ms) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (mp == ms) & (np == ns) + % ok +else + error('gsw_C_from_SP: p has wrong dimensions') +end %if + +if ms == 1 + SP = SP.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Setting up the constants +%-------------------------------------------------------------------------- + +a0 = 0.0080; +a1 = -0.1692; +a2 = 25.3851; +a3 = 14.0941; +a4 = -7.0261; +a5 = 2.7081; + +b0 = 0.0005; +b1 = -0.0056; +b2 = -0.0066; +b3 = -0.0375; +b4 = 0.0636; +b5 = -0.0144; + +c0 = 0.6766097; +c1 = 2.00564e-2; +c2 = 1.104259e-4; +c3 = -6.9698e-7; +c4 = 1.0031e-9; + +d1 = 3.426e-2; +d2 = 4.464e-4; +d3 = 4.215e-1; +d4 = -3.107e-3; + +e1 = 2.070e-5; +e2 = -6.370e-10; +e3 = 3.989e-15; + +p0 = 4.577801212923119e-3; +p1 = 1.924049429136640e-1; +p2 = 2.183871685127932e-5; +p3 = -7.292156330457999e-3; +p4 = 1.568129536470258e-4; +p5 = -1.478995271680869e-6; +p6 = 9.086442524716395e-4; +p7 = -1.949560839540487e-5; +p8 = -3.223058111118377e-6; +p9 = 1.175871639741131e-7; +p10 = -7.522895856600089e-5; +p11 = -2.254458513439107e-6; +p12 = 6.179992190192848e-7; +p13 = 1.005054226996868e-8; +p14 = -1.923745566122602e-9; +p15 = 2.259550611212616e-6; +p16 = 1.631749165091437e-7; +p17 = -5.931857989915256e-9; +p18 = -4.693392029005252e-9; +p19 = 2.571854839274148e-10; +p20 = 4.198786822861038e-12; + +q0 = 5.540896868127855e-5; +q1 = 2.015419291097848e-1; +q2 = -1.445310045430192e-5; +q3 = -1.567047628411722e-2; +q4 = 2.464756294660119e-4; +q5 = -2.575458304732166e-7; +q6 = 5.071449842454419e-3; +q7 = -9.081985795339206e-5; +q8 = -3.635420818812898e-6; +q9 = 2.249490528450555e-8; +q10 = -1.143810377431888e-3; +q11 = 2.066112484281530e-5; +q12 = 7.482907137737503e-7; +q13 = 4.019321577844724e-8; +q14 = -5.755568141370501e-10; +q15 = 1.120748754429459e-4; +q16 = -2.420274029674485e-6; +q17 = -4.774829347564670e-8; +q18 = -4.279037686797859e-9; +q19 = -2.045829202713288e-10; +q20 = 5.025109163112005e-12; + +r0 = 3.432285006604888e-3; +r1 = 1.672940491817403e-1; +r2 = 2.640304401023995e-5; +r3 = 1.082267090441036e-1; +r4 = -6.296778883666940e-5; +r5 = -4.542775152303671e-7; +r6 = -1.859711038699727e-1; +r7 = 7.659006320303959e-4; +r8 = -4.794661268817618e-7; +r9 = 8.093368602891911e-9; +r10 = 1.001140606840692e-1; +r11 = -1.038712945546608e-3; +r12 = -6.227915160991074e-6; +r13 = 2.798564479737090e-8; +r14 = -1.343623657549961e-10; +r15 = 1.024345179842964e-2; +r16 = 4.981135430579384e-4; +r17 = 4.466087528793912e-6; +r18 = 1.960872795577774e-8; +r19 = -2.723159418888634e-10; +r20 = 1.122200786423241e-12; + +u0 = 5.180529787390576e-3; +u1 = 1.052097167201052e-3; +u2 = 3.666193708310848e-5; +u3 = 7.112223828976632; +u4 = -3.631366777096209e-4; +u5 = -7.336295318742821e-7; +u6 = -1.576886793288888e+2; +u7 = -1.840239113483083e-3; +u8 = 8.624279120240952e-6; +u9 = 1.233529799729501e-8; +u10 = 1.826482800939545e+3; +u11 = 1.633903983457674e-1; +u12 = -9.201096427222349e-5; +u13 = -9.187900959754842e-8; +u14 = -1.442010369809705e-10; +u15 = -8.542357182595853e+3; +u16 = -1.408635241899082; +u17 = 1.660164829963661e-4; +u18 = 6.797409608973845e-7; +u19 = 3.345074990451475e-10; +u20 = 8.285687652694768e-13; + +k = 0.0162; + +t68 = t.*1.00024; +ft68 = (t68 - 15)./(1 + k.*(t68 - 15)); + +x = sqrt(SP); +Rtx = nan(size(SP)); + +%-------------------------------------------------------------------------- +% Finding the starting value of Rtx, the square root of Rt, using four +% different polynomials of SP and t68. +%-------------------------------------------------------------------------- +[I] = find( SP >= 9); +if ~isempty(I) + Rtx(I) = p0 + x(I).*(p1 + p4*t68(I) + x(I).*(p3 + p7*t68(I) + x(I).*(p6 ... + + p11*t68(I) + x(I).*(p10 + p16*t68(I)+ x(I).*p15))))... + + t68(I).*(p2+ t68(I).*(p5 + x(I).*x(I).*(p12 + x(I).*p17) + p8*x(I) ... + + t68(I).*(p9 + x(I).*(p13 + x(I).*p18)+ t68(I).*(p14 + p19*x(I) + p20*t68(I))))); +end + +[I] = find(SP >= 0.25 & SP < 9); +if ~isempty(I) + Rtx(I) = q0 + x(I).*(q1 + q4*t68(I) + x(I).*(q3 + q7*t68(I) + x(I).*(q6 ... + + q11*t68(I) + x(I).*(q10 + q16*t68(I)+ x(I).*q15))))... + + t68(I).*(q2+ t68(I).*(q5 + x(I).*x(I).*(q12 + x(I).*q17) + q8*x(I) ... + + t68(I).*(q9 + x(I).*(q13 + x(I).*q18)+ t68(I).*(q14 + q19*x(I) + q20*t68(I))))); +end + +[I] = find(SP >= 0.003 & SP < 0.25); +if ~isempty(I) + Rtx(I) = r0 + x(I).*(r1 + r4*t68(I) + x(I).*(r3 + r7*t68(I) + x(I).*(r6 ... + + r11*t68(I) + x(I).*(r10 + r16*t68(I)+ x(I).*r15))))... + + t68(I).*(r2+ t68(I).*(r5 + x(I).*x(I).*(r12 + x(I).*r17) + r8*x(I) ... + + t68(I).*(r9 + x(I).*(r13 + x(I).*r18)+ t68(I).*(r14 + r19*x(I) + r20*t68(I))))); +end + +[I] = find(SP < 0.003); +if ~isempty(I) + Rtx(I) = u0 + x(I).*(u1 + u4*t68(I) + x(I).*(u3 + u7*t68(I) + x(I).*(u6 ... + + u11*t68(I) + x(I).*(u10 + u16*t68(I)+ x(I).*u15))))... + + t68(I).*(u2+ t68(I).*(u5 + x(I).*x(I).*(u12 + x(I).*u17) + u8*x(I) ... + + t68(I).*(u9 + x(I).*(u13 + x(I).*u18)+ t68(I).*(u14 + u19*x(I) + u20*t68(I))))); +end + +%-------------------------------------------------------------------------- +% Finding the starting value of dSP_dRtx, the derivative of SP with respect +% to Rtx. +%-------------------------------------------------------------------------- +dSP_dRtx = a1 + (2*a2 + (3*a3 + (4*a4 + 5*a5.*Rtx).*Rtx).*Rtx).*Rtx ... + + ft68.*(b1 + (2*b2 + (3*b3 + (4*b4 + 5*b5.*Rtx).*Rtx).*Rtx).*Rtx); +[I2] = find(SP < 2); +if ~isempty(I2) + x = 400.*(Rtx(I2).*Rtx(I2)); + sqrty = 10.*Rtx(I2); + part1 = 1 + x.*(1.5 + x) ; + part2 = 1 + sqrty.*(1 + sqrty.*(1 + sqrty)); + Hill_ratio = gsw_Hill_ratio_at_SP2(t(I2)); + dSP_dRtx(I2) = dSP_dRtx(I2)... + + a0.*800.*Rtx(I2).*(1.5 + 2*x)./(part1.*part1)... + + b0.*ft68(I2).*(10 + sqrty.*(20 + 30.*sqrty))./(part2.*part2); + dSP_dRtx(I2) = Hill_ratio.*dSP_dRtx(I2); +end + +%-------------------------------------------------------------------------- +% One iteration through the modified Newton-Raphson method achieves an +% error in Practical Salinity of about 10^-12 for all combinations of the +% inputs. One and a half iterations of the modified Newton-Raphson method +% achevies a maximum error in terms of Practical Salinity of better than +% 2x10^-14 everywhere. +% +% We recommend one and a half iterations of the modified Newton-Raphson +% method. +% +% Begin the modified Newton-Raphson method. +%-------------------------------------------------------------------------- + SP_est = a0 + (a1 + (a2 + (a3 + (a4 + a5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx ... + + ft68.*(b0 + (b1 + (b2+ (b3 + (b4 + b5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx); + [I2] = find(SP_est < 2); + if ~isempty(I2) + x = 400.*(Rtx(I2).*Rtx(I2)); + sqrty = 10.*Rtx(I2); + part1 = 1 + x.*(1.5 + x) ; + part2 = 1 + sqrty.*(1 + sqrty.*(1 + sqrty)); + SP_Hill_raw = SP_est(I2) - a0./part1 - b0.*ft68(I2)./part2; + Hill_ratio = gsw_Hill_ratio_at_SP2(t(I2)); + SP_est(I2) = Hill_ratio.*SP_Hill_raw; + end + + Rtx_old = Rtx; + Rtx = Rtx_old - (SP_est - SP)./dSP_dRtx; + + Rtxm = 0.5*(Rtx + Rtx_old); % This mean value of Rtx, Rtxm, is the +% value of Rtx at which the derivative dSP_dRtx is evaluated. + + dSP_dRtx = a1 + (2*a2 + (3*a3 + (4*a4 + 5*a5.*Rtxm).*Rtxm).*Rtxm).*Rtxm ... + + ft68.*(b1 + (2*b2 + (3*b3 + (4*b4 + 5*b5.*Rtxm).*Rtxm).*Rtxm).*Rtxm); + + [I2] = find(SP_est < 2); + if ~isempty(I2) + x = 400.*(Rtxm(I2).*Rtxm(I2)); + sqrty = 10.*Rtxm(I2); + part1 = 1 + x.*(1.5 + x) ; + part2 = 1 + sqrty.*(1 + sqrty.*(1 + sqrty)); + dSP_dRtx(I2) = dSP_dRtx(I2)... + + a0.*800.*Rtxm(I2).*(1.5 + 2*x)./(part1.*part1)... + + b0.*ft68(I2).*(10 + sqrty.*(20 + 30.*sqrty))./(part2.*part2); + Hill_ratio = gsw_Hill_ratio_at_SP2(t(I2)); + dSP_dRtx(I2) = Hill_ratio.*dSP_dRtx(I2); + end + +%-------------------------------------------------------------------------- +% The line below is where Rtx is updated at the end of the one full +% iteration of the modified Newton-Raphson technique. +%-------------------------------------------------------------------------- + Rtx = Rtx_old - (SP_est - SP)./dSP_dRtx; +%-------------------------------------------------------------------------- +% Now we do another half iteration of the modified Newton-Raphson +% technique, making a total of one and a half modified N-R iterations. +%-------------------------------------------------------------------------- +SP_est = a0 + (a1 + (a2 + (a3 + (a4 + a5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx ... + + ft68.*(b0 + (b1 + (b2+ (b3 + (b4 + b5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx); + [I2] = find(SP_est < 2); + if ~isempty(I2) + x = 400.*(Rtx(I2).*Rtx(I2)); + sqrty = 10.*Rtx(I2); + part1 = 1 + x.*(1.5 + x) ; + part2 = 1 + sqrty.*(1 + sqrty.*(1 + sqrty)); + SP_Hill_raw = SP_est(I2) - a0./part1 - b0.*ft68(I2)./part2; + Hill_ratio = gsw_Hill_ratio_at_SP2(t(I2)); + SP_est(I2) = Hill_ratio.*SP_Hill_raw; + end + Rtx = Rtx - (SP_est - SP)./dSP_dRtx; + +%-------------------------------------------------------------------------- +% The following lines of code are commented out, but when activated, return +% the error, SP_error, in Rtx (in terms of psu). +% +% SP_est = a0 + (a1 + (a2 + (a3 + (a4 + a5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx ... +% + ft68.*(b0 + (b1 + (b2+ (b3 + (b4 + b5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx); +% [I2] = find(SP_est < 2); +% if ~isempty(I2) +% x = 400.*(Rtx(I2).*Rtx(I2)); +% sqrty = 10.*Rtx(I2); +% part1 = 1 + x.*(1.5 + x) ; +% part2 = 1 + sqrty.*(1 + sqrty.*(1 + sqrty)); +% SP_Hill_raw = SP_est(I2) - a0./part1 - b0.*ft68(I2)./part2; +% Hill_ratio = gsw_Hill_ratio_at_SP2(t(I2)); +% SP_est(I2) = Hill_ratio.*SP_Hill_raw; +% end +% +% SP_error = abs(SP - SP_est); +% +%--------------This is the end of the error testing------------------------ + + +%-------------------------------------------------------------------------- +% Now go from Rtx to Rt and then to the conductivity ratio R at pressure p. +%-------------------------------------------------------------------------- +Rt = Rtx.*Rtx; +A = d3 + d4.*t68; +B = 1 + d1.*t68 + d2.*t68.^2; +C = p.*(e1 + e2.*p + e3.*p.^2); +% rt_lc (i.e. rt_lower_case) corresponds to rt as defined in +% the UNESCO 44 (1983) routines. +rt_lc = c0 + (c1 + (c2 + (c3 + c4.*t68).*t68).*t68).*t68; + +D = B - A.*rt_lc.*Rt; +E = rt_lc.*Rt.*A.*(B + C); +Ra = sqrt(D.^2 + 4*E) - D; +R = 0.5*Ra./A; + +% The dimensionless conductivity ratio, R, is the conductivity input, C, +% divided by the present estimate of C(SP=35, t_68=15, p=0) which is +% 42.9140 mS/cm (=4.29140 S/m^). +C = 42.9140.*R; + +if transposed + C = C.'; +end + +end diff --git a/Toolbox/gsw_Helmholtz_energy_t_exact.m b/Toolbox/gsw_Helmholtz_energy_t_exact.m new file mode 100644 index 0000000..3be464e --- /dev/null +++ b/Toolbox/gsw_Helmholtz_energy_t_exact.m @@ -0,0 +1,95 @@ +function Helmholtz_energy_t_exact = gsw_Helmholtz_energy_t_exact(SA,t,p) + +% gsw_Helmholtz_energy_t_exact Helmholtz energy of seawater +%========================================================================== +% +% USAGE: +% Helmholtz_energy_t_exact = gsw_Helmholtz_energy_t_exact(SA,t,p) +% +% DESCRIPTION: +% Calculates the Helmholtz energy of seawater. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & t need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% +% OUTPUT: +% Helmholtz_energy_t_exact = Helmholtz energy [ J/kg ] +% +% AUTHOR: +% Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 2.13 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin==3) + error('gsw_Helmholtz_energy_t_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_Helmholtz_energy_t_exact: SA and t must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_Helmholtz_energy_t_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +db2Pa = 1e4; +n0 = 0; +n1 = 1; + +Helmholtz_energy_t_exact = gsw_gibbs(n0,n0,n0,SA,t,p) ... + - (db2Pa*p + 101325).*gsw_gibbs(n0,n0,n1,SA,t,p); + +if transposed + Helmholtz_energy_t_exact = Helmholtz_energy_t_exact.'; +end + +end \ No newline at end of file diff --git a/Toolbox/gsw_IPV_vs_fNsquared_ratio.m b/Toolbox/gsw_IPV_vs_fNsquared_ratio.m new file mode 100644 index 0000000..06bd224 --- /dev/null +++ b/Toolbox/gsw_IPV_vs_fNsquared_ratio.m @@ -0,0 +1,180 @@ +function [IPV_vs_fNsquared_ratio, p_mid] = gsw_IPV_vs_fNsquared_ratio(SA,CT,p,p_ref) + +% gsw_IPV_vs_fNsquared_ratio ratio of the vertical gradient of +% potential density (with reference pressure, p_ref), +% to the vertical gradient of locally-referenced +% potential density (48-term equation) +%========================================================================== +% +% USAGE: +% [IPV_vs_fNsquared_ratio, p_mid] = gsw_IPV_vs_fNsquared_ratio(SA,CT,p,p_ref) +% +% DESCRIPTION: +% Calculates the ratio of the vertical gradient of potential density to +% the vertical gradient of locally-referenced potential density. This +% ratio is also the ratio of the planetary Isopycnal Potential Vorticity +% (IPV) to f times N^2, hence the name for this variable, +% IPV_vs_fNsquared_ratio (see Eqn. (3.20.5) of IOC et al. (2010)). +% The reference sea pressure, p_ref, of the potential density surface must +% have a constant value. +% +% IPV_vs_fNsquared_ratio is evaluated at the mid pressure between the +% individual data points in the vertical. This function uses the +% computationally-efficient 48-term expression for density in terms of +% SA, CT and p (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% p_ref = reference sea pressure of the potential density surface +% ( i.e. absolute reference pressure - 10.1325 dbar ) [ dbar ] +% +% SA & CT need to have the same dimensions. +% p & p_ref may have dimensions 1x1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% IPV_vs_fNsquared_ratio +% = The ratio of the vertical gradient of potential density +% referenced to p_ref, to the vertical gradient of locally- +% referenced potential density. It is ouput on the same +% vertical (M-1)xN grid as p_mid. +% IPV_vs_fNsquared_ratio is dimensionless. [ unitless ] +% p_mid = mid pressure between the individual points of the p grid. +% That is, p_mid is on a (M-1)xN grid. [ dbar ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (23rd March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (3.20.5) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3 | nargin == 4) + error('gsw_IPV_vs_fNsquared_ratio: Requires three or four inputs') +end %if +if ~(nargout == 2) + error('gsw_IPV_vs_fNsquared_ratio: Requires two outputs') +end %if + +if nargin == 3 +% Assume reference pressure, p_ref, is 0 dbar. + p_ref = 0; +end %if + +if ~isscalar(unique(p_ref)) + error('gsw_IPV_vs_fNsquared_ratio: The reference pressures differ, they should be unique') +end + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_IPV_vs_fNsquared_ratio: SA and CT must have same dimensions') +end + +if (ms*ns == 1) + error('gsw_IPV_vs_fNsquared_ratio: There must be at least 2 values') +end + +if (mp == 1) & (np == 1) % p scalar - must be two bottles + error('gsw_IPV_vs_fNsquared_ratio: There must be at least 2 values') +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_IPV_vs_fNsquared_ratio: Inputs array dimensions arguments do not agree') +end %if + + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + [mp,np] = size(p); + transposed = 1; +else + transposed = 0; +end + +p_ref = unique(p_ref)*ones(mp-1,np); %resize the reference pressure + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +Ishallow = 1:(mp-1); +Ideep = 2:mp; +p_mid = (p(Ishallow,:) + p(Ideep,:))/2; +SA_mid = (SA(Ishallow,:) + SA(Ideep,:))/2; +CT_mid = (CT(Ishallow,:) + CT(Ideep,:))/2; + +dSA = SA(Ishallow,:) - SA(Ideep,:); +dCT = CT(Ishallow,:) - CT(Ideep,:); + +[dummy,alpha,beta] = gsw_rho_alpha_beta(SA_mid,CT_mid,p_mid); +[dummy,alpha_pref,beta_pref] = gsw_rho_alpha_beta(SA_mid,CT_mid,p_ref); + +%-------------------------------------------------------------------------- +% This function calculates IPV_vs_fNsquared_ratio using the computationally +% efficient 48-term expression for density in terms of SA, CT and p. If +% one wanted to compute this with the full TEOS-10 Gibbs function +% expression for density, the following lines of code will enable this. +% +% pt_mid = gsw_pt_from_CT(SA_mid,CT_mid); +% pr0 = zeros(size(SA_mid)); +% t_mid = gsw_pt_from_t(SA_mid,pt_mid,pr0,p_mid); +% beta = gsw_beta_const_CT_t_exact(SA_mid,t_mid,p_mid); +% alpha = gsw_alpha_wrt_CT_t_exact(SA_mid,t_mid,p_mid); +% beta_pref = gsw_beta_const_CT_t_exact(SA_mid,t_mid,p_ref); +% alpha_pref = gsw_alpha_wrt_CT_t_exact(SA_mid,t_mid,p_ref); +% +%-----------This is the end of the alternative code------------------------ + +numerator = dCT.*alpha_pref - dSA.*beta_pref; +denominator = dCT.*alpha - dSA.*beta; + +IPV_vs_fNsquared_ratio = nan(size(SA_mid)); +[I] = find(denominator ~= 0); +if ~isempty(I) + IPV_vs_fNsquared_ratio(I) = numerator(I)./denominator(I); +end + +if transposed + IPV_vs_fNsquared_ratio = IPV_vs_fNsquared_ratio.'; + p_mid = p_mid.'; +end + +end \ No newline at end of file diff --git a/Toolbox/gsw_IPV_vs_fNsquared_ratio_CT25.m b/Toolbox/gsw_IPV_vs_fNsquared_ratio_CT25.m deleted file mode 100644 index 4d131d5..0000000 --- a/Toolbox/gsw_IPV_vs_fNsquared_ratio_CT25.m +++ /dev/null @@ -1,187 +0,0 @@ -function [IPV_vs_fNsquared_ratio_CT25, p_mid, in_funnel] = gsw_IPV_vs_fNsquared_ratio_CT25(SA,CT,p,pr) - -% gsw_IPV_vs_fNsquared_ratio_CT25 ratio of the vertical gradient of -% potential density (with reference pressure, pr), -% to the vertical gradient of locally-referenced -% potential density (25-term equation) -%========================================================================== -% -% USAGE: -% [IPV_vs_fNsquared_ratio_CT25, p_mid, in_funnel] = gsw_IPV_vs_fNsquared_ratio_CT25(SA,CT,p,pr) -% -% DESCRIPTION: -% Calculates the ratio of the vertical gradient of potential density to -% the vertical gradient of locally-referenced potential density. This -% ratio is also the ratio of the planetary Isopycnal Potential Vorticity -% (IPV) to f times N^2, hence the name for this variable, -% IPV_vs_fNsquared_ratio_CT25 (see Eqn. (3.20.5) of IOC et al. (2010)). -% The reference sea pressure of the potential density surface must have a -% constant value. -% -% IPV_vs_fNsquared_ratio_CT25 is evaluated at the mid pressure between the -% individual data points in the vertical. This function uses the -% computationally-efficient 25-term expression for density in terms of -% SA, CT and p (McDougall et al., 2010). -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) -% pr = reference sea pressure of the potential density surface -% (ie. absolute reference pressure - 10.1325 dbar) [ dbar ] -% -% SA & CT need to have the same dimensions. -% p & pr may have dimensions 1x1 or 1xN or MxN, where SA & CT are MxN. -% -% OUTPUT: -% IPV_vs_fNsquared_ratio_CT25 -% = The ratio of the vertical gradient of -% potential density referenced to pr, to the -% vertical gradient of locally-referenced -% potential density. It is ouput on the same -% vertical (M-1)xN grid as p_mid. -% IPV_vs_fNsquared_ratio_CT25 is dimensionless -% [ unitless ] -% p_mid = mid pressure between the individual points of -% the p grid. That is, p_mid is on a (M-1)xN -% grid. p_mid has units of dbar. [ dbar ] -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). -% -% AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] -% -% VERSION NUMBER: 2.0 (23rd August, 2010) -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See Eqn. (3.20.5) of this TEOS-10 Manual. -% -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 3 | nargin == 4) - error('gsw_IPV_vs_fNsquared_ratio_CT25: Requires three or four inputs') -end %if -if ~(nargout == 2 | nargout == 3) - error('gsw_IPV_vs_fNsquared_ratio_CT25: Requires two or three outputs') -end %if - -if nargin == 3 -% Assume reference pressure, pr, is 0 dbar. - pr = 0; -end %if - -if ~isscalar(unique(pr)) - error('gsw_IPV_vs_fNsquared_ratio_CT25: The reference pressures differ, they should be unique') -end - -[ms,ns] = size(SA); -[mt,nt] = size(CT); -[mp,np] = size(p); - -if (mt ~= ms | nt ~= ns) - error('gsw_IPV_vs_fNsquared_ratio_CT25: SA and CT must have same dimensions') -end - -if (ms*ns == 1) - error('gsw_IPV_vs_fNsquared_ratio_CT25: There must be at least 2 values') -end - -if (mp == 1) & (np == 1) % p scalar - must be two bottles - error('gsw_IPV_vs_fNsquared_ratio_CT25: There must be at least 2 values') -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_IPV_vs_fNsquared_ratio_CT25: Inputs array dimensions arguments do not agree') -end %if - -pr = unique(pr).*size(SA); - -if ms == 1 - SA = SA'; - CT = CT'; - p = p'; - pr = pr'; - [mp,np] = size(p); - transposed = 1; -else - transposed = 0; -end - -pr = unique(pr)*ones(mp-1,np); %resize the reference pressure - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -Ishallow = 1:(mp-1); -Ideep = 2:mp; -p_mid = (p(Ishallow,:) + p(Ideep,:))/2; -SA_mid = (SA(Ishallow,:) + SA(Ideep,:))/2; -CT_mid = (CT(Ishallow,:) + CT(Ideep,:))/2; - -in_funnel = (gsw_infunnel(SA(Ishallow,:),CT(Ishallow,:),p(Ishallow,:)) .*... - gsw_infunnel(SA(Ideep,:),CT(Ishallow,:),p(Ishallow,:))); - -dSA = SA(Ishallow,:) - SA(Ideep,:); -dCT = CT(Ishallow,:) - CT(Ideep,:); - -[dummy,alpha,beta, dummy2] = gsw_rho_alpha_beta_CT25(SA_mid,CT_mid,p_mid); -[dummy,alpha_pr,beta_pr, dummy2] = gsw_rho_alpha_beta_CT25(SA_mid,CT_mid,pr); - -%-------------------------------------------------------------------------- -% This function calculates IPV_vs_fNsquared_ratio_CT25 using the -% computationally-efficient 25-term expression for density in terms of SA, -% CT and p. If one wanted to compute this with the full TEOS-10 Gibbs -% function expression for density, the following lines of code will enable -% this. -% -% pt_mid = gsw_pt_from_CT(SA_mid,CT_mid); -% pr0 = zeros(size(SA_mid)); -% t_mid = gsw_pt_from_t(SA_mid,pt_mid,pr0,p_mid); -% beta = gsw_beta_const_CT(SA_mid,t_mid,p_mid); -% alpha = gsw_alpha_wrt_CT(SA_mid,t_mid,p_mid); -% beta_pr = gsw_beta_const_CT(SA_mid,t_mid,pr); -% alpha_pr = gsw_alpha_wrt_CT(SA_mid,t_mid,pr); -% -%-----------This is the end of the alternative code------------------------ - -anum = dCT.*alpha_pr - dSA.*beta_pr; -adenom = dCT.*alpha - dSA.*beta; - -IPV_vs_fNsquared_ratio_CT25 = nan(size(SA_mid)); -[I] = find(adenom ~= 0); -if ~isempty(I) - IPV_vs_fNsquared_ratio_CT25(I) = anum(I)./adenom(I); -end - -if transposed - IPV_vs_fNsquared_ratio_CT25 = IPV_vs_fNsquared_ratio_CT25'; - p_mid = p_mid'; - in_funnel = in_funnel'; -end - -end \ No newline at end of file diff --git a/Toolbox/gsw_Nsquared_CT25.m b/Toolbox/gsw_Nsquared.m similarity index 59% rename from Toolbox/gsw_Nsquared_CT25.m rename to Toolbox/gsw_Nsquared.m index e504624..fb5c24e 100644 --- a/Toolbox/gsw_Nsquared_CT25.m +++ b/Toolbox/gsw_Nsquared.m @@ -1,11 +1,11 @@ -function [n2, p_mid, in_funnel] = gsw_Nsquared_CT25(SA,CT,p,lat) +function [N2, p_mid] = gsw_Nsquared(SA,CT,p,lat) -% gsw_Nsquared_CT25 buoyancy frequency squared (N^2) -% (25-term equation) +% gsw_Nsquared buoyancy (Brunt-Vaisala) frequency squared (N^2) +% (48-term equation) %========================================================================== % % USAGE: -% [N2, p_mid, in_funnel] = gsw_Nsquared_CT25(SA,CT,p,{lat}) +% [N2, p_mid] = gsw_Nsquared(SA,CT,p,{lat}) % % DESCRIPTION: % Calculates the buoyancy frequency squared (N^2)(i.e. the Brunt-Vaisala @@ -15,17 +15,22 @@ % N = g x -------------- % dP % -% Note. This routine uses rho from "gsw_rho_CT25", which is the -% computationally-efficient 25-term expression for density in terms of -% SA, CT and p. +% Note. This routine uses rho from "gsw_rho", which is the computationally +% efficient 48-term expression for density in terms of SA, CT and p. % Note also that the pressure increment, dP, in the above formula is in -% Pa, so that it is 10^4 times the pressure incerment dp in dbar. +% Pa, so that it is 10^4 times the pressure increment dp in dbar. +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: % SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% ( i.e. absolute pressure - 10.1325 dbar ) % % OPTIONAL: % lat = latitude in decimal degrees north [ -90 ... +90 ] @@ -37,34 +42,28 @@ % where SA & CT are MxN. % % OUTPUT: -% n2 = Brunt-Vaisala Frequency squared (M-1xN) [ s^-2 ] -% p_mid = Mid pressure between p grid (M-1xN) [ dbar ] -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). +% N2 = Brunt-Vaisala Frequency squared (M-1xN) [ 1/s^2 ] +% p_mid = Mid pressure between p grid (M-1xN) [ dbar ] % % AUTHOR: -% Trevor McDougall and Paul Barker. [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (22nd July, 2010) +% VERSION NUMBER: 3.0 (22nd March, 2011) % % REFERENCES: -% Griffies, S. M., 2004: Fundamentals of Ocean Climate Models. Princeton, +% Griffies, S. M., 2004: Fundamentals of Ocean Climate Models. Princeton, % NJ: Princeton University Press, 518 pp + xxxiv. % -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of % seawater - 2010: Calculation and use of thermodynamic properties. % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See section 3.10 and Eqn. (3.10.2) of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -75,10 +74,10 @@ %-------------------------------------------------------------------------- if ~(nargin == 3 | nargin == 4) - error('gsw_Nsquared_CT25: Requires three or four inputs') + error('gsw_Nsquared: Requires three or four inputs') end %if -if ~(nargout == 2 | nargout == 3) - error('gsw_Nsquared_CT25: Requires two or three outputs') +if ~(nargout == 2) + error('gsw_Nsquared: Requires two outputs') end %if [ms,ns] = size(SA); @@ -86,29 +85,32 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_Nsquared_CT25: SA and CT must have same dimensions') + error('gsw_Nsquared: SA and CT must have same dimensions') end if (ms*ns == 1) - error('gsw_Nsquared_CT25: There must be at least 2 bottles') + error('gsw_Nsquared: There must be at least 2 bottles') end if (mp == 1) & (np == 1) % p is a scalar - must be two bottles - error('gsw_Nsquared_CT25: There must be at least 2 bottles') + error('gsw_Nsquared: There must be at least 2 bottles') elseif (ns == np) & (mp == 1) % p is row vector, p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_Nsquared_CT25: Inputs array dimensions arguments do not agree') + error('gsw_Nsquared: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - CT = CT'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -118,7 +120,7 @@ if exist('lat','var') if transposed - lat = lat'; + lat = lat.'; end [mL,nL] = size(lat); [ms,ns] = size(SA); @@ -131,7 +133,7 @@ elseif (ms == mL) & (ns == nL) % ok else - error('gsw_bfrq_CT25.m: Inputs array dimensions arguments do not agree') + error('gsw_Nsquared: Inputs array dimensions arguments do not agree') end %if grav = gsw_grav(lat,p); else @@ -142,28 +144,26 @@ % Start of the calculation %-------------------------------------------------------------------------- -in_funnel = gsw_infunnel(SA,CT,p); - db2Pa = 1e4; Ishallow = 1:(mp-1); Ideep = 2:mp; p_mid = (p(Ishallow,:) + p(Ideep,:))/2; -[d_rho_local_deep, dummy] = gsw_rho_CT25(SA(Ideep,:),CT(Ideep,:),p_mid); -[d_rho_local_shallow, dummy] = gsw_rho_CT25(SA(Ishallow,:),CT(Ishallow,:),p_mid); +d_rho_local_deep = gsw_rho(SA(Ideep,:),CT(Ideep,:),p_mid); +d_rho_local_shallow = gsw_rho(SA(Ishallow,:),CT(Ishallow,:),p_mid); d_rho_local = d_rho_local_deep - d_rho_local_shallow; %-------------------------------------------------------------------------- % This function calculates d_rho_local using the computationally-efficient -% 25-term expression for density in terms of SA, CT and p. If one wanted to +% 48-term expression for density in terms of SA, CT and p. If one wanted to % compute d_rho_local with the full TEOS-10 Gibbs function expression for % density, the following lines of code will enable this. % % pt = gsw_pt_from_CT(SA,CT); % pr0 = zeros(size(SA)); % t = gsw_pt_from_t(SA,pt,pr0,p); -% d_rho_local = gsw_rho(SA(Ideep,:),t(Ideep,:),p_mid) - ... -% gsw_rho(SA(Ishallow,:),t(Ishallow,:),p_mid); +% d_rho_local = gsw_rho_t_exact(SA(Ideep,:),t(Ideep,:),p_mid) - ... +% gsw_rho_t_exact(SA(Ishallow,:),t(Ishallow,:),p_mid); % %----This is the end of the alternative code to evaluate d_rho_local------- @@ -171,12 +171,11 @@ d_p = (p(Ideep,:) - p(Ishallow,:) ); % the pressure difference is converted from dbar to Pa -n2 = (grav_local.*grav_local).*(d_rho_local)./(db2Pa.*d_p); +N2 = (grav_local.*grav_local).*(d_rho_local)./(db2Pa.*d_p); if transposed - n2 = n2'; - p_mid = p_mid'; - in_funnel = in_funnel'; + N2 = N2.'; + p_mid = p_mid.'; end end \ No newline at end of file diff --git a/Toolbox/gsw_P0.m b/Toolbox/gsw_P0.m new file mode 100644 index 0000000..7149e59 --- /dev/null +++ b/Toolbox/gsw_P0.m @@ -0,0 +1,33 @@ +function P0 = gsw_P0 + +% gsw_P0 Absolute Pressure of one standard atmosphere +%========================================================================== +% +% USAGE: +% P0 = gsw_P0 +% +% DESCRIPTION: +% Absolute Pressure of one standard atmosphere in Pa, 101325 Pa. +% +% OUTPUT: +% P0 = Absolute Pressure of one standard atmosphere. [ Pa ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. +% See section 2.2, appendix A.2 and Table D.1 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +P0 = 101325; + +end diff --git a/Toolbox/gsw_R_from_SP.m b/Toolbox/gsw_R_from_SP.m new file mode 100644 index 0000000..665e12a --- /dev/null +++ b/Toolbox/gsw_R_from_SP.m @@ -0,0 +1,412 @@ +function R = gsw_R_from_SP(SP,t,p) + +% gsw_R_from_SP conductivity ratio from SP +%========================================================================== +% +% USAGE: +% R = gsw_R_from_SP(SP,t,p) +% +% DESCRIPTION: +% Calculates conductivity ratio from (SP,t,p) using PSS-78 in the range +% 2 < SP < 42. If the input Practical Salinity is less than 2 then a +% modified form of the Hill et al. (1986) fomula is used for Practical +% Salinity. The modification of the Hill et al. (1986) expression is to +% ensure that it is exactly consistent with PSS-78 at SP = 2. +% +% The conductivity ratio returned by this function is consistent with the +% input value of Practical Salinity, SP, to 2x10^-14 psu over the full +% range of input parameters (from pure fresh water up to SP = 42 psu). +% This error of 2x10^-14 psu is machine precision at typical seawater +% salinities. This accuracy is achieved by having four different +% polynomials for the starting value of Rtx (the square root of Rt) in +% four different ranges of SP, and by using one and a half iterations of +% a computationally efficient modified Newton-Raphson technique to find +% the root of the equation. +% +% Note that strictly speaking PSS-78 (Unesco, 1983) defines Practical +% Salinity in terms of the conductivity ratio, R, without actually +% specifying the value of C(35,15,0) (which we currently take to be +% 42.9140 mS cm^-1 (Culkin and Smith, 1980)). +% +% INPUT: +% SP = Practical Salinity (PSS-78) [ unitless ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SP & t need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SP & t are MxN. +% +% OUTPUT: +% R = conductivity ratio [ unitless ] +% +% AUTHOR: +% Trevor McDougall, Paul Barker and Rich Pawlowicz [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (6th April, 2011) +% +% REFERENCES: +% Culkin and Smith, 1980: Determination of the Concentration of Potassium +% Chloride Solution Having the Same Electrical Conductivity, at 15C and +% Infinite Frequency, as Standard Seawater of Salinity 35.0000 +% (Chlorinity 19.37394), IEEE J. Oceanic Eng, 5, 22-23. +% +% Hill, K.D., T.M. Dauphinee & D.J. Woods, 1986: The extension of the +% Practical Salinity Scale 1978 to low salinities. IEEE J. Oceanic Eng., +% 11, 109 - 112. +% +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See appendix E of this TEOS-10 Manual. +% +% Unesco, 1983: Algorithms for computation of fundamental properties of +% seawater. Unesco Technical Papers in Marine Science, 44, 53 pp. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_R_from_SP: Must have 3 input arguments') +end %if + +% These few lines ensure that SP is non-negative. +[I_neg_SP] = find(SP < 0); +if ~isempty(I_neg_SP) + error('gsw_R_from_SP: SP must be non-negative!') +end + +[ms,ns] = size(SP); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_R_from_SP: SP and t must have same dimensions') +end + +if mp==1 & np==1 % p is a scalar. Fill to size of SP + p = p(1)*ones(ms,ns); +elseif np==ns & mp==1 % p is row vector, + p = p(ones(1,ms),:); % copy down each column. +elseif mp==ms & np==1 % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (np == ms) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif mp==ms & np==ns + % ok +else + error('gsw_R_from_SP: p has wrong dimensions') +end %if + +if ms == 1 + SP = SP.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Setting up the constants +%-------------------------------------------------------------------------- + +a0 = 0.0080; +a1 = -0.1692; +a2 = 25.3851; +a3 = 14.0941; +a4 = -7.0261; +a5 = 2.7081; + +b0 = 0.0005; +b1 = -0.0056; +b2 = -0.0066; +b3 = -0.0375; +b4 = 0.0636; +b5 = -0.0144; + +c0 = 0.6766097; +c1 = 2.00564e-2; +c2 = 1.104259e-4; +c3 = -6.9698e-7; +c4 = 1.0031e-9; + +d1 = 3.426e-2; +d2 = 4.464e-4; +d3 = 4.215e-1; +d4 = -3.107e-3; + +e1 = 2.070e-5; +e2 = -6.370e-10; +e3 = 3.989e-15; + +p0 = 4.577801212923119e-3; +p1 = 1.924049429136640e-1; +p2 = 2.183871685127932e-5; +p3 = -7.292156330457999e-3; +p4 = 1.568129536470258e-4; +p5 = -1.478995271680869e-6; +p6 = 9.086442524716395e-4; +p7 = -1.949560839540487e-5; +p8 = -3.223058111118377e-6; +p9 = 1.175871639741131e-7; +p10 = -7.522895856600089e-5; +p11 = -2.254458513439107e-6; +p12 = 6.179992190192848e-7; +p13 = 1.005054226996868e-8; +p14 = -1.923745566122602e-9; +p15 = 2.259550611212616e-6; +p16 = 1.631749165091437e-7; +p17 = -5.931857989915256e-9; +p18 = -4.693392029005252e-9; +p19 = 2.571854839274148e-10; +p20 = 4.198786822861038e-12; + +q0 = 5.540896868127855e-5; +q1 = 2.015419291097848e-1; +q2 = -1.445310045430192e-5; +q3 = -1.567047628411722e-2; +q4 = 2.464756294660119e-4; +q5 = -2.575458304732166e-7; +q6 = 5.071449842454419e-3; +q7 = -9.081985795339206e-5; +q8 = -3.635420818812898e-6; +q9 = 2.249490528450555e-8; +q10 = -1.143810377431888e-3; +q11 = 2.066112484281530e-5; +q12 = 7.482907137737503e-7; +q13 = 4.019321577844724e-8; +q14 = -5.755568141370501e-10; +q15 = 1.120748754429459e-4; +q16 = -2.420274029674485e-6; +q17 = -4.774829347564670e-8; +q18 = -4.279037686797859e-9; +q19 = -2.045829202713288e-10; +q20 = 5.025109163112005e-12; + +r0 = 3.432285006604888e-3; +r1 = 1.672940491817403e-1; +r2 = 2.640304401023995e-5; +r3 = 1.082267090441036e-1; +r4 = -6.296778883666940e-5; +r5 = -4.542775152303671e-7; +r6 = -1.859711038699727e-1; +r7 = 7.659006320303959e-4; +r8 = -4.794661268817618e-7; +r9 = 8.093368602891911e-9; +r10 = 1.001140606840692e-1; +r11 = -1.038712945546608e-3; +r12 = -6.227915160991074e-6; +r13 = 2.798564479737090e-8; +r14 = -1.343623657549961e-10; +r15 = 1.024345179842964e-2; +r16 = 4.981135430579384e-4; +r17 = 4.466087528793912e-6; +r18 = 1.960872795577774e-8; +r19 = -2.723159418888634e-10; +r20 = 1.122200786423241e-12; + +u0 = 5.180529787390576e-3; +u1 = 1.052097167201052e-3; +u2 = 3.666193708310848e-5; +u3 = 7.112223828976632; +u4 = -3.631366777096209e-4; +u5 = -7.336295318742821e-7; +u6 = -1.576886793288888e+2; +u7 = -1.840239113483083e-3; +u8 = 8.624279120240952e-6; +u9 = 1.233529799729501e-8; +u10 = 1.826482800939545e+3; +u11 = 1.633903983457674e-1; +u12 = -9.201096427222349e-5; +u13 = -9.187900959754842e-8; +u14 = -1.442010369809705e-10; +u15 = -8.542357182595853e+3; +u16 = -1.408635241899082; +u17 = 1.660164829963661e-4; +u18 = 6.797409608973845e-7; +u19 = 3.345074990451475e-10; +u20 = 8.285687652694768e-13; + +k = 0.0162; + +t68 = t.*1.00024; +ft68 = (t68 - 15)./(1 + k.*(t68 - 15)); + +x = sqrt(SP); +Rtx = nan(size(SP)); + +%-------------------------------------------------------------------------- +% Finding the starting value of Rtx, the square root of Rt, using four +% different polynomials of SP and t68. +%-------------------------------------------------------------------------- +[I] = find( SP >= 9); +if ~isempty(I) + Rtx(I) = p0 + x(I).*(p1 + p4*t68(I) + x(I).*(p3 + p7*t68(I) + x(I).*(p6 ... + + p11*t68(I) + x(I).*(p10 + p16*t68(I)+ x(I).*p15))))... + + t68(I).*(p2+ t68(I).*(p5 + x(I).*x(I).*(p12 + x(I).*p17) + p8*x(I) ... + + t68(I).*(p9 + x(I).*(p13 + x(I).*p18)+ t68(I).*(p14 + p19*x(I) + p20*t68(I))))); +end + +[I] = find( SP >= 0.25 & SP < 9); +if ~isempty(I) + Rtx(I) = q0 + x(I).*(q1 + q4*t68(I) + x(I).*(q3 + q7*t68(I) + x(I).*(q6 ... + + q11*t68(I) + x(I).*(q10 + q16*t68(I)+ x(I).*q15))))... + + t68(I).*(q2+ t68(I).*(q5 + x(I).*x(I).*(q12 + x(I).*q17) + q8*x(I) ... + + t68(I).*(q9 + x(I).*(q13 + x(I).*q18)+ t68(I).*(q14 + q19*x(I) + q20*t68(I))))); +end + +[I] = find( SP >= 0.003 & SP < 0.25); +if ~isempty(I) + Rtx(I) = r0 + x(I).*(r1 + r4*t68(I) + x(I).*(r3 + r7*t68(I) + x(I).*(r6 ... + + r11*t68(I) + x(I).*(r10 + r16*t68(I)+ x(I).*r15))))... + + t68(I).*(r2+ t68(I).*(r5 + x(I).*x(I).*(r12 + x(I).*r17) + r8*x(I) ... + + t68(I).*(r9 + x(I).*(r13 + x(I).*r18)+ t68(I).*(r14 + r19*x(I) + r20*t68(I))))); +end + +[I] = find( SP < 0.003); +if ~isempty(I) + Rtx(I) = u0 + x(I).*(u1 + u4*t68(I) + x(I).*(u3 + u7*t68(I) + x(I).*(u6 ... + + u11*t68(I) + x(I).*(u10 + u16*t68(I)+ x(I).*u15))))... + + t68(I).*(u2+ t68(I).*(u5 + x(I).*x(I).*(u12 + x(I).*u17) + u8*x(I) ... + + t68(I).*(u9 + x(I).*(u13 + x(I).*u18)+ t68(I).*(u14 + u19*x(I) + u20*t68(I))))); +end + +%-------------------------------------------------------------------------- +% Finding the starting value of dSP_dRtx, the derivative of SP with respect +% to Rtx. +%-------------------------------------------------------------------------- +dSP_dRtx = a1 + (2*a2 + (3*a3 + (4*a4 + 5*a5.*Rtx).*Rtx).*Rtx).*Rtx ... + + ft68.*(b1 + (2*b2 + (3*b3 + (4*b4 + 5*b5.*Rtx).*Rtx).*Rtx).*Rtx); +[I2] = find(SP < 2); +if ~isempty(I2) + x = 400.*(Rtx(I2).*Rtx(I2)); + sqrty = 10.*Rtx(I2); + part1 = 1 + x.*(1.5 + x) ; + part2 = 1 + sqrty.*(1 + sqrty.*(1 + sqrty)); + Hill_ratio = gsw_Hill_ratio_at_SP2(t(I2)); + dSP_dRtx(I2) = dSP_dRtx(I2)... + + a0.*800.*Rtx(I2).*(1.5 + 2*x)./(part1.*part1)... + + b0.*ft68(I2).*(10 + sqrty.*(20 + 30.*sqrty))./(part2.*part2); + dSP_dRtx(I2) = Hill_ratio.*dSP_dRtx(I2); +end + +%-------------------------------------------------------------------------- +% One iteration through the modified Newton-Raphson method achieves an +% error in Practical Salinity of about 10^-12 for all combinations of the +% inputs. One and a half iterations of the modified Newton-Raphson method +% achevies a maximum error in terms of Practical Salinity of better than +% 2x10^-14 everywhere. +% +% We recommend one and a half iterations of the modified Newton-Raphson +% method. +% +% Begin the modified Newton-Raphson method. +%-------------------------------------------------------------------------- + + SP_est = a0 + (a1 + (a2 + (a3 + (a4 + a5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx ... + + ft68.*(b0 + (b1 + (b2+ (b3 + (b4 + b5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx); + [I2] = find(SP_est < 2); + if ~isempty(I2) + x = 400.*(Rtx(I2).*Rtx(I2)); + sqrty = 10.*Rtx(I2); + part1 = 1 + x.*(1.5 + x) ; + part2 = 1 + sqrty.*(1 + sqrty.*(1 + sqrty)); + SP_Hill_raw = SP_est(I2) - a0./part1 - b0.*ft68(I2)./part2; + Hill_ratio = gsw_Hill_ratio_at_SP2(t(I2)); + SP_est(I2) = Hill_ratio.*SP_Hill_raw; + end + + Rtx_old = Rtx; + Rtx = Rtx_old - (SP_est - SP)./dSP_dRtx; + Rtxm = 0.5*(Rtx + Rtx_old); % This mean value of Rtx, Rtxm, is the +% value of Rtx at which the derivative dSP_dRtx is evaluated. + + dSP_dRtx = a1 + (2*a2 + (3*a3 + (4*a4 + 5*a5.*Rtxm).*Rtxm).*Rtxm).*Rtxm ... + + ft68.*(b1 + (2*b2 + (3*b3 + (4*b4 + 5*b5.*Rtxm).*Rtxm).*Rtxm).*Rtxm); + + [I2] = find(SP_est < 2); + if ~isempty(I2) + x = 400.*(Rtxm(I2).*Rtxm(I2)); + sqrty = 10.*Rtxm(I2); + part1 = 1 + x.*(1.5 + x) ; + part2 = 1 + sqrty.*(1 + sqrty.*(1 + sqrty)); + dSP_dRtx(I2) = dSP_dRtx(I2)... + + a0.*800.*Rtxm(I2).*(1.5 + 2*x)./(part1.*part1)... + + b0.*ft68(I2).*(10 + sqrty.*(20 + 30.*sqrty))./(part2.*part2); + Hill_ratio = gsw_Hill_ratio_at_SP2(t(I2)); + dSP_dRtx(I2) = Hill_ratio.*dSP_dRtx(I2); + end + +%-------------------------------------------------------------------------- +% The line below is where Rtx is updated at the end of the one full +% iteration of the modified Newton-Raphson technique. +%-------------------------------------------------------------------------- + Rtx = Rtx_old - (SP_est - SP)./dSP_dRtx; +%-------------------------------------------------------------------------- +% Now we do another half iteration of the modified Newton-Raphson +% technique, making a total of one and a half modified N-R iterations. +%-------------------------------------------------------------------------- +SP_est = a0 + (a1 + (a2 + (a3 + (a4 + a5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx ... + + ft68.*(b0 + (b1 + (b2+ (b3 + (b4 + b5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx); + [I2] = find(SP_est < 2); + if ~isempty(I2) + x = 400.*(Rtx(I2).*Rtx(I2)); + sqrty = 10.*Rtx(I2); + part1 = 1 + x.*(1.5 + x) ; + part2 = 1 + sqrty.*(1 + sqrty.*(1 + sqrty)); + SP_Hill_raw = SP_est(I2) - a0./part1 - b0.*ft68(I2)./part2; + Hill_ratio = gsw_Hill_ratio_at_SP2(t(I2)); + SP_est(I2) = Hill_ratio.*SP_Hill_raw; + end + Rtx = Rtx - (SP_est - SP)./dSP_dRtx; + +%-------------------------------------------------------------------------- +% The following lines of code are commented out, but when activated, return +% the error, SP_error, in Rtx (in terms of psu). +% SP_est = a0 + (a1 + (a2 + (a3 + (a4 + a5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx ... +% + ft68.*(b0 + (b1 + (b2+ (b3 + (b4 + b5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx); +% [I2] = find(SP_est < 2); +% if ~isempty(I2) +% x = 400.*(Rtx(I2).*Rtx(I2)); +% sqrty = 10.*Rtx(I2); +% part1 = 1 + x.*(1.5 + x) ; +% part2 = 1 + sqrty.*(1 + sqrty.*(1 + sqrty)); +% SP_Hill_raw = SP_est(I2) - a0./part1 - b0.*ft68(I2)./part2; +% Hill_ratio = gsw_Hill_ratio_at_SP2(t(I2)); +% SP_est(I2) = Hill_ratio.*SP_Hill_raw; +% end +% +% SP_error = abs(SP - SP_est); +% +%--------------This is the end of the error testing------------------------ + + +%-------------------------------------------------------------------------- +% Now go from Rtx to Rt and then to the conductivity ratio R at pressure p. +%-------------------------------------------------------------------------- +Rt = Rtx.*Rtx; +A = d3 + d4.*t68; +B = 1 + d1.*t68 + d2.*t68.^2; +C = p.*(e1 + e2.*p + e3.*p.^2); +% rt_lc (i.e. rt_lower_case) corresponds to rt as defined in +% the UNESCO 44 (1983) routines. +rt_lc = c0 + (c1 + (c2 + (c3 + c4.*t68).*t68).*t68).*t68; + +D = B - A.*rt_lc.*Rt; +E = rt_lc.*Rt.*A.*(B + C); +Ra = sqrt(D.^2 + 4*E) - D; +R = 0.5*Ra./A; + +if transposed + R = R'; +end + +end diff --git a/Toolbox/gsw_SA_CT_plot.m b/Toolbox/gsw_SA_CT_plot.m new file mode 100644 index 0000000..853e61d --- /dev/null +++ b/Toolbox/gsw_SA_CT_plot.m @@ -0,0 +1,128 @@ +function gsw_SA_CT_plot(SA,CT,p_ref,isopycs,title_string) + +% gsw_SA_CT_plot plots Absolute Salinity - Conservative Temperature +% profiles on a SA-CT diagram including freezing line and +% selected potential density contours.(48-term equation) +%========================================================================== +% +% USAGE: +% gsw_SA_CT_plot(SA,CT,p_ref,isopycs,title_string) +% +% DESCRIPTION: +% Produces a plot of Absolute Salinity - Conservative Temperature +% profiles. The diagram also plots the Conservative Temperature freezing +% point for p = 0 dbar assuming the seawater is completely saturated with +% dissolved air and user defined potential density contours. This +% function uses the computationally efficient 48-term expression for +% density in terms of SA, CT and p (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% +% Optional: +% p_ref = reference sea pressure for the isopycnals [ dbar ] +% (i.e. absolute reference pressure - 10.1325 dbar) +% If it is not suppled a default of 0 dbar is used. +% isopycs = isopycnals, can be either an array of isopynals or the +% number of isopynals to appear on the plot. If it is not +% supplied the programme defaults to 5 isopynals. +% title_string = title text to appear at the top of the plot. +% +% SA & CT need to have the same dimensions. +% p_ref should be a scalar, (i.e. have dimensions 1x1). +% isopycs can be either 1x1 or 1xN or Mx1 +% +% AUTHOR: +% Rich Pawlowicz [ help_gsw@csiro.au ] +% Note. This function was extracted and adapted from Rich Pawlowicz's +% ocean toolbox. +% +% MODIFIED: +% Paul Barker & Trevor McDougall +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +if (nargin < 2), + error('gsw_SA_CT_plot: You need to supply both Absolute Salinity and Conservative Temperature'); +end + +if ~exist('p_ref','var'), + p_ref = 0; + isopycs = 5; +end + +if ~isscalar(unique(p_ref)) + error('gsw_SA_CT_plot: Multiple reference pressures'); +else + p_ref = unique(p_ref); +end + +isopycs = isopycs(:); +min_SA_data = min(min(SA(:))); +max_SA_data = max(max(SA(:))); +min_CT_data = min(min(CT(:))); +max_CT_data = max(max(CT(:))); + +SA_min = min_SA_data - 0.1*(max_SA_data - min_SA_data); +SA_max = max_SA_data + 0.1*(max_SA_data - min_SA_data); +SA_axis = [SA_min:(SA_max-SA_min)/200:SA_max]; + +CT_freezing = gsw_CT_freezing(SA_axis,0); +CT_min = min_CT_data - 0.1*(max_CT_data - min_CT_data); +CT_max = max_CT_data + 0.1*(max_CT_data - min_CT_data); +if CT_min > (min(CT_freezing) - 0.5) + CT_min = min(CT_freezing)- 0.5; +end +CT_axis = [CT_min:(CT_max-CT_min)/200:CT_max]; + +clear min_SA_data max_SA_data min_CT_data max_CT_data + +SA_gridded = meshgrid(SA_axis,1:length(CT_axis)); +CT_gridded = meshgrid(CT_axis,1:length(SA_axis))'; + +isopycs_gridded = gsw_rho_CT(SA_gridded,CT_gridded,p_ref)-1000; +% figure +if ~isempty(isopycs) + [c1,h] = contour(SA_gridded,CT_gridded,isopycs_gridded,isopycs,':','Color',[.5 .5 .5]); +end +hold on; +[c2] = plot(SA(:,1),CT(:,1),'k.','linewidth',2); + +if exist('c1','var') + clabel(c1,h,'labelspacing',360,'fontsize',8,'color',[.5 .5 .5]); +end + +axis('square'); +axis([SA_min SA_max CT_min CT_max]); +xlabel('Absolute Salinity, \it{S}\rm_A (g kg^-^1) ','fontsize',13); +ylabel('Conservative Temperature, {\Theta} ({\circ}C)','fontsize',13); +if exist('title_string','var') + title([title_string]) +else + title('\it{S}\rm_A - {\Theta} diagram','fontsize',14) +end +set(gca,'tickdir','out') + +line(SA_axis,CT_freezing,'LineStyle','--'); + +text(0.01,0.99,[' p_r_e_f = ' int2str(p_ref) ' dbar'],... + 'horiz','left','Vert','top','units','normalized','color',[.3 .3 .3]); + +end diff --git a/Toolbox/gsw_SA_Sstar_from_SP.m b/Toolbox/gsw_SA_Sstar_from_SP.m index 90ae246..7fdabda 100644 --- a/Toolbox/gsw_SA_Sstar_from_SP.m +++ b/Toolbox/gsw_SA_Sstar_from_SP.m @@ -16,8 +16,8 @@ % INPUT: % SP = Practical Salinity (PSS-78) [ unitless ] % p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) -% long = longitude in decimal degrees [ 0 ... +360 ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% long = longitude in decimal degrees [ 0 ... +360 ] % or [ -180 ... +180 ] % lat = latitude in decimal degrees north [ -90 ... +90 ] % @@ -34,9 +34,9 @@ % hundred kilometres inland from the coast. % % AUTHOR: -% David Jackett, Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help@teos-10.org ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (11th November, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -59,10 +59,11 @@ % Check variables and resize if necessary %-------------------------------------------------------------------------- -if ~(nargin==4) +if ~(nargin == 4) error('gsw_SA_Sstar_from_SP: Requires four inputs') end %if -if ~(nargout==2 | nargout==3) + +if ~(nargout == 2 | nargout == 3) error('gsw_SA_Sstar_from_SP: Requires two or three outputs') end %if @@ -72,12 +73,12 @@ if (mp == 1) & (np == 1) % p is a scalar - fill to size of SP p = p*ones(size(SP)); elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. + p = p(ones(1,ms),:); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then - p = p(ones(1,ms), :); % copy down each column. + p = p.'; % transposed then + p = p(ones(1,ms),:); % copy down each column. elseif (ms == mp) & (ns == np) % ok else @@ -93,7 +94,7 @@ elseif (ms == mla) & (nla == 1) % lat is a column vector, lat = lat(:,ones(1,ns)); % copy across each row. elseif (ns == mla) & (nla == 1) % lat is a transposed row vector, - lat = lat'; % transposed then + lat = lat.'; % transposed then lat = lat(ones(1,ms), :); % copy down each column. elseif (ms == mla) & (ns == nla) % ok @@ -106,6 +107,7 @@ if ~isempty(Iwest) long(Iwest) = long(Iwest) + 360; end + if (mlo == 1) & (nlo == 1) % long is a scalar - fill to size of SP long = long*ones(size(SP)); elseif (ns == nlo) & (mlo == 1) % long is a row vector, @@ -113,7 +115,7 @@ elseif (ms == mlo) & (nlo == 1) % long is a column vector, long = long(:,ones(1,ns)); % copy across each row. elseif (ns == mlo) & (nlo == 1) % long is a transposed row vector, - long = long'; % transposed then + long = long.'; % transposed then long = long(ones(1,ms), :); % copy down each column. elseif (ms == mlo) & (ns == nlo) % ok @@ -122,53 +124,78 @@ end %if if ms == 1 - SP = SP'; - p = p'; - lat = lat'; - long = long'; + SP = SP.'; + p = p.'; + lat = lat.'; + long = long.'; transposed = 1; else transposed = 0; end +[Iout_of_range] = find(p < 100 & SP > 120); +SP(Iout_of_range) = NaN; +[Iout_of_range] = find(p >= 100 & SP > 42); +SP(Iout_of_range) = NaN; + +[Inan] = find(abs(SP) == 99999 | abs(SP) == 999999); +SP(Inan) = NaN; +[Inan] = find(abs(p) == 99999 | abs(p) == 999999); +p(Inan) = NaN; +[Inan] = find(abs(long) == 9999 | abs(long) == 99999); +long(Inan) = NaN; +[Inan] = find(abs(lat) == 9999 | abs(lat) == 99999); +lat(Inan) = NaN; + +if ~isempty(find(p < -1.5 | p > 12000)) + error('gsw_SA_Sstar_from_SP: pressure is out of range') +end +if ~isempty(find(long < 0 | long > 360)) + error('gsw_SA_Sstar_from_SP: longitude is out of range') +end +if ~isempty(find(abs(lat) > 90)) + error('gsw_SA_Sstar_from_SP: latitude is out of range') +end + %-------------------------------------------------------------------------- % Start of the calculation %-------------------------------------------------------------------------- -% + % These few lines ensure that SP is non-negative. [I_neg_SP] = find(SP < 0); if ~isempty(I_neg_SP) SP(I_neg_SP) = 0; end -r1 = 0.35; +uPS = 1.004715428571429; % uPS = 35.16504/35; +r_1 = 0.35; -inds = find(isfinite(SP)); +[Iocean] = find(~isnan(SP.*p.*lat.*long)); SA = nan(size(SP)); Sstar = nan(size(SP)); -dSA = nan(size(SP)); +SAAR = nan(size(SP)); in_ocean = nan(size(SP)); -[dSA(inds), in_ocean(inds)] = gsw_delta_SA(p(inds),long(inds),lat(inds)); +[SAAR(Iocean), in_ocean(Iocean)] = gsw_SAAR(p(Iocean),long(Iocean),lat(Iocean)); -SA(inds) = (35.16504/35)*SP(inds) + dSA(inds); +SA(Iocean) = uPS*SP(Iocean).*(1 + SAAR(Iocean)); -Sstar(inds) = (35.16504/35)*SP(inds) - r1* dSA(inds); +Sstar(Iocean) = uPS*SP(Iocean).*(1 - r_1.*SAAR(Iocean)); -SA_baltic(inds) = gsw_SA_from_SP_Baltic(SP(inds),long(inds),lat(inds)); +SA_baltic(Iocean) = gsw_SA_from_SP_Baltic(SP(Iocean),long(Iocean),lat(Iocean)); -indsbaltic = find(~isnan(SA_baltic(inds))); +[Ibaltic] = find(~isnan(SA_baltic(Iocean))); -SA(inds(indsbaltic)) = SA_baltic(inds(indsbaltic)); +SA(Iocean(Ibaltic)) = SA_baltic(Iocean(Ibaltic)); %In the Baltic Sea, Sstar = SA. -Sstar(inds(indsbaltic)) = SA_baltic(inds(indsbaltic)); +Sstar(Iocean(Ibaltic)) = SA_baltic(Iocean(Ibaltic)); if transposed - SA = SA'; - Sstar = Sstar'; - in_ocean = in_ocean'; + SA = SA.'; + Sstar = Sstar.'; + in_ocean = in_ocean.'; end end diff --git a/Toolbox/gsw_SA_from_SP.m b/Toolbox/gsw_SA_from_SP.m index 3a7a15a..a8aee59 100644 --- a/Toolbox/gsw_SA_from_SP.m +++ b/Toolbox/gsw_SA_from_SP.m @@ -7,15 +7,15 @@ % [SA, in_ocean] = gsw_SA_from_SP(SP,p,long,lat) % % DESCRIPTION: -% Calculates Absolute Salinity from Practical Salinity. -% Since SP is non-negative by definition, this function changes any -% negative input values of SP to be zero. +% Calculates Absolute Salinity from Practical Salinity. Since SP is +% non-negative by definition, this function changes any negative input +% values of SP to be zero. % % INPUT: % SP = Practical Salinity (PSS-78) [ unitless ] % p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) -% long = longitude in decimal degrees [ 0 ... +360 ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% long = longitude in decimal degrees [ 0 ... +360 ] % or [ -180 ... +180 ] % lat = latitude in decimal degrees north [ -90 ... +90 ] % @@ -23,7 +23,7 @@ % where SP is MxN. % % OUTPUT: -% SA = Absolute Salinity [ g/kg ] +% SA = Absolute Salinity [ g/kg ] % in_ocean = 0, if long and lat are a long way from the ocean % = 1, if long and lat are in the ocean % Note. This flag is only set when the observation is well and truly on @@ -31,9 +31,9 @@ % hundred kilometres inland from the coast. % % AUTHOR: -% David Jackett, Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall & Paul Barker [ help@teos-10.org ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (31st May, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -70,7 +70,7 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok @@ -87,7 +87,7 @@ elseif (ms == mla) & (nla == 1) % lat is a column vector, lat = lat(:,ones(1,ns)); % copy across each row. elseif (ns == mla) & (nla == 1) % lat is a transposed row vector, - lat = lat'; % transposed then + lat = lat.'; % transposed then lat = lat(ones(1,ms), :); % copy down each column. elseif (ms == mla) & (ns == nla) % ok @@ -100,6 +100,7 @@ if ~isempty(Iwest) long(Iwest) = long(Iwest) + 360; end + if (mlo == 1) & (nlo == 1) % long is a scalar - fill to size of SP long = long*ones(size(SP)); elseif (ns == nlo) & (mlo == 1) % long is a row vector, @@ -107,8 +108,11 @@ elseif (ms == mlo) & (nlo == 1) % long is a column vector, long = long(:,ones(1,ns)); % copy across each row. elseif (ns == mlo) & (nlo == 1) % long is a transposed row vector, - long = long'; % transposed then + long = long.'; % transposed then long = long(ones(1,ms), :); % copy down each column. +elseif (ms == nlo) & (mlo == 1) % long is a transposed column vector, + long = long.'; % transposed then + long = long(:,ones(1,ns)); % copy down each column. elseif (ms == mlo) & (ns == nlo) % ok else @@ -116,15 +120,39 @@ end %if if ms == 1 - SP = SP'; - p = p'; - lat = lat'; - long = long'; + SP = SP.'; + p = p.'; + lat = lat.'; + long = long.'; transposed = 1; else transposed = 0; end +[Iout_of_range] = find(p < 100 & SP > 120); +SP(Iout_of_range) = NaN; +[Iout_of_range] = find(p >= 100 & SP > 42); +SP(Iout_of_range) = NaN; + +[Inan] = find(abs(SP) == 99999 | abs(SP) == 999999); +SP(Inan) = NaN; +[Inan] = find(abs(p) == 99999 | abs(p) == 999999); +p(Inan) = NaN; +[Inan] = find(abs(long) == 9999 | abs(long) == 99999); +long(Inan) = NaN; +[Inan] = find(abs(lat) == 9999 | abs(lat) == 99999); +lat(Inan) = NaN; + +if ~isempty(find(p < -1.5 | p > 12000)) + error('gsw_SA_from_SP: pressure is out of range') +end +if ~isempty(find(long < 0 | long > 360)) + error('gsw_SA_from_SP: longitude is out of range') +end +if ~isempty(find(abs(lat) > 90)) + error('gsw_SA_from_SP: latitude is out of range') +end + %-------------------------------------------------------------------------- % Start of the calculation %-------------------------------------------------------------------------- @@ -135,21 +163,27 @@ SP(I_neg_SP) = 0; end -inds = find(isfinite(SP)); +[Iocean] = find(~isnan(SP.*p.*lat.*long)); SA = nan(size(SP)); -dSA = nan(size(SP)); +SAAR = nan(size(SP)); in_ocean = nan(size(SP)); -[dSA(inds), in_ocean(inds)] = gsw_delta_SA(p(inds),long(inds),lat(inds)); +% The following function (gsw_SAAR) finds SAAR in the non-Baltic parts of +% the world ocean. (Actually, this gsw_SAAR look-up table returns values +% of zero in the Baltic Sea since SAAR in the Baltic is a function of SP, +% not space. +[SAAR(Iocean), in_ocean(Iocean)] = gsw_SAAR(p(Iocean),long(Iocean),lat(Iocean)); -SA(inds) = (35.16504/35)*SP(inds) + dSA(inds); +SA(Iocean) = (35.16504/35)*SP(Iocean).*(1 + SAAR(Iocean)); -SA_baltic(inds) = gsw_SA_from_SP_Baltic(SP(inds),long(inds),lat(inds)); +% Here the Practical Salinity in the Baltic is used to calculate the +% Absolute Salinity there. +SA_baltic(Iocean) = gsw_SA_from_SP_Baltic(SP(Iocean),long(Iocean),lat(Iocean)); -indsbaltic = find(~isnan(SA_baltic(inds))); +[Ibaltic] = find(~isnan(SA_baltic(Iocean))); -SA(inds(indsbaltic)) = SA_baltic(inds(indsbaltic)); +SA(Iocean(Ibaltic)) = SA_baltic(Iocean(Ibaltic)); if transposed SA = SA'; diff --git a/Toolbox/gsw_SA_from_Sstar.m b/Toolbox/gsw_SA_from_Sstar.m index 6ba5c3b..33e8b11 100644 --- a/Toolbox/gsw_SA_from_Sstar.m +++ b/Toolbox/gsw_SA_from_Sstar.m @@ -12,7 +12,7 @@ % INPUT: % Sstar = Preformed Salinity [ g/kg ] % p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% ( i.e. absolute pressure - 10.1325 dbar ) % long = longitude in decimal degrees [ 0 ... +360 ] % or [ -180 ... +180 ] % lat = latitude in decimal degrees north [ -90 ... +90 ] @@ -21,7 +21,7 @@ % where Sstar is MxN. % % OUTPUT: -% SA = Absolute Salinity [ g/kg ] +% SA = Absolute Salinity [ g/kg ] % in_ocean = 0, if long and lat are a long way from the ocean % = 1, if long and lat are in the ocean % Note. This flag is only set when the observation is well and truly on @@ -29,9 +29,9 @@ % hundred kilometres inland from the coast. % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (27th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -60,48 +60,57 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else error('gsw_SA_from_Sstar: Inputs array dimensions arguments do not agree') end %if -[mL,nL] = size(lat); +[mla,nla] = size(lat); -if (mL == 1) & (nL == 1) % lat is a scalar - fill to size of Sstar +if (mla == 1) & (nla == 1) % lat is a scalar - fill to size of Sstar lat = lat*ones(size(Sstar)); -elseif (ns == nL) & (mL == 1) % lat is a row vector, +elseif (ns == nla) & (mla == 1) % lat is a row vector, lat = lat(ones(1,ms), :); % copy down each column. -elseif (ms == mL) & (nL == 1) % lat is a column vector, +elseif (ms == mla) & (nla == 1) % lat is a column vector, lat = lat(:,ones(1,ns)); % copy across each row. -elseif (ms == mL) & (ns == nL) +elseif (ns == mla) & (nla == 1) % lat is a transposed row vector, + lat = lat.'; % transposed then + lat = lat(ones(1,ms), :); % copy down each column. +elseif (ms == mla) & (ns == nla) % ok else error('gsw_SA_from_Sstar: Inputs array dimensions arguments do not agree') end %if -[mL,nL] = size(long); +[mlo,nlo] = size(long); [Iwest] =find(long < 0); if ~isempty(Iwest) long(Iwest) = long(Iwest) + 360; end -if (mL == 1) & (nL == 1) % long is a scalar - fill to size of Sstar +if (mlo == 1) & (nlo == 1) % long is a scalar - fill to size of Sstar long = long*ones(size(Sstar)); -elseif (ns == nL) & (mL == 1) % long is a row vector, +elseif (ns == nlo) & (mlo == 1) % long is a row vector, long = long(ones(1,ms), :); % copy down each column. -elseif (ms == mL) & (nL == 1) % long is a column vector, +elseif (ms == mlo) & (nlo == 1) % long is a column vector, long = long(:,ones(1,ns)); % copy across each row. -elseif (ms == mL) & (ns == nL) +elseif (ns == mlo) & (nlo == 1) % long is a transposed row vector, + long = long.'; % transposed then + long = long(ones(1,ms), :); % copy down each column. +elseif (ms == mlo) & (ns == nlo) % ok else error('gsw_SA_from_Sstar: Inputs array dimensions arguments do not agree') end %if if ms == 1 - Sstar = Sstar'; - p = p'; - lat = lat'; - long = long'; + Sstar = Sstar.'; + p = p.'; + lat = lat.'; + long = long.'; transposed = 1; else transposed = 0; @@ -111,17 +120,17 @@ % Start of the calculation %-------------------------------------------------------------------------- -r1 = 0.35; +r_1 = 0.35; -inds = find(isfinite(Sstar)); +[Iocean] = find(~isnan(Sstar.*p.*lat.*long)); SA = nan(size(Sstar)); -dSA = nan(size(Sstar)); +SAAR = nan(size(Sstar)); in_ocean = nan(size(Sstar)); -[dSA(inds), in_ocean(inds)] = gsw_delta_SA(p(inds),long(inds),lat(inds)); +[SAAR(Iocean), in_ocean(Iocean)] = gsw_SAAR(p(Iocean),long(Iocean),lat(Iocean)); -SA(inds) = Sstar(inds) + (1+r1)*dSA(inds); +SA(Iocean) = Sstar(Iocean).*(1 + SAAR(Iocean))./(1 - r_1*SAAR(Iocean)); % In the Baltic Sea, SA = Sstar, and note that gsw_delta_SA returns zero % for dSA in the Baltic. diff --git a/Toolbox/gsw_SA_from_rho.m b/Toolbox/gsw_SA_from_rho.m index 36d2d23..a143461 100644 --- a/Toolbox/gsw_SA_from_rho.m +++ b/Toolbox/gsw_SA_from_rho.m @@ -1,35 +1,43 @@ -function SA = gsw_SA_from_rho(rho,t,p) +function SA = gsw_SA_from_rho(rho,CT,p) -% gsw_SA_from_rho Absolute Salinity from density measurements +% gsw_SA_from_rho Absolute Salinity from density % ========================================================================= % % USAGE: -% SA = gsw_SA_from_rho(rho,t,p) -% +% SA = gsw_SA_from_rho(rho,CT,p) +% % DESCRIPTION: -% Calculates the Absolute Salinity of a seawater sample, for given values -% of its density, in-situ temperature and sea pressure (in dbar). +% Calculates the Absolute Salinity of a seawater sample, for given values +% of its density, Conservative Temperature and sea pressure (in dbar). +% This function uses the computationally-efficient 48-term expression for +% density in terms of SA, CT and p (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: % rho = density of a seawater sample (e.g. 1026 kg/m^3). [ kg/m^3 ] % Note. This input has not had 1000 kg/m^3 subtracted from it. % That is, it is 'density', not 'density anomaly'. -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% (i.e. absolute pressure - 10.1325 dbar) +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % -% rho & t need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where rho & t are MxN. +% rho & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where rho & CT are MxN. % % OUTPUT: -% SA = Absolute Salinity. [ g/kg ] -% Note. This is expressed on the Reference-Composition Salinity -% Scale of Millero et al. (2008). +% SA = Absolute Salinity. [ g/kg ] +% Note. This is expressed on the Reference-Composition Salinity +% Scale of Millero et al. (2008). % % AUTHOR: -% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd August, 2010) +% VERSION NUMBER: 3.0 (4th April, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -38,6 +46,11 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See section 2.5 of this TEOS-10 Manual. % +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% % Millero, F. J., R. Feistel, D. G. Wright, and T. J. McDougall, 2008: % The composition of Standard Seawater and the definition of the % Reference-Composition Salinity Scale, Deep-Sea Res. I, 55, 50-72. @@ -51,23 +64,26 @@ %-------------------------------------------------------------------------- if ~(nargin==3) - error('gsw_SA_from_rho.: Requires three inputs') + error('gsw_SA_from_rho: Requires three inputs') end %if [md,nd] = size(rho); -[mt,nt] = size(t); +[mt,nt] = size(CT); [mp,np] = size(p); if (mt ~= md | nt ~= nd) - error('gsw_SA_from_rho: rho and t must have same dimensions') + error('gsw_SA_from_rho: rho and CT must have same dimensions') end -if (mp == 1) & (np == 1) % p scalar - fill to size of rho +if (mp == 1) & (np == 1) % p scalar - fill to size of rho p = p*ones(size(rho)); -elseif (nd == np) & (mp == 1) % p is row vector, +elseif (nd == np) & (mp == 1) % p is row vector, p = p(ones(1,md), :); % copy down each column. -elseif (md == mp) & (np == 1) % p is column vector, +elseif (md == mp) & (np == 1) % p is column vector, p = p(:,ones(1,nd)); % copy across each row. +elseif (nd == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,md), :); % copy down each column. elseif (md == mp) & (nd == np) % ok else @@ -75,9 +91,9 @@ end %if if md == 1 - rho = rho'; - t = t'; - p = p'; + rho = rho.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -87,39 +103,43 @@ % Start of the calculation %-------------------------------------------------------------------------- -n0 = 0; -n1 = 1; - v_lab = ones(size(rho))./rho; +v_0 = gsw_specvol(zeros(size(rho)),CT,p); +v_50 = gsw_specvol(50*ones(size(rho)),CT,p); + +SA = 50*(v_lab - v_0)./(v_50 - v_0); % initial estimate of SA. -v_0 = gsw_gibbs(n0,n0,n1,0,t,p); -v_120 = gsw_gibbs(n0,n0,n1,120,t,p); - -SA = 120*(v_lab - v_0)./(v_120 - v_0); % initial estimate of SA. +[Ior] = find(SA < 0 | SA > 50); +if ~isempty(Ior) + SA(Ior) = NaN; +end -[Ior] = find(SA < 0 | SA > 120); +v_SA = (v_50 - v_0)./50; %initial estimate of v_SA, the SA derivative of v -v_SA = (v_120 - v_0)./120; %initial estimate of v_SA, the SA derivative of v +%-------------------------------------------------------------------------- +% Begin the modified Newton-Raphson iterative procedure +%-------------------------------------------------------------------------- for Number_of_iterations = 1:2 SA_old = SA; - delta_v = gsw_gibbs(n0,n0,n1,SA_old,t,p) - v_lab; + delta_v = gsw_specvol(SA_old,CT,p) - v_lab; SA = SA_old - delta_v./v_SA ; % this is half way through the modified N-R method SA_mean = 0.5*(SA + SA_old); - v_SA = gsw_gibbs(n1,n0,n1,SA_mean,t,p); + [rho,alpha,beta] = gsw_rho_alpha_beta(SA_mean,CT,p); + v_SA = - beta./rho; SA = SA_old - delta_v./v_SA; + [Ior] = find(SA < 0 | SA > 50); + if ~isempty(Ior) + SA(Ior) = NaN; + end end % After two iterations of this modified Newton-Raphson iteration, -% the error in SA is typically no larger than 2x10^-13 g/kg. +% the error in SA is no larger than 8x10^-13 g/kg, which +% is machine precision for this calculation. -if ~isempty(Ior) - SA(Ior) = NaN; -end - if transposed - SA = SA'; + SA = SA.'; end end - diff --git a/Toolbox/gsw_SA_from_rho_CT.m b/Toolbox/gsw_SA_from_rho_CT.m new file mode 100644 index 0000000..2a0a09d --- /dev/null +++ b/Toolbox/gsw_SA_from_rho_CT.m @@ -0,0 +1,118 @@ +function SA = gsw_SA_from_rho_CT(rho,CT,p) + +% gsw_SA_from_rho_CT Absolute Salinity from density +% ========================================================================= +% +% USAGE: +% SA = gsw_SA_from_rho_CT(rho,CT,p), or equivalently +% SA = gsw_SA_from_rho(rho,CT,p) +% +% Note that gsw_SA_from_rho(rho,CT,p) is identical to +% gsw_SA_from_rho_CT(rho,CT,p). The extra "_CT" emphasises that the input +% temperature is Conservative Temperature, but the extra "_CT" part of the +% function name is not needed. +% +% DESCRIPTION: +% Calculates the Absolute Salinity of a seawater sample, for given values +% of its density, Conservative Temperature and sea pressure (in dbar). +% This function uses the computationally-efficient 48-term expression for +% density in terms of SA, CT and p (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% rho = density of a seawater sample (e.g. 1026 kg/m^3). [ kg/m^3 ] +% Note. This input has not had 1000 kg/m^3 subtracted from it. +% That is, it is 'density', not 'density anomaly'. +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% rho & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where rho & CT are MxN. +% +% OUTPUT: +% SA = Absolute Salinity. [ g/kg ] +% Note. This is expressed on the Reference-Composition Salinity +% Scale of Millero et al. (2008). +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (4th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 2.5 of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% Millero, F. J., R. Feistel, D. G. Wright, and T. J. McDougall, 2008: +% The composition of Standard Seawater and the definition of the +% Reference-Composition Salinity Scale, Deep-Sea Res. I, 55, 50-72. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin==3) + error('gsw_SA_from_rho_CT: Requires three inputs') +end %if + +[md,nd] = size(rho); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= md | nt ~= nd) + error('gsw_SA_from_rho_CT: rho and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of rho + p = p*ones(size(rho)); +elseif (nd == np) & (mp == 1) % p is row vector, + p = p(ones(1,md), :); % copy down each column. +elseif (md == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,nd)); % copy across each row. +elseif (nd == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,md), :); % copy down each column. +elseif (md == mp) & (nd == np) + % ok +else + error('gsw_SA_from_rho_CT: Inputs array dimensions arguments do not agree') +end %if + +if md == 1 + rho = rho.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +SA = gsw_SA_from_rho(rho,CT,p); + +if transposed + SA = SA.'; +end + +end diff --git a/Toolbox/gsw_SA_from_rho_CT_exact.m b/Toolbox/gsw_SA_from_rho_CT_exact.m new file mode 100644 index 0000000..da32e6f --- /dev/null +++ b/Toolbox/gsw_SA_from_rho_CT_exact.m @@ -0,0 +1,138 @@ +function SA = gsw_SA_from_rho_CT_exact(rho,CT,p) + +% gsw_SA_from_rho_CT_exact Absolute Salinity from density +% ========================================================================= +% +% USAGE: +% SA = gsw_SA_from_rho_CT_exact(rho,CT,p) +% +% DESCRIPTION: +% Calculates the Absolute Salinity of a seawater sample, for given values +% of its density, Conservative Temperature and sea pressure (in dbar). +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely +% gsw_SA_from_rho_CT(rho,CT,p), which uses the computationally +% efficient 48-term expression for density in terms of SA, CT and p +% (McDougall et al., 2011). +% +% INPUT: +% rho = density of a seawater sample (e.g. 1026 kg/m^3). [ kg/m^3 ] +% Note. This input has not had 1000 kg/m^3 subtracted from it. +% That is, it is 'density', NOT 'density anomaly'. +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% rho & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where rho & CT are MxN. +% +% OUTPUT: +% SA = Absolute Salinity. [ g/kg ] +% Note. This is expressed on the Reference-Composition Salinity +% Scale of Millero et al. (2008). +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (5th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 2.5 of this TEOS-10 Manual. +% +% Millero, F. J., R. Feistel, D. G. Wright, and T. J. McDougall, 2008: +% The composition of Standard Seawater and the definition of the +% Reference-Composition Salinity Scale, Deep-Sea Res. I, 55, 50-72. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin==3) + error('gsw_SA_from_rho_CT_exact: Requires three inputs') +end %if + +[md,nd] = size(rho); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= md | nt ~= nd) + error('gsw_SA_from_rho_CT_exact: rho and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of rho + p = p*ones(size(rho)); +elseif (nd == np) & (mp == 1) % p is row vector, + p = p(ones(1,md), :); % copy down each column. +elseif (md == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,nd)); % copy across each row. +elseif (nd == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,md), :); % copy down each column. +elseif (md == mp) & (nd == np) + % ok +else + error('gsw_SA_from_rho_CT_exact: Inputs array dimensions arguments do not agree') +end %if + +if md == 1 + rho = rho.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +v_lab = ones(size(rho))./rho; +v_0 = gsw_specvol_CT_exact(zeros(size(rho)),CT,p); +v_120 = gsw_specvol_CT_exact(120*ones(size(rho)),CT,p); + +SA = 120*(v_lab - v_0)./(v_120 - v_0); % initial estimate of SA. + +[Ior] = find(SA < 0 | SA > 120); +if ~isempty(Ior) + SA(Ior) = NaN; +end + +v_SA = (v_120 - v_0)./120; %initial estimate of v_SA, the SA derivative of v + +%-------------------------------------------------------------------------- +% Begin the modified Newton-Raphson iterative procedure +%-------------------------------------------------------------------------- + +for Number_of_iterations = 1:2 + SA_old = SA; + delta_v = gsw_specvol_CT_exact(SA_old,CT,p) - v_lab; + SA = SA_old - delta_v./v_SA ; % this is half way through the modified N-R method + SA_mean = 0.5*(SA + SA_old); + [rho,alpha,beta] = gsw_rho_alpha_beta_CT_exact(SA_mean,CT,p); + v_SA = - beta./rho; + SA = SA_old - delta_v./v_SA; + [Ior] = find(SA < 0 | SA > 120); + if ~isempty(Ior) + SA(Ior) = NaN; + end +end + +% After two iterations of this modified Newton-Raphson iteration, +% the error in SA is no larger than 8x10^-13 g kg^-1, which +% is machine precision for this calculation. + +if transposed + SA = SA.'; +end + +end diff --git a/Toolbox/gsw_SA_from_rho_t_exact.m b/Toolbox/gsw_SA_from_rho_t_exact.m new file mode 100644 index 0000000..ed1085f --- /dev/null +++ b/Toolbox/gsw_SA_from_rho_t_exact.m @@ -0,0 +1,127 @@ +function SA = gsw_SA_from_rho_t_exact(rho,t,p) + +% gsw_SA_from_rho_t_exact Absolute Salinity from density measurements +% ========================================================================= +% +% USAGE: +% SA = gsw_SA_from_rho_t_exact(rho,t,p) +% +% DESCRIPTION: +% Calculates the Absolute Salinity of a seawater sample, for given values +% of its density, in-situ temperature and sea pressure (in dbar). +% +% INPUT: +% rho = density of a seawater sample (e.g. 1026 kg/m^3) [ kg/m^3 ] +% Note. This input has not had 1000 kg/m^3 subtracted from it. +% That is, it is 'density', not 'density anomaly'. +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% rho & t need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where rho & t are MxN. +% +% OUTPUT: +% SA = Absolute Salinity [ g/kg ] +% Note. This is expressed on the Reference-Composition Salinity +% Scale of Millero et al. (2008). +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (28th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 2.5 of this TEOS-10 Manual. +% +% Millero, F. J., R. Feistel, D. G. Wright, and T. J. McDougall, 2008: +% The composition of Standard Seawater and the definition of the +% Reference-Composition Salinity Scale, Deep-Sea Res. I, 55, 50-72. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin==3) + error('gsw_SA_from_rho_t_exact: Requires three inputs') +end %if + +[md,nd] = size(rho); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt ~= md | nt ~= nd) + error('gsw_SA_from_rho_t_exact: rho and t must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of rho + p = p*ones(size(rho)); +elseif (nd == np) & (mp == 1) % p is row vector, + p = p(ones(1,md), :); % copy down each column. +elseif (md == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,nd)); % copy across each row. +elseif (nd == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,md), :); % copy down each column. +elseif (md == mp) & (nd == np) + % ok +else + error('gsw_SA_from_rho_t_exact: Inputs array dimensions arguments do not agree') +end %if + +if md == 1 + rho = rho.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +n0 = 0; +n1 = 1; + +v_lab = ones(size(rho))./rho; + +v_0 = gsw_gibbs(n0,n0,n1,0,t,p); +v_120 = gsw_gibbs(n0,n0,n1,120,t,p); + +SA = 120*(v_lab - v_0)./(v_120 - v_0); % initial estimate of SA. + +[Ior] = find(SA < 0 | SA > 120); +SA(Ior) = NaN; +v_SA = (v_120 - v_0)./120; %initial estimate of v_SA, the SA derivative of v + +for Number_of_iterations = 1:2 + SA_old = SA; + delta_v = gsw_gibbs(n0,n0,n1,SA_old,t,p) - v_lab; + SA = SA_old - delta_v./v_SA ; % this is half way through the modified N-R method + [Ior] = find(SA < 0 | SA > 120); + SA(Ior) = NaN; + SA_mean = 0.5*(SA + SA_old); + v_SA = gsw_gibbs(n1,n0,n1,SA_mean,t,p); + SA = SA_old - delta_v./v_SA; + [Ior] = find(SA < 0 | SA > 120); + SA(Ior) = NaN; +end + +% After two iterations of this modified Newton-Raphson iteration, +% the error in SA is no larger than 2x10^-13 g/kg. + +if transposed + SA = SA.'; +end + +end diff --git a/Toolbox/gsw_SP_from_C.m b/Toolbox/gsw_SP_from_C.m new file mode 100644 index 0000000..04541e7 --- /dev/null +++ b/Toolbox/gsw_SP_from_C.m @@ -0,0 +1,195 @@ +function SP = gsw_SP_from_C(C,t,p) + +% gsw_SP_from_C Practical Salinity from conductivity +%========================================================================== +% +% USAGE: +% SP = gsw_SP_from_C(C,t,p) +% +% DESCRIPTION: +% Calculates Practical Salinity, SP, from conductivity, C, primarily using +% the PSS-78 algorithm. Note that the PSS-78 algorithm for Practical +% Salinity is only valid in the range 2 < SP < 42. If the PSS-78 +% algorithm produces a Practical Salinity that is less than 2 then the +% Practical Salinity is recalculated with a modified form of the Hill et +% al. (1986) formula. The modification of the Hill et al. (1986) +% expression is to ensure that it is exactly consistent with PSS-78 +% at SP = 2. Note that the input values of conductivity need to be in +% units of mS/cm (not S/m). +% +% INPUT: +% C = conductivity [ mS/cm ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% t & p may have dimensions 1x1 or Mx1 or 1xN or MxN, where C is MxN. +% +% OUTPUT: +% SP = Practical Salinity on the PSS-78 scale [ unitless ] +% +% AUTHOR: +% Paul Barker, Trevor McDougall and Rich Pawlowicz [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (1st April, 2010) +% +% REFERENCES: +% Culkin and Smith, 1980: Determination of the Concentration of Potassium +% Chloride Solution Having the Same Electrical Conductivity, at 15C and +% Infinite Frequency, as Standard Seawater of Salinity 35.0000 +% (Chlorinity 19.37394), IEEE J. Oceanic Eng, 5, 22-23. +% +% Hill, K.D., T.M. Dauphinee & D.J. Woods, 1986: The extension of the +% Practical Salinity Scale 1978 to low salinities. IEEE J. Oceanic Eng., +% 11, 109 - 112. +% +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See appendix E of this TEOS-10 Manual. +% +% Unesco, 1983: Algorithms for computation of fundamental properties of +% seawater. Unesco Technical Papers in Marine Science, 44, 53 pp. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_SP_from_C: Requires three input arguments') +end %if + +[mc,nc] = size(C); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt == 1) & (nt == 1) % t scalar - fill to size of C + t = t*ones(size(C)); +elseif (nc == nt) & (mt == 1) % t is row vector, + t = t(ones(1,mc), :); % copy down each column. +elseif (mc == mt) & (nt == 1) % t is column vector, + t = t(:,ones(1,nc)); % copy across each row. +elseif (nc == mt) & (nt == 1) % t is a transposed row vector, + t = t.'; % transposed then + t = t(ones(1,mc), :); % copy down each column. +elseif (mc == mt) & (nc == nt) + % ok +else + error('gsw_SP_from_C: Inputs array dimensions arguments do not agree') +end %if + +if (mp == 1) & (np == 1) % p scalar - fill to size of C + p = p*ones(size(C)); +elseif (nc == np) & (mp == 1) % p is row vector, + p = p(ones(1,mc), :); % copy down each column. +elseif (mc == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,nc)); % copy across each row. +elseif (nc == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,mc), :); % copy down each column. +elseif (mc == mp) & (nc == np) + % ok +else + error('gsw_SP_from_C: Inputs array dimensions arguments do not agree') +end %if + +if mc == 1 + C = C.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +a0 = 0.0080; +a1 = -0.1692; +a2 = 25.3851; +a3 = 14.0941; +a4 = -7.0261; +a5 = 2.7081; + +b0 = 0.0005; +b1 = -0.0056; +b2 = -0.0066; +b3 = -0.0375; +b4 = 0.0636; +b5 = -0.0144; + +c0 = 0.6766097; +c1 = 2.00564e-2; +c2 = 1.104259e-4; +c3 = -6.9698e-7; +c4 = 1.0031e-9; + +d1 = 3.426e-2; +d2 = 4.464e-4; +d3 = 4.215e-1; +d4 = -3.107e-3; + +e1 = 2.070e-5; +e2 = -6.370e-10; +e3 = 3.989e-15; + +k = 0.0162; + +t68 = t.*1.00024; +ft68 = (t68 - 15)./(1 + k*(t68 - 15)); + +% The dimensionless conductivity ratio, R, is the conductivity input, C, +% divided by the present estimate of C(SP=35, t_68=15, p=0) which is +% 42.9140 mS/cm (=4.29140 S/m), (Culkin and Smith, 1980). + +R = 0.023302418791070513.*C; % 0.023302418791070513 = 1./42.9140 + +% rt_lc corresponds to rt as defined in the UNESCO 44 (1983) routines. +rt_lc = c0 + (c1 + (c2 + (c3 + c4.*t68).*t68).*t68).*t68; +Rp = 1 + (p.*(e1 + e2.*p + e3.*p.*p))./ ... + (1 + d1.*t68 + d2.*t68.*t68 + (d3 + d4.*t68).*R); +Rt = R./(Rp.*rt_lc); + +[Ierror] = find(Rt < 0); +if ~isempty(Ierror) + Rt(Ierror) = NaN; +end + +Rtx = sqrt(Rt); + +SP = a0 + (a1 + (a2 + (a3 + (a4 + a5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx + ... + ft68.*(b0 + (b1 + (b2 + (b3 + (b4 + b5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx); + +% The following section of the code is designed for SP < 2 based on the +% Hill et al. (1986) algorithm. This algorithm is adjusted so that it is +% exactly equal to the PSS-78 algorithm at SP = 2. + +[I2] = find(SP < 2); +if ~isempty(I2) + Hill_ratio = gsw_Hill_ratio_at_SP2(t(I2)); + x = 400*Rt(I2); + sqrty = 10*Rtx(I2); + part1 = 1 + x.*(1.5 + x) ; + part2 = 1 + sqrty.*(1 + sqrty.*(1 + sqrty)); + SP_Hill_raw = SP(I2) - a0./part1 - b0.*ft68(I2)./part2; + SP(I2) = Hill_ratio.*SP_Hill_raw; +end + +% These few lines ensure that SP is non-negative. +[I_neg_SP] = find(SP < 0); +if ~isempty(I_neg_SP) + SP(I_neg_SP) = 0; +end + +if transposed + SP = SP.'; +end + +end diff --git a/Toolbox/gsw_SP_from_R.m b/Toolbox/gsw_SP_from_R.m new file mode 100644 index 0000000..f264823 --- /dev/null +++ b/Toolbox/gsw_SP_from_R.m @@ -0,0 +1,183 @@ +function SP = gsw_SP_from_R(R,t,p) + +% gsw_SP_from_R Practical Salinity from conductivity ratio +%========================================================================== +% +% USAGE: +% SP = gsw_SP_from_R(R,t,p) +% +% DESCRIPTION: +% Calculates Practical Salinity, SP, from the conductivity ratio, R, +% primarily using the PSS-78 algorithm. Note that the PSS-78 algorithm +% for Practical Salinity is only valid in the range 2 < SP < 42. If the +% PSS-78 algorithm produces a Practical Salinity that is less than 2 then +% the Practical Salinity is recalculated with a modified form of the +% Hill et al. (1986) formula. The modification of the Hill et al. (1986) +% expression are to ensure that it is exactly consistent with PSS-78 +% at SP = 2. +% +% INPUT: +% R = conductivity ratio [ unitless ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% t & p may have dimensions 1x1 or Mx1 or 1xN or MxN, where R is MxN. +% +% OUTPUT: +% SP = Practical Salinity on the PSS-78 scale [ unitless ] +% +% AUTHOR: +% Paul Barker, Trevor McDougall and Rich Pawlowicz [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (1st April, 2011) +% +% REFERENCES: +% Hill, K.D., T.M. Dauphinee & D.J. Woods, 1986: The extension of the +% Practical Salinity Scale 1978 to low salinities. IEEE J. Oceanic Eng., +% OE-11, 1, 109 - 112. +% +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See appendix E of this TEOS-10 Manual. +% +% Unesco, 1983: Algorithms for computation of fundamental properties of +% seawater. Unesco Technical Papers in Marine Science, 44, 53 pp. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_SP_from_R: Requires three input arguments') +end %if + +[mc,nc] = size(R); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt == 1) & (nt == 1) % t scalar - fill to size of R + t = t*ones(size(R)); +elseif (nc == nt) & (mt == 1) % t is row vector, + t = t(ones(1,mc), :); % copy down each column. +elseif (mc == mt) & (nt == 1) % t is column vector, + t = t(:,ones(1,nc)); % copy across each row. +elseif (nc == mt) & (nt == 1) % t is a transposed row vector, + t = t.'; % transposed then + t = t(ones(1,mc), :); % copy down each column. +elseif (mc == mt) & (nc == nt) + % ok +else + error('gsw_SP_from_R: Inputs array dimensions arguments do not agree') +end %if + +if (mp == 1) & (np == 1) % p scalar - fill to size of R + p = p*ones(size(R)); +elseif (nc == np) & (mp == 1) % p is row vector, + p = p(ones(1,mc), :); % copy down each column. +elseif (mc == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,nc)); % copy across each row. +elseif (nc == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,mc), :); % copy down each column. +elseif (mc == mp) & (nc == np) + % ok +else + error('gsw_SP_from_R: Inputs array dimensions arguments do not agree') +end + +if mc == 1 + R = R.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +a0 = 0.0080; +a1 = -0.1692; +a2 = 25.3851; +a3 = 14.0941; +a4 = -7.0261; +a5 = 2.7081; + +b0 = 0.0005; +b1 = -0.0056; +b2 = -0.0066; +b3 = -0.0375; +b4 = 0.0636; +b5 = -0.0144; + +c0 = 0.6766097; +c1 = 2.00564e-2; +c2 = 1.104259e-4; +c3 = -6.9698e-7; +c4 = 1.0031e-9; + +d1 = 3.426e-2; +d2 = 4.464e-4; +d3 = 4.215e-1; +d4 = -3.107e-3; + +e1 = 2.070e-5; +e2 = -6.370e-10; +e3 = 3.989e-15; + +k = 0.0162; + +t68 = t.*1.00024; +ft68 = (t68 - 15)./(1 + k*(t68 - 15)); + +% rt_lc corresponds to rt as defined in the UNESCO 44 (1983) routines. +rt_lc = c0 + (c1 + (c2 + (c3 + c4.*t68).*t68).*t68).*t68; +Rp = 1 + (p.*(e1 + e2.*p + e3.*p.*p))./ ... + (1 + d1.*t68 + d2.*t68.*t68 + (d3 + d4.*t68).*R); +Rt = R./(Rp.*rt_lc); + +[Ierror] = find(Rt < 0); +if ~isempty(Ierror) + Rt(Ierror) = NaN; +end + +Rtx = sqrt(Rt); + +SP = a0 + (a1 + (a2 + (a3 + (a4 + a5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx + ... + ft68.*(b0 + (b1 + (b2+ (b3 + (b4 + b5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx); + +% The following section of the code is designed for SP < 2 based on the +% Hill et al. (1986) algorithm. This algorithm is adjusted so that it is +% exactly equal to the PSS-78 algorithm at SP = 2. + +[I2] = find(SP < 2); +if ~isempty(I2) + Hill_ratio = gsw_Hill_ratio_at_SP2(t(I2)); + x = 400*Rt(I2); + sqrty = 10*Rtx(I2); + part1 = 1 + x.*(1.5 + x) ; + part2 = 1 + sqrty.*(1 + sqrty.*(1 + sqrty)); + SP_Hill_raw = SP(I2) - a0./part1 - b0.*ft68(I2)./part2; + SP(I2) = Hill_ratio.*SP_Hill_raw; +end + +% These few lines ensure that SP is non-negative. +[I_neg_SP] = find(SP < 0); +if ~isempty(I_neg_SP) + SP(I_neg_SP) = 0; +end + +if transposed + SP = SP.'; +end + +end diff --git a/Toolbox/gsw_SP_from_SA.m b/Toolbox/gsw_SP_from_SA.m index 165f3e2..8711068 100644 --- a/Toolbox/gsw_SP_from_SA.m +++ b/Toolbox/gsw_SP_from_SA.m @@ -12,7 +12,7 @@ % INPUT: % SA = Absolute Salinity [ g/kg ] % p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% ( i.e. absolute pressure - 10.1325 dbar ) % long = longitude in decimal degrees [ 0 ... +360 ] % or [ -180 ... +180 ] % lat = latitude in decimal degrees north [ -90 ... +90 ] @@ -29,9 +29,9 @@ % hundred kilometres inland from the coast. % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (27th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -54,54 +54,63 @@ [ms,ns] = size(SA); [mp,np] = size(p); -if (mp == 1) & (np == 1) % p scalar - fill to size of SA +if (mp == 1) & (np == 1) % p scalar - fill to size of SA p = p*ones(size(SA)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transpose, then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else error('gsw_SP_from_SA: Inputs array dimensions arguments do not agree') end %if -[mL,nL] = size(lat); +[mla,nla] = size(lat); -if (mL == 1) & (nL == 1) % lat is a scalar - fill to size of SA +if (mla == 1) & (nla == 1) % lat is a scalar - fill to size of SA lat = lat*ones(size(SA)); -elseif (ns == nL) & (mL == 1) % lat is a row vector, +elseif (ns == nla) & (mla == 1) % lat is a row vector, lat = lat(ones(1,ms), :); % copy down each column. -elseif (ms == mL) & (nL == 1) % lat is a column vector, +elseif (ms == mla) & (nla == 1) % lat is a column vector, lat = lat(:,ones(1,ns)); % copy across each row. -elseif (ms == mL) & (ns == nL) +elseif (ns == mla) & (nla == 1) % lat is a transposed row vector, + lat = lat.'; % transpose, then + lat = lat(ones(1,ms), :); % copy down each column. +elseif (ms == mla) & (ns == nla) % ok else error('gsw_SP_from_SA: Inputs array dimensions arguments do not agree') end %if -[mL,nL] = size(long); -[Iwest] =find(long < 0); +[mlo,nlo] = size(long); +[Iwest] = find(long < 0); if ~isempty(Iwest) long(Iwest) = long(Iwest) + 360; end -if (mL == 1) & (nL == 1) % long is a scalar - fill to size of SA +if (mlo == 1) & (nlo == 1) % long is a scalar - fill to size of SA long = long*ones(size(SA)); -elseif (ns == nL) & (mL == 1) % long is a row vector, +elseif (ns == nlo) & (mlo == 1) % long is a row vector, long = long(ones(1,ms), :); % copy down each column. -elseif (ms == mL) & (nL == 1) % long is a column vector, +elseif (ms == mlo) & (nlo == 1) % long is a column vector, long = long(:,ones(1,ns)); % copy across each row. -elseif (ms == mL) & (ns == nL) +elseif (ns == mlo) & (nlo == 1) % long is a transposed row vector, + long = long.'; % transpose, then + long = long(ones(1,ms), :); % copy down each column. +elseif (ms == mlo) & (ns == nlo) % ok else error('gsw_SP_from_SA: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - p = p'; - lat = lat'; - long = long'; + SA = SA.'; + p = p.'; + lat = lat.'; + long = long.'; transposed = 1; else transposed = 0; @@ -111,25 +120,25 @@ % Start of the calculation %-------------------------------------------------------------------------- -inds = find(isfinite(SA)); +[Iocean] = find(~isnan(SA.*p.*lat.*long)); SP = nan(size(SA)); -dSA = nan(size(SA)); +SAAR = nan(size(SA)); in_ocean = nan(size(SA)); -[dSA(inds), in_ocean(inds)] = gsw_delta_SA(p(inds),long(inds),lat(inds)); +[SAAR(Iocean), in_ocean(Iocean)] = gsw_SAAR(p(Iocean),long(Iocean),lat(Iocean)); -SP(inds) = (35/35.16504)*(SA(inds) - dSA(inds)); +SP(Iocean) = (35/35.16504)*SA(Iocean)./(1 + SAAR(Iocean)); -SP_baltic(inds) = gsw_SP_from_SA_Baltic(SA(inds),long(inds),lat(inds)); +SP_baltic(Iocean) = gsw_SP_from_SA_Baltic(SA(Iocean),long(Iocean),lat(Iocean)); -indsbaltic = find(~isnan(SP_baltic(inds))); +[Ibaltic] = find(~isnan(SP_baltic(Iocean))); -SP(inds(indsbaltic)) = SP_baltic(inds(indsbaltic)); +SP(Iocean(Ibaltic)) = SP_baltic(Iocean(Ibaltic)); if transposed - SP = SP'; - in_ocean = in_ocean'; + SP = SP.'; + in_ocean = in_ocean.'; end end diff --git a/Toolbox/gsw_molality.m b/Toolbox/gsw_SP_from_SR.m similarity index 54% rename from Toolbox/gsw_molality.m rename to Toolbox/gsw_SP_from_SR.m index 780c356..2eb755b 100644 --- a/Toolbox/gsw_molality.m +++ b/Toolbox/gsw_SP_from_SR.m @@ -1,24 +1,24 @@ -function molality = gsw_molality(SA) +function SP = gsw_SP_from_SR(SR) -% gsw_molality molality of seawater +% gsw_SP_from_SR Practical Salinity from Reference Salinity %========================================================================== % % USAGE: -% molality = gsw_molality(SA) +% SP = gsw_SP_from_SR(SR) % % DESCRIPTION: -% Calculates the molality of seawater +% Calculates Practical Salinity from Reference Salinity. % % INPUT: -% SA = Absolute Salinity [ g/kg ] +% SR = Reference Salinity [ g/kg ] % % OUTPUT: -% molality = molality of seawater [ mol/kg ] +% SP = Practical Salinity (PSS-78) [ unitless ] % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (28th September, 2010) +% VERSION NUMBER: 3.0 (27th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -31,23 +31,19 @@ %========================================================================== %-------------------------------------------------------------------------- -% Check variables and resize if necessary +% Check variables %-------------------------------------------------------------------------- if ~(nargin == 1) - error('gsw_molality: Requires one input') + error('gsw_SP_from_SR: Requires only one input') end %if %-------------------------------------------------------------------------- % Start of the calculation %-------------------------------------------------------------------------- -M_S = 0.0314038218; % mole-weighted average atomic weight of the elements - % of sea salt, in units of kg/mol. -[Isalty] = find(SA >= 0); +rec_u_PS = 0.995306702338459; % rec_u_PS = 1/u_PS = 1/(35.16504/35) -molality = nan(size(SA)); - -molality(Isalty) = SA(Isalty)./(M_S*(1000 - SA(Isalty))); % molality of seawater in mol/kg +SP = rec_u_PS.*SR; end diff --git a/Toolbox/gsw_SP_from_Sstar.m b/Toolbox/gsw_SP_from_Sstar.m index 0c8510d..1387829 100644 --- a/Toolbox/gsw_SP_from_Sstar.m +++ b/Toolbox/gsw_SP_from_Sstar.m @@ -12,7 +12,7 @@ % INPUT: % Sstar = Preformed Salinity [ g/kg ] % p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% ( i.e. absolute pressure - 10.1325 dbar ) % long = longitude in decimal degrees [ 0 ... +360 ] % or [ -180 ... +180 ] % lat = latitude in decimal degrees north [ -90 ... +90 ] @@ -21,7 +21,7 @@ % where Sstar is MxN. % % OUTPUT: -% SP = Practical Salinity (PSS-78) [ unitless ] +% SP = Practical Salinity (PSS-78) [ unitless ] % in_ocean = 0, if long and lat are a long way from the ocean % = 1, if long and lat are in the ocean % Note. This flag is only set when the observation is well and truly on @@ -29,9 +29,9 @@ % hundred kilometres inland from the coast. % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (27th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -54,54 +54,63 @@ [ms,ns] = size(Sstar); [mp,np] = size(p); -if (mp == 1) & (np == 1) % p scalar - fill to size of Sstar +if (mp == 1) & (np == 1) % p scalar - fill to size of Sstar p = p*ones(size(Sstar)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transpose, then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else error('gsw_SP_from_Sstar: Inputs array dimensions arguments do not agree') end %if -[mL,nL] = size(lat); +[mla,nla] = size(lat); -if (mL == 1) & (nL == 1) % lat is a scalar - fill to size of Sstar +if (mla == 1) & (nla == 1) % lat is a scalar - fill to size of Sstar lat = lat*ones(size(Sstar)); -elseif (ns == nL) & (mL == 1) % lat is a row vector, +elseif (ns == nla) & (mla == 1) % lat is a row vector, lat = lat(ones(1,ms), :); % copy down each column. -elseif (ms == mL) & (nL == 1) % lat is a column vector, +elseif (ms == mla) & (nla == 1) % lat is a column vector, lat = lat(:,ones(1,ns)); % copy across each row. -elseif (ms == mL) & (ns == nL) +elseif (ns == mla) & (nla == 1) % lat is a transposed row vector, + lat = lat.'; % transpose, then + lat = lat(ones(1,ms), :); % copy down each column. +elseif (ms == mla) & (ns == nla) % ok else error('gsw_SP_from_Sstar: Inputs array dimensions arguments do not agree') end %if -[mL,nL] = size(long); -[Iwest] =find(long < 0); +[mlo,nlo] = size(long); +[Iwest] = find(long < 0); if ~isempty(Iwest) long(Iwest) = long(Iwest) + 360; end -if (mL == 1) & (nL == 1) % long is a scalar - fill to size of Sstar +if (mlo == 1) & (nlo == 1) % long is a scalar - fill to size of Sstar long = long*ones(size(Sstar)); -elseif (ns == nL) & (mL == 1) % long is a row vector, +elseif (ns == nlo) & (mlo == 1) % long is a row vector, long = long(ones(1,ms), :); % copy down each column. -elseif (ms == mL) & (nL == 1) % long is a column vector, +elseif (ms == mlo) & (nlo == 1) % long is a column vector, long = long(:,ones(1,ns)); % copy across each row. -elseif (ms == mL) & (ns == nL) +elseif (ns == mlo) & (nlo == 1) % long is a transposed row vector, + long = long.'; % transpose, then + long = long(ones(1,ms), :); % copy down each column. +elseif (ms == mlo) & (ns == nlo) % ok else error('gsw_SP_from_Sstar: Inputs array dimensions arguments do not agree') end %if if ms == 1 - Sstar = Sstar'; - p = p'; - lat = lat'; - long = long'; + Sstar = Sstar.'; + p = p.'; + lat = lat.'; + long = long.'; transposed = 1; else transposed = 0; @@ -111,29 +120,29 @@ % Start of the calculation %-------------------------------------------------------------------------- -r1 = 0.35; +r_1 = 0.35; -inds = find(isfinite(Sstar)); +[Iocean] = find(~isnan(Sstar.*p.*lat.*long)); SP = nan(size(Sstar)); -dSA = nan(size(Sstar)); +SAAR = nan(size(Sstar)); in_ocean = nan(size(Sstar)); -[dSA(inds), in_ocean(inds)] = gsw_delta_SA(p(inds),long(inds),lat(inds)); +[SAAR(Iocean), in_ocean(Iocean)] = gsw_SAAR(p(Iocean),long(Iocean),lat(Iocean)); -SP(inds) = (35/35.16504)*(Sstar(inds) + r1*dSA(inds)); +SP(Iocean) = (35/35.16504)*Sstar(Iocean)./(1 - r_1*SAAR(Iocean)); %In the Baltic Sea, SA = Sstar. -SP_baltic(inds) = gsw_SP_from_SA_Baltic(Sstar(inds),long(inds),lat(inds)); +SP_baltic(Iocean) = gsw_SP_from_SA_Baltic(Sstar(Iocean),long(Iocean),lat(Iocean)); -indsbaltic = find(~isnan(SP_baltic(inds))); +[Ibaltic] = find(~isnan(SP_baltic(Iocean))); -SP(inds(indsbaltic)) = SP_baltic(inds(indsbaltic)); +SP(Iocean(Ibaltic)) = SP_baltic(Iocean(Ibaltic)); if transposed - SP = SP'; - in_ocean = in_ocean'; + SP = SP.'; + in_ocean = in_ocean.'; end end diff --git a/Toolbox/gsw_SP_from_cndr.m b/Toolbox/gsw_SP_from_cndr.m deleted file mode 100644 index 3170100..0000000 --- a/Toolbox/gsw_SP_from_cndr.m +++ /dev/null @@ -1,154 +0,0 @@ -function SP = gsw_SP_from_cndr(R,t,p) - -% gsw_SP_from_cndr Practical Salinity from conductivity -%========================================================================== -% -% USAGE: -% SP = gsw_SP_from_cndr(R,t,p) -% -% DESCRIPTION: -% Calculates Practical Salinity from conductivity ratio (R), using the -% PSS-78 algorithm. Note that the PSS-78 algorithm for Practical Salinity -% is only valid in the range 2 < SP < 42. The output, SP, of this -% function is constrained to be non-negative. -% -% INPUT: -% R = Conductivity ratio [ unitless ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) -% -% t & p may have dimensions 1x1 or Mx1 or 1xN or MxN, where R is MxN. -% -% OUTPUT: -% SP = Practical Salinity on the PSS-78 scale [ unitless ] -% -% AUTHOR: -% 17th April 1993. Phil Morgan [ help_gsw@csiro.au ] -% -% MODIFIED: -% 12th December 2003. Lindsay Pender, Converted to ITS-90. -% 28th July 2010. by Paul Barker -% -% VERSION NUMBER: 2.0 (3rd August, 2010) -% -% REFERENCES: -% Fofonoff, P. and R.C. Millard Jr. 1983: Algorithms for computation of -% fundamental properties of seawater. Unesco Tech. Pap. in Mar. Sci., 44, -% 53 pp. -% -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See appendix E of this TEOS-10 Manual. -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 3) - error('gsw_SP_from_cndr.m: Requires three input arguments') -end %if - -[mc,nc] = size(R); -[mt,nt] = size(t); -[mp,np] = size(p); - -if (mt == 1) & (nt == 1) % t scalar - fill to size of R - t = t*ones(size(R)); -elseif (nc == nt) & (mt == 1) % t is row vector, - t = t(ones(1,mc), :); % copy down each column. -elseif (mc == mt) & (nt == 1) % t is column vector, - t = t(:,ones(1,nc)); % copy across each row. -elseif (mc == mt) & (nc == nt) - % ok -else - error('gsw_SP_from_cndr.m: Inputs array dimensions arguments do not agree') -end %if - -if (mp == 1) & (np == 1) % p scalar - fill to size of R - p = p*ones(size(R)); -elseif (nc == np) & (mp == 1) % p is row vector, - p = p(ones(1,mc), :); % copy down each column. -elseif (mc == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,nc)); % copy across each row. -elseif (mc == mp) & (nc == np) - % ok -else - error('gsw_SP_from_cndr.m: Inputs array dimensions arguments do not agree') -end %if - -if mc == 1 - R = R'; - t = t'; - p = p'; - transposed = 1; -else - transposed = 0; -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -t68 = t * 1.00024; -d_t68 = t68 - 15; - -a0 = 0.0080; -a1 = -0.1692; -a2 = 25.3851; -a3 = 14.0941; -a4 = -7.0261; -a5 = 2.7081; - -b0 = 0.0005; -b1 = -0.0056; -b2 = -0.0066; -b3 = -0.0375; -b4 = 0.0636; -b5 = -0.0144; - -c0 = 0.6766097; -c1 = 2.00564e-2; -c2 = 1.104259e-4; -c3 = -6.9698e-7; -c4 = 1.0031e-9; - -d1 = 3.426e-2; -d2 = 4.464e-4; -d3 = 4.215e-1; -d4 = -3.107e-3; - -e1 = 2.070e-5; -e2 = -6.370e-10; -e3 = 3.989e-15; - -k = 0.0162; - -rt = c0 + (c1 + (c2 + (c3 + c4.*t68).*t68).*t68).*t68; -Rp = 1 + ( p.*(e1 + e2.*p + e3.*p.*p) ) ./ ... - (1 + d1.*t68 + d2.*t68.*t68 + (d3 + d4.*t68).*R); -Rt = R./(Rp.*rt); -Rtx = sqrt(Rt); - -d_S = (d_t68 ./ (1 + k*d_t68)) .* ... - (b0 + (b1 + (b2+ (b3 + (b4 + b5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx); -S = a0 + (a1 + (a2 + (a3 + (a4 + a5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx; -SP = S + d_S; -% -% These few lines ensure that SP is non-negative. -[I_neg_SP] = find(SP < 0); -if ~isempty(I_neg_SP) - SP(I_neg_SP) = 0; -end - -if transposed - SP = SP'; -end - -end diff --git a/Toolbox/gsw_SP_salinometer.m b/Toolbox/gsw_SP_salinometer.m new file mode 100644 index 0000000..e6c0b48 --- /dev/null +++ b/Toolbox/gsw_SP_salinometer.m @@ -0,0 +1,149 @@ +function SP = gsw_SP_salinometer(Rt,t) + +% gsw_SP_salinometer Practical Salinity from a laboratory salinometer +%========================================================================== +% +% USAGE: +% SP = gsw_SP_salinometer(Rt,t) +% +% DESCRIPTION: +% Calculates Practical Salinity SP from a salinometer, primarily using the +% PSS-78 algorithm. Note that the PSS-78 algorithm for Practical Salinity +% is only valid in the range 2 < SP < 42. If the PSS-78 algorithm +% produces a Practical Salinity that is less than 2 then the Practical +% Salinity is recalculated with a modified form of the Hill et al. (1986) +% formula. The modification of the Hill et al. (1986) expression is to +% ensure that it is exactly consistent with PSS-78 at SP = 2. +% +% A laboratory salinometer has the ratio of conductivities, Rt, as an +% output, and the present function uses this conductivity ratio and the +% temperature t of the salinometer bath as the two input variables. +% +% INPUT: +% Rt = C(SP,t_68,0)/C(SP=35,t_68,0) [ unitless ] +% t = temperature of the bath of the salinometer, +% measured on the ITS-90 scale (ITS-90) [ deg C ] +% +% OUTPUT: +% SP = Practical Salinity on the PSS-78 scale [ unitless ] +% +% t may have dimensions 1x1 or Mx1 or 1xN or MxN, where Rt is MxN. +% +% AUTHOR: +% Paul Barker, Trevor McDougall and Rich Pawlowicz [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (30th March, 2011) +% +% REFERENCES: +% Fofonoff, P. and R.C. Millard Jr. 1983: Algorithms for computation of +% fundamental properties of seawater. Unesco Tech. Pap. in Mar. Sci., 44, +% 53 pp. +% +% Hill, K.D., T.M. Dauphinee & D.J. Woods, 1986: The extension of the +% Practical Salinity Scale 1978 to low salinities. IEEE J. Oceanic Eng., +% 11, 109 - 112. +% +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See appendix E of this TEOS-10 Manual, and in particular, +% Eqns. (E.2.1) and (E.2.6). +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_SP_salinometer.m: Requires two input arguments') +end %if + +[mc,nc] = size(Rt); +[mt,nt] = size(t); + +if (mt == 1) & (nt == 1) % t scalar - fill to size of Rt + t = t*ones(size(Rt)); +elseif (nc == nt) & (mt == 1) % t is row vector, + t = t(ones(1,mc), :); % copy down each column. +elseif (mc == mt) & (nt == 1) % t is column vector, + t = t(:,ones(1,nc)); % copy across each row. +elseif (nc == mt) & (np == 1) % t is a transposed row vector, + t = t.'; % transposed then + t = t(ones(1,mc), :); % copy down each column. +elseif (mc == mt) & (nc == nt) + % ok +else + error('gsw_SP_salinometer.m: Inputs array dimensions arguments do not agree') +end %if + +if mc == 1 + Rt = Rt.'; + t = t.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +a0 = 0.0080; +a1 = -0.1692; +a2 = 25.3851; +a3 = 14.0941; +a4 = -7.0261; +a5 = 2.7081; + +b0 = 0.0005; +b1 = -0.0056; +b2 = -0.0066; +b3 = -0.0375; +b4 = 0.0636; +b5 = -0.0144; + +k = 0.0162; + +t68 = t.*1.00024; +ft68 = (t68 - 15)./(1 + k*(t68 - 15)); + +[Ierror] = find(Rt < 0); +if ~isempty(Ierror) + Rt(Ierror) = NaN; +end + +Rtx = sqrt(Rt); + +SP = a0 + (a1 + (a2 + (a3 + (a4 + a5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx + ... + ft68.*(b0 + (b1 + (b2+ (b3 + (b4 + b5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx); + +% The following section of the code is designed for SP < 2 based on the +% Hill et al. (1986) algorithm. This algorithm is adjusted so that it is +% exactly equal to the PSS-78 algorithm at SP = 2. + +[I2] = find(SP < 2); +if ~isempty(I2) + Hill_ratio = gsw_Hill_ratio_at_SP2(t(I2)); + x = 400*Rt(I2); + sqrty = 10*Rtx(I2); + part1 = 1 + x.*(1.5 + x) ; + part2 = 1 + sqrty.*(1 + sqrty.*(1 + sqrty)); + SP_Hill_raw = SP(I2) - a0./part1 - b0.*ft68(I2)./part2; + SP(I2) = Hill_ratio.*SP_Hill_raw; +end + +% These few lines ensure that SP is non-negative. +[I_neg_SP] = find(SP < 0); +if ~isempty(I_neg_SP) + SP(I_neg_SP) = 0; +end + +if transposed + SP = SP.'; +end + +end diff --git a/Toolbox/gsw_SR_from_SP.m b/Toolbox/gsw_SR_from_SP.m new file mode 100644 index 0000000..79d958f --- /dev/null +++ b/Toolbox/gsw_SR_from_SP.m @@ -0,0 +1,49 @@ +function SR = gsw_SR_from_SP(SP) + +% gsw_SR_from_SP Reference Salinity from Practical Salinity +%========================================================================== +% +% USAGE: +% SR = gsw_SR_from_SP(SP) +% +% DESCRIPTION: +% Calculates Reference Salinity from Practical Salinity. +% +% INPUT: +% SP = Practical Salinity (PSS-78) [ unitless ] +% +% OUTPUT: +% SR = Reference Salinity [ g/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (27th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables +%-------------------------------------------------------------------------- + +if ~(nargin == 1) + error('gsw_SR_from_SP: Requires only one input') +end %if + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +u_PS = 1.004715428571429; % u_PS = (35.16504/35) + +SR = u_PS.*SP; + +end diff --git a/Toolbox/gsw_SSO.m b/Toolbox/gsw_SSO.m new file mode 100644 index 0000000..5cd56e5 --- /dev/null +++ b/Toolbox/gsw_SSO.m @@ -0,0 +1,43 @@ +function SSO = gsw_SSO + +% gsw_SSO Standard Ocean Reference Salinity +%========================================================================== +% +% USAGE: +% SSO = gsw_SSO +% +% DESCRIPTION: +% SSO is the Standard Ocean Reference Salinity (35.16504 g/kg). +% +% SSO is the best estimate of the Absolute Salinity of Standard Seawater +% when the seawater sample has a Practical Salinity, SP, of 35 +% (Millero et al., 2008), and this number is a fundmental part of the +% TEOS-10 definition of seawater. +% +% OUTPUT: +% SSO = Standard Ocean Reference Salinity. [ g/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. +% See appendices A.3, A.5 and Table D.4 of this TEOS-10 Manual. +% +% Millero, F. J., R. Feistel, D. G. Wright, and T. J. McDougall, 2008: +% The composition of Standard Seawater and the definition of the +% Reference-Composition Salinity Scale, Deep-Sea Res. I, 55, 50-72. +% See Table 4 and section 5 of this paper. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +SSO = 35.16504; + +end diff --git a/Toolbox/gsw_SonCl.m b/Toolbox/gsw_SonCl.m new file mode 100644 index 0000000..d48ee2a --- /dev/null +++ b/Toolbox/gsw_SonCl.m @@ -0,0 +1,37 @@ +function SonCl = gsw_SonCl + +% gsw_SonCl SP to Chlorinity ratio +%========================================================================== +% +% USAGE: +% SonCl = gsw_SonCl +% +% DESCRIPTION: +% The ratio of Practical Salinity, SP, to Chlorinity, 1.80655 kg/g for +% Reference Seawater (Millero et al., 2008). This is the ratio that was +% used by the JPOTS committee in their construction of the 1978 Practical +% Salinity Scale (PSS-78) to convert between the laboratory measurements +% of seawater samples (which were measured in Chlorinity) to Practical +% Salinity. +% +% OUTPUT: +% SonCl = SP to Chlorinity ratio [ (g/kg)^-1 ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% Millero, F. J., R. Feistel, D. G. Wright, and T. J. McDougall, 2008: +% The composition of Standard Seawater and the definition of the +% Reference-Composition Salinity Scale, Deep-Sea Res. I, 55, 50-72. +% See section 5 below Eqn. (5.5) of this paper. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +SonCl = 1.80655; + +end diff --git a/Toolbox/gsw_Sstar_from_SA.m b/Toolbox/gsw_Sstar_from_SA.m index d8f8545..86b3b67 100644 --- a/Toolbox/gsw_Sstar_from_SA.m +++ b/Toolbox/gsw_Sstar_from_SA.m @@ -12,7 +12,7 @@ % INPUT: % SA = Absolute Salinity [ g/kg ] % p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% ( i.e. absolute pressure - 10.1325 dbar ) % long = longitude in decimal degrees [ 0 ... +360 ] % or [ -180 ... +180 ] % lat = latitude in decimal degrees north [ -90 ... +90 ] @@ -29,9 +29,9 @@ % hundred kilometres inland from the coast. % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (27th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -54,54 +54,63 @@ [ms,ns] = size(SA); [mp,np] = size(p); -if (mp == 1) & (np == 1) % p scalar - fill to size of SA +if (mp == 1) & (np == 1) % p scalar - fill to size of SA p = p*ones(size(SA)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transpose, then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else error('gsw_Sstar_from_SA: Inputs array dimensions arguments do not agree') end %if -[mL,nL] = size(lat); +[mla,nla] = size(lat); -if (mL == 1) & (nL == 1) % lat is a scalar - fill to size of SA +if (mla == 1) & (nla == 1) % lat is a scalar - fill to size of SA lat = lat*ones(size(SA)); -elseif (ns == nL) & (mL == 1) % lat is a row vector, +elseif (ns == nla) & (mla == 1) % lat is a row vector, lat = lat(ones(1,ms), :); % copy down each column. -elseif (ms == mL) & (nL == 1) % lat is a column vector, +elseif (ms == mla) & (nla == 1) % lat is a column vector, lat = lat(:,ones(1,ns)); % copy across each row. -elseif (ms == mL) & (ns == nL) +elseif (ns == mla) & (nla == 1) % lat is a transposed row vector, + lat = lat.'; % transpose, then + lat = lat(ones(1,ms), :); % copy down each column. +elseif (ms == mla) & (ns == nla) % ok else error('gsw_Sstar_from_SA: Inputs array dimensions arguments do not agree') end %if -[mL,nL] = size(long); +[mlo,nlo] = size(long); [Iwest] =find(long < 0); if ~isempty(Iwest) long(Iwest) = long(Iwest) + 360; end -if (mL == 1) & (nL == 1) % long is a scalar - fill to size of SA +if (mlo == 1) & (nlo == 1) % long is a scalar - fill to size of SA long = long*ones(size(SA)); -elseif (ns == nL) & (mL == 1) % long is a row vector, +elseif (ns == nlo) & (mlo == 1) % long is a row vector, long = long(ones(1,ms), :); % copy down each column. -elseif (ms == mL) & (nL == 1) % long is a column vector, +elseif (ms == mlo) & (nlo == 1) % long is a column vector, long = long(:,ones(1,ns)); % copy across each row. -elseif (ms == mL) & (ns == nL) +elseif (ns == mlo) & (nlo == 1) % long is a transposed row vector, + long = long.'; % transpose, then + long = long(ones(1,ms), :); % copy down each column. +elseif (ms == mlo) & (ns == nlo) % ok else error('gsw_Sstar_from_SA: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - p = p'; - lat = lat'; - long = long'; + SA = SA.'; + p = p.'; + lat = lat.'; + long = long.'; transposed = 1; else transposed = 0; @@ -111,24 +120,24 @@ % Start of the calculation %-------------------------------------------------------------------------- -r1 = 0.35; +r_1 = 0.35; -inds = find(isfinite(SA)); +[Iocean] = find(~isnan(SA.*p.*lat.*long)); Sstar = nan(size(SA)); -dSA = nan(size(SA)); +SAAR = nan(size(SA)); in_ocean = nan(size(SA)); -[dSA(inds), in_ocean(inds)] = gsw_delta_SA(p(inds),long(inds),lat(inds)); +[SAAR(Iocean), in_ocean(Iocean)] = gsw_SAAR(p(Iocean),long(Iocean),lat(Iocean)); -Sstar(inds) = SA(inds) - (1+r1)*dSA(inds); +Sstar(Iocean) = SA(Iocean).*(1 - r_1*SAAR(Iocean))./(1 + SAAR(Iocean)); % In the Baltic Sea, Sstar = SA, and note that gsw_delta_SA returns zero % for dSA in the Baltic. if transposed - Sstar = Sstar'; - in_ocean = in_ocean'; + Sstar = Sstar.'; + in_ocean = in_ocean.'; end end diff --git a/Toolbox/gsw_Sstar_from_SP.m b/Toolbox/gsw_Sstar_from_SP.m index b7181a0..e8db1ca 100644 --- a/Toolbox/gsw_Sstar_from_SP.m +++ b/Toolbox/gsw_Sstar_from_SP.m @@ -14,8 +14,8 @@ % INPUT: % SP = Practical Salinity (PSS-78) [ unitless ] % p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) -% long = longitude in decimal degrees [ 0 ... +360 ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% long = longitude in decimal degrees [ 0 ... +360 ] % or [ -180 ... +180 ] % lat = latitude in decimal degrees north [ -90 ... +90 ] % @@ -31,9 +31,9 @@ % hundred kilometres inland from the coast. % % AUTHOR: -% David Jackett, Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall & Paul Barker [ help@teos-10.org ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (27th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -69,86 +69,119 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else error('gsw_Sstar_from_SP: Inputs array dimensions arguments do not agree') end %if -[mL,nL] = size(lat); +[mla,nla] = size(lat); -if (mL == 1) & (nL == 1) % lat is a scalar - fill to size of SP +if (mla == 1) & (nla == 1) % lat is a scalar - fill to size of SP lat = lat*ones(size(SP)); -elseif (ns == nL) & (mL == 1) % lat is a row vector, +elseif (ns == nla) & (mla == 1) % lat is a row vector, lat = lat(ones(1,ms), :); % copy down each column. -elseif (ms == mL) & (nL == 1) % lat is a column vector, +elseif (ms == mla) & (nla == 1) % lat is a column vector, lat = lat(:,ones(1,ns)); % copy across each row. -elseif (ms == mL) & (ns == nL) +elseif (ns == mla) & (nla == 1) % lat is a transposed row vector, + lat = lat.'; % transposed then + lat = lat(ones(1,ms), :); % copy down each column. +elseif (ms == mla) & (ns == nla) % ok else error('gsw_Sstar_from_SP: Inputs array dimensions arguments do not agree') end %if -[mL,nL] = size(long); +[mlo,nlo] = size(long); [Iwest] =find(long < 0); if ~isempty(Iwest) long(Iwest) = long(Iwest) + 360; end -if (mL == 1) & (nL == 1) % long is a scalar - fill to size of SP +if (mlo == 1) & (nlo == 1) % long is a scalar - fill to size of SP long = long*ones(size(SP)); -elseif (ns == nL) & (mL == 1) % long is a row vector, +elseif (ns == nlo) & (mlo == 1) % long is a row vector, long = long(ones(1,ms), :); % copy down each column. -elseif (ms == mL) & (nL == 1) % long is a column vector, +elseif (ms == mlo) & (nlo == 1) % long is a column vector, long = long(:,ones(1,ns)); % copy across each row. -elseif (ms == mL) & (ns == nL) +elseif (ns == mlo) & (nlo == 1) % long is a transposed row vector, + long = long.'; % transposed then + long = long(ones(1,ms), :); % copy down each column. +elseif (ms == mlo) & (ns == nlo) % ok else error('gsw_Sstar_from_SP: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SP = SP'; - p = p'; - lat = lat'; - long = long'; + SP = SP.'; + p = p.'; + lat = lat.'; + long = long.'; transposed = 1; else transposed = 0; end +[Iout_of_range] = find(p < 100 & SP > 120); +SP(Iout_of_range) = NaN; +[Iout_of_range] = find(p >= 100 & SP > 42); +SP(Iout_of_range) = NaN; + +[Inan] = find(abs(SP) == 99999 | abs(SP) == 999999); +SP(Inan) = NaN; +[Inan] = find(abs(p) == 99999 | abs(p) == 999999); +p(Inan) = NaN; +[Inan] = find(abs(long) == 9999 | abs(long) == 99999); +long(Inan) = NaN; +[Inan] = find(abs(lat) == 9999 | abs(lat) == 99999); +lat(Inan) = NaN; + +if ~isempty(find(p < -1.5 | p > 12000)) + error('gsw_Sstar_from_SP: pressure is out of range') +end +if ~isempty(find(long < 0 | long > 360)) + error('gsw_Sstar_from_SP: longitude is out of range') +end +if ~isempty(find(abs(lat) > 90)) + error('gsw_Sstar_from_SP: latitude is out of range') +end + %-------------------------------------------------------------------------- % Start of the calculation %-------------------------------------------------------------------------- -% + % These few lines ensure that SP is non-negative. [I_neg_SP] = find(SP < 0); if ~isempty(I_neg_SP) SP(I_neg_SP) = 0; end -r1 = 0.35; +r_1 = 0.35; -inds = find(isfinite(SP)); +[Iocean] = find(~isnan(SP.*p.*lat.*long)); Sstar = nan(size(SP)); -dSA = nan(size(SP)); +SAAR = nan(size(SP)); in_ocean = nan(size(SP)); -[dSA(inds), in_ocean(inds)] = gsw_delta_SA(p(inds),long(inds),lat(inds)); +[SAAR(Iocean), in_ocean(Iocean)] = gsw_SAAR(p(Iocean),long(Iocean),lat(Iocean)); -Sstar(inds) = (35.16504/35)*SP(inds) - r1* dSA(inds); +Sstar(Iocean) = (35.16504/35)*SP(Iocean).*(1 - r_1.*SAAR(Iocean)); %In the Baltic Sea, Sstar = SA. -Sstar_baltic(inds) = gsw_SA_from_SP_Baltic(SP(inds),long(inds),lat(inds)); +Sstar_baltic(Iocean) = gsw_SA_from_SP_Baltic(SP(Iocean),long(Iocean),lat(Iocean)); -indsbaltic = find(~isnan(Sstar_baltic(inds))); +Ibaltic = find(~isnan(Sstar_baltic(Iocean))); -Sstar(inds(indsbaltic)) = Sstar_baltic(inds(indsbaltic)); +Sstar(Iocean(Ibaltic)) = Sstar_baltic(Iocean(Ibaltic)); if transposed - Sstar = Sstar'; - in_ocean = in_ocean'; + Sstar = Sstar.'; + in_ocean = in_ocean.'; end end diff --git a/Toolbox/gsw_T0.m b/Toolbox/gsw_T0.m new file mode 100644 index 0000000..9e90c52 --- /dev/null +++ b/Toolbox/gsw_T0.m @@ -0,0 +1,34 @@ +function T0 = gsw_T0 + +% gsw_T0 Celcius zero point +%========================================================================== +% +% USAGE: +% T0 = gsw_T0 +% +% DESCRIPTION: +% The Celcius zero point; 273.15 K. That is T = t + T0 where T is the +% Absolute Temperature (in degrees K) and t is temperature in degrees C. +% +% OUTPUT: +% T0 = the Celcius zero point. [ K ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. +% See Table D.1 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +T0 = 273.15; + +end diff --git a/Toolbox/gsw_Turner_Rsubrho_CT25.m b/Toolbox/gsw_Turner_Rsubrho.m similarity index 53% rename from Toolbox/gsw_Turner_Rsubrho_CT25.m rename to Toolbox/gsw_Turner_Rsubrho.m index df361f2..89487ef 100644 --- a/Toolbox/gsw_Turner_Rsubrho_CT25.m +++ b/Toolbox/gsw_Turner_Rsubrho.m @@ -1,10 +1,10 @@ -function [Tu, Rsubrho, p_mid, in_funnel] = gsw_Turner_Rsubrho_CT25(SA,CT,p) +function [Tu, Rsubrho, p_mid] = gsw_Turner_Rsubrho(SA,CT,p) -% gsw_Turner_Rsubrho_CT25 Turner angle & Rsubrho +% gsw_Turner_Rsubrho Turner angle & Rsubrho (48-term equation) %========================================================================== % % USAGE: -% [Tu, Rsubrho, p_mid, in_funnel] = gsw_Turner_Rsubrho_CT25(SA,CT,p) +% [Tu, Rsubrho, p_mid] = gsw_Turner_Rsubrho(SA,CT,p) % % DESCRIPTION: % Calculates the Turner angle and the Rsubrho as a function of pressure @@ -13,35 +13,41 @@ % and Absolute Salinity to the vertical stability (the square of the % Brunt-Vaisala Frequency squared, N^2). Tu and Rsubrho are evaluated at % the mid pressure between the individual data points in the vertical. -% This function uses computationally-efficient 25-term expression for -% density in terms of SA, CT and p (McDougall et al., 2010). +% This function uses computationally-efficient 48-term expression for +% density in terms of SA, CT and p (McDougall et al., 2011). Note that +% in the double-diffusive literature, papers concerned with the +% "diffusive" form of double-diffusive convection often define the +% stability ratio as the reciprocal of what is defined here as the +% stability ratio. +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) -% SA & CT need to have the same dimensions, -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions, +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. % % OUTPUT: -% Tu = Turner angle, on the same (M-1)xN grid as p_mid. -% Turner angle has units of: [ degrees of rotation ] -% Rsubrho = Stability Ratio, on the same (M-1)xN grid as p_mid. -% Rsubrho is dimensionless. [ unitless ] -% p_mid = mid pressure between the indivual points of the p grid. -% That is, p_mid is on a (M-1)xN grid in the vertical. -% p_mid has units of: [ dbar ] -% in_funnel = 0, if (SA, CT and p) are outside the "funnel" -% = 1, if (SA, CT and p) are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). +% Tu = Turner angle, on the same (M-1)xN grid as p_mid. +% Turner angle has units of: [ degrees of rotation ] +% Rsubrho = Stability Ratio, on the same (M-1)xN grid as p_mid. +% Rsubrho is dimensionless. [ unitless ] +% p_mid = mid pressure between the indivual points of the p grid. +% That is, p_mid is on a (M-1)xN grid in the vertical. +% p_mid has units of: [ dbar ] % % AUTHOR: -% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (26th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -50,11 +56,10 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See Eqns. (3.15.1) and (3.16.1) of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -65,11 +70,11 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_Turner_Rsubrho_CT25: Requires three inputs') + error('gsw_Turner_Rsubrho: Requires three inputs') end %if -if ~(nargout == 3 | nargout == 4) - error('gsw_Turner_Rsubrho_CT25: Requires three or four outputs') +if ~(nargout == 3 ) + error('gsw_Turner_Rsubrho: Requires three outputs') end %if [ms,ns] = size(SA); @@ -77,7 +82,7 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns ) - error('gsw_Turner_Rsubrho_CT25: SA and CT must have same dimensions') + error('gsw_Turner_Rsubrho: SA and CT must have same dimensions') end if (ms*ns == 1) @@ -90,18 +95,21 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (np == ms) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_Turner_Rsubrho_CT25: Inputs array dimensions arguments do not agree') + error('gsw_Turner_Rsubrho: Inputs array dimensions arguments do not agree') end %if [mp,np] = size(p); if ms == 1 - SA = SA'; - CT = CT'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -116,7 +124,6 @@ if ~isempty(I_neg_SA) SA(I_neg_SA) = 0; end -in_funnel = gsw_infunnel(SA,CT,p); Ishallow = 1:(mp-1); Ideep = 2:mp; @@ -127,19 +134,19 @@ dSA = SA(Ishallow,:) - SA(Ideep,:); dCT = CT(Ishallow,:) - CT(Ideep,:); -[dummy, alpha, beta, dummy2] = gsw_rho_alpha_beta_CT25(SA_mid,CT_mid,p_mid); +[dummy, alpha, beta] = gsw_rho_alpha_beta(SA_mid,CT_mid,p_mid); %-------------------------------------------------------------------------- % This function evaluates Tu and Rsubrho using the computationally-efficient -% 25-term expression for density in terms of SA, CT and p. If one wanted to +% 48-term expression for density in terms of SA, CT and p. If one wanted to % compute Tu and Rsubrho using the full TEOS-10 Gibbs function expression % for density, the following lines of code would do that. % % pt_mid = gsw_pt_from_CT(SA_mid,CT_mid); % pr0 = zeros(size(SA_mid)); % t_mid = gsw_pt_from_t(SA_mid,pt_mid,pr0,p_mid); -% beta = gsw_beta_const_CT(SA_mid,t_mid,p_mid); -% alpha = gsw_alpha_wrt_CT(SA_mid,t_mid,p_mid); +% beta = gsw_beta_const_CT_t_exact(SA_mid,t_mid,p_mid); +% alpha = gsw_alpha_wrt_CT_t_exact(SA_mid,t_mid,p_mid); % % --------------This is the end of the alternative code-------------------- @@ -153,10 +160,9 @@ end if transposed - Tu = Tu'; - Rsubrho = Rsubrho'; - p_mid = p_mid'; - in_funnel = in_funnel'; + Tu = Tu.'; + Rsubrho = Rsubrho.'; + p_mid = p_mid.'; end end diff --git a/Toolbox/gsw_adiabatic_lapse_rate.m b/Toolbox/gsw_adiabatic_lapse_rate_t_exact.m similarity index 60% rename from Toolbox/gsw_adiabatic_lapse_rate.m rename to Toolbox/gsw_adiabatic_lapse_rate_t_exact.m index 3957979..b4434da 100644 --- a/Toolbox/gsw_adiabatic_lapse_rate.m +++ b/Toolbox/gsw_adiabatic_lapse_rate_t_exact.m @@ -1,32 +1,32 @@ -function adiabatic_lapse_rate = gsw_adiabatic_lapse_rate(SA,t,p) +function adiabatic_lapse_rate_t_exact = gsw_adiabatic_lapse_rate_t_exact(SA,t,p) -% gsw_adiabatic_lapse_rate adiabatic lapse rate +% gsw_adiabatic_lapse_rate_t_exact adiabatic lapse rate %========================================================================== % % USAGE: -% adiabatic_lapse_rate = gsw_adiabatic_lapse_rate(SA,t,p) +% adiabatic_lapse_rate_t_exact = gsw_adiabatic_lapse_rate_t_exact(SA,t,p) % % DESCRIPTION: % Calculates the adiabatic lapse rate of sea water % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% adiabatic_lapse_rate = adiabatic lapse rate [ K/Pa ] +% adiabatic_lapse_rate_t_exact = adiabatic lapse rate [ K/Pa ] % Note. The output is in unit of degress Celsius per Pa, % (or equivilently K/Pa) not in units of K/dbar. % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -44,15 +44,15 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_adiabatic_lapse_rate: Requires three inputs') -end %if + error('gsw_adiabatic_lapse_rate_t_exact: Requires three inputs') +end [ms,ns] = size(SA); [mt,nt] = size(t); [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_adiabatic_lapse_rate: SA and t must have same dimensions') + error('gsw_adiabatic_lapse_rate_t_exact: SA and t must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -61,16 +61,19 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_adiabatic_lapse_rate: Inputs array dimensions arguments do not agree') + error('gsw_adiabatic_lapse_rate_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -84,10 +87,10 @@ n1 = 1; n2 = 2; -adiabatic_lapse_rate = - gsw_gibbs(n0,n1,n1,SA,t,p)./(gsw_gibbs(n0,n2,n0,SA,t,p)); +adiabatic_lapse_rate_t_exact = -gsw_gibbs(n0,n1,n1,SA,t,p)./(gsw_gibbs(n0,n2,n0,SA,t,p)); if transposed - adiabatic_lapse_rate = adiabatic_lapse_rate'; + adiabatic_lapse_rate_t_exact = adiabatic_lapse_rate_t_exact.'; end end diff --git a/Toolbox/gsw_alpha.m b/Toolbox/gsw_alpha.m new file mode 100644 index 0000000..94ef948 --- /dev/null +++ b/Toolbox/gsw_alpha.m @@ -0,0 +1,225 @@ +function alpha = gsw_alpha(SA,CT,p) + +% gsw_alpha thermal expansion coefficient with respect to +% Conservative Temperature (48-term equation) +%========================================================================== +% +% USAGE: +% alpha = gsw_alpha(SA,CT,p) +% +% DESCRIPTION: +% Calculates the thermal expansion coefficient of seawater with respect to +% Conservative Temperature using the computationally-efficient 48-term +% expression for density in terms of SA, CT and p (McDougall et al., 2011) +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% alpha = thermal expansion coefficient [ 1/K ] +% with respect to Conservative Temperature +% +% AUTHOR: +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (23rd March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (2.18.3) of this TEOS-10 manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_alpha: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_alpha: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_alpha: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +v01 = 9.998420897506056e+2; +v02 = 2.839940833161907; +v03 = -3.147759265588511e-2; +v04 = 1.181805545074306e-3; +v05 = -6.698001071123802; +v06 = -2.986498947203215e-2; +v07 = 2.327859407479162e-4; +v08 = -3.988822378968490e-2; +v09 = 5.095422573880500e-4; +v10 = -1.426984671633621e-5; +v11 = 1.645039373682922e-7; +v12 = -2.233269627352527e-2; +v13 = -3.436090079851880e-4; +v14 = 3.726050720345733e-6; +v15 = -1.806789763745328e-4; +v16 = 6.876837219536232e-7; +v17 = -3.087032500374211e-7; +v18 = -1.988366587925593e-8; +v19 = -1.061519070296458e-11; +v20 = 1.550932729220080e-10; +v21 = 1.0; +v22 = 2.775927747785646e-3; +v23 = -2.349607444135925e-5; +v24 = 1.119513357486743e-6; +v25 = 6.743689325042773e-10; +v26 = -7.521448093615448e-3; +v27 = -2.764306979894411e-5; +v28 = 1.262937315098546e-7; +v29 = 9.527875081696435e-10; +v30 = -1.811147201949891e-11; +v31 = -3.303308871386421e-5; +v32 = 3.801564588876298e-7; +v33 = -7.672876869259043e-9; +v34 = -4.634182341116144e-11; +v35 = 2.681097235569143e-12; +v36 = 5.419326551148740e-6; +v37 = -2.742185394906099e-5; +v38 = -3.212746477974189e-7; +v39 = 3.191413910561627e-9; +v40 = -1.931012931541776e-12; +v41 = -1.105097577149576e-7; +v42 = 6.211426728363857e-10; +v43 = -1.119011592875110e-10; +v44 = -1.941660213148725e-11; +v45 = -1.864826425365600e-14; +v46 = 1.119522344879478e-14; +v47 = -1.200507748551599e-15; +v48 = 6.057902487546866e-17; + +a01 = 2.839940833161907; +a02 = -6.295518531177023e-2; +a03 = 3.545416635222918e-3; +a04 = -2.986498947203215e-2; +a05 = 4.655718814958324e-4; +a06 = 5.095422573880500e-4; +a07 = -2.853969343267241e-5; +a08 = 4.935118121048767e-7; +a09 = -3.436090079851880e-4; +a10 = 7.452101440691467e-6; +a11 = 6.876837219536232e-7; +a12 = -1.988366587925593e-8; +a13 = -2.123038140592916e-11; + +a14 = 2.775927747785646e-3; +a15 = -4.699214888271850e-5; +a16 = 3.358540072460230e-6; +a17 = 2.697475730017109e-9; +a18 = -2.764306979894411e-5; +a19 = 2.525874630197091e-7; +a20 = 2.858362524508931e-9; +a21 = -7.244588807799565e-11; +a22 = 3.801564588876298e-7; +a23 = -1.534575373851809e-8; +a24 = -1.390254702334843e-10; +a25 = 1.072438894227657e-11; +a26 = -3.212746477974189e-7; +a27 = 6.382827821123254e-9; +a28 = -5.793038794625329e-12; +a29 = 6.211426728363857e-10; +a30 = -1.941660213148725e-11; +a31 = -3.729652850731201e-14; +a32 = 1.119522344879478e-14; +a33 = 6.057902487546866e-17; + +sqrtSA = sqrt(SA); + +v_hat_denominator = v01 + CT.*(v02 + CT.*(v03 + v04*CT)) ... + + SA.*(v05 + CT.*(v06 + v07*CT) ... + + sqrtSA.*(v08 + CT.*(v09 + CT.*(v10 + v11*CT)))) ... + + p.*(v12 + CT.*(v13 + v14*CT) + SA.*(v15 + v16*CT) ... + + p.*(v17 + CT.*(v18 + v19*CT) + v20*SA)); + +v_hat_numerator = v21 + CT.*(v22 + CT.*(v23 + CT.*(v24 + v25*CT))) ... + + SA.*(v26 + CT.*(v27 + CT.*(v28 + CT.*(v29 + v30*CT))) + v36*SA ... + + sqrtSA.*(v31 + CT.*(v32 + CT.*(v33 + CT.*(v34 + v35*CT))))) ... + + p.*(v37 + CT.*(v38 + CT.*(v39 + v40*CT)) ... + + SA.*(v41 + v42*CT) ... + + p.*(v43 + CT.*(v44 + v45*CT + v46*SA) ... + + p.*(v47 + v48*CT))); + +spec_vol = v_hat_numerator./v_hat_denominator; + +dvhatden_dCT = a01 + CT.*(a02 + a03*CT) ... + + SA.*(a04 + a05*CT ... + + sqrtSA.*(a06 + CT.*(a07 + a08*CT))) ... + + p.*(a09 + a10*CT + a11*SA ... + + p.*(a12 + a13*CT)); + +dvhatnum_dCT = a14 + CT.*(a15 + CT.*(a16 + a17*CT)) ... + + SA.*(a18 + CT.*(a19 + CT.*(a20 + a21*CT)) ... + + sqrtSA.*(a22 + CT.*(a23 + CT.*(a24 + a25*CT)))) ... + + p.*(a26 + CT.*(a27 + a28*CT) + a29*SA ... + + p.*(a30 + a31*CT + a32*SA + a33*p)); + +alpha = (dvhatnum_dCT - dvhatden_dCT.*spec_vol)./v_hat_numerator; + +if transposed + alpha = alpha.'; +end + +end diff --git a/Toolbox/gsw_alpha_CT.m b/Toolbox/gsw_alpha_CT.m new file mode 100644 index 0000000..f81e52b --- /dev/null +++ b/Toolbox/gsw_alpha_CT.m @@ -0,0 +1,111 @@ +function alpha_CT = gsw_alpha_CT(SA,CT,p) + +% gsw_alpha_CT thermal expansion coefficient with respect to +% Conservative Temperature (48-term equation) +%========================================================================== +% +% USAGE: +% alpha_CT = gsw_alpha_CT(SA,CT,p), or equivalently +% alpha = gsw_alpha(SA,CT,p) +% +% Note that gsw_alpha(SA,CT,p) is identical to gsw_alpha_CT(SA,CT,p). +% The extra "_CT" emphasises that the input temperature is Conservative +% Temperature, but the extra "_CT" part of the function name is not +% needed. +% +% DESCRIPTION: +% Calculates the thermal expansion coefficient of seawater with respect to +% Conservative Temperature using the computationally-efficient 48-term +% expression for density in terms of SA, CT and p (McDougall et al., 2011) +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% alpha_CT = thermal expansion coefficient [ 1/K ] +% with respect to Conservative Temperature +% +% AUTHOR: +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (23rd March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (2.18.3) of this TEOS-10 manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_alpha_CT: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_alpha_CT: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_alpha_CT: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +alpha_CT = gsw_alpha(SA,CT,p); + +if transposed + alpha_CT = alpha_CT.'; +end + +end diff --git a/Toolbox/gsw_alpha_CT_exact.m b/Toolbox/gsw_alpha_CT_exact.m new file mode 100644 index 0000000..7359f58 --- /dev/null +++ b/Toolbox/gsw_alpha_CT_exact.m @@ -0,0 +1,105 @@ +function alpha_CT_exact = gsw_alpha_CT_exact(SA,CT,p) + +% gsw_alpha_CT_exact thermal expansion coefficient +% with respect to Conservative Temperature +%========================================================================== +% +% USAGE: +% alpha_CT_exact = gsw_alpha_CT_exact(SA,CT,p) +% +% DESCRIPTION: +% Calculates the thermal expansion coefficient of seawater with respect to +% Conservative Temperature from Absolute Salinity and Conservative +% Temperature. +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely gsw_alpha_wrt_CT(SA,CT,p) +% which uses the computationally efficient 48-term expression for density +% in terms of SA, CT and p (McDougall et al., (2011)). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% alpha_CT_exact = thermal expansion coefficient [ 1/K ] +% with respect to Conservative Temperature +% +% AUTHOR: +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (23rd March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (2.18.3) of this TEOS-10 manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_alpha_CT_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_alpha_CT_exact: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_alpha_CT_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +t = gsw_t_from_CT(SA,CT,p); +alpha_CT_exact = gsw_alpha_wrt_CT_t_exact(SA,t,p); + +if transposed + alpha_CT_exact = alpha_CT_exact.'; +end + +end diff --git a/Toolbox/gsw_alpha_wrt_CT.m b/Toolbox/gsw_alpha_wrt_CT_t_exact.m similarity index 72% rename from Toolbox/gsw_alpha_wrt_CT.m rename to Toolbox/gsw_alpha_wrt_CT_t_exact.m index 7112023..ad83cc9 100644 --- a/Toolbox/gsw_alpha_wrt_CT.m +++ b/Toolbox/gsw_alpha_wrt_CT_t_exact.m @@ -1,11 +1,11 @@ -function alpha_wrt_CT = gsw_alpha_wrt_CT(SA,t,p) +function alpha_wrt_CT_t_exact = gsw_alpha_wrt_CT_t_exact(SA,t,p) -% gsw_alpha_wrt_CT thermal expansion coefficient -% with respect to Conservative temperature +% gsw_alpha_wrt_CT_t_exact thermal expansion coefficient +% with respect to Conservative Temperature %========================================================================== % % USAGE: -% alpha_wrt_CT = gsw_alpha_wrt_CT(SA,t,p) +% alpha_wrt_CT_t_exact = gsw_alpha_wrt_CT_t_exact(SA,t,p) % % DESCRIPTION: % Calculates the thermal expansion coefficient of seawater with respect to @@ -15,19 +15,19 @@ % SA = Absolute Salinity [ g/kg ] % t = in-situ temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% alpha_wrt_CT = thermal expansion coefficient [ 1/K ] -% with respect to Conservative Temperature +% alpha_wrt_CT_t_exact = thermal expansion coefficient [ 1/K ] +% with respect to Conservative Temperature % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -45,7 +45,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_alpha_wrt_CT: Requires three inputs') + error('gsw_alpha_wrt_CT_t_exact: Requires three inputs') end %if [ms,ns] = size(SA); @@ -53,7 +53,7 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_alpha_wrt_CT: SA and t must have same dimensions') + error('gsw_alpha_wrt_CT_t_exact: SA and t must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -63,18 +63,18 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_alpha_wrt_CT: Inputs array dimensions arguments do not agree') + error('gsw_alpha_wrt_CT_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -94,10 +94,10 @@ factor = -cp0./((273.15+pt0).*gsw_gibbs(n0,n2,n0,SA,t,p)); -alpha_wrt_CT = factor.*(gsw_gibbs(n0,n1,n1,SA,t,p)./gsw_gibbs(n0,n0,n1,SA,t,p)); +alpha_wrt_CT_t_exact = factor.*(gsw_gibbs(n0,n1,n1,SA,t,p)./gsw_gibbs(n0,n0,n1,SA,t,p)); if transposed - alpha_wrt_CT = alpha_wrt_CT'; + alpha_wrt_CT_t_exact = alpha_wrt_CT_t_exact.'; end end diff --git a/Toolbox/gsw_alpha_wrt_pt.m b/Toolbox/gsw_alpha_wrt_pt_t_exact.m similarity index 70% rename from Toolbox/gsw_alpha_wrt_pt.m rename to Toolbox/gsw_alpha_wrt_pt_t_exact.m index b492554..f434141 100644 --- a/Toolbox/gsw_alpha_wrt_pt.m +++ b/Toolbox/gsw_alpha_wrt_pt_t_exact.m @@ -1,11 +1,11 @@ -function alpha_wrt_pt = gsw_alpha_wrt_pt(SA,t,p) +function alpha_wrt_pt_t_exact = gsw_alpha_wrt_pt_t_exact(SA,t,p) -% gsw_alpha_wrt_pt thermal expansion coefficient +% gsw_alpha_wrt_pt_t_exact thermal expansion coefficient % with respect to potential temperature %========================================================================== % % USAGE: -% alpha_wrt_pt = gsw_alpha_wrt_pt(SA,t,p) +% alpha_wrt_pt_t_exact = gsw_alpha_wrt_pt_t_exact(SA,t,p) % % DESCRIPTION: % Calculates the thermal expansion coefficient of seawater with respect to @@ -15,20 +15,20 @@ % SA = Absolute Salinity [ g/kg ] % t = in-situ temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% alpha_wrt_pt = thermal expansion coefficient [ 1/K ] -% with respect to potential temperature, -% and with a reference pressure of zero dbar. +% alpha_wrt_pt_t_exact = thermal expansion coefficient [ 1/K ] +% with respect to potential temperature, +% with a reference pressure of zero dbar. % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -46,7 +46,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_alpha_wrt_pt: Requires three inputs') + error('gsw_alpha_wrt_pt_t_exact: Requires three inputs') end %if [ms,ns] = size(SA); @@ -54,7 +54,7 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_alpha_wrt_pt: SA and t must have same dimensions') + error('gsw_alpha_wrt_pt_t_exact: SA and t must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -64,18 +64,18 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_alpha_wrt_pt: Inputs array dimensions arguments do not agree') + error('gsw_alpha_wrt_pt_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -94,10 +94,10 @@ factor = gsw_gibbs(n0,n2,n0,SA,pt0,pr0)./gsw_gibbs(n0,n2,n0,SA,t,p); -alpha_wrt_pt = factor.*(gsw_gibbs(n0,n1,n1,SA,t,p)./gsw_gibbs(n0,n0,n1,SA,t,p)); +alpha_wrt_pt_t_exact = factor.*(gsw_gibbs(n0,n1,n1,SA,t,p)./gsw_gibbs(n0,n0,n1,SA,t,p)); if transposed - alpha_wrt_pt = alpha_wrt_pt'; + alpha_wrt_pt_t_exact = alpha_wrt_pt_t_exact.'; end end diff --git a/Toolbox/gsw_alpha_wrt_t.m b/Toolbox/gsw_alpha_wrt_t_exact.m similarity index 65% rename from Toolbox/gsw_alpha_wrt_t.m rename to Toolbox/gsw_alpha_wrt_t_exact.m index 6fc5992..0ca59a5 100644 --- a/Toolbox/gsw_alpha_wrt_t.m +++ b/Toolbox/gsw_alpha_wrt_t_exact.m @@ -1,11 +1,11 @@ -function alpha_wrt_t = gsw_alpha_wrt_t(SA,t,p) +function alpha_wrt_t_exact = gsw_alpha_wrt_t_exact(SA,t,p) -% gsw_alpha_wrt_t thermal expansion coefficient +% gsw_alpha_wrt_t_exact thermal expansion coefficient % with respect to in-situ temperature %========================================================================== % % USAGE: -% alpha_wrt_t = gsw_alpha_wrt_t(SA,t,p) +% alpha_wrt_t_exact = gsw_alpha_wrt_t_exact(SA,t,p) % % DESCRIPTION: % Calculates the thermal expansion coefficient of seawater with respect to @@ -15,32 +15,26 @@ % SA = Absolute Salinity [ g/kg ] % t = in-situ temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% alpha_wrt_t = thermal expansion coefficient [ 1/K ] -% with respect to in-situ temperature +% alpha_wrt_t_exact = thermal expansion coefficient [ 1/K ] +% with respect to in-situ temperature % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of % seawater - 2010: Calculation and use of thermodynamic properties. % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. -% See Eqn. (2.18.1) of this TEOS-10 manual. -% -% McDougall, T.J., D.R. Jackett and F.J. Millero, 2010: An algorithm -% for estimating Absolute Salinity in the global ocean. Submitted to -% Ocean Science. A preliminary version is available at Ocean Sci. -% Discuss., 6, 215-242. -% http://www.ocean-sci-discuss.net/6/215/2009/osd-6-215-2009-print.pdf +% See Eqn. (2.18.1) of this TEOS-10 manual. % % The software is available from http://www.TEOS-10.org % @@ -51,7 +45,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_alpha_wrt_t: Requires three inputs') + error('gsw_alpha_wrt_t_exact: Requires three inputs') end %if [ms,ns] = size(SA); @@ -59,7 +53,7 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_alpha_wrt_t: SA and t must have same dimensions') + error('gsw_alpha_wrt_t_exact: SA and t must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -69,18 +63,18 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_alpha_wrt_t: Inputs array dimensions arguments do not agree') + error('gsw_alpha_wrt_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -93,10 +87,10 @@ n0 = 0; n1 = 1; -alpha_wrt_t = gsw_gibbs(n0,n1,n1,SA,t,p)./gsw_gibbs(n0,n0,n1,SA,t,p); +alpha_wrt_t_exact = gsw_gibbs(n0,n1,n1,SA,t,p)./gsw_gibbs(n0,n0,n1,SA,t,p); if transposed - alpha_wrt_t = alpha_wrt_t'; + alpha_wrt_t_exact = alpha_wrt_t_exact.'; end end diff --git a/Toolbox/gsw_atomic_weight.m b/Toolbox/gsw_atomic_weight.m new file mode 100644 index 0000000..ba10e59 --- /dev/null +++ b/Toolbox/gsw_atomic_weight.m @@ -0,0 +1,42 @@ +function atomic_weight = gsw_atomic_weight + +% gsw_atomic_weight mole-weighted atomic weight of sea salt +%========================================================================== +% +% USAGE: +% atomic_weight = gsw_atomic_weight +% +% DESCRIPTION: +% This function returns the mole-weighted atomic weight of sea salt of +% Reference Composition, which is 31.4038218 g/mol. This has been +% defined as part of the Reference-Composition Salinity Scale of 2008 +% (Millero et al., 2008). +% +% OUTPUT: +% atomic_weight = mole-weighted atomic weight of sea salt of Reference +% Composition [ g/mol ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Table D.4 of this TEOS-10 Manual. +% +% Millero, F. J., R. Feistel, D. G. Wright, and T. J. McDougall, 2008: +% The composition of Standard Seawater and the definition of the +% Reference-Composition Salinity Scale, Deep-Sea Res. I, 55, 50-72. +% See Eqn. (5.3) of this paper. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +atomic_weight = 31.4038218; + +end diff --git a/Toolbox/gsw_beta.m b/Toolbox/gsw_beta.m new file mode 100644 index 0000000..4fe118c --- /dev/null +++ b/Toolbox/gsw_beta.m @@ -0,0 +1,212 @@ +function beta = gsw_beta(SA,CT,p) + +% gsw_beta saline contraction coefficient at constant +% Conservative Temperature (48-term equation) +%========================================================================== +% +% USAGE: +% beta = gsw_beta(SA,CT,p) +% +% DESCRIPTION: +% Calculates the saline (i.e. haline) contraction coefficient of seawater +% at constant Conservative Temperature using the computationally-efficient +% 48-term expression for density in terms of SA, CT and p +% (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% beta = saline contraction coefficient [ kg/g ] +% at constant Conservative Temperature +% +% AUTHOR: +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (23rd March, 2010) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (2.19.3) of this TEOS-10 manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_beta: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_beta: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_beta: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +v01 = 9.998420897506056e+2; +v02 = 2.839940833161907; +v03 = -3.147759265588511e-2; +v04 = 1.181805545074306e-3; +v05 = -6.698001071123802; +v06 = -2.986498947203215e-2; +v07 = 2.327859407479162e-4; +v08 = -3.988822378968490e-2; +v09 = 5.095422573880500e-4; +v10 = -1.426984671633621e-5; +v11 = 1.645039373682922e-7; +v12 = -2.233269627352527e-2; +v13 = -3.436090079851880e-4; +v14 = 3.726050720345733e-6; +v15 = -1.806789763745328e-4; +v16 = 6.876837219536232e-7; +v17 = -3.087032500374211e-7; +v18 = -1.988366587925593e-8; +v19 = -1.061519070296458e-11; +v20 = 1.550932729220080e-10; +v21 = 1.0; +v22 = 2.775927747785646e-3; +v23 = -2.349607444135925e-5; +v24 = 1.119513357486743e-6; +v25 = 6.743689325042773e-10; +v26 = -7.521448093615448e-3; +v27 = -2.764306979894411e-5; +v28 = 1.262937315098546e-7; +v29 = 9.527875081696435e-10; +v30 = -1.811147201949891e-11; +v31 = -3.303308871386421e-5; +v32 = 3.801564588876298e-7; +v33 = -7.672876869259043e-9; +v34 = -4.634182341116144e-11; +v35 = 2.681097235569143e-12; +v36 = 5.419326551148740e-6; +v37 = -2.742185394906099e-5; +v38 = -3.212746477974189e-7; +v39 = 3.191413910561627e-9; +v40 = -1.931012931541776e-12; +v41 = -1.105097577149576e-7; +v42 = 6.211426728363857e-10; +v43 = -1.119011592875110e-10; +v44 = -1.941660213148725e-11; +v45 = -1.864826425365600e-14; +v46 = 1.119522344879478e-14; +v47 = -1.200507748551599e-15; +v48 = 6.057902487546866e-17; + +b01 = -6.698001071123802; +b02 = -2.986498947203215e-2; +b03 = 2.327859407479162e-4; +b04 = -5.983233568452735e-2; +b05 = 7.643133860820750e-4; +b06 = -2.140477007450431e-5; +b07 = 2.467559060524383e-7; +b08 = -1.806789763745328e-4; +b09 = 6.876837219536232e-7; +b10 = 1.550932729220080e-10; +b11 = -7.521448093615448e-3; +b12 = -2.764306979894411e-5; +b13 = 1.262937315098546e-7; +b14 = 9.527875081696435e-10; +b15 = -1.811147201949891e-11; +b16 = -4.954963307079632e-5; +b17 = 5.702346883314446e-7; +b18 = -1.150931530388857e-8; +b19 = -6.951273511674217e-11; +b20 = 4.021645853353715e-12; +b21 = 1.083865310229748e-5; +b22 = -1.105097577149576e-7; +b23 = 6.211426728363857e-10; +b24 = 1.119522344879478e-14; + +sqrtSA = sqrt(SA); + +v_hat_denominator = v01 + CT.*(v02 + CT.*(v03 + v04*CT)) ... + + SA.*(v05 + CT.*(v06 + v07*CT) ... + + sqrtSA.*(v08 + CT.*(v09 + CT.*(v10 + v11*CT)))) ... + + p.*(v12 + CT.*(v13 + v14*CT) + SA.*(v15 + v16*CT) ... + + p.*(v17 + CT.*(v18 + v19*CT) + v20*SA)); + +v_hat_numerator = v21 + CT.*(v22 + CT.*(v23 + CT.*(v24 + v25*CT))) ... + + SA.*(v26 + CT.*(v27 + CT.*(v28 + CT.*(v29 + v30*CT))) + v36*SA ... + + sqrtSA.*(v31 + CT.*(v32 + CT.*(v33 + CT.*(v34 + v35*CT))))) ... + + p.*(v37 + CT.*(v38 + CT.*(v39 + v40*CT)) ... + + SA.*(v41 + v42*CT) ... + + p.*(v43 + CT.*(v44 + v45*CT + v46*SA) ... + + p.*(v47 + v48*CT))); + +spec_vol = v_hat_numerator./v_hat_denominator; + +dvhatden_dSA = b01 + CT.*(b02 + b03*CT) ... + + sqrtSA.*(b04 + CT.*(b05 + CT.*(b06 + b07*CT))) ... + + p.*(b08 + b09*CT + b10*p) ; + +dvhatnum_dSA = b11 + CT.*(b12 + CT.*(b13 + CT.*(b14 + b15*CT))) ... + + sqrtSA.*(b16 + CT.*(b17 + CT.*(b18 + CT.*(b19 + b20*CT)))) + b21*SA ... + + p.*(b22 + CT.*(b23 + b24*p)); + +beta = (dvhatden_dSA.*spec_vol - dvhatnum_dSA)./v_hat_numerator; + +if transposed + beta = beta.'; +end + +end diff --git a/Toolbox/gsw_beta_CT.m b/Toolbox/gsw_beta_CT.m new file mode 100644 index 0000000..514979f --- /dev/null +++ b/Toolbox/gsw_beta_CT.m @@ -0,0 +1,112 @@ +function beta_CT = gsw_beta_CT(SA,CT,p) + +% gsw_beta_CT saline contraction coefficient at constant +% Conservative Temperature (48-term equation) +%========================================================================== +% +% USAGE: +% beta_CT = gsw_beta_CT(SA,CT,p), or equivalently +% beta = gsw_beta(SA,CT,p) +% +% Note that gsw_beta(SA,CT,p) is identical to gsw_beta_CT(SA,CT,p). +% The extra "_CT" emphasises that the input temperature is Conservative +% Temperature, but the extra "_CT" part of the function name is not +% needed. +% +% DESCRIPTION: +% Calculates the saline (i.e. haline) contraction coefficient of seawater +% at constant Conservative Temperature using the computationally-efficient +% 48-term expression for density in terms of SA, CT and p +% (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% beta_CT = saline contraction coefficient [ kg/g ] +% at constant Conservative Temperature +% +% AUTHOR: +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (23rd March, 2010) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (2.19.3) of this TEOS-10 manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_beta_CT: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_beta_CT: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_beta_CT: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +beta_CT = gsw_beta(SA,CT,p); + +if transposed + beta_CT = beta_CT.'; +end + +end diff --git a/Toolbox/gsw_beta_const_CT.m b/Toolbox/gsw_beta_CT_exact.m similarity index 50% rename from Toolbox/gsw_beta_const_CT.m rename to Toolbox/gsw_beta_CT_exact.m index 9ef6188..d194ae0 100644 --- a/Toolbox/gsw_beta_const_CT.m +++ b/Toolbox/gsw_beta_CT_exact.m @@ -1,33 +1,38 @@ -function beta_const_CT = gsw_beta_const_CT(SA,t,p) +function beta_CT_exact = gsw_beta_CT_exact(SA,CT,p) -% gsw_beta_const_CT saline contraction coefficient +% gsw_beta_CT_exact saline contraction coefficient % at constant Conservative temperature %========================================================================== % % USAGE: -% beta_const_CT = gsw_beta_const_CT(SA,t,p) +% beta_CT_exact = gsw_beta_CT_exact(SA,CT,p) % % DESCRIPTION: -% Calculates the saline (i. e. haline) contraction coefficient of seawater +% Calculates the saline (i.e. haline) contraction coefficient of seawater % at constant Conservative Temperature. -% +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely gsw_beta_const_CT(SA,CT,p) +% which uses the computationally efficient 48-term expression for density +% in terms of SA, CT and p (McDougall et al., (2011)). +% % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % -% SA & t need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. % % OUTPUT: -% beta_const_CT = saline contraction coefficient [ kg/g ] -% at constant Conservative Temperature +% beta_CT_exact = saline contraction coefficient [ kg/g ] +% at constant Conservative Temperature % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (23rd March, 2010) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -36,6 +41,11 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See Eqn. (2.19.3) of this TEOS-10 manual. % +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% % The software is available from http://www.TEOS-10.org % %========================================================================== @@ -45,15 +55,15 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_beta_const_CT: Requires three inputs') + error('gsw_beta_CT_exact: Requires three inputs') end %if [ms,ns] = size(SA); -[mt,nt] = size(t); +[mt,nt] = size(CT); [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_beta_const_CT: SA and t must have same dimensions') + error('gsw_beta_CT_exact: SA and CT must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -63,18 +73,18 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_beta_const_CT: Inputs array dimensions arguments do not agree') + error('gsw_beta_CT_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -84,25 +94,11 @@ % Start of the calculation %-------------------------------------------------------------------------- -n0 = 0; -n1 = 1; -n2 = 2; - -pr0 = zeros(size(p)); - -pt0 = gsw_pt0_from_t(SA,t,p); - -gp = gsw_gibbs(n0,n0,n1,SA,t,p); - -factora = gsw_gibbs(n1,n1,n0,SA,t,p) - gsw_gibbs(n1,n0,n0,SA,pt0,pr0)./(273.15+pt0); - -factor = factora./(gp.*gsw_gibbs(n0,n2,n0,SA,t,p)); - -beta_const_CT = gsw_gibbs(n0,n1,n1,SA,t,p).*factor - ... - gsw_gibbs(n1,n0,n1,SA,t,p)./gp; +t = gsw_t_from_CT(SA,CT,p); +beta_CT_exact = gsw_beta_const_CT_t_exact(SA,t,p); if transposed - beta_const_CT = beta_const_CT'; + beta_CT_exact = beta_CT_exact.'; end end diff --git a/Toolbox/gsw_beta_const_CT_t_exact.m b/Toolbox/gsw_beta_const_CT_t_exact.m new file mode 100644 index 0000000..f2264c9 --- /dev/null +++ b/Toolbox/gsw_beta_const_CT_t_exact.m @@ -0,0 +1,143 @@ +function beta_const_CT_t_exact = gsw_beta_const_CT_t_exact(SA,t,p) + +% gsw_beta_const_CT_t_exact saline contraction coefficient +% at constant Conservative temperature +%========================================================================== +% +% USAGE: +% beta_const_CT_t_exact = gsw_beta_const_CT_t_exact(SA,t,p) +% +% DESCRIPTION: +% Calculates the saline (i.e. haline) contraction coefficient of seawater +% at constant Conservative Temperature. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar) +% +% SA & t need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% +% OUTPUT: +% beta_const_CT_t_exact = saline contraction coefficient [ kg/g ] +% at constant Conservative Temperature +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (10th April 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (2.19.3) of this TEOS-10 manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_beta_const_CT_t_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_beta_const_CT_t_exact: SA and t must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_beta_const_CT_t_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +n0 = 0; +n1 = 1; +n2 = 2; +db2Pa = 1e-4; +sfac = 0.0248826675584615; % sfac = 1/(40*(35.16504/35)). + +pt0 = gsw_pt0_from_t(SA,t,p); + +x2 = sfac.*SA; +x = sqrt(x2); +y = 0.025*t; +y_pt = 0.025*pt0; +z = db2Pa*p; %Note.The input pressure (p) is sea pressure in units of dbar. + +g_SA_T_mod = 1187.3715515697959 + z.*(1458.233059470092 + ... + z.*(-687.913805923122 + z.*(249.375342232496 + z.*(-63.313928772146 + 14.09317606630898.*z)))) + ... + x.*(-1480.222530425046 + x.*(2175.341332000392 + x.*(-980.14153344888 + 220.542973797483.*x) + ... + y.*(-548.4580073635929 + y.*(592.4012338275047 + y.*(-274.2361238716608 + 49.9394019139016.*y))) - ... + 90.6734234051316.*z) + z.*(-525.876123559641 + (249.57717834054571 - 88.449193048287.*z).*z) + ... + y.*(-258.3988055868252 + z.*(2298.348396014856 + z.*(-325.1503575102672 + 153.8390924339484.*z)) + ... + y.*(-90.2046337756875 - 4142.8793862113125.*z + y.*(10.50720794170734 + 2814.78225133626.*z)))) + ... + y.*(3520.125411988816 + y.*(-1351.605895580406 + ... + y.*(731.4083582010072 + y.*(-216.60324087531103 + 25.56203650166196.*y) + ... + z.*(-2381.829935897496 + (597.809129110048 - 291.8983352012704.*z).*z)) + ... + z.*(4165.4688847996085 + z.*(-1229.337851789418 + (681.370187043564 - 66.7696405958478.*z).*z))) + ... + z.*(-3443.057215135908 + z.*(1349.638121077468 + ... + z.*(-713.258224830552 + (176.8161433232 - 31.68006188846728.*z).*z)))); +g_SA_T_mod = 0.5*sfac*0.025*g_SA_T_mod; + +g_SA_mod = 8645.36753595126 + ... + x.*(-7296.43987145382 + x.*(8103.20462414788 + ... + y_pt.*(2175.341332000392 + y_pt.*(-274.2290036817964 + ... + y_pt.*(197.4670779425016 + y_pt.*(-68.5590309679152 + 9.98788038278032.*y_pt)))) + ... + x.*(-5458.34205214835 - 980.14153344888.*y_pt + ... + x.*(2247.60742726704 - 340.1237483177863.*x + 220.542973797483.*y_pt))) + ... + y_pt.*(-1480.222530425046 + ... + y_pt.*(-129.1994027934126 + ... + y_pt.*(-30.0682112585625 + y_pt.*(2.626801985426835 ))))) + ... + y_pt.*(1187.3715515697959 + ... + y_pt.*(1760.062705994408 + y_pt.*(-450.535298526802 + ... + y_pt.*(182.8520895502518 + y_pt.*(-43.3206481750622 + 4.26033941694366.*y_pt))))); +g_SA_mod = 0.5*sfac*g_SA_mod; + +gp = gsw_gibbs(n0,n0,n1,SA,t,p); + +factora = g_SA_T_mod - g_SA_mod./(273.15+pt0); + +factor = factora./(gp.*gsw_gibbs(n0,n2,n0,SA,t,p)); + +beta_const_CT_t_exact = gsw_gibbs(n0,n1,n1,SA,t,p).*factor ... + - gsw_gibbs(n1,n0,n1,SA,t,p)./gp; + +if transposed + beta_const_CT_t_exact = beta_const_CT_t_exact.'; +end + +end diff --git a/Toolbox/gsw_beta_const_pt_t_exact.m b/Toolbox/gsw_beta_const_pt_t_exact.m new file mode 100644 index 0000000..df8b7ba --- /dev/null +++ b/Toolbox/gsw_beta_const_pt_t_exact.m @@ -0,0 +1,137 @@ +function beta_const_pt_t_exact = gsw_beta_const_pt_t_exact(SA,t,p) + +% gsw_beta_const_pt_t_exact saline contraction coefficient +% at constant potential temperature +%========================================================================== +% +% USAGE: +% beta_const_pt_t_exact = gsw_beta_const_pt_t_exact(SA,t,p) +% +% DESCRIPTION: +% Calculates the saline (i.e. haline) contraction coefficient of seawater +% at constant potential temperature with a reference pressure of 0 dbar. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & t need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% +% OUTPUT: +% beta_const_pt_t_exact = saline contraction coefficient [ kg/g ] +% at constant potential temperature +% and with a reference pressure of 0 dbar. +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (10th April 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (2.19.2) of this TEOS-10 manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_beta_const_pt_t_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_beta_const_pt_t_exact: SA and t must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_beta_const_pt_t_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +n0 = 0; +n1 = 1; +n2 = 2; +db2Pa = 1e-4; +sfac = 0.0248826675584615; % sfac = 1/(40*(35.16504/35)). + +pt0 = gsw_pt0_from_t(SA,t,p); + +x2 = sfac.*SA; +x = sqrt(x2); +y = 0.025*t; +y_pt = 0.025*pt0; +z = db2Pa*p; %Note.The input pressure (p) is sea pressure in units of dbar. + +g_SA_T_mod = 1187.3715515697959 + z.*(1458.233059470092 + ... + z.*(-687.913805923122 + z.*(249.375342232496 + z.*(-63.313928772146 + 14.09317606630898.*z)))) + ... + x.*(-1480.222530425046 + x.*(2175.341332000392 + x.*(-980.14153344888 + 220.542973797483.*x) + ... + y.*(-548.4580073635929 + y.*(592.4012338275047 + y.*(-274.2361238716608 + 49.9394019139016.*y))) - ... + 90.6734234051316.*z) + z.*(-525.876123559641 + (249.57717834054571 - 88.449193048287.*z).*z) + ... + y.*(-258.3988055868252 + z.*(2298.348396014856 + z.*(-325.1503575102672 + 153.8390924339484.*z)) + ... + y.*(-90.2046337756875 - 4142.8793862113125.*z + y.*(10.50720794170734 + 2814.78225133626.*z)))) + ... + y.*(3520.125411988816 + y.*(-1351.605895580406 + ... + y.*(731.4083582010072 + y.*(-216.60324087531103 + 25.56203650166196.*y) + ... + z.*(-2381.829935897496 + (597.809129110048 - 291.8983352012704.*z).*z)) + ... + z.*(4165.4688847996085 + z.*(-1229.337851789418 + (681.370187043564 - 66.7696405958478.*z).*z))) + ... + z.*(-3443.057215135908 + z.*(1349.638121077468 + ... + z.*(-713.258224830552 + (176.8161433232 - 31.68006188846728.*z).*z)))); +g_SA_T_mod = 0.5*sfac*0.025*g_SA_T_mod; + +g_SA_pt_mod = 1187.3715515697959 + ... + x.*(-1480.222530425046 + x.*(2175.341332000392 + x.*(-980.14153344888 + 220.542973797483.*x) + ... + y_pt.*(-548.4580073635929 + y_pt.*(592.4012338275047 + y_pt.*(-274.2361238716608 + 49.9394019139016.*y_pt)))) + ... + y_pt.*(-258.3988055868252 + ... + y_pt.*(-90.2046337756875 + y_pt.*(10.50720794170734)))) + ... + y_pt.*(3520.125411988816 + y_pt.*(-1351.605895580406 + ... + y_pt.*(731.4083582010072 + y_pt.*(-216.60324087531103 + 25.56203650166196.*y_pt)))); +g_SA_pt_mod = 0.5*sfac*0.025*g_SA_pt_mod; + +gp = gsw_gibbs(n0,n0,n1,SA,t,p); + +factor = (g_SA_T_mod - g_SA_pt_mod)./(gp.*gsw_gibbs(n0,n2,n0,SA,t,p)); + +beta_const_pt_t_exact = gsw_gibbs(n0,n1,n1,SA,t,p).*factor ... + - gsw_gibbs(n1,n0,n1,SA,t,p)./gp; + +if transposed + beta_const_pt_t_exact = beta_const_pt_t_exact.'; +end + +end diff --git a/Toolbox/gsw_beta_const_t.m b/Toolbox/gsw_beta_const_t_exact.m similarity index 71% rename from Toolbox/gsw_beta_const_t.m rename to Toolbox/gsw_beta_const_t_exact.m index d265fbd..fd8484b 100644 --- a/Toolbox/gsw_beta_const_t.m +++ b/Toolbox/gsw_beta_const_t_exact.m @@ -1,11 +1,11 @@ -function beta_const_t = gsw_beta_const_t(SA,t,p) +function beta_const_t_exact = gsw_beta_const_t_exact(SA,t,p) -% gsw_beta_const_t saline contraction coefficient +% gsw_beta_const_t_exact saline contraction coefficient % at constant in-situ temperature %========================================================================== % % USAGE: -% beta_const_t = gsw_beta_const_t(SA,t,p) +% beta_const_t_exact = gsw_beta_const_t_exact(SA,t,p) % % DESCRIPTION: % Calculates the saline (i.e. haline) contraction coefficient of seawater @@ -15,19 +15,19 @@ % SA = Absolute Salinity [ g/kg ] % t = in-situ temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% beta_const_t = saline contraction coefficient [ kg/g ] -% at constant in-situ temperature +% beta_const_t_exact = saline contraction coefficient [ kg/g ] +% at constant in-situ temperature % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -45,7 +45,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_beta_const_t: Requires three inputs') + error('gsw_beta_const_t_exact: Requires three inputs') end %if [ms,ns] = size(SA); @@ -53,7 +53,7 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_beta_const_t: SA and t must have same dimensions') + error('gsw_beta_const_t_exact: SA and t must have same dimensions') end if (mp == 1) & (np == 1) % p is a scalar - fill to size of SA @@ -63,18 +63,18 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_beta_const_t: Inputs array dimensions arguments do not agree') + error('gsw_beta_const_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -87,10 +87,10 @@ n0 = 0; n1 = 1; -beta_const_t = -gsw_gibbs(n1,n0,n1,SA,t,p)./gsw_gibbs(n0,n0,n1,SA,t,p); +beta_const_t_exact = -gsw_gibbs(n1,n0,n1,SA,t,p)./gsw_gibbs(n0,n0,n1,SA,t,p); if transposed - beta_const_t = beta_const_t'; + beta_const_t_exact = beta_const_t_exact.'; end end diff --git a/Toolbox/gsw_brineSA_CT.m b/Toolbox/gsw_brineSA_CT.m new file mode 100644 index 0000000..1153153 --- /dev/null +++ b/Toolbox/gsw_brineSA_CT.m @@ -0,0 +1,308 @@ +function brineSA_CT = gsw_brineSA_CT(CT,p,saturation_fraction) + +% gsw_brineSA_CT Absolute Salinity of seawater at the freezing point +%========================================================================== +% +% USAGE: +% brineSA_CT = gsw_brineSA_CT(CT,p,saturation_fraction) +% +% DESCRIPTION: +% Calculates the Absolute Salinity of seawater at the freezing temperature. +% That is, the output is the Absolute Salinity of seawater, with the +% fraction saturation_fraction of dissolved air, that is in equilibrium +% with ice at Conservative Temperature CT and pressure p. If the input +% values are such that there is no positive value of Absolute Salinity for +% which seawater is frozen, the output, brineSA_CT, is put equal to -99. +% +% INPUT: +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% OPTIONAL: +% saturation_fraction = the saturation fraction of dissolved air in +% seawater +% (i.e., saturation_fraction must be between 0 and 1, and the default +% is 1, completely saturated) +% +% p & saturation_fraction (if provided) may have dimensions 1x1 or Mx1 or +% 1xN or MxN, where CT is MxN. +% +% OUTPUT: +% brineSA_CT = Absolute Salinity of seawater when it freezes, for +% given input values of Conservative Temperature +% pressure and air saturation fraction. [ g/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (28th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. +% See section 3.33 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2 | nargin == 3) + error('gsw_brineSA_CT: Requires either two or three inputs') +end %if + +if ~exist('saturation_fraction','var') + saturation_fraction = 1; +end + +if (saturation_fraction < 0 | saturation_fraction > 1) + error('gsw_brineSA_CT: saturation_fraction MUST be between zero and one.') +end + +[mt,nt] = size(CT); +[mp,np] = size(p); +[map,nap] = size(saturation_fraction); + +if (mp == 1) & (np == 1) % p scalar - fill to size of CT + p = p*ones(size(CT)); +elseif (nt == np) & (mp == 1) % p is row vector, + p = p(ones(1,mt), :); % copy down each column. +elseif (mt == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,nt)); % copy across each row. +elseif (nt == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,mt), :); % copy down each column. +elseif (mt == mp) & (nt == np) + % ok +else + error('gsw_brineSA_CT: Inputs array dimensions arguments do not agree') +end %if + +if (map == 1) & (nap == 1) % saturation_fraction scalar + saturation_fraction = saturation_fraction*ones(size(CT)); % fill to size of SA +elseif (nt == nap) & (map == 1) % saturation_fraction is row vector, + saturation_fraction = saturation_fraction(ones(1,mt), :); % copy down each column. +elseif (mt == map) & (nap == 1) % saturation_fraction is column vector, + saturation_fraction = saturation_fraction(:,ones(1,nt)); % copy across each row. +elseif (nt == map) & (nap == 1) % saturation_fraction is a transposed row vector, + saturation_fraction = saturation_fraction.'; % transposed then + saturation_fraction = saturation_fraction(ones(1,mt), :); % copy down each column. +elseif (mt == map) & (nt == nap) + % ok +else + error('gsw_brineSA_CT: Inputs array dimensions arguments do not agree') +end %if + +if mt == 1 + CT = CT.'; + p = p.'; + saturation_fraction = saturation_fraction.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +a = 0.014289763856964; % Note that a = 0.502500117621/35.16504. +b = 0.057000649899720; + +c0 = 0.017947064327968736; +% +c1 = -6.076099099929818; +c2 = 4.883198653547851; +c3 = -11.88081601230542; +c4 = 13.34658511480257; +c5 = -8.722761043208607; +c6 = 2.082038908808201; +% +c7 = -7.389420998107497; +c8 = -2.110913185058476; +c9 = 0.2295491578006229; +% +c10 = -0.9891538123307282; +c11 = -0.08987150128406496; +c12 = 0.3831132432071728; +c13 = 1.054318231187074; +c14 = 1.065556599652796; +c15 = -0.7997496801694032; +c16 = 0.3850133554097069; +c17 = -2.078616693017569; +c18 = 0.8756340772729538; +c19 = -2.079022768390933; +c20 = 1.596435439942262; +c21 = 0.1338002171109174; +c22 = 1.242891021876471; + +p0 = 2.570124672768757e-1; +p1 = -1.917742353032266e+1; +p2 = -1.413382858617969e-2; +p3 = -5.427484830917552e-1; +p4 = -4.126621135193472e-4; +p5 = -4.176407833276121e-7; +p6 = 4.688217641883641e-5; +p7 = -3.039808885885726e-8; +p8 = -4.990118091261456e-11; +p9 = -9.733920711119464e-9; +p10 = -7.723324202726337e-12; +p11 = 7.121854166249257e-16; +p12 = 1.256474634100811e-12; +p13 = 2.105103897918125e-15; +p14 = 8.663811778227171e-19; + +p_r = p.*1e-4; + +% Form the first estimate of brineSA_CT from a polynomial in CT and p_r. +SA = -(CT + 9*p_r)./0.06; % A rough estimate to get the saturated CT. + +[Ineg] = find(SA < 0); +if ~isempty(Ineg) + SA(Ineg) = 0; +end +CTsat = CT ... + - (1-saturation_fraction).*(1e-3).*(2.4-a.*SA).*(1+b.*(1-SA./35.16504)); + +SA = p0 + p.*(p2 + p4*CTsat + p.*(p5 + CTsat.*(p7 + p9*CTsat) ... + + p.*(p8 + CTsat.*(p10 + p12*CTsat) + p.*(p11 + p13*CTsat + p14*p)))) ... + + CTsat.*(p1 + CTsat.*(p3 + p6*p)); + +CT_freezing_zero_SA = c0 + p_r.*(c7 + p_r.*(c8 + c9.*p_r)) ... + - saturation_fraction.*(2.4e-3).*(1 + b); + +% Find CT > CT_freezing_zero_SA. If this is the case, the input values +% represent seawater that is not frozen (at any positive SA). +[Itw] = find(CT > CT_freezing_zero_SA); % Itw stands for "I_too_warm" + if ~isempty(Itw) + SA(Itw) = NaN; + end + +% Find -SA_cut_off < SA < SA_cut_off, replace the above estimate of SA +% with one based on (CT_freezing_zero_SA - CT). +SA_cut_off = 2.5; % This is the band of SA within +- 2.5 g/kg of SA = 0, +% which we treat differently in calculating the initial +% values of both SA and dCT_dSA. +[Ico] = find(abs(SA) < SA_cut_off); + +[Icoa] = find(SA < 0 & SA >= -SA_cut_off); +if ~isempty(Icoa) + SA(Icoa) = 0; +end + +% Find SA < -SA_cut_off, set them to NaN. +[Inan] = find(SA < -SA_cut_off); +if ~isempty(Inan) + SA(Inan) = NaN; +end + +%-------------------------------------------------------------------------- +% Form the first estimate of dCT_dSA, the derivative of CT with respect +% to SA at fixed p. +%-------------------------------------------------------------------------- +SA_r = 0.01*SA; +x = sqrt(SA_r); +dCT_dSA_part = 2*c1 + x.*(3*c2 + x.*(4*c3 + x.*(5*c4 + x.*(6*c5 + 7*c6.*x))))... + + p_r.*(2*c10 + p_r.*(2*c12 + p_r.*(2*c15 + 4*c21.*x.*x))... + + x.*x.*(4*c13 + 4*c17.*p_r + 6*c19.*x.*x)... + + x.*(3*c11 + 3*p_r.*(c14 + c18.*p_r)... + + x.*x.*(5*c16 + 5*c20.*p_r + 7*c22.*x.*x))); +dCT_dSA = 0.5*0.01*dCT_dSA_part ... + - saturation_fraction.*(1e-3).*(-a.*(1 + b.*(1-SA./35.16504)) ... + - b.*(2.4 - a.*SA)./35.16504); + +% Now replace the estimate of SA with the one based on +% (CT_freezing_zero_SA - CT) when (abs(SA) < SA_cut_off). +if ~isempty(Ico) + SA(Ico) = (CT(Ico) - CT_freezing_zero_SA(Ico))./dCT_dSA(Ico); +end + +%-------------------------------------------------------------------------- +% Begin the modified Newton-Raphson method to solve the root of +% CT_freezing = CT for SA. +%-------------------------------------------------------------------------- +Number_of_Iterations = 2; +for I_iter = 1:Number_of_Iterations + +%-------------------------------------------------------------------------- +% CT_freezing temperature function evaluation (the forward function +% evaluation), being the same as gsw_CT_freezing(SA,p,saturation_fraction). +%-------------------------------------------------------------------------- +SA_r = 0.01*SA; +x = sqrt(SA_r); +SA_old = SA; +CT_freezing = c0 ... + + SA_r.*(c1 + x.*(c2 + x.*(c3 + x.*(c4 + x.*(c5 + c6.*x))))) ... + + p_r.*(c7 + p_r.*(c8 + c9.*p_r)) ... + + SA_r.*p_r.*(c10 + p_r.*(c12 + p_r.*(c15 + c21.*SA_r)) + SA_r.*(c13 + c17.*p_r + c19.*SA_r) ... + + x.*(c11 + p_r.*(c14 + c18.*p_r) + SA_r.*(c16 + c20.*p_r + c22.*SA_r))) ... + - saturation_fraction.*(1e-3).*(2.4 - a.*SA).*(1 + b.*(1 - SA./35.16504)); + +SA = SA_old - (CT_freezing - CT)./dCT_dSA; +% This is the half-way point of the modified Newton-Raphson solution method. + SA_r = 0.5*0.01*(SA + SA_old); % This is now the mean value of SA and SA_old. +x = sqrt(SA_r); +dCT_dSA_part = 2*c1 + x.*(3*c2 + x.*(4*c3 + x.*(5*c4 + x.*(6*c5 + 7*c6.*x))))... + + p_r.*(2*c10 + p_r.*(2*c12 + p_r.*(2*c15 + 4*c21.*x.*x))... + + x.*x.*(4*c13 + 4*c17.*p_r + 6*c19.*x.*x)... + + x.*(3*c11 + 3*p_r.*(c14 + c18.*p_r)... + + x.*x.*(5*c16 + 5*c20.*p_r + 7*c22.*x.*x))); + +dCT_dSA = 0.5*0.01*dCT_dSA_part ... + - saturation_fraction.*(1e-3).*(-a.*(1 + b.*(1-SA./35.16504)) ... + - b.*(2.4 - a.*SA)./35.16504); + +SA = SA_old - (CT_freezing - CT)./dCT_dSA; + +end + +%-------------------------------------------------------------------------- +% The following lines of code, if implemented, calculates the error of +% this function in terms of Conservative Temperature, CT_error. +% With Number_of_Iterations = 1, the maximum error in CT is 2x10^-7 C. +% With Number_of_Iterations = 2, the maximum error in CT is 7x10^-15 C, +% which is the machine precision of the computer. +% Number_of_Iterations = 2 is what we recommend. +% +% SA_r = 0.01*SA; +% x = sqrt(SA_r); +% CT_freezing = c0 ... +% + SA_r.*(c1 + x.*(c2 + x.*(c3 + x.*(c4 + x.*(c5 + c6.*x))))) ... +% + p_r.*(c7 + p_r.*(c8 + c9.*p_r)) ... +% + SA_r.*p_r.*(c10 + p_r.*(c12 + p_r.*(c15 + c21.*SA_r)) + SA_r.*(c13 + c17.*p_r + c19.*SA_r) ... +% + x.*(c11 + p_r.*(c14 + c18.*p_r) + SA_r.*(c16 + c20.*p_r + c22.*SA_r))) ... +% - saturation_fraction.*(1e-3).*(2.4 - a.*SA).*(1 + b.*(1 - SA./35.16504)); +% +% CT_error = abs(CT_freezing - CT); +% +% [Iout_of_range] = find(p > 10000 | SA > 120 | ... +% p + SA.*71.428571428571402 > 13571.42857142857); +% if ~isempty(Iout_of_range) +% CT_error(Iout_of_range) = NaN; +% end +% +%--------------------This is the end of the error calculation-------------- + +brineSA_CT = SA; + +[Iout_of_range] = find(p > 10000 | SA > 120 | ... + p + SA.*71.428571428571402 > 13571.42857142857); +if ~isempty(Iout_of_range) + brineSA_CT(Iout_of_range) = NaN; +end + +if ~isempty(Itw) + brineSA_CT(Itw) = -99; % If the CT input is too warm, then there is +end % no (positive) value of SA that represents frozen seawater. + +if transposed + brineSA_CT = brineSA_CT.'; +end + +end \ No newline at end of file diff --git a/Toolbox/gsw_brineSA_t.m b/Toolbox/gsw_brineSA_t.m new file mode 100644 index 0000000..0c9b402 --- /dev/null +++ b/Toolbox/gsw_brineSA_t.m @@ -0,0 +1,294 @@ +function brineSA_t = gsw_brineSA_t(t,p,saturation_fraction) + +% gsw_brineSA_t Absolute Salinity of seawater at the freezing point +%========================================================================== +% +% USAGE: +% brineSA_t = gsw_brineSA_t(t,p,saturation_fraction) +% +% DESCRIPTION: +% Calculates the Absolute Salinity of seawater at the freezing temperature. +% That is, the output is the Absolute Salinity of seawater, with the +% fraction saturation_fraction of dissolved air, that is in equilibrium +% with ice at in-situ temperature t and pressure p. If the input values +% are such that there is no positive value of Absolute Salinity for which +% seawater is frozen, the output, brineSA_t, is put equal to -99. +% +% INPUT: +% t = in situ Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% OPTIONAL: +% saturation_fraction = the saturation fraction of dissolved air in +% seawater +% (i.e., saturation_fraction must be between 0 and 1, and the default +% is 1, completely saturated) +% +% p & saturation_fraction (if provided) may have dimensions 1x1 or Mx1 or +% 1xN or MxN, where t is MxN. +% +% OUTPUT: +% brineSA_t = Absolute Salinity of seawater when it freezes, for +% given input values of in situ temperature, pressure and +% air saturation fraction. [ g/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (28th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. +% See section 3.33 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2 | nargin == 3) + error('gsw_brineSA_t: Requires either two or three inputs') +end %if + +if ~exist('saturation_fraction','var') + saturation_fraction = 1; +end + + if (saturation_fraction < 0 | saturation_fraction > 1) + error('gsw_brineSA_t: saturation_fraction MUST be between zero and one.') +end + +[mt,nt] = size(t); +[mp,np] = size(p); +[map,nap] = size(saturation_fraction); + +if (mp == 1) & (np == 1) % p scalar - fill to size of t + p = p*ones(size(t)); +elseif (nt == np) & (mp == 1) % p is row vector, + p = p(ones(1,mt), :); % copy down each column. +elseif (mt == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,nt)); % copy across each row. +elseif (nt == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,mt), :); % copy down each column. +elseif (mt == mp) & (nt == np) + % ok +else + error('gsw_brineSA_t: Inputs array dimensions arguments do not agree') +end %if + +if (map == 1) & (nap == 1) % saturation_fraction scalar + saturation_fraction = saturation_fraction*ones(size(t)); % fill to size of SA +elseif (nt == nap) & (map == 1) % saturation_fraction is row vector, + saturation_fraction = saturation_fraction(ones(1,mt), :); % copy down each column. +elseif (mt == map) & (nap == 1) % saturation_fraction is column vector, + saturation_fraction = saturation_fraction(:,ones(1,nt)); % copy across each row. +elseif (nt == map) & (nap == 1) % saturation_fraction is a transposed row vector, + saturation_fraction = saturation_fraction.'; % transposed then + saturation_fraction = saturation_fraction(ones(1,mt), :); % copy down each column. +elseif (mt == map) & (nt == nap) + % ok +else + error('gsw_brineSA_t: Inputs array dimensions arguments do not agree') +end %if + +if mt == 1 + t = t.'; + p = p.'; + saturation_fraction = saturation_fraction.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +a = 0.014289763856964; % Note that a = 0.502500117621/35.16504. +b = 0.057000649899720; + +p0 = 2.570124672768757e-1; +p1 = -1.917742353032266e1; +p2 = -1.413382858617969e-2; +p3 = -5.427484830917552e-1; +p4 = -4.126621135193472e-4; +p5 = -4.176407833276121e-7; +p6 = 4.688217641883641e-5; +p7 = -3.039808885885726e-8; +p8 = -4.990118091261456e-11; +p9 = -9.733920711119464e-9; +p10 = -7.723324202726337e-12; +p11 = 7.121854166249257e-16; +p12 = 1.256474634100811e-12; +p13 = 2.105103897918125e-15; +p14 = 8.663811778227171e-19; + +% Coefficients from gsw_t_freezing +% t0 = 0.002519; + t1 = -5.946302841607319; + t2 = 4.136051661346983; + t3 = -1.115150523403847e1; + t4 = 1.476878746184548e1; + t5 = -1.088873263630961e1; + t6 = 2.961018839640730; +% t7 = -7.433320943962606; +% t8 = -1.561578562479883; +% t9 = 4.073774363480365e-2; + t10 = 1.158414435887717e-2; + t11 = -4.122639292422863e-1; + t12 = -1.123186915628260e-1; + t13 = 5.715012685553502e-1; + t14 = 2.021682115652684e-1; + t15 = 4.140574258089767e-2; + t16 = -6.034228641903586e-1; + t17 = -1.205825928146808e-2; + t18 = -2.812172968619369e-1; + t19 = 1.877244474023750e-2; + t20 = -1.204395563789007e-1; + t21 = 2.349147739749606e-1; + t22 = 2.748444541144219e-3; + +p_r = p.*1e-4; + +%-------------------------------------------------------------------------- +% Form the first estimate of brineSA_t, called SA here, from a polynomial +% in CT and p_r. +%-------------------------------------------------------------------------- +SA = -(t + 9*p_r)./0.06; % A rough estimate to get the saturated CT. +[Ineg] = find(SA < 0); +if ~isempty(Ineg) + SA(Ineg) = 0; +end +CT = gsw_CT_from_t(SA,t,p); +CTsat = CT ... + - (1-saturation_fraction).*(1e-3).*(2.4-a.*SA).*(1+b.*(1-SA./35.16504)); + +SA = p0 + p.*(p2 + p4*CTsat + p.*(p5 + CTsat.*(p7 + p9*CTsat) ... + + p.*(p8 + CTsat.*(p10 + p12*CTsat) + p.*(p11 + p13*CTsat + p14*p)))) ... + + CTsat.*(p1 + CTsat.*(p3 + p6*p)); + +t_freezing_zero_SA = gsw_t_freezing(zeros(size(t)),p,saturation_fraction); + +% Find t > t_freezing_zero_SA. If this is the case, the input values +% represent seawater that is not frozen (at any positive SA). +[Itw] = find(t > t_freezing_zero_SA); % Itw stands for "I_too_warm" + if ~isempty(Itw) + SA(Itw) = NaN; + end + +% Find -SA_cut_off < SA < SA_cut_off, replace the above estimate of SA +% with one based on (t_freezing_zero_SA - t). +SA_cut_off = 2.5; % This is the band of SA within +- 2.5 g/kg of SA = 0, +% which we treat differently in calculating the initial +% values of both SA and dCT_dSA. +[Ico] = find(abs(SA) < SA_cut_off); + +[Icoa] = find(SA < 0 & SA >= -SA_cut_off); +if ~isempty(Icoa) + SA(Icoa) = 0; +end + +% Find SA < -SA_cut_off, set them to NaN. +[Inan] = find(SA < -SA_cut_off); +if ~isempty(Inan) + SA(Inan) = NaN; +end + +%--------------------------------------------------------------------------- +% Form the first estimate of dt_dSA, the derivative of t with respect +% to SA at fixed p, using the coefficients, t0 ... t22 from gsw_t_freezing. +%-------------------------------------------------------------------------- +SA_r = 0.01*SA; +x = sqrt(SA_r); +dt_dSA_part = 2*t1 + x.*(3*t2 + x.*(4*t3 + x.*(5*t4 + x.*(6*t5 + 7*t6.*x))))... + + p_r.*(2*t10 + p_r.*(2*t12 + p_r.*(2*t15 + 4*t21.*x.*x))... + + x.*x.*(4*t13 + 4*t17.*p_r + 6*t19.*x.*x)... + + x.*(3*t11 + 3*p_r.*(t14 + t18.*p_r)... + + x.*x.*(5*t16 + 5*t20.*p_r + 7*t22.*x.*x))); +dt_dSA = 0.5*0.01*dt_dSA_part ... + + saturation_fraction.*(1e-3)./70.33008; + +% Now replace the estimate of SA with the one based on +% (t_freezing_zero_SA - t) when (abs(SA) < SA_cut_off). +if ~isempty(Ico) + SA(Ico) = (t(Ico) - t_freezing_zero_SA(Ico))./dt_dSA(Ico); +end + +%--------------------------------------------------------------------------- +% Begin the modified Newton-Raphson method to find the root of +% t_freezing = t for SA. +%--------------------------------------------------------------------------- +Number_of_Iterations = 5; +for I_iter = 1:Number_of_Iterations + + SA_old = SA; + + t_freezing = gsw_t_freezing(SA_old,p,saturation_fraction); + + SA = SA_old - (t_freezing - t)./dt_dSA; + % This is the half-way point of the modified Newton-Raphson solution method. + SA_r = 0.5*0.01*(SA + SA_old); % This is now the mean value of SA and SA_old. + x = sqrt(SA_r); + dt_dSA_part = 2*t1 + x.*(3*t2 + x.*(4*t3 + x.*(5*t4 + x.*(6*t5 + 7*t6.*x))))... + + p_r.*(2*t10 + p_r.*(2*t12 + p_r.*(2*t15 + 4*t21.*x.*x))... + + x.*x.*(4*t13 + 4*t17.*p_r + 6*t19.*x.*x)... + + x.*(3*t11 + 3*p_r.*(t14 + t18.*p_r)... + + x.*x.*(5*t16 + 5*t20.*p_r + 7*t22.*x.*x))); + dt_dSA = 0.5*0.01*dt_dSA_part ... + + saturation_fraction.*(1e-3)./70.33008; + + SA = SA_old - (t_freezing - t)./dt_dSA; + +end + +%-------------------------------------------------------------------------- +% The following lines of code, if implemented, calculate the error of +% this function in terms of in-situ temperature, t. +% With Number_of_Iterations = 4, the maximum error in t is 3x10^-13 C. +% With Number_of_Iterations = 5, the maximum error in t is 2x10^-14 C, +% which is the machine precision of the computer. +% Number_of_Iterations = 5 is what we recommend. +% +% [InSA] = find(SA < 0); +% if ~isempty(InSA) +% SA(InSA) = NaN; +% end +% +% t_freezing = gsw_t_freezing(SA,p,saturation_fraction); +% +% t_error = abs(t_freezing - t); +% +% [Iout_of_range] = find(p > 10000 | SA > 120 | ... +% p + SA.*71.428571428571402 > 13571.42857142857); +% if ~isempty(Iout_of_range) +% t_error(Iout_of_range) = NaN; +% end +% +%-----------------This is the end of the error calculation----------------- + +brineSA_t = SA; + +[Iout_of_range] = find(p > 10000 | SA > 120 | ... + p + SA.*71.428571428571402 > 13571.42857142857); +if ~isempty(Iout_of_range) + brineSA_t(Iout_of_range) = NaN; +end + +if ~isempty(Itw) + brineSA_t(Itw) = -99; % If the t input is too warm, then there is +% no (positive) value of SA that represents frozen seawater. +end + +if transposed + brineSA_t = brineSA_t.'; +end + +end \ No newline at end of file diff --git a/Toolbox/gsw_cabbeling_CT25.m b/Toolbox/gsw_cabbeling.m similarity index 50% rename from Toolbox/gsw_cabbeling_CT25.m rename to Toolbox/gsw_cabbeling.m index eb69449..ba92d51 100644 --- a/Toolbox/gsw_cabbeling_CT25.m +++ b/Toolbox/gsw_cabbeling.m @@ -1,40 +1,41 @@ -function [cabbeling_CT25, in_funnel] = gsw_cabbeling_CT25(SA,CT,p) +function cabbeling = gsw_cabbeling(SA,CT,p) -% gsw_cabbeling_CT25 cabbeling coefficient -% (25-term equation) +% gsw_cabbeling cabbeling coefficient +% (48-term equation) %========================================================================== % % USAGE: -% [cabbeling_CT25, in_funnel] = gsw_cabbeling_CT25(SA,CT,p) +% cabbeling = gsw_cabbeling(SA,CT,p) % % DESCRIPTION: % Calculates the cabbeling coefficient of seawater with respect to -% Conservative Temperature. This function uses the computationally- -% efficient 25-term expression for density in terms of SA, CT and p -% (McDougall et al., 2010) +% Conservative Temperature. This function uses the computationally- +% efficient 48-term expression for density in terms of SA, CT and p +% (McDougall et al., 2011) % +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% % INPUT: % SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & CT need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. % % OUTPUT: -% cabbeling_CT25 = Cabbeling coefficient with respect to -% Conservative Temperature. [ 1/(K^2) ] -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). +% cabbeling = cabbeling coefficient with respect to [ 1/K^2 ] +% Conservative Temperature. % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (24th August, 2010) +% VERSION NUMBER: 3.0 (23rd March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -43,11 +44,10 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See Eqns. (3.9.2) and (P.4) of this TEOS-10 manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, -% R. Feistel and R. W. Hallberg, 2010: A computationally efficient -% 25-term expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted to -% Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -58,7 +58,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_cabbeling_CT25: Requires three inputs') + error('gsw_cabbeling: Requires three inputs') end %if [ms,ns] = size(SA); @@ -66,7 +66,7 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_cabbeling_CT25: SA and t must have same dimensions') + error('gsw_cabbeling: SA and CT must have same dimensions') end if (mp == 1) & (np == 1) % p is a scalar - fill to size of SA @@ -76,18 +76,18 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_cabbeling_CT25: Inputs array dimensions arguments do not agree') + error('gsw_cabbeling: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - CT = CT'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -97,20 +97,18 @@ % Start of the calculation %-------------------------------------------------------------------------- -in_funnel = gsw_infunnel(SA,CT,p); - dCT = 1e-3; % increment in Conservative Temperature is 1e-3 deg C. CT_l = CT - dCT; CT_u = CT + dCT; -[dummy,alpha_CT,beta_CT,flag] = gsw_rho_alpha_beta_CT25(SA,CT,p); -[dummy,alpha_CT_u,dummy2,flag] = gsw_rho_alpha_beta_CT25(SA,CT_u,p); -[dummy,alpha_CT_l,dummy2,flag] = gsw_rho_alpha_beta_CT25(SA,CT_l,p); +[dummy,alpha,beta] = gsw_rho_alpha_beta(SA,CT,p); +alpha_u = gsw_alpha(SA,CT_u,p); +alpha_l = gsw_alpha(SA,CT_l,p); -ratio_CT = alpha_CT./beta_CT; -alpha_CT_CT = (alpha_CT_u - alpha_CT_l)./(CT_u-CT_l); +alpha_on_beta = alpha./beta; +alpha_CT = (alpha_u - alpha_l)./(CT_u-CT_l); -dSA = 1e-3; % increment in Absolute Salinity is 1e-3 g/kg. +dSA = 1e-3; % increment in Absolute Salinity is 1e-3 g kg^-1 inds_l = find(SA>=dSA); SA_l = nan(size(SA)); if ~isempty(inds_l) @@ -122,17 +120,17 @@ end SA_u = SA + dSA; -[dummy,alpha_CT_u,beta_CT_u,flag] = gsw_rho_alpha_beta_CT25(SA_u,CT,p); -[dummy,alpha_CT_l,beta_CT_l,flag] = gsw_rho_alpha_beta_CT25(SA_u,CT,p); +[dummy,alpha_u,beta_u] = gsw_rho_alpha_beta(SA_u,CT,p); +[dummy,alpha_l,beta_l] = gsw_rho_alpha_beta(SA_l,CT,p); -alpha_CT_SA = (alpha_CT_u - alpha_CT_l)./(SA_u-SA_l); -beta_CT_SA = (beta_CT_u - beta_CT_l)./(SA_u-SA_l); -cabbeling_CT25 = alpha_CT_CT + ratio_CT.*(2.*alpha_CT_SA - ratio_CT.*beta_CT_SA); +alpha_SA = (alpha_u - alpha_l)./(SA_u-SA_l); +beta_SA = (beta_u - beta_l)./(SA_u-SA_l); +cabbeling = alpha_CT + alpha_on_beta.*(2.*alpha_SA - alpha_on_beta.*beta_SA); %-------------------------------------------------------------------------- -% This function calculates cabbeling_CT25 using the computationally-efficient -% 25-term expression for density in terms of SA, CT and p. If one wanted to -% compute cabbeling_CT25 with the full TEOS-10 Gibbs function expression +% This function calculates cabbeling using the computationally-efficient +% 48-term expression for density in terms of SA, CT and p. If one wanted +% to compute cabbeling with the full TEOS-10 Gibbs function expression % for density, the following lines of code will enable this. % % pr0 = zeros(size(p)); @@ -145,10 +143,10 @@ % t_l = gsw_pt_from_t(SA,pt_l,pr0,p); % t_u = gsw_pt_from_t(SA,pt_u,pr0,p); % t = 0.5*(t_l + t_u); -% alpha_CT = gsw_alpha_wrt_CT(SA,t,p); -% beta_CT = gsw_beta_const_CT(SA,t,p); -% ratio_CT = alpha_CT./beta_CT; -% alpha_CT_CT = (gsw_alpha_wrt_CT(SA,t_u,p)-gsw_alpha_wrt_CT(SA,t_l,p))./(CT_u-CT_l); +% alpha = gsw_alpha_wrt_CT_t_exact(SA,t,p); +% beta = gsw_beta_const_CT_t_exact(SA,t,p); +% alpha_on_beta = alpha./beta; +% alpha_CT = (gsw_alpha_wrt_CT_t_exact(SA,t_u,p)-gsw_alpha_wrt_CT_t_exact(SA,t_l,p))./(CT_u-CT_l); % dSA = 1e-3; %increment in Absolute Salinity is 1e-3 g/kg % SA_l = nan(size(SA)); % inds_l = find(SA>=dSA); @@ -159,16 +157,15 @@ % if ~isempty(inds_l) % SA_l(inds_l) = 0; % end -% SA_u = SA+dSA; -% alpha_CT_SA = (gsw_alpha_wrt_CT(SA_u,t,p)-gsw_alpha_wrt_CT(SA_l,t,p))./(SA_u-SA_l); -% beta_CT_SA = (gsw_beta_const_CT(SA_u,t,p)-gsw_beta_const_CT(SA_l,t,p))./(SA_u-SA_l); -% cabbeling_CT = alpha_CT_CT + ratio_CT.*(2.*alpha_CT_SA - ratio_CT.*beta_CT_SA); +% SA_u = SA + dSA; +% alpha_SA = (gsw_alpha_wrt_CT_t_exact(SA_u,t,p)-gsw_alpha_wrt_CT_t_exact(SA_l,t,p))./(SA_u-SA_l); +% beta_SA = (gsw_beta_const_CT_t_exact(SA_u,t,p)-gsw_beta_const_CT_t_exact(SA_l,t,p))./(SA_u-SA_l); +% cabbeling = alpha_CT + alpha_on_beta.*(2.*alpha_SA - alpha_on_beta.*beta_SA); % %---------------This is the end of the alternative code-------------------- if transposed - cabbeling_CT25 = cabbeling_CT25'; - in_funnel = in_funnel'; + cabbeling = cabbeling.'; end end diff --git a/Toolbox/gsw_check_functions.m b/Toolbox/gsw_check_functions.m index 2128d60..cc5582c 100644 --- a/Toolbox/gsw_check_functions.m +++ b/Toolbox/gsw_check_functions.m @@ -23,10 +23,18 @@ error('You have not added the GSW subdirectories to you MATLAB Path') end -gsw_data = 'gsw_data_v2_0.mat'; +try + gsw_installation_dir = which ('gsw_gibbs.html'); + builddocsearchdb ([gsw_installation_dir(1:end-14)]) + clear gsw_installation_dir +end + +gsw_data = 'gsw_data_v3_0.mat'; gsw_data_file = which(gsw_data); load (gsw_data_file,'gsw_cv'); +gsw_ver + try cprintf('text',' \n'); cprintf('strings','This function is running three stored vertical profiles through\n'); @@ -47,115 +55,677 @@ fprintf(1,' checking '); end -gsw_chks = 1; +gsw_cf.gsw_chks = 1; + +%% Practical Salinity (SP):- PSS-78 + +gsw_cf.C = gsw_C_from_SP(gsw_cv.SP_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.IC_from_SP] = find(abs(gsw_cv.C_from_SP - gsw_cf.C) >= gsw_cv.C_from_SP_ca); +if ~isempty(gsw_cf.IC_from_SP) + try + cprintf('err','gsw_C_from_SP: Failed\n'); + catch + fprintf(2,'gsw_C_from_SP: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.SP_from_C = gsw_SP_from_C(gsw_cf.C,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.ISP_from_C] = find(abs(gsw_cv.SP_from_C - gsw_cf.SP_from_C) >= gsw_cv.SP_from_C_ca); +if ~isempty(gsw_cf.ISP_from_C) + try + cprintf('err','gsw_SP_from_C: Failed\n'); + catch + fprintf(2,'gsw_SP_from_C: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.R = gsw_R_from_SP(gsw_cv.SP_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.IR_from_SP] = find(abs(gsw_cv.R_from_SP - gsw_cf.R) >= gsw_cv.R_from_SP_ca); +if ~isempty(gsw_cf.IR_from_SP) + try + cprintf('err','gsw_R_from_SP: Failed\n'); + catch + fprintf(2,'gsw_R_from_SP: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end -%% Absolute Salinity (SA) and Preformed Salinity (Sstar) +gsw_cf.SP_from_R = gsw_SP_from_R(gsw_cf.R,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.ISP_from_R] = find(abs(gsw_cv.SP_from_R - gsw_cf.SP_from_R) >= gsw_cv.SP_from_R_ca); +if ~isempty(gsw_cf.ISP_from_R) + try + cprintf('err','gsw_SP_from_R: Failed\n'); + catch + fprintf(2,'gsw_SP_from_R: Failed\n'); + end + gsw_chks = 0; +end + +gsw_cf.SP_salinometer = gsw_SP_salinometer(gsw_cv.Rt_chck_cast,gsw_cv.t_chck_cast); +[gsw_cf.ISP_salinometer] = find(abs(gsw_cv.SP_salinometer - gsw_cf.SP_salinometer) >= gsw_cv.SP_salinometer_ca); +if ~isempty(gsw_cf.ISP_salinometer) + try + cprintf('err','gsw_SP_salinometer: Failed\n'); + catch + fprintf(2,'gsw_SP_salinometer: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +%% Absolute Salinity (SA), Preformed Salinity (Sstar) and Conservative Temperature (CT) -SA_chck_cast = gsw_SA_from_SP(gsw_cv.SP_chck_cast,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); -[ISA_from_SP] = find((gsw_cv.SA_from_SP - SA_chck_cast) >= gsw_cv.SA_from_SP_ca); -if ~isempty(ISA_from_SP) +gsw_cf.SA_from_SP = gsw_SA_from_SP(gsw_cv.SP_chck_cast,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); +[gsw_cf.ISA_from_SP] = find(abs(gsw_cv.SA_from_SP - gsw_cf.SA_from_SP) >= gsw_cv.SA_from_SP_ca); +if ~isempty(gsw_cf.ISA_from_SP) try cprintf('err','gsw_SA_from_SP: Failed. Note that this will cause many other programmes in the GSW toolbox to fail.\n'); catch fprintf(2,'gsw_SA_from_SP: Failed. Note that this will cause many other programmes in the GSW toolbox to fail.\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -Sstar_from_SP = gsw_Sstar_from_SP(gsw_cv.SP_chck_cast,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); -[ISstar_from_SP] = find((gsw_cv.Sstar_from_SP - Sstar_from_SP) >= gsw_cv.Sstar_from_SP_ca); -if ~isempty(ISstar_from_SP) +gsw_cf.Sstar_from_SP = gsw_Sstar_from_SP(gsw_cv.SP_chck_cast,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); +[gsw_cf.ISstar_from_SP] = find(abs(gsw_cv.Sstar_from_SP - gsw_cf.Sstar_from_SP) >= gsw_cv.Sstar_from_SP_ca); +if ~isempty(gsw_cf.ISstar_from_SP) try cprintf('err','gsw_Sstar_from_SP: Failed\n'); catch fprintf(2,'gsw_Sstar_from_SP: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -[SA_SA_Sstar_from_SP, Sstar_SA_Sstar_from_SP] = gsw_SA_Sstar_from_SP(gsw_cv.SP_chck_cast,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); -[ISA_Sstar_from_SP] = find((gsw_cv.SA_SA_Sstar_from_SP - SA_SA_Sstar_from_SP) >= gsw_cv.SA_SA_Sstar_from_SP_ca | ... - (gsw_cv.Sstar_SA_Sstar_from_SP - Sstar_SA_Sstar_from_SP) >= gsw_cv.Sstar_SA_Sstar_from_SP_ca); -if ~isempty(ISA_Sstar_from_SP) +gsw_cf.CT_chck_cast = gsw_CT_from_t(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.ICT_from_t] = find(abs(gsw_cv.CT_from_t - gsw_cf.CT_chck_cast) >= gsw_cv.CT_from_t_ca); +if ~isempty(gsw_cf.ICT_from_t) + try + cprintf('err','gsw_CT_from_t: Failed. Note that this will cause many other programmes in the GSW toolbox to fail.\n'); + catch + fprintf(2,'gsw_CT_from_t: Failed. Note that this will cause many other programmes in the GSW toolbox to fail.\n'); + end + gsw_cf.gsw_chks = 0; +end + +%% other conversions between temperatures, salinities, pressure and height + +gsw_cf.deltaSA_from_SP = gsw_deltaSA_from_SP(gsw_cv.SP_chck_cast,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); +[gsw_cf.IdeltaSA_from_SP] = find(abs(gsw_cv.deltaSA_from_SP - gsw_cf.deltaSA_from_SP) >= gsw_cv.deltaSA_from_SP_ca); +if ~isempty(gsw_cf.IdeltaSA_from_SP) + try + cprintf('err','gsw_deltaSA_from_SP: Failed\n'); + catch + fprintf(2,'gsw_deltaSA_from_SP: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +[gsw_cf.SA_SA_Sstar_from_SP, gsw_cf.Sstar_SA_Sstar_from_SP] = gsw_SA_Sstar_from_SP(gsw_cv.SP_chck_cast,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); +[gsw_cf.ISA_Sstar_from_SP] = find(abs(gsw_cv.SA_SA_Sstar_from_SP - gsw_cf.SA_SA_Sstar_from_SP) >= gsw_cv.SA_SA_Sstar_from_SP_ca | ... + abs(gsw_cv.Sstar_SA_Sstar_from_SP - gsw_cf.Sstar_SA_Sstar_from_SP) >= gsw_cv.Sstar_SA_Sstar_from_SP_ca); +if ~isempty(gsw_cf.ISA_Sstar_from_SP) try cprintf('err','gsw_SA_Sstar_from_SP: Failed\n'); catch fprintf(2,'gsw_SA_Sstar_from_SP: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -%% Conservative Temperature (CT) +gsw_cf.SR_from_SP = gsw_SR_from_SP(gsw_cv.SP_chck_cast); +[gsw_cf.ISR_from_SP] = find(abs(gsw_cv.SR_from_SP - gsw_cf.SR_from_SP) >= gsw_cv.SR_from_SP_ca); +if ~isempty(gsw_cf.ISR_from_SP) + try + cprintf('err','gsw_SR_from_SP: Failed\n'); + catch + fprintf(2,'gsw_SR_from_SP: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end -CT_chck_cast = gsw_CT_from_t(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[ICT_from_t] = find((gsw_cv.CT_from_t - CT_chck_cast) >= gsw_cv.CT_from_t_ca); -if ~isempty(ICT_from_t) +gsw_cf.SP_from_SR = gsw_SP_from_SR(gsw_cf.SR_from_SP); +[gsw_cf.ISP_from_SR] = find(abs(gsw_cv.SP_from_SR - gsw_cf.SP_from_SR) >= gsw_cv.SP_from_SR_ca); +if ~isempty(gsw_cf.ISP_from_SR) try - cprintf('err','gsw_CT_from_t: Failed. Note that this will cause many other programmes in the GSW toolbox to fail.\n'); + cprintf('err','gsw_SP_from_SR: Failed\n'); catch - fprintf(2,'gsw_CT_from_t: Failed. Note that this will cause many other programmes in the GSW toolbox to fail.\n'); + fprintf(2,'gsw_SP_from_SR: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; +end + +gsw_cf.SP_from_SA = gsw_SP_from_SA(gsw_cv.SA_chck_cast,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); +[gsw_cf.ISP_from_SA] = find(abs(gsw_cv.SP_chck_cast - gsw_cf.SP_from_SA) >= gsw_cv.SP_from_SA_ca); +if ~isempty(gsw_cf.ISP_from_SA) + try + cprintf('err','gsw_SP_from_SA: Failed\n'); + catch + fprintf(2,'gsw_SP_from_SA: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.Sstar_from_SA = gsw_Sstar_from_SA(gsw_cv.SA_chck_cast,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); +[gsw_cf.ISstar_from_SA] = find(abs(gsw_cv.Sstar_from_SA - gsw_cf.Sstar_from_SA) >= gsw_cv.Sstar_from_SA_ca); +if ~isempty(gsw_cf.ISstar_from_SA) + try + cprintf('err','gsw_Sstar_from_SA: Failed\n'); + catch + fprintf(2,'gsw_Sstar_from_SA: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.SA_from_Sstar = gsw_SA_from_Sstar(gsw_cf.Sstar_from_SA,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); +[gsw_cf.ISA_from_Sstar] = find(abs(gsw_cv.SA_from_Sstar - gsw_cf.SA_from_Sstar) >= gsw_cv.SA_from_Sstar_ca); +if ~isempty(gsw_cf.ISA_from_Sstar) + try + cprintf('err','gsw_SA_from_Sstar: Failed\n'); + catch + fprintf(2,'gsw_SA_from_Sstar: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.SP_from_Sstar = gsw_SP_from_Sstar(gsw_cf.Sstar_from_SA,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); +[gsw_cf.ISP_from_Sstar] = find(abs(gsw_cv.SP_from_Sstar - gsw_cf.SP_from_Sstar) >= gsw_cv.SP_from_Sstar_ca); +if ~isempty(gsw_cf.ISP_from_Sstar) + try + cprintf('err','gsw_SP_from_Sstar: Failed\n'); + catch + fprintf(2,'gsw_SP_from_Sstar: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.t_from_CT = gsw_t_from_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.It_from_CT] = find(abs(gsw_cv.t_chck_cast - gsw_cf.t_from_CT) >= gsw_cv.t_from_CT_ca); +if ~isempty(gsw_cf.It_from_CT) + try + cprintf('err','gsw_t_from_CT: Failed.\n'); + catch + fprintf(2,'gsw_t_from_CT: Failed.\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.pt = gsw_pt_from_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Ipt_from_CT] = find(abs(gsw_cv.pt_from_CT - gsw_cf.pt) >= gsw_cv.pt_from_CT_ca); +if ~isempty(gsw_cf.Ipt_from_CT) + try + cprintf('err','gsw_pt_from_CT: Failed\n'); + catch + fprintf(2,'gsw_pt_from_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.CT_from_pt = gsw_CT_from_pt(gsw_cv.SA_chck_cast,gsw_cf.pt); +[gsw_cf.ICT_from_pt] = find(abs(gsw_cv.CT_from_pt - gsw_cf.CT_from_pt) >= gsw_cv.CT_from_pt_ca); +if ~isempty(gsw_cf.ICT_from_pt) + try + cprintf('err','gsw_CT_from_pt: Failed\n'); + catch + fprintf(2,'gsw_CT_from_pt: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.pot_enthalpy_from_pt = gsw_pot_enthalpy_from_pt(gsw_cv.SA_chck_cast,gsw_cf.pt); +[gsw_cf.Ipot_enthalpy] = find(abs(gsw_cv.pot_enthalpy_from_pt - gsw_cf.pot_enthalpy_from_pt) >= gsw_cv.pot_enthalpy_from_pt_ca); +if ~isempty(gsw_cf.Ipot_enthalpy) + try + cprintf('err','gsw_pot_enthalpy_from_pt: Failed\n'); + catch + fprintf(2,'gsw_pot_enthalpy_from_pt: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.pt0_from_t = gsw_pt0_from_t(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ipt0] = find(abs(gsw_cv.pt0_from_t - gsw_cf.pt0_from_t) >= gsw_cv.pt0_from_t_ca); +if ~isempty(gsw_cf.Ipt0) + try + cprintf('err','gsw_pt0_from_t: Failed\n'); + catch + fprintf(2,'gsw_pt0_from_t: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.pt_from_t = gsw_pt_from_t(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr); +[gsw_cf.Ipt_from_t] = find(abs(gsw_cv.pt_from_t - gsw_cf.pt_from_t) >= gsw_cv.pt_from_t_ca); +if ~isempty(gsw_cf.Ipt_from_t) + try + cprintf('err','gsw_pt_from_t: Failed\n'); + catch + fprintf(2,'gsw_pt_from_t: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +if gsw_cf.gsw_chks == 1 ; + try + cprintf('text','.'); + catch + fprintf(1,'.'); + end +end + +gsw_cf.t90_from_t48 = gsw_t90_from_t48(gsw_cv.t_chck_cast); +[gsw_cf.It90_from_t48] = find(abs(gsw_cv.t90_from_t48 - gsw_cf.t90_from_t48) >= gsw_cv.t90_from_t48_ca); +if ~isempty(gsw_cf.It90_from_t48) + try + cprintf('err','gsw_t90_from_t48: Failed\n'); + catch + fprintf(2,'gsw_t90_from_t48: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.t90_from_t68 = gsw_t90_from_t68(gsw_cv.t_chck_cast); +[gsw_cf.It90_from_t68] = find(abs(gsw_cv.t90_from_t68 - gsw_cf.t90_from_t68) >= gsw_cv.t90_from_t68_ca); +if ~isempty(gsw_cf.It90_from_t68) + try + cprintf('err','gsw_t90_from_t68: Failed\n'); + catch + fprintf(2,'gsw_t90_from_t68: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.z_from_p = gsw_z_from_p(gsw_cv.p_chck_cast,gsw_cv.lat_chck_cast); +[gsw_cf.Iz_from_p] = find(abs(gsw_cv.z_from_p - gsw_cf.z_from_p) >= gsw_cv.z_from_p_ca); +if ~isempty(gsw_cf.Iz_from_p) + try + cprintf('err','gsw_z_from_p: Failed\n'); + catch + fprintf(2,'gsw_z_from_p: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.p_from_z = gsw_p_from_z(gsw_cf.z_from_p,gsw_cv.lat_chck_cast); +[gsw_cf.Ip_from_z] = find(abs(gsw_cv.p_from_z - gsw_cf.p_from_z) >= gsw_cv.p_from_z_ca); +if ~isempty(gsw_cf.Ip_from_z) + try + cprintf('err','gsw_p_from_z: Failed\n'); + catch + fprintf(2,'gsw_p_from_z: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.depth_from_z = gsw_depth_from_z(gsw_cf.z_from_p); +[gsw_cf.Idepth_from_z] = find(abs(gsw_cv.depth_from_z - gsw_cf.depth_from_z) >= gsw_cv.depth_from_z_ca); +if ~isempty(gsw_cf.Idepth_from_z) + try + cprintf('err','gsw_depth_from_z: Failed\n'); + catch + fprintf(2,'gsw_depth_from_z: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.z_from_depth = gsw_z_from_depth(gsw_cf.depth_from_z); +[gsw_cf.Iz_from_depth] = find(abs(gsw_cv.z_from_depth - gsw_cf.z_from_depth) >= gsw_cv.z_from_depth_ca); +if ~isempty(gsw_cf.Iz_from_depth) + try + cprintf('err','gsw_z_from_depth: Failed\n'); + catch + fprintf(2,'gsw_z_from_depth: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.Abs_Pressure_from_p = gsw_Abs_Pressure_from_p(gsw_cv.p_chck_cast); +[gsw_cf.IAbs_Pressure_from_p] = find(abs(gsw_cv.Abs_Pressure_from_p - gsw_cf.Abs_Pressure_from_p) >= gsw_cv.Abs_Pressure_from_p_ca); +if ~isempty(gsw_cf.IAbs_Pressure_from_p) + try + cprintf('err','gsw_Abs_Pressure_from_p: Failed\n'); + catch + fprintf(2,'gsw_Abs_Pressure_from_p: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.p_from_Abs_Pressure = gsw_p_from_Abs_Pressure(gsw_cf.Abs_Pressure_from_p); +[gsw_cf.Ip_from_Abs_Pressure] = find(abs(gsw_cv.p_from_Abs_Pressure - gsw_cf.p_from_Abs_Pressure) >= gsw_cv.p_from_Abs_Pressure_ca); +if ~isempty(gsw_cf.Ip_from_Abs_Pressure) + try + cprintf('err','gsw_p_from_Abs_Pressure: Failed\n'); + catch + fprintf(2,'gsw_p_from_Abs_Pressure: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.entropy_from_CT = gsw_entropy_from_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Ientropy_from_CT] = find(abs(gsw_cv.entropy_from_CT - gsw_cf.entropy_from_CT) >= gsw_cv.entropy_from_CT_ca); +if ~isempty(gsw_cf.Ientropy_from_CT) + try + cprintf('err','gsw_entropy_from_CT: Failed\n'); + catch + fprintf(2,'gsw_entropy_from_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.CT_from_entropy = gsw_CT_from_entropy(gsw_cv.SA_chck_cast,gsw_cf.entropy_from_CT); +[gsw_cf.ICT_from_entropy] = find(abs(gsw_cv.CT_from_entropy - gsw_cf.CT_from_entropy) >= gsw_cv.CT_from_entropy_ca); +if ~isempty(gsw_cf.ICT_from_entropy) + try + cprintf('err','gsw_CT_from_entropy: Failed\n'); + catch + fprintf(2,'gsw_CT_from_entropy: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.entropy_from_pt = gsw_entropy_from_pt(gsw_cv.SA_chck_cast,gsw_cf.pt_from_t); +[gsw_cf.Ientropy_from_pt] = find(abs(gsw_cv.entropy_from_pt - gsw_cf.entropy_from_pt) >= gsw_cv.entropy_from_pt_ca); +if ~isempty(gsw_cf.Ientropy_from_pt) + try + cprintf('err','gsw_entropy_from_pt: Failed\n'); + catch + fprintf(2,'gsw_entropy_from_pt: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.pt_from_entropy = gsw_pt_from_entropy(gsw_cv.SA_chck_cast,gsw_cf.entropy_from_pt); +[gsw_cf.Ipt_from_entropy] = find(abs(gsw_cv.pt_from_entropy - gsw_cf.pt_from_entropy) >= gsw_cv.pt_from_entropy_ca); +if ~isempty(gsw_cf.Ipt_from_entropy) + try + cprintf('err','gsw_pt_from_entropy: Failed\n'); + catch + fprintf(2,'gsw_pt_from_entropy: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.molality_from_SA = gsw_molality_from_SA(gsw_cv.SA_chck_cast); +[gsw_cf.Imolality_from_SA] = find(abs(gsw_cv.molality_from_SA - gsw_cf.molality_from_SA) >= gsw_cv.molality_from_SA_ca); +if ~isempty(gsw_cf.Imolality_from_SA) + try + cprintf('err','gsw_molality_from_SA: Failed\n'); + catch + fprintf(2,'gsw_molality_from_SA: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.ionic_strength_from_SA = gsw_ionic_strength_from_SA(gsw_cv.SA_chck_cast); +[gsw_cf.Iionic_strength_from_SA] = find(abs(gsw_cv.ionic_strength_from_SA - gsw_cf.ionic_strength_from_SA) >= gsw_cv.ionic_strength_from_SA_ca); +if ~isempty(gsw_cf.Iionic_strength_from_SA) + try + cprintf('err','gsw_ionic_strength_from_SA: Failed\n'); + catch + fprintf(2,'gsw_ionic_strength_from_SA: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +%% density and enthalpy, based on the 48-term expression for density +if gsw_cf.gsw_chks == 1 ; + try + cprintf('text','.'); + catch + fprintf(1,'.'); + end +end + +gsw_cf.rho = gsw_rho_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Irho] = find(abs(gsw_cv.rho - gsw_cf.rho) >= gsw_cv.rho_ca); +if ~isempty(gsw_cf.Irho) + try + cprintf('err','gsw_rho_CT: Failed\n'); + catch + fprintf(2,'gsw_rho_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.alpha = gsw_alpha_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ialpha] = find(abs(gsw_cv.alpha - gsw_cf.alpha) >= gsw_cv.alpha_ca); +if ~isempty(gsw_cf.Ialpha) + try + cprintf('err','gsw_alpha_CT: Failed\n'); + catch + fprintf(2,'gsw_alpha_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.beta = gsw_beta_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ibeta] = find(abs(gsw_cv.beta - gsw_cf.beta) >= gsw_cv.beta_ca); +if ~isempty(gsw_cf.Ibeta) + try + cprintf('err','gsw_beta_CT: Failed\n'); + catch + fprintf(2,'gsw_beta_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +[gsw_cf.rho_rab, gsw_cf.alpha_rab, gsw_cf.beta_rab] = gsw_rho_alpha_beta_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Irho_rab] = find(abs(gsw_cv.rho_rab - gsw_cf.rho_rab) >= gsw_cv.rho_rab_ca | ... + abs(gsw_cv.alpha_rab - gsw_cf.alpha_rab) >= gsw_cv.alpha_rab_ca | ... + abs(gsw_cv.beta_rab - gsw_cf.beta_rab) >= gsw_cv.beta_rab_ca); +if ~isempty(gsw_cf.Irho_rab) + try + cprintf('err','gsw_rho_alpha_beta_CT: Failed\n'); + catch + fprintf(2,'gsw_rho_alpha_beta_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.specvol = gsw_specvol_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ispecvol] = find(abs(gsw_cv.specvol - gsw_cf.specvol) >= gsw_cv.specvol_ca); +if ~isempty(gsw_cf.Ispecvol) + try + cprintf('err','gsw_specvol_CT: Failed\n'); + catch + fprintf(2,'gsw_specvol_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.specvol_anom = gsw_specvol_anom_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ispecvol_anom] = find(abs(gsw_cv.specvol_anom - gsw_cf.specvol_anom) >= gsw_cv.specvol_anom_ca); +if ~isempty(gsw_cf.Ispecvol_anom) + try + cprintf('err','gsw_specvol_anom_CT: Failed\n'); + catch + fprintf(2,'gsw_specvol_anom_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.sigma0 = gsw_sigma0_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Isigma0] = find(abs(gsw_cv.sigma0 - gsw_cf.sigma0) >= gsw_cv.sigma0_ca); +if ~isempty(gsw_cf.Isigma0) + try + cprintf('err','gsw_sigma0_CT: Failed\n'); + catch + fprintf(2,'gsw_sigma0_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.sigma1 = gsw_sigma1_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Isigma1_CT] = find(abs(gsw_cv.sigma1 - gsw_cf.sigma1) >= gsw_cv.sigma1_ca); +if ~isempty(gsw_cf.Isigma1_CT) + try + cprintf('err','gsw_sigma1_CT: Failed\n'); + catch + fprintf(2,'gsw_sigma1_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.sigma2 = gsw_sigma2_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Isigma2] = find(abs(gsw_cv.sigma2 - gsw_cf.sigma2) >= gsw_cv.sigma2_ca); +if ~isempty(gsw_cf.Isigma2) + try + cprintf('err','gsw_sigma2_CT: Failed\n'); + catch + fprintf(2,'gsw_sigma2_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.sigma3 = gsw_sigma3_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Isigma3] = find(abs(gsw_cv.sigma3 - gsw_cf.sigma3) >= gsw_cv.sigma3_ca); +if ~isempty(gsw_cf.Isigma3) + try + cprintf('err','gsw_sigma3_CT: Failed\n'); + catch + fprintf(2,'gsw_sigma3_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.sigma4 = gsw_sigma4_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Isigma4] = find(abs(gsw_cv.sigma4 - gsw_cf.sigma4) >= gsw_cv.sigma4_ca); +if ~isempty(gsw_cf.Isigma4) + try + cprintf('err','gsw_sigma4_CT: Failed\n'); + catch + fprintf(2,'gsw_sigma4_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.sound_speed = gsw_sound_speed_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Isound_speed] = find(abs(gsw_cv.sound_speed - gsw_cf.sound_speed) >= gsw_cv.sound_speed_ca); +if ~isempty(gsw_cf.Isound_speed) + try + cprintf('err','gsw_sound_speed_CT: Failed\n'); + catch + fprintf(2,'gsw_sound_speed_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.internal_energy = gsw_internal_energy_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Iinternal_energy] = find(abs(gsw_cv.internal_energy - gsw_cf.internal_energy) >= gsw_cv.internal_energy_ca); +if ~isempty(gsw_cf.Iinternal_energy) + try + cprintf('err','gsw_internal_energy_CT: Failed\n'); + catch + fprintf(2,'gsw_internal_energy_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.enthalpy = gsw_enthalpy_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ienthalpy] = find(abs(gsw_cv.enthalpy - gsw_cf.enthalpy) >= gsw_cv.enthalpy_ca); +if ~isempty(gsw_cf.Ienthalpy) + try + cprintf('err','gsw_enthalpy_CT: Failed\n'); + catch + fprintf(2,'gsw_enthalpy_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.enthalpy_diff = gsw_enthalpy_diff_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast_shallow,gsw_cv.p_chck_cast_deep); +[gsw_cf.Ienthalpy_diff] = find(abs(gsw_cv.enthalpy_diff - gsw_cf.enthalpy_diff) >= gsw_cv.enthalpy_diff_ca); +if ~isempty(gsw_cf.Ienthalpy_diff) + try + cprintf('err','gsw_enthalpy_diff_CT: Failed\n'); + catch + fprintf(2,'gsw_enthalpy_diff_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.dynamic_enthalpy = gsw_dynamic_enthalpy_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Idynamic_enthalpy] = find(abs(gsw_cv.dynamic_enthalpy - gsw_cf.dynamic_enthalpy) >= gsw_cv.dynamic_enthalpy_ca); +if ~isempty(gsw_cf.Idynamic_enthalpy) + try + cprintf('err','gsw_dynamic_enthalpy: Failed\n'); + catch + fprintf(2,'gsw_dynamic_enthalpy: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end + +gsw_cf.SA_from_rho = gsw_SA_from_rho_CT(gsw_cf.rho,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.ISA_from_rho] = find(abs(gsw_cv.SA_from_rho - gsw_cf.SA_from_rho) >= gsw_cv.SA_from_rho_ca); +if ~isempty(gsw_cf.ISA_from_rho) + try + cprintf('err','gsw_SA_from_rho_CT: Failed\n'); + catch + fprintf(2,'gsw_SA_from_rho_CT: Failed\n'); + end + gsw_cf.gsw_chks = 0; end -%% other conversions between temperatures, salinities, pressure and height - -t_from_CT = gsw_t_from_CT(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[It_from_CT] = find((gsw_cv.t_chck_cast - t_from_CT) >= gsw_cv.t_from_CT_ca); -if ~isempty(It_from_CT) +gsw_cf.CT_maxdensity = gsw_CT_maxdensity(gsw_cv.SA_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.ICT_maxdensity] = find(abs(gsw_cv.CT_maxdensity - gsw_cf.CT_maxdensity) >= gsw_cv.CT_maxdensity_ca); +if ~isempty(gsw_cf.ICT_maxdensity) try - cprintf('err','gsw_t_from_CT: Failed.\n'); + cprintf('err','gsw_CT_maxdensity: Failed\n'); catch - fprintf(2,'gsw_t_from_CT: Failed.\n'); + fprintf(2,'gsw_CT_maxdensity: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -pt = gsw_pt_from_t(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr); -[Ipt_from_t] = find((gsw_cv.pt_from_t - pt) >= gsw_cv.pt_from_t_ca); -if ~isempty(Ipt_from_t) +gsw_cf.CT_from_rho = gsw_CT_from_rho(gsw_cf.rho,gsw_cv.SA_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.ICT_from_rho] = find(abs(gsw_cv.CT_from_rho - gsw_cf.CT_from_rho) >= gsw_cv.CT_from_rho_ca); +if ~isempty(gsw_cf.ICT_from_rho) try - cprintf('err','gsw_pt_from_t: Failed\n'); + cprintf('err','gsw_CT_from_rho: Failed\n'); catch - fprintf(2,'gsw_pt_from_t: Failed\n'); + fprintf(2,'gsw_CT_from_rho: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -CT_from_pt = gsw_CT_from_pt(SA_chck_cast,pt); -[ICT_from_pt] = find((gsw_cv.CT_from_pt - CT_from_pt) >= gsw_cv.CT_from_pt_ca); -if ~isempty(ICT_from_pt) +%% water column properties, based on the 48-term expression for density + +[gsw_cf.n2, gsw_cf.p_mid_n2] = gsw_Nsquared(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast,gsw_cv.lat_chck_cast); +[gsw_cf.INsquared] = find(abs(gsw_cv.n2 - gsw_cf.n2) >= gsw_cv.n2_ca | abs(gsw_cv.p_mid_n2 - gsw_cf.p_mid_n2) >= gsw_cv.p_mid_n2_ca); +if ~isempty(gsw_cf.INsquared) try - cprintf('err','gsw_CT_from_pt: Failed\n'); + cprintf('err','gsw_Nsquared: Failed\n'); catch - fprintf(2,'gsw_CT_from_pt: Failed\n'); + fprintf(2,'gsw_Nsquared: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -pot_enthalpy = gsw_pot_enthalpy_from_pt(SA_chck_cast,pt); -[Ipot_enthalpy] = find((gsw_cv.pot_enthalpy - pot_enthalpy) >= gsw_cv.pot_enthalpy_ca); -if ~isempty(Ipot_enthalpy) +[gsw_cf.Tu, gsw_cf.Rsubrho, gsw_cf.p_mid_TuRsr] = gsw_Turner_Rsubrho(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.ITurner] = find(abs(gsw_cv.Tu - gsw_cf.Tu) >= gsw_cv.Tu_ca | abs(gsw_cv.Rsubrho - gsw_cf.Rsubrho) >= gsw_cv.Rsubrho_ca | ... + abs(gsw_cv.p_mid_TuRsr - gsw_cf.p_mid_TuRsr) >= gsw_cv.p_mid_TuRsr_ca); +if ~isempty(gsw_cf.ITurner) try - cprintf('err','gsw_pot_enthalpy_from_pt: Failed\n'); + cprintf('err','gsw_Turner_Rsubrho: Failed\n'); catch - fprintf(2,'gsw_pot_enthalpy_from_pt: Failed\n'); + fprintf(2,'gsw_Turner_Rsubrho: Failed\n'); end gsw_chks = 0; end -pt0 = gsw_pt0_from_t(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ipt0] = find((gsw_cv.pt0 - pt0) >= gsw_cv.pt0_ca); -if ~isempty(Ipt0) +[gsw_cf.IPVfN2, gsw_cf.p_mid_IPVfN2] = gsw_IPV_vs_fNsquared_ratio(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr); +[gsw_cf.IIPVfN2] = find(abs(gsw_cv.IPVfN2 - gsw_cf.IPVfN2) >= gsw_cv.IPVfN2_ca | ... + abs(gsw_cv.p_mid_IPVfN2 - gsw_cf.p_mid_IPVfN2) >= gsw_cv.p_mid_IPVfN2_ca); +if ~isempty(gsw_cf.IIPVfN2) try - cprintf('err','gsw_pt0_from_t: Failed\n'); + cprintf('err','gsw_IPV_vs_fNsquared_ratio: Failed\n'); catch - fprintf(2,'gsw_pt0_from_t: Failed\n'); + fprintf(2,'gsw_IPV_vs_fNsquared_ratio: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -if gsw_chks == 1 ; +if gsw_cf.gsw_chks == 1 ; try cprintf('text','.'); catch @@ -163,220 +733,223 @@ end end -pt_from_CT = gsw_pt_from_CT(SA_chck_cast,CT_chck_cast); -[Ipt_from_CT] = find((gsw_cv.pt - pt_from_CT) >= gsw_cv.pt_ca); -if ~isempty(Ipt_from_CT) +%% neutral and non-linear properties, based on the 48-term expression for density + +gsw_cf.cabbeling = gsw_cabbeling(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Icabbeling] = find(abs(gsw_cv.cabbeling - gsw_cf.cabbeling) >= gsw_cv.cabbeling_ca); +if ~isempty(gsw_cf.Icabbeling) try - cprintf('err','gsw_pt_from_CT: Failed\n'); + cprintf('err','gsw_cabbeling: Failed\n'); catch - fprintf(2,'gsw_pt_from_CT: Failed\n'); + fprintf(2,'gsw_cabbeling: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -Sstar_from_SA = gsw_Sstar_from_SA(SA_chck_cast,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); -[ISstar_from_SA] = find((gsw_cv.Sstar_from_SA - Sstar_from_SA) >= gsw_cv.Sstar_from_SA_ca); -if ~isempty(ISstar_from_SA) +gsw_cf.thermobaric = gsw_thermobaric(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ithermobaric] = find(abs(gsw_cv.thermobaric - gsw_cf.thermobaric) >= gsw_cv.thermobaric_ca); +if ~isempty(gsw_cf.Ithermobaric) try - cprintf('err','gsw_Sstar_from_SA: Failed\n'); + cprintf('err','gsw_thermobaric: Failed\n'); catch - fprintf(2,'gsw_Sstar_from_SA: Failed\n'); + fprintf(2,'gsw_thermobaric: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -SA_from_Sstar = gsw_SA_from_Sstar(SA_chck_cast,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); -[ISA_from_Sstar] = find((gsw_cv.SA_from_Sstar - SA_from_Sstar) >= gsw_cv.SA_from_Sstar_ca); -if ~isempty(ISA_from_Sstar) +if gsw_cf.gsw_chks == 1 ; try - cprintf('err','gsw_SA_from_Sstar: Failed\n'); + cprintf('text','.'); catch - fprintf(2,'gsw_SA_from_Sstar: Failed\n'); + fprintf(1,'.'); end - gsw_chks = 0; end -SP_from_SA = gsw_SP_from_SA(SA_chck_cast,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); -[ISP_from_SA] = find((gsw_cv.SP_chck_cast - SP_from_SA) >= gsw_cv.SP_from_SA_ca); -if ~isempty(ISP_from_SA) +gsw_cf.isopycnal_slope_ratio = gsw_isopycnal_slope_ratio(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr); +[gsw_cf.Iisopycnal_slope_ratio] = find(abs(gsw_cv.isopycnal_slope_ratio - gsw_cf.isopycnal_slope_ratio) >= gsw_cv.isopycnal_slope_ratio_ca); +if ~isempty(gsw_cf.Iisopycnal_slope_ratio) try - cprintf('err','gsw_SP_from_SA: Failed\n'); + cprintf('err','gsw_isopycnal_slope_ratio: Failed\n'); catch - fprintf(2,'gsw_SP_from_SA: Failed\n'); + fprintf(2,'gsw_isopycnal_slope_ratio: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -SP_from_Sstar = gsw_SP_from_SA(SA_chck_cast,gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); -[ISP_from_Sstar] = find((gsw_cv.SP_from_Sstar - SP_from_Sstar) >= gsw_cv.SP_from_Sstar_ca); -if ~isempty(ISP_from_Sstar) +[gsw_cf.G_CT, gsw_cf.p_mid_G_CT] = gsw_isopycnal_vs_ntp_CT_ratio(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr); +[gsw_cf.IG_CT] = find(abs(gsw_cv.G_CT - gsw_cf.G_CT) >= gsw_cv.G_CT_ca | ... + (gsw_cv.p_mid_G_CT - gsw_cf.p_mid_G_CT) >= gsw_cv.p_mid_G_CT_ca); +if ~isempty(gsw_cf.IG_CT) try - cprintf('err','gsw_SP_from_Sstar: Failed\n'); + cprintf('err','gsw_isopycnal_vs_ntp_CT_ratio: Failed\n'); catch - fprintf(2,'gsw_SP_from_Sstar: Failed\n'); + fprintf(2,'gsw_isopycnal_vs_ntp_CT_ratio: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -z_from_p = gsw_z_from_p(gsw_cv.p_chck_cast,gsw_cv.lat_chck_cast); -[Iz_from_p] = find((gsw_cv.z_from_p - z_from_p) >= gsw_cv.z_from_p_ca); -if ~isempty(Iz_from_p) +gsw_cf.ntpptCT = gsw_ntp_pt_vs_CT_ratio(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.IntpptCT] = find(abs(gsw_cv.ntpptCT - gsw_cf.ntpptCT) >= gsw_cv.ntpptCT_ca); +if ~isempty(gsw_cf.IntpptCT) try - cprintf('err','gsw_z_from_p: Failed\n'); + cprintf('err','gsw_ntp_pt_vs_CT_ratio: Failed\n'); catch - fprintf(2,'gsw_z_from_p: Failed\n'); + fprintf(2,'gsw_ntp_pt_vs_CT_ratio: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -p_from_z = gsw_p_from_z(z_from_p,gsw_cv.lat_chck_cast); -[Ip_from_z] = find((gsw_cv.p_from_z - p_from_z) >= gsw_cv.p_from_z_ca); -if ~isempty(Ip_from_z) +%% geostrophic streamfunctions, based on the 48-term expression for density + +gsw_cf.geo_strf_dyn_height = gsw_geo_strf_dyn_height(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr); +[gsw_cf.Igeo_strf_dyn_height] = find(abs(gsw_cv.geo_strf_dyn_height - gsw_cf.geo_strf_dyn_height) >= gsw_cv.geo_strf_dyn_height_ca); +if ~isempty(gsw_cf.Igeo_strf_dyn_height) try - cprintf('err','gsw_p_from_z: Failed\n'); + cprintf('err','gsw_geo_strf_dyn_height: Failed\n'); catch - fprintf(2,'gsw_p_from_z: Failed\n'); + fprintf(2,'gsw_geo_strf_dyn_height: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -t90_from_t68 = gsw_t90_from_t68(gsw_cv.t_chck_cast); -[It90_from_t68] = find((gsw_cv.t90_from_t68 - t90_from_t68) >= gsw_cv.t90_from_t68_ca); -if ~isempty(It90_from_t68) +[gsw_cf.geo_strf_dyn_height_pc, gsw_cf.geo_strf_dyn_height_pc_p_mid] = gsw_geo_strf_dyn_height_pc(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.delta_p_chck_cast); +[gsw_cf.Igeo_strf_dyn_height_pc] = find(abs(gsw_cv.geo_strf_dyn_height_pc - gsw_cf.geo_strf_dyn_height_pc) >= gsw_cv.geo_strf_dyn_height_pc_ca | ... + abs(gsw_cv.geo_strf_dyn_height_pc_p_mid - gsw_cf.geo_strf_dyn_height_pc_p_mid) >= gsw_cv.geo_strf_dyn_height_pc_p_mid_ca); +if ~isempty(gsw_cf.Igeo_strf_dyn_height_pc) try - cprintf('err','gsw_t90_from_t68: Failed\n'); + cprintf('err','gsw_geo_strf_dyn_height_pc: Failed\n'); catch - fprintf(2,'gsw_t90_from_t68: Failed\n'); + fprintf(2,'gsw_geo_strf_dyn_height_pc: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -t90_from_t48 = gsw_t90_from_t48(gsw_cv.t_chck_cast); -[It90_from_t48] = find((gsw_cv.t90_from_t48 - t90_from_t48) >= gsw_cv.t90_from_t48_ca); -if ~isempty(It90_from_t48) +gsw_cf.geo_strf_isopycnal = gsw_geo_strf_isopycnal(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr,gsw_cv.Neutral_Density,gsw_cv.p_Neutral_Density); +[gsw_cf.Igeo_strf_isopycnal] = find(abs(gsw_cv.geo_strf_isopycnal - gsw_cf.geo_strf_isopycnal) >= gsw_cv.geo_strf_isopycnal_ca); +if ~isempty(gsw_cf.Igeo_strf_isopycnal) try - cprintf('err','gsw_t90_from_t48: Failed\n'); + cprintf('err','gsw_geo_strf_isopycnal: Failed\n'); catch - fprintf(2,'gsw_t90_from_t48: Failed\n'); + fprintf(2,'gsw_geo_strf_isopycnal: Failed\n'); end gsw_chks = 0; end -%% density and enthalpy, based on the 25-term expression for density -if gsw_chks == 1 ; +[gsw_cf.geo_strf_isopycnal_pc, gsw_cf.geo_strf_isopycnal_pc_p_mid] = gsw_geo_strf_isopycnal_pc(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.delta_p_chck_cast,gsw_cv.Neutral_Density(1),3); +[gsw_cf.Igeo_strf_isopycnal_pc] = find(abs(gsw_cv.geo_strf_isopycnal_pc - gsw_cf.geo_strf_isopycnal_pc) >= gsw_cv.geo_strf_isopycnal_pc_ca |... + abs(gsw_cv.geo_strf_isopycnal_pc_p_mid - gsw_cf.geo_strf_isopycnal_pc_p_mid) >= gsw_cv.geo_strf_isopycnal_pc_p_mid_ca); +if ~isempty(gsw_cf.Igeo_strf_isopycnal_pc) try - cprintf('text','.'); + cprintf('err','gsw_geo_strf_isopycnal_pc: Failed\n'); catch - fprintf(1,'.'); + fprintf(2,'gsw_geo_strf_isopycnal_pc: Failed\n'); end + gsw_cf.gsw_chks = 0; end -rho_CT25 = gsw_rho_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Irho_CT25] = find((gsw_cv.rho_CT25 - rho_CT25) >= gsw_cv.rho_CT25_ca); -if ~isempty(Irho_CT25) +gsw_cf.geo_strf_Montgomery = gsw_geo_strf_Montgomery(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr); +[gsw_cf.Igeo_strf_Montgomery] = find(abs(gsw_cv.geo_strf_Montgomery - gsw_cf.geo_strf_Montgomery) >= gsw_cv.geo_strf_Montgomery_ca); +if ~isempty(gsw_cf.Igeo_strf_Montgomery) try - cprintf('err','gsw_rho_CT25: Failed\n'); + cprintf('err','gsw_geo_strf_Montgomery: Failed\n'); catch - fprintf(2,'gsw_rho_CT25: Failed\n'); + fprintf(2,'gsw_geo_strf_Montgomery: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -[rho_CT25rab, alpha_CT25rab, beta_CT25rab] = gsw_rho_alpha_beta_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Irho_CT25rab] = find((gsw_cv.rho_CT25rab - rho_CT25rab) >= gsw_cv.rho_CT25rab_ca | ... - (gsw_cv.alpha_CT25rab - alpha_CT25rab) >= gsw_cv.alpha_CT25rab_ca | ... - (gsw_cv.beta_CT25rab - beta_CT25rab) >= gsw_cv.beta_CT25rab_ca); -if ~isempty(Irho_CT25rab) +gsw_cf.geo_strf_Cunningham = gsw_geo_strf_Cunningham(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr); +[gsw_cf.Igeo_strf_Cunningham] = find(abs(gsw_cv.geo_strf_Cunningham - gsw_cf.geo_strf_Cunningham) >= gsw_cv.geo_strf_Cunningham_ca); +if ~isempty(gsw_cf.Igeo_strf_Cunningham) try - cprintf('err','gsw_rho_alpha_beta_CT25: Failed\n'); + cprintf('err','gsw_geo_strf_Cunningham: Failed\n'); catch - fprintf(2,'gsw_rho_alpha_beta_CT25: Failed\n'); + fprintf(2,'gsw_geo_strf_Cunningham: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -specvol_CT25 = gsw_specvol_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Ispecvol_CT25] = find((gsw_cv.specvol_CT25 - specvol_CT25) >= gsw_cv.specvol_CT25_ca); -if ~isempty(Ispecvol_CT25) - try - cprintf('err','gsw_specvol_CT25: Failed\n'); - catch - fprintf(2,'gsw_specvol_CT25: Failed\n'); - end - gsw_chks = 0; -end +%% Geostrophic velocity -specvol_anom_CT25 = gsw_specvol_anom_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Ispecvol_anom_CT25] = find((gsw_cv.specvol_anom_CT25 - specvol_anom_CT25) >= gsw_cv.specvol_anom_CT25_ca); -if ~isempty(Ispecvol_anom_CT25) +[gsw_cf.geo_strf_velocity, gsw_cf.geo_strf_velocity_mid_lat, gsw_cf.geo_strf_velocity_mid_long] = gsw_geostrophic_velocity(gsw_cf.geo_strf_dyn_height,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Igeostrophic_velo] = find(abs(gsw_cv.geo_strf_velocity - gsw_cf.geo_strf_velocity) >= gsw_cv.geo_strf_velocity_ca | ... + abs(gsw_cv.geo_strf_velocity_mid_lat - gsw_cf.geo_strf_velocity_mid_lat) >= gsw_cv.geo_strf_velocity_mid_lat_ca | ... + abs(gsw_cv.geo_strf_velocity_mid_long - gsw_cf.geo_strf_velocity_mid_long) >= gsw_cv.geo_strf_velocity_mid_long_ca); +if ~isempty(gsw_cf.Igeostrophic_velo) try - cprintf('err','gsw_specvol_anom_CT25: Failed\n'); + cprintf('err','gsw_geostrophic_velocity: Failed\n'); catch - fprintf(2,'gsw_specvol_anom_CT25: Failed\n'); + fprintf(2,'gsw_geostrophic_velocity: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -enthalpy_CT25 = gsw_enthalpy_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Ienthalpy_CT25] = find((gsw_cv.enthalpy_CT25 - enthalpy_CT25) >= gsw_cv.enthalpy_CT25_ca); -if ~isempty(Ienthalpy_CT25) +%% derivatives of enthalpy, entropy, CT and pt + +[gsw_cf.CT_SA, gsw_cf.CT_pt] = gsw_CT_first_derivatives(gsw_cv.SA_chck_cast,gsw_cf.pt); +[gsw_cf.ICT_first_deriv] = find(abs(gsw_cv.CT_SA - gsw_cf.CT_SA) >= gsw_cv.CT_SA_ca | ... + (gsw_cv.CT_pt - gsw_cf.CT_pt) >= gsw_cv.CT_pt_ca); +if ~isempty(gsw_cf.ICT_first_deriv) try - cprintf('err','gsw_enthalpy_CT25: Failed\n'); + cprintf('err','gsw_CT_first_derivatives: Failed\n'); catch - fprintf(2,'gsw_enthalpy_CT25: Failed\n'); + fprintf(2,'gsw_CT_first_derivatives: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -enthalpy_diff_CT25 = gsw_enthalpy_diff_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast_shallow,gsw_cv.p_chck_cast_deep); -[Ienthalpy_diff_CT25] = find((gsw_cv.enthalpy_diff_CT25 - enthalpy_diff_CT25) >= gsw_cv.enthalpy_diff_CT25_ca); -if ~isempty(Ienthalpy_diff_CT25) +[gsw_cf.CT_SA_SA, gsw_cf.CT_SA_pt, gsw_cf.CT_pt_pt] = gsw_CT_second_derivatives(gsw_cv.SA_chck_cast,gsw_cf.pt); +[gsw_cf.ICT_second_deriv] = find(abs(gsw_cv.CT_SA_SA - gsw_cf.CT_SA_SA) >= gsw_cv.CT_SA_SA_ca | ... + abs(gsw_cv.CT_SA_pt - gsw_cf.CT_SA_pt) >= gsw_cv.CT_SA_pt_ca | ... + abs(gsw_cv.CT_pt_pt - gsw_cf.CT_pt_pt) >= gsw_cv.CT_pt_pt_ca); +if ~isempty(gsw_cf.ICT_second_deriv) try - cprintf('err','gsw_enthalpy_diff_CT25: Failed\n'); + cprintf('err','gsw_CT_second_derivatives: Failed\n'); catch - fprintf(2,'gsw_enthalpy_diff_CT25: Failed\n'); + fprintf(2,'gsw_CT_second_derivatives: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -%% water column properties, based on the 25-term expression for density - -[n2, p_mid_n2] = gsw_Nsquared_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast,gsw_cv.lat_chck_cast); -[INsquared] = find((gsw_cv.n2 - n2) >= gsw_cv.n2_ca | (gsw_cv.p_mid_n2 - p_mid_n2) >= gsw_cv.p_mid_n2_ca); -if ~isempty(INsquared) +[gsw_cf.h_SA, gsw_cf.h_CT, gsw_cf.h_P] = gsw_enthalpy_first_derivatives(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ienthalpy_first_deriv] = find(abs(gsw_cv.h_SA - gsw_cf.h_SA) >= gsw_cv.h_SA_ca | ... + abs(gsw_cv.h_CT - gsw_cf.h_CT) >= gsw_cv.h_CT_ca | ... + abs(gsw_cv.h_P - gsw_cf.h_P) >= gsw_cv.h_P_ca); +if ~isempty(gsw_cf.Ienthalpy_first_deriv) try - cprintf('err','gsw_Nsquared_CT25: Failed\n'); + cprintf('err','gsw_enthalpy_first_derivatives: Failed\n'); catch - fprintf(2,'gsw_Nsquared_CT25: Failed\n'); + fprintf(2,'gsw_enthalpy_first_derivatives: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -[Tu, Rsubrho, p_mid_TuRsr] = gsw_Turner_Rsubrho_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[ITurner] = find((gsw_cv.Tu - Tu) >= gsw_cv.Tu_ca | (gsw_cv.Rsubrho - Rsubrho) >= gsw_cv.Rsubrho_ca | ... - (gsw_cv.p_mid_TuRsr - p_mid_TuRsr) >= gsw_cv.p_mid_TuRsr_ca); -if ~isempty(ITurner) +[gsw_cf.h_SA_SA, gsw_cf.h_SA_CT, gsw_cf.h_CT_CT] = gsw_enthalpy_second_derivatives(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ienthalpy_second_deriv] = find(abs(gsw_cv.h_SA_SA - gsw_cf.h_SA_SA) >= gsw_cv.h_SA_SA_ca | ... + abs(gsw_cv.h_SA_CT - gsw_cf.h_SA_CT) >= gsw_cv.h_SA_CT_ca | ... + abs(gsw_cv.h_CT_CT - gsw_cf.h_CT_CT) >= gsw_cv.h_CT_CT_ca); +if ~isempty(gsw_cf.Ienthalpy_second_deriv) try - cprintf('err','gsw_Turner_Rsubrho_CT25: Failed\n'); + cprintf('err','gsw_enthalpy_second_derivatives: Failed\n'); catch - fprintf(2,'gsw_Turner_Rsubrho_CT25: Failed\n'); + fprintf(2,'gsw_enthalpy_second_derivatives: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -[IPVfN2, p_mid_IPVfN2] = gsw_IPV_vs_fNsquared_ratio_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr); -[IIPVfN2] = find((gsw_cv.IPVfN2 - IPVfN2) >= gsw_cv.IPVfN2_ca | ... - (gsw_cv.p_mid_IPVfN2 - p_mid_IPVfN2) >= gsw_cv.p_mid_IPVfN2_ca); -if ~isempty(IIPVfN2) +[gsw_cf.eta_SA, gsw_cf.eta_CT] = gsw_entropy_first_derivatives(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Ientropy_first_deriv] = find(abs(gsw_cv.eta_SA - gsw_cf.eta_SA) >= gsw_cv.eta_SA_ca | ... + abs(gsw_cv.eta_CT - gsw_cf.eta_CT) >= gsw_cv.eta_CT_ca); +if ~isempty(gsw_cf.Ientropy_first_deriv) try - cprintf('err','gsw_IPV_vs_fNsquared_ratio_CT25: Failed\n'); + cprintf('err','gsw_enthalpy_first_derivatives: Failed\n'); catch - fprintf(2,'gsw_IPV_vs_fNsquared_ratio_CT25: Failed\n'); + fprintf(2,'gsw_enthalpy_first_derivatives: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -if gsw_chks == 1 ; +if gsw_cf.gsw_chks == 1 ; try cprintf('text','.'); catch @@ -384,595 +957,613 @@ end end -%% geostrophic streamfunctions, based on the 25-term expression for density - -geo_strf_dyn_height = gsw_geo_strf_dyn_height(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Igeo_strf_dyn_height] = find((gsw_cv.geo_strf_dyn_height - geo_strf_dyn_height) >= gsw_cv.geo_strf_dyn_height_ca); -if ~isempty(Igeo_strf_dyn_height) +[gsw_cf.eta_SA_SA, gsw_cf.eta_SA_CT, gsw_cf.eta_CT_CT] = gsw_entropy_second_derivatives(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Ientropy_second_deriv] = find((abs(gsw_cv.eta_SA_SA - gsw_cf.eta_SA_SA)) >= gsw_cv.eta_SA_SA_ca |... + abs(gsw_cv.eta_SA_CT - gsw_cf.eta_SA_CT) >= gsw_cv.eta_SA_CT_ca |... + abs(gsw_cv.eta_CT_CT - gsw_cf.eta_CT_CT) >= gsw_cv.eta_CT_CT_ca); +if ~isempty(gsw_cf.Ientropy_second_deriv) try - cprintf('err','gsw_geo_strf_dyn_height: Failed\n'); + cprintf('err','gsw_entropy_second_derivatives: Failed\n'); catch - fprintf(2,'gsw_geo_strf_dyn_height: Failed\n'); + fprintf(2,'gsw_entropy_second_derivatives: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -[geo_strf_dyn_height_pc, dh_pmid] = gsw_geo_strf_dyn_height_pc(SA_chck_cast,CT_chck_cast,gsw_cv.delta_p_chck_cast); -[Igeo_strf_dyn_height_pc] = find((gsw_cv.geo_strf_dyn_height_pc - geo_strf_dyn_height_pc) >= gsw_cv.geo_strf_dyn_height_pc_ca | ... - (gsw_cv.dh_pmid - dh_pmid) >= gsw_cv.dh_pmid_ca); -if ~isempty(Igeo_strf_dyn_height_pc) +[gsw_cf.pt_SA, gsw_cf.pt_CT] = gsw_pt_first_derivatives(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Ipt_first_deriv] = find(abs(gsw_cv.pt_SA - gsw_cf.pt_SA) >= gsw_cv.pt_SA_ca |... + abs(gsw_cv.pt_CT - gsw_cf.pt_CT) >= gsw_cv.pt_CT_ca); +if ~isempty(gsw_cf.Ipt_first_deriv) try - cprintf('err','gsw_geo_strf_dyn_height_pc: Failed\n'); + cprintf('err','gsw_pt_first_derivatives: Failed\n'); catch - fprintf(2,'gsw_geo_strf_dyn_height_pc: Failed\n'); + fprintf(2,'gsw_pt_first_derivatives: Failed\n'); end gsw_chks = 0; end -geo_strf_McD_Klocker = gsw_geo_strf_McD_Klocker(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast,gsw_cv.Neutral_Density,gsw_cv.p_Neutral_Density); -[Igeo_strf_McD_Klocker] = find((gsw_cv.geo_strf_McD_Klocker - geo_strf_McD_Klocker) >= gsw_cv.geo_strf_McD_Klocker_ca); -if ~isempty(Igeo_strf_McD_Klocker) +[gsw_cf.pt_SA_SA, gsw_cf.pt_SA_CT, gsw_cf.pt_CT_CT] = gsw_pt_second_derivatives(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Ipt_second_deriv] = find(abs(gsw_cv.pt_SA_SA - gsw_cf.pt_SA_SA) >= gsw_cv.pt_SA_SA_ca | ... + abs(gsw_cv.pt_SA_CT - gsw_cf.pt_SA_CT) >= gsw_cv.pt_SA_CT_ca | ... + abs(gsw_cv.pt_CT_CT - gsw_cf.pt_CT_CT) >= gsw_cv.pt_CT_CT_ca); +if ~isempty(gsw_cf.Ipt_second_deriv) try - cprintf('err','gsw_geo_strf_McD_Klocker: Failed\n'); + cprintf('err','gsw_pt_second_derivatives: Failed\n'); catch - fprintf(2,'gsw_geo_strf_McD_Klocker: Failed\n'); + fprintf(2,'gsw_pt_second_derivatives: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -[geo_strf_McD_Klocker_pc, mk_p_mid] = gsw_geo_strf_McD_Klocker_pc(SA_chck_cast,CT_chck_cast,gsw_cv.delta_p_chck_cast,gsw_cv.Neutral_Density(1),3); -[Igeo_strf_McD_Klocker_pc] = find((gsw_cv.geo_strf_McD_Klocker_pc - geo_strf_McD_Klocker_pc) >= gsw_cv.geo_strf_McD_Klocker_pc_ca |... - (gsw_cv.mk_p_mid - mk_p_mid) >= gsw_cv.mk_p_mid_ca); -if ~isempty(Igeo_strf_McD_Klocker_pc) +%% freezing temperatures + +gsw_cf.CT_freezing = gsw_CT_freezing(gsw_cv.SA_chck_cast,gsw_cv.p_chck_cast,0); +[gsw_cf.ICT_freezing] = find(abs(gsw_cv.CT_freezing - gsw_cf.CT_freezing) >= gsw_cv.CT_freezing_ca); +if ~isempty(gsw_cf.ICT_freezing) try - cprintf('err','gsw_geo_strf_McD_Klocker_pc: Failed\n'); + cprintf('err','gsw_CT_freezing: Failed\n'); catch - fprintf(2,'gsw_geo_strf_McD_Klocker_pc: Failed\n'); + fprintf(2,'gsw_CT_freezing: Failed\n'); end gsw_chks = 0; end -geo_strf_Montgomery = gsw_geo_strf_Montgomery(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Igeo_strf_Montgomery] = find((gsw_cv.geo_strf_Montgomery - geo_strf_Montgomery) >= gsw_cv.geo_strf_Montgomery_ca); -if ~isempty(Igeo_strf_Montgomery) +gsw_cf.t_freezing = gsw_t_freezing(gsw_cv.SA_chck_cast,gsw_cv.p_chck_cast,0); +[gsw_cf.It_freezing] = find(abs(gsw_cv.t_freezing - gsw_cf.t_freezing) >= gsw_cv.t_freezing_ca); +if ~isempty(gsw_cf.It_freezing) try - cprintf('err','gsw_geo_strf_Montgomery: Failed\n'); + cprintf('err','gsw_t_freezing: Failed\n'); catch - fprintf(2,'gsw_geo_strf_Montgomery: Failed\n'); + fprintf(2,'gsw_t_freezing: Failed\n'); end gsw_chks = 0; end -geo_strf_Cunningham = gsw_geo_strf_Cunningham(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Igeo_strf_Cunningham] = find((gsw_cv.geo_strf_Cunningham - geo_strf_Cunningham) >= gsw_cv.geo_strf_Cunningham_ca); -if ~isempty(Igeo_strf_Cunningham) +gsw_cf.brineSA_CT = gsw_brineSA_CT(gsw_cf.CT_freezing,gsw_cv.p_chck_cast,0.5); +[gsw_cf.IbrineSA_CT] = find(abs(gsw_cv.brineSA_CT - gsw_cf.brineSA_CT) >= gsw_cv.brineSA_CT_ca); +if ~isempty(gsw_cf.IbrineSA_CT) try - cprintf('err','gsw_geo_strf_Cunningham: Failed\n'); + cprintf('err','gsw_brineSA_CT: Failed\n'); catch - fprintf(2,'gsw_geo_strf_Cunningham: Failed\n'); + fprintf(2,'gsw_brineSA_CT: Failed\n'); end gsw_chks = 0; end -[geo_str_velocity, gv_mid_lat, gv_mid_long] = gsw_geostrophic_velocity(geo_strf_dyn_height,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast,gsw_cv.p_chck_cast); -[Igeostrophic_velo] = find((gsw_cv.geo_str_velocity - geo_str_velocity) >= gsw_cv.geo_str_velocity_ca | ... - (gsw_cv.gv_mid_lat - gv_mid_lat) >= gsw_cv.gv_mid_lat_ca | ... - (gsw_cv.gv_mid_long - gv_mid_long) >= gsw_cv.gv_mid_long_ca); -if ~isempty(Igeostrophic_velo) +gsw_cf.brineSA_t = gsw_brineSA_t(gsw_cf.t_freezing,gsw_cv.p_chck_cast,0.5); +[gsw_cf.IbrineSA_t] = find(abs(gsw_cv.brineSA_t - gsw_cf.brineSA_t) >= gsw_cv.brineSA_t_ca); +if ~isempty(gsw_cf.IbrineSA_t) try - cprintf('err','gsw_geostrophic_velocity: Failed\n'); + cprintf('err','gsw_brineSA_t: Failed\n'); catch - fprintf(2,'gsw_geostrophic_velocity: Failed\n'); + fprintf(2,'gsw_brineSA_t: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -%% neutral and non-linear properties, based on the 25-term expression for density -cabbeling_CT25 = gsw_cabbeling_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Icabbeling_CT25] = find((gsw_cv.cabbeling_CT25 - cabbeling_CT25) >= gsw_cv.cabbeling_CT25_ca); -if ~isempty(Icabbeling_CT25) +%% isobaric melting enthalpy and isobaric + +gsw_cf.latentheat_melting = gsw_latentheat_melting(gsw_cv.SA_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ilatentheat_melting] = find(abs(gsw_cv.latentheat_melting - gsw_cf.latentheat_melting) >= gsw_cv.latentheat_melting_ca); +if ~isempty(gsw_cf.Ilatentheat_melting) try - cprintf('err','gsw_cabbeling_CT25: Failed\n'); + cprintf('err','gsw_latentheat_melting: Failed\n'); catch - fprintf(2,'gsw_cabbeling_CT25: Failed\n'); + fprintf(2,'gsw_latentheat_melting: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -thermobaric_CT25 = gsw_thermobaric_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Ithermobaric_CT25] = find((gsw_cv.thermobaric_CT25 - thermobaric_CT25) >= gsw_cv.thermobaric_CT25_ca); -if ~isempty(Ithermobaric_CT25) +gsw_cf.latentheat_evap_CT = gsw_latentheat_evap_CT(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Ilatentheat_evap_CT] = find(abs(gsw_cv.latentheat_evap_CT - gsw_cf.latentheat_evap_CT) >= gsw_cv.latentheat_evap_CT_ca); +if ~isempty(gsw_cf.Ilatentheat_evap_CT) try - cprintf('err','gsw_thermobaric_CT25: Failed\n'); + cprintf('err','gsw_latentheat_evap_CT: Failed\n'); catch - fprintf(2,'gsw_thermobaric_CT25: Failed\n'); + fprintf(2,'gsw_latentheat_evap_CT: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -if gsw_chks == 1 ; +gsw_cf.latentheat_evap_t = gsw_latentheat_evap_t(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast); +[gsw_cf.Ilatentheat_evap_t] = find(abs(gsw_cv.latentheat_evap_t - gsw_cf.latentheat_evap_t) >= gsw_cv.latentheat_evap_t_ca); +if ~isempty(gsw_cf.Ilatentheat_evap_t) try - cprintf('text','.'); + cprintf('err','gsw_latentheat_evap_t: Failed\n'); catch - fprintf(1,'.'); + fprintf(2,'gsw_latentheat_evap_t: Failed\n'); end + gsw_cf.gsw_chks = 0; end -isopycnal_slope_ratio_CT25 = gsw_isopycnal_slope_ratio_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr); -[Iisopycnal_slope_ratio_CT25] = find((gsw_cv.isopycnal_slope_ratio_CT25 - isopycnal_slope_ratio_CT25) >= gsw_cv.isopycnal_slope_ratio_CT25_ca); -if ~isempty(Iisopycnal_slope_ratio_CT25) +%% planet earth properties + +gsw_cf.f = gsw_f(gsw_cv.lat_chck_cast); +[gsw_cf.If] = find(abs(gsw_cv.f - gsw_cf.f) >= gsw_cv.f_ca); +if ~isempty(gsw_cf.If) try - cprintf('err','gsw_isopycnal_slope_ratio_CT25: Failed\n'); + cprintf('err','gsw_f: Failed\n'); catch - fprintf(2,'gsw_isopycnal_slope_ratio_CT25: Failed\n'); + fprintf(2,'gsw_f: Failed\n'); end gsw_chks = 0; end -[G_CT_CT25, p_mid_G_CT_CT25] = gsw_isopycnal_vs_ntp_CT_ratio_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr); -[IG_CT] = find((gsw_cv.G_CT_CT25 - G_CT_CT25) >= gsw_cv.G_CT_CT25_ca | ... - (gsw_cv.p_mid_G_CT_CT25 - p_mid_G_CT_CT25) >= gsw_cv.p_mid_G_CT_CT25_ca); -if ~isempty(IG_CT) +gsw_cf.grav = gsw_grav(gsw_cv.lat_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Igrav] = find(abs(gsw_cv.grav - gsw_cf.grav) >= gsw_cv.grav_ca); +if ~isempty(gsw_cf.Igrav) try - cprintf('err','gsw_isopycnal_vs_ntp_CT_ratio_CT25: Failed\n'); + cprintf('err','gsw_grav: Failed\n'); catch - fprintf(2,'gsw_isopycnal_vs_ntp_CT_ratio_CT25: Failed\n'); + fprintf(2,'gsw_grav: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -ntpptCT_CT25 = gsw_ntp_pt_vs_CT_ratio_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[IntpptCT_CT25] = find((gsw_cv.ntpptCT_CT25 - ntpptCT_CT25) >= gsw_cv.ntpptCT_CT25_ca); -if ~isempty(IntpptCT_CT25) +gsw_cf.distance = gsw_distance(gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Idistance] = find(abs(gsw_cv.distance - gsw_cf.distance) >= gsw_cv.distance_ca); +if ~isempty(gsw_cf.Idistance) try - cprintf('err','gsw_ntp_pt_vs_CT_ratio_CT25: Failed\n'); + cprintf('err','gsw_distance: Failed\n'); catch - fprintf(2,'gsw_ntp_pt_vs_CT_ratio_CT25: Failed\n'); + fprintf(2,'gsw_distance: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -%% basic thermodynamic properties +%% steric_height -rho = gsw_rho(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Irho] = find((gsw_cv.rho - rho) >= gsw_cv.rho_ca); -if ~isempty(Irho) +gsw_cf.steric_height = gsw_steric_height(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr); +[gsw_cf.Isteric_height] = find(abs(gsw_cv.steric_height - gsw_cf.steric_height) >= gsw_cv.steric_height_ca); +if ~isempty(gsw_cf.Isteric_height) try - cprintf('err','gsw_rho: Failed\n'); + cprintf('err','gsw_steric_height: Failed\n'); catch - fprintf(2,'gsw_rho: Failed\n'); + fprintf(2,'gsw_steric_height: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -pot_rho = gsw_pot_rho(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr); -[Ipot_rho] = find((gsw_cv.pot_rho - pot_rho) >= gsw_cv.pot_rho_ca); -if ~isempty(Ipot_rho) + +%% TEOS-10 constants + +gsw_cf.T0 = gsw_T0; +[gsw_cf.IT0] = find(abs(gsw_cv.T0 - gsw_cf.T0) > 1e-13); +if ~isempty(gsw_cf.IT0) try - cprintf('err','gsw_pot_rho: Failed\n'); + cprintf('err','gsw_T0: Failed\n'); catch - fprintf(2,'gsw_pot_rho: Failed\n'); + fprintf(2,'gsw_T0: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -specvol = gsw_specvol(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ispecvol] = find((gsw_cv.specvol - specvol) >= gsw_cv.specvol_ca); -if ~isempty(Ispecvol) +gsw_cf.P0 = gsw_P0; +[gsw_cf.IP0] = find(abs(gsw_cv.P0 - gsw_cf.P0) > 1e-13); +if ~isempty(gsw_cf.IP0) try - cprintf('err','gsw_specvol: Failed\n'); + cprintf('err','gsw_P0: Failed\n'); catch - fprintf(2,'gsw_specvol: Failed\n'); + fprintf(2,'gsw_P0: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -specvol_anom = gsw_specvol_anom(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ispecvol_anom] = find((gsw_cv.specvol_anom - specvol_anom) >= gsw_cv.specvol_anom_ca); -if ~isempty(Ispecvol_anom) +gsw_cf.SSO = gsw_SSO; +[gsw_cf.ISSO] = find(abs(gsw_cv.SSO - gsw_cf.SSO) > 1e-13); +if ~isempty(gsw_cf.ISSO) try - cprintf('err','gsw_specvol_anom: Failed\n'); + cprintf('err','gsw_SSO: Failed\n'); catch - fprintf(2,'gsw_specvol_anom: Failed\n'); + fprintf(2,'gsw_SSO: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -alpha_wrt_CT = gsw_alpha_wrt_CT(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ialpha_wrt_CT] = find((gsw_cv.alpha_wrt_CT - alpha_wrt_CT) >= gsw_cv.alpha_wrt_CT_ca); -if ~isempty(Ialpha_wrt_CT) +gsw_cf.uPS = gsw_uPS; +[gsw_cf.IuPS] = find(abs(gsw_cv.uPS - gsw_cf.uPS) > 1e-13); +if ~isempty(gsw_cf.IuPS) try - cprintf('err','gsw_alpha_wrt_CT: Failed\n'); + cprintf('err','gsw_uPS: Failed\n'); catch - fprintf(2,'gsw_alpha_wrt_CT: Failed\n'); + fprintf(2,'gsw_uPS: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -alpha_wrt_pt = gsw_alpha_wrt_pt(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ialpha_wrt_pt] = find((gsw_cv.alpha_wrt_pt - alpha_wrt_pt) >= gsw_cv.alpha_wrt_pt_ca); -if ~isempty(Ialpha_wrt_pt) +gsw_cf.cp0 = gsw_cp0; +[gsw_cf.Icp0] = find(abs(gsw_cv.cp0 - gsw_cf.cp0) > 1e-13); +if ~isempty(gsw_cf.Icp0) try - cprintf('err','gsw_alpha_wrt_pt: Failed\n'); + cprintf('err','gsw_cp0: Failed\n'); catch - fprintf(2,'gsw_alpha_wrt_pt: Failed\n'); + fprintf(2,'gsw_cp0: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -alpha_wrt_t = gsw_alpha_wrt_t(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ialpha_wrt_t] = find((gsw_cv.alpha_wrt_t - alpha_wrt_t) >= gsw_cv.alpha_wrt_t_ca); -if ~isempty(Ialpha_wrt_t) +gsw_cf.C3515 = gsw_C3515; +[gsw_cf.IC3515] = find(abs(gsw_cv.C3515 - gsw_cf.C3515) > 1e-13); +if ~isempty(gsw_cf.IC3515) try - cprintf('err','gsw_alpha_wrt_t: Failed\n'); + cprintf('err','gsw_C3515: Failed\n'); catch - fprintf(2,'gsw_alpha_wrt_t: Failed\n'); + fprintf(2,'gsw_C3515: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -if gsw_chks == 1 ; +gsw_cf.SonCl = gsw_SonCl; +[gsw_cf.ISonCl] = find(abs(gsw_cv.SonCl - gsw_cf.SonCl) > 1e-13); +if ~isempty(gsw_cf.ISonCl) try - cprintf('text','.'); + cprintf('err','gsw_SonCl: Failed\n'); catch - fprintf(1,'.'); + fprintf(2,'gsw_SonCl: Failed\n'); end + gsw_cf.gsw_chks = 0; end -beta_const_CT = gsw_beta_const_CT(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ibeta_const_CT] = find((gsw_cv.beta_const_CT - beta_const_CT) >= gsw_cv.beta_const_CT_ca); -if ~isempty(Ibeta_const_CT) +gsw_cf.valence_factor = gsw_valence_factor; +[gsw_cf.Ivalence_factor] = find(abs(gsw_cv.valence_factor - gsw_cf.valence_factor) > 1e-13); +if ~isempty(gsw_cf.Ivalence_factor) try - cprintf('err','gsw_beta_const_CT: Failed\n'); + cprintf('err','gsw_valence_factor: Failed\n'); catch - fprintf(2,'gsw_beta_const_CT: Failed\n'); + fprintf(2,'gsw_valence_factor: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -beta_const_pt = gsw_beta_const_pt(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ibeta_const_pt] = find((gsw_cv.beta_const_pt - beta_const_pt) >= gsw_cv.beta_const_pt_ca); -if ~isempty(Ibeta_const_pt) +gsw_cf.atomic_weight = gsw_atomic_weight; +[gsw_cf.Iatomic_weight] = find(abs(gsw_cv.atomic_weight - gsw_cf.atomic_weight) > 1e-13); +if ~isempty(gsw_cf.Iatomic_weight) try - cprintf('err','gsw_beta_const_pt: Failed\n'); + cprintf('err','gsw_atomic_weight: Failed\n'); catch - fprintf(2,'gsw_beta_const_pt: Failed\n'); + fprintf(2,'gsw_atomic_weight: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -beta_const_t = gsw_beta_const_t(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ibeta_const_t] = find((gsw_cv.beta_const_t - beta_const_t) >= gsw_cv.beta_const_t_ca); -if ~isempty(Ibeta_const_t) +%% density and enthalpy in terms of CT, derived from the exact Gibbs function + +gsw_cf.rho_CT_exact = gsw_rho_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Irho_CT_exact] = find(abs(gsw_cv.rho_CT_exact - gsw_cf.rho_CT_exact) >= gsw_cv.rho_CT_exact_ca); +if ~isempty(gsw_cf.Irho_CT_exact) try - cprintf('err','gsw_beta_const_t: Failed\n'); + cprintf('err','gsw_rho_CT_exact: Failed\n'); catch - fprintf(2,'gsw_beta_const_t: Failed\n'); + fprintf(2,'gsw_rho_CT_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -entropy = gsw_entropy(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ientropy] = find((gsw_cv.entropy - entropy) >= gsw_cv.entropy_ca); -if ~isempty(Ientropy) +gsw_cf.alpha_CT_exact = gsw_alpha_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ialpha_CT_exact] = find(abs(gsw_cv.alpha_CT_exact - gsw_cf.alpha_CT_exact) >= gsw_cv.alpha_CT_exact_ca); +if ~isempty(gsw_cf.Ialpha_CT_exact) try - cprintf('err','gsw_entropy: Failed\n'); + cprintf('err','gsw_alpha_CT_exact: Failed\n'); catch - fprintf(2,'gsw_entropy: Failed\n'); + fprintf(2,'gsw_alpha_CT_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -internal_energy = gsw_internal_energy(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Iinternal_energy] = find((gsw_cv.internal_energy - internal_energy) >= gsw_cv.internal_energy_ca); -if ~isempty(Iinternal_energy) +gsw_cf.beta_CT_exact = gsw_beta_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ibeta_CT_exact] = find(abs(gsw_cv.beta_CT_exact - gsw_cf.beta_CT_exact) >= gsw_cv.beta_CT_exact_ca); +if ~isempty(gsw_cf.Ibeta_CT_exact) try - cprintf('err','gsw_internal_energy: Failed\n'); + cprintf('err','gsw_beta_CT_exact: Failed\n'); catch - fprintf(2,'gsw_internal_energy: Failed\n'); + fprintf(2,'gsw_beta_CT_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -enthalpy = gsw_enthalpy(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ienthalpy] = find((gsw_cv.enthalpy - enthalpy) >= gsw_cv.enthalpy_ca); -if ~isempty(Ienthalpy) +[gsw_cf.rho_CTrab_exact, gsw_cf.alpha_CTrab_exact, gsw_cf.beta_CTrab_exact] = gsw_rho_alpha_beta_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Irho_CTrab_exact] = find(abs(gsw_cv.rho_CTrab_exact - gsw_cf.rho_CTrab_exact) >= gsw_cv.rho_CT_exact_rab_ca | ... + abs(gsw_cv.alpha_CTrab_exact - gsw_cf.alpha_CTrab_exact) >= gsw_cv.alpha_CT_exact_rab_ca | ... + abs(gsw_cv.beta_CTrab_exact - gsw_cf.beta_CTrab_exact) >= gsw_cv.beta_CT_exact_rab_ca); +if ~isempty(gsw_cf.Irho_CTrab_exact) try - cprintf('err','gsw_enthalpy: Failed\n'); + cprintf('err','gsw_rho_alpha_beta_CT_exact: Failed\n'); catch - fprintf(2,'gsw_enthalpy: Failed\n'); + fprintf(2,'gsw_rho_alpha_beta_CT_exact: Failed\n'); end gsw_chks = 0; end -cp = gsw_cp(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Icp] = find((gsw_cv.cp - cp) >= gsw_cv.cp_ca); -if ~isempty(Icp) +gsw_cf.specvol_CT_exact = gsw_specvol_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ispecvol_CT_exact] = find(abs(gsw_cv.specvol_CT_exact - gsw_cf.specvol_CT_exact) >= gsw_cv.specvol_CT_exact_ca); +if ~isempty(gsw_cf.Ispecvol_CT_exact) try - cprintf('err','gsw_cp: Failed\n'); + cprintf('err','gsw_specvol_CT_exact: Failed\n'); catch - fprintf(2,'gsw_cp: Failed\n'); + fprintf(2,'gsw_specvol_CT_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -isochoric_heat_cap = gsw_isochoric_heat_cap(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Iisochoric_heat_cap] = find((gsw_cv.isochoric_heat_cap - isochoric_heat_cap) >= gsw_cv.isochoric_heat_cap_ca); -if ~isempty(Iisochoric_heat_cap) +gsw_cf.specvol_anom_CT_exact = gsw_specvol_anom_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ispecvol_anom_CT_exact] = find(abs(gsw_cv.specvol_anom_CT_exact - gsw_cf.specvol_anom_CT_exact) >= gsw_cv.specvol_anom_CT_exact_ca); +if ~isempty(gsw_cf.Ispecvol_anom_CT_exact) try - cprintf('err','gsw_isochoric_heat_cap: Failed\n'); + cprintf('err','gsw_specvol_anom_CT_exact: Failed\n'); catch - fprintf(2,'gsw_isochoric_heat_cap: Failed\n'); + fprintf(2,'gsw_specvol_anom_CT_exact: Failed\n'); end gsw_chks = 0; end -chem_potential = gsw_chem_potential_relative(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ichem_potential] = find((gsw_cv.chem_potential - chem_potential) >= gsw_cv.chem_potential_ca); -if ~isempty(Ichem_potential) +gsw_cf.sigma0_CT_exact = gsw_sigma0_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Isigma0_CT_exact] = find(abs(gsw_cv.sigma0_CT_exact - gsw_cf.sigma0_CT_exact) >= gsw_cv.sigma0_CT_exact_ca); +if ~isempty(gsw_cf.Isigma0_CT_exact) try - cprintf('err','gsw_chem_potential_relative: Failed\n'); + cprintf('err','gsw_sigma0_CT_exact: Failed\n'); catch - fprintf(2,'gsw_chem_potential_relative: Failed\n'); + fprintf(2,'gsw_sigma0_CT_exact: Failed\n'); end gsw_chks = 0; end -chem_potential_water = gsw_chem_potential_water(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ichem_potential_water] = find((gsw_cv.chem_potential_water - chem_potential_water) >= gsw_cv.chem_potential_water_ca); -if ~isempty(Ichem_potential_water) +gsw_cf.sigma1_CT_exact = gsw_sigma1_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Isigma1_CT_exact] = find(abs(gsw_cv.sigma1_CT_exact - gsw_cf.sigma1_CT_exact) >= gsw_cv.sigma1_CT_exact_ca); +if ~isempty(gsw_cf.Isigma1_CT_exact) try - cprintf('err','gsw_chem_potential_water: Failed\n'); + cprintf('err','gsw_sigma1_CT_exact: Failed\n'); catch - fprintf(2,'gsw_chem_potential_water: Failed\n'); + fprintf(2,'gsw_sigma1_CT_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -if gsw_chks == 1 ; +gsw_cf.sigma2_CT_exact = gsw_sigma2_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Isigma2_CT_exact] = find(abs(gsw_cv.sigma2_CT_exact - gsw_cf.sigma2_CT_exact) >= gsw_cv.sigma2_CT_exact_ca); +if ~isempty(gsw_cf.Isigma2_CT_exact) try - cprintf('text','.'); + cprintf('err','gsw_sigma2_CT_exact: Failed\n'); catch - fprintf(1,'.'); + fprintf(2,'gsw_sigma2_CT_exact: Failed\n'); end + gsw_chks = 0; end -chem_potential_salt = gsw_chem_potential_salt(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ichem_potential_salt] = find((gsw_cv.chem_potential_salt - chem_potential_salt) >= gsw_cv.chem_potential_salt_ca); -if ~isempty(Ichem_potential_salt) +gsw_cf.sigma3_CT_exact = gsw_sigma3_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Isigma3_CT_exact] = find(abs(gsw_cv.sigma3_CT_exact - gsw_cf.sigma3_CT_exact) >= gsw_cv.sigma3_CT_exact_ca); +if ~isempty(gsw_cf.Isigma3_CT_exact) try - cprintf('err','gsw_chem_potential_salt: Failed\n'); + cprintf('err','gsw_sigma3_CT_exact: Failed\n'); catch - fprintf(2,'gsw_chem_potential_salt: Failed\n'); + fprintf(2,'gsw_sigma3_CT_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -Helmholtz_energy = gsw_Helmholtz_energy(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[IHelmholtz_energy] = find((gsw_cv.Helmholtz_energy - Helmholtz_energy) >= gsw_cv.Helmholtz_energy_ca); -if ~isempty(IHelmholtz_energy) +gsw_cf.sigma4_CT_exact = gsw_sigma4_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast); +[gsw_cf.Isigma4_CT_exact] = find(abs(gsw_cv.sigma4_CT_exact - gsw_cf.sigma4_CT_exact) >= gsw_cv.sigma4_CT_exact_ca); +if ~isempty(gsw_cf.Isigma4_CT_exact) try - cprintf('err','gsw_Helmholtz_energy: Failed\n'); + cprintf('err','gsw_sigma4_CT_exact: Failed\n'); catch - fprintf(2,'gsw_Helmholtz_energy: Failed\n'); + fprintf(2,'gsw_sigma4_CT_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -sound_speed = gsw_sound_speed(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Isound_speed] = find((gsw_cv.sound_speed - sound_speed) >= gsw_cv.sound_speed_ca); -if ~isempty(Isound_speed) +gsw_cf.sound_speed_CT_exact = gsw_sound_speed_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Isound_speed_CT_exact] = find(abs(gsw_cv.sound_speed_CT_exact - gsw_cf.sound_speed_CT_exact) >= gsw_cv.sound_speed_CT_exact_ca); +if ~isempty(gsw_cf.Isound_speed_CT_exact) try - cprintf('err','gsw_sound_speed: Failed\n'); + cprintf('err','gsw_sound_speed_CT_exact: Failed\n'); catch - fprintf(2,'gsw_sound_speed: Failed\n'); + fprintf(2,'gsw_sound_speed_CT_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -kappa = gsw_kappa(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ikappa] = find((gsw_cv.kappa - kappa) >= gsw_cv.kappa_ca); -if ~isempty(Ikappa) +gsw_cf.internal_energy_CT_exact = gsw_internal_energy_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Iinternal_energy_CT_exact] = find(abs(gsw_cv.internal_energy_CT_exact - gsw_cf.internal_energy_CT_exact) >= gsw_cv.internal_energy_CT_exact_ca); +if ~isempty(gsw_cf.Iinternal_energy_CT_exact) try - cprintf('err','gsw_kappa: Failed\n'); + cprintf('err','gsw_internal_energy_CT_exact: Failed\n'); catch - fprintf(2,'gsw_kappa: Failed\n'); + fprintf(2,'gsw_internal_energy_CT_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -kappa_const_t = gsw_kappa_const_t(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Ikappa_const_t] = find((gsw_cv.kappa_const_t - kappa_const_t) >= gsw_cv.kappa_const_t_ca); -if ~isempty(Ikappa_const_t) +gsw_cf.enthalpy_CT_exact = gsw_enthalpy_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ienthalpy_CT_exact] = find(abs(gsw_cv.enthalpy_CT_exact - gsw_cf.enthalpy_CT_exact) >= gsw_cv.enthalpy_CT_exact_ca); +if ~isempty(gsw_cf.Ienthalpy_CT_exact) try - cprintf('err','gsw_kappa_const_t: Failed\n'); + cprintf('err','gsw_enthalpy_CT_exact: Failed\n'); catch - fprintf(2,'gsw_kappa_const_t: Failed\n'); + fprintf(2,'gsw_enthalpy_CT_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -adiabatic_lapse_rate = gsw_adiabatic_lapse_rate(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Iadiabatic_lapse_rate] = find((gsw_cv.adiabatic_lapse_rate - adiabatic_lapse_rate) >= gsw_cv.adiabatic_lapse_rate_ca); -if ~isempty(Iadiabatic_lapse_rate) +gsw_cf.enthalpy_diff_CT_exact = gsw_enthalpy_diff_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast_shallow,gsw_cv.p_chck_cast_deep); +[gsw_cf.Ienthalpy_diff_CT_exact] = find(abs(gsw_cv.enthalpy_diff_CT_exact - gsw_cf.enthalpy_diff_CT_exact) >= gsw_cv.enthalpy_diff_CT_exact_ca); +if ~isempty(gsw_cf.Ienthalpy_diff_CT_exact) try - cprintf('err','gsw_adiabatic_lapse_rate: Failed\n'); + cprintf('err','gsw_enthalpy_diff_CT_exact: Failed\n'); catch - fprintf(2,'gsw_adiabatic_lapse_rate: Failed\n'); + fprintf(2,'gsw_enthalpy_diff_CT_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -molality = gsw_molality(SA_chck_cast); -[Imolality] = find((gsw_cv.molality - molality) >= gsw_cv.molality_ca); -if ~isempty(Imolality) +gsw_cf.dynamic_enthalpy_CT_exact = gsw_dynamic_enthalpy_CT_exact(gsw_cv.SA_chck_cast,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Idynamic_enthalpy_CT_exact] = find(abs(gsw_cv.dynamic_enthalpy_CT_exact - gsw_cf.dynamic_enthalpy_CT_exact) >= gsw_cv.dynamic_enthalpy_CT_exact_ca); +if ~isempty(gsw_cf.Idynamic_enthalpy_CT_exact) try - cprintf('err','gsw_molality: Failed\n'); + cprintf('err','gsw_dynamic_enthalpy_CT_exact: Failed\n'); catch - fprintf(2,'gsw_molality: Failed\n'); + fprintf(2,'gsw_dynamic_enthalpy_CT_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -ionic_strength = gsw_ionic_strength(SA_chck_cast); -[Iionic_strength] = find((gsw_cv.ionic_strength - ionic_strength) >= gsw_cv.ionic_strength_ca); -if ~isempty(Iionic_strength) +gsw_cf.SA_from_rho_CT_exact = gsw_SA_from_rho_CT_exact(gsw_cf.rho_CT_exact,gsw_cv.CT_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.ISA_from_rho_CT_exact] = find(abs(gsw_cv.SA_from_rho_CT_exact - gsw_cf.SA_from_rho_CT_exact) >= gsw_cv.SA_from_rho_CT_exact_ca); +if ~isempty(gsw_cf.ISA_from_rho_CT_exact) try - cprintf('err','gsw_ionic_strength: Failed\n'); + cprintf('err','gsw_SA_from_rho_CT_exact: Failed\n'); catch - fprintf(2,'gsw_ionic_strength: Failed\n'); + fprintf(2,'gsw_SA_from_rho_CT_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -osmotic_coefficient = gsw_osmotic_coefficient(SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Iosmotic_coefficient] = find((gsw_cv.osmotic_coefficient - osmotic_coefficient) >= gsw_cv.osmotic_coefficient_ca); -if ~isempty(Iosmotic_coefficient) +gsw_cf.CT_from_rho_exact = gsw_CT_from_rho_exact(gsw_cf.rho_CT_exact,gsw_cv.SA_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.ICT_from_rho_exact] = find(abs(gsw_cv.CT_from_rho_exact - gsw_cf.CT_from_rho_exact) >= gsw_cv.CT_from_rho_exact_ca); +if ~isempty(gsw_cf.ICT_from_rho_exact) try - cprintf('err','gsw_osmotic_coefficient: Failed\n'); + cprintf('err','gsw_CT_from_rho_exact: Failed\n'); catch - fprintf(2,'gsw_osmotic_coefficient: Failed\n'); + fprintf(2,'gsw_CT_from_rho_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -[t_maxden, pt_maxden, CT_maxden] = gsw_temps_maxdensity(SA_chck_cast,gsw_cv.p_chck_cast); -[Itemps_maxd] = find((gsw_cv.t_maxden - t_maxden) >= gsw_cv.t_maxden_ca | ... - (gsw_cv.pt_maxden - pt_maxden) >= gsw_cv.pt_maxden_ca | ... - (gsw_cv.CT_maxden - CT_maxden) >= gsw_cv.CT_maxden_ca); -if ~isempty(Itemps_maxd) +gsw_cf.CT_maxdensity_exact = gsw_CT_maxdensity_exact(gsw_cv.SA_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.ICT_maxdensity_exact] = find(abs(gsw_cv.CT_maxdensity_exact - gsw_cf.CT_maxdensity_exact) >= gsw_cv.CT_maxdensity_exact_ca); +if ~isempty(gsw_cf.ICT_maxdensity_exact) try - cprintf('err','gsw_temps_maxdensity: Failed\n'); + cprintf('err','gsw_CT_maxdensity_exact: Failed\n'); catch - fprintf(2,'gsw_temps_maxdensity: Failed\n'); + fprintf(2,'gsw_CT_maxdensity_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -if gsw_chks == 1 ; +%% basic thermodynamic properties interms of in-situ t, derived from the exact Gibbs function + +gsw_cf.rho_t_exact = gsw_rho_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Irho_t_exact] = find(abs(gsw_cv.rho_t_exact - gsw_cf.rho_t_exact) >= gsw_cv.rho_t_exact_ca); +if ~isempty(gsw_cf.Irho_t_exact) try - cprintf('text','.'); + cprintf('err','gsw_rho_t_exact: Failed\n'); catch - fprintf(1,'.'); + fprintf(2,'gsw_rho_t_exact: Failed\n'); end + gsw_cf.gsw_chks = 0; end -%% basic thermodynamic properties in terms of CT and pt - -rho_CT = gsw_rho_CT(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Irho_CT] = find((gsw_cv.rho_CT - rho_CT) >= gsw_cv.rho_CT_ca); -if ~isempty(Irho_CT) +gsw_cf.pot_rho_t_exact = gsw_pot_rho_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast,gsw_cv.pr); +[gsw_cf.Ipot_rho_t_exact] = find(abs(gsw_cv.pot_rho_t_exact - gsw_cf.pot_rho_t_exact) >= gsw_cv.pot_rho_t_exact_ca); +if ~isempty(gsw_cf.Ipot_rho_t_exact) try - cprintf('err','gsw_rho_CT: Failed\n'); + cprintf('err','gsw_pot_rho_t_exact: Failed\n'); catch - fprintf(2,'gsw_rho_CT: Failed\n'); + fprintf(2,'gsw_pot_rho_t_exact: Failed\n'); end gsw_chks = 0; end -[rho_CTrab, alpha_CTrab, beta_CTrab] = gsw_rho_alpha_beta_CT(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Irho_alpha_beta] = find((gsw_cv.rho_CTrab - rho_CTrab) >= gsw_cv.rho_CTrab_ca |... - (gsw_cv.alpha_CTrab - alpha_CTrab) >= gsw_cv.alpha_CTrab_ca |... - (gsw_cv.beta_CTrab - beta_CTrab) >= gsw_cv.beta_CTrab_ca); -if ~isempty(Irho_alpha_beta) +gsw_cf.sigma0_pt0_exact = gsw_sigma0_pt0_exact(gsw_cv.SA_chck_cast,gsw_cf.pt0_from_t); +[gsw_cf.Isigma0_pt0_exact] = find(abs(gsw_cv.sigma0_pt0_exact - gsw_cf.sigma0_pt0_exact) >= gsw_cv.sigma0_pt0_exact_ca); +if ~isempty(gsw_cf.Isigma0_pt0_exact) try - cprintf('err','gsw_rho_alpha_beta_CT: Failed\n'); + cprintf('err','gsw_sigma0_pt0_exact: Failed\n'); catch - fprintf(2,'gsw_rho_alpha_beta_CT: Failed\n'); + fprintf(2,'gsw_sigma0_pt0_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -specvol_CT = gsw_specvol_CT25(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Ispecvol_CT] = find((gsw_cv.specvol_CT - specvol_CT) >= gsw_cv.specvol_CT_ca); -if ~isempty(Ispecvol_CT) +gsw_cf.alpha_wrt_CT_t_exact = gsw_alpha_wrt_CT_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ialpha_wrt_CT_t_exact] = find(abs(gsw_cv.alpha_wrt_CT_t_exact - gsw_cf.alpha_wrt_CT_t_exact) >= gsw_cv.alpha_wrt_CT_t_exact_ca); +if ~isempty(gsw_cf.Ialpha_wrt_CT_t_exact) try - cprintf('err','gsw_specvol_CT25: Failed\n'); + cprintf('err','gsw_alpha_wrt_CT_t_exact: Failed\n'); catch - fprintf(2,'gsw_specvol_CT25: Failed\n'); + fprintf(2,'gsw_alpha_wrt_CT_t_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -specvol_anom_CT = gsw_specvol_anom_CT(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Ispecvol_anom_CT] = find((gsw_cv.specvol_anom_CT - specvol_anom_CT) >= gsw_cv.specvol_anom_CT_ca); -if ~isempty(Ispecvol_anom_CT) +gsw_cf.alpha_wrt_pt_t_exact = gsw_alpha_wrt_pt_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ialpha_wrt_pt_t_exact] = find(abs(gsw_cv.alpha_wrt_pt_t_exact - gsw_cf.alpha_wrt_pt_t_exact) >= gsw_cv.alpha_wrt_pt_t_exact_ca); +if ~isempty(gsw_cf.Ialpha_wrt_pt_t_exact) try - cprintf('err','gsw_specvol_anom_CT: Failed\n'); + cprintf('err','gsw_alpha_wrt_pt_t_exact: Failed\n'); catch - fprintf(2,'gsw_specvol_anom_CT: Failed\n'); + fprintf(2,'gsw_alpha_wrt_pt_t_exact: Failed\n'); end gsw_chks = 0; end -sigma0_CT = gsw_sigma0_CT(SA_chck_cast,CT_chck_cast); -[Isigma0_CT] = find((gsw_cv.sigma0_CT - sigma0_CT) >= gsw_cv.sigma0_CT_ca); -if ~isempty(Isigma0_CT) +gsw_cf.alpha_wrt_t_exact = gsw_alpha_wrt_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ialpha_wrt_t_exact] = find(abs(gsw_cv.alpha_wrt_t_exact - gsw_cf.alpha_wrt_t_exact) >= gsw_cv.alpha_wrt_t_exact_ca); +if ~isempty(gsw_cf.Ialpha_wrt_t_exact) try - cprintf('err','gsw_sigma0_CT: Failed\n'); + cprintf('err','gsw_alpha_wrt_t_exact: Failed\n'); catch - fprintf(2,'gsw_sigma0_CT: Failed\n'); + fprintf(2,'gsw_alpha_wrt_t_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -sigma1_CT = gsw_sigma1_CT(SA_chck_cast,CT_chck_cast); -[Isigma1_CT] = find((gsw_cv.sigma1_CT - sigma1_CT) >= gsw_cv.sigma1_CT_ca); -if ~isempty(Isigma1_CT) +gsw_cf.beta_const_CT_t_exact = gsw_beta_const_CT_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ibeta_const_CT_t_exact] = find(abs(gsw_cv.beta_const_CT_t_exact - gsw_cf.beta_const_CT_t_exact) >= gsw_cv.beta_const_CT_t_exact_ca); +if ~isempty(gsw_cf.Ibeta_const_CT_t_exact) try - cprintf('err','gsw_sigma1_CT: Failed\n'); + cprintf('err','gsw_beta_const_CT_t_exact: Failed\n'); catch - fprintf(2,'gsw_sigma1_CT: Failed\n'); + fprintf(2,'gsw_beta_const_CT_t_exact: Failed\n'); end gsw_chks = 0; end -sigma2_CT = gsw_sigma2_CT(SA_chck_cast,CT_chck_cast); -[Isigma2_CT] = find((gsw_cv.sigma2_CT - sigma2_CT) >= gsw_cv.sigma2_CT_ca); -if ~isempty(Isigma2_CT) +gsw_cf.beta_const_pt_t_exact = gsw_beta_const_pt_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ibeta_const_pt_t_exact] = find(abs(gsw_cv.beta_const_pt_t_exact - gsw_cf.beta_const_pt_t_exact) >= gsw_cv.beta_const_pt_t_exact_ca); +if ~isempty(gsw_cf.Ibeta_const_pt_t_exact) try - cprintf('err','gsw_sigma2_CT: Failed\n'); + cprintf('err','gsw_beta_const_pt_t_exact: Failed\n'); catch - fprintf(2,'gsw_sigma2_CT: Failed\n'); + fprintf(2,'gsw_beta_const_pt_t_exact: Failed\n'); end gsw_chks = 0; end -sigma3_CT = gsw_sigma3_CT(SA_chck_cast,CT_chck_cast); -[Isigma3_CT] = find((gsw_cv.sigma3_CT - sigma3_CT) >= gsw_cv.sigma3_CT_ca); -if ~isempty(Isigma3_CT) +gsw_cf.beta_const_t_exact = gsw_beta_const_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ibeta_const_t_exact] = find(abs(gsw_cv.beta_const_t_exact - gsw_cf.beta_const_t_exact) >= gsw_cv.beta_const_t_exact_ca); +if ~isempty(gsw_cf.Ibeta_const_t_exact) try - cprintf('err','gsw_sigma3_CT: Failed\n'); + cprintf('err','gsw_beta_const_t_exact: Failed\n'); catch - fprintf(2,'gsw_sigma3_CT: Failed\n'); + fprintf(2,'gsw_beta_const_t_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -sigma4_CT = gsw_sigma4_CT(SA_chck_cast,CT_chck_cast); -[Isigma4_CT] = find((gsw_cv.sigma4_CT - sigma4_CT) >= gsw_cv.sigma4_CT_ca); -if ~isempty(Isigma4_CT) +gsw_cf.specvol_t_exact = gsw_specvol_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ispecvol_t_exact] = find(abs(gsw_cv.specvol_t_exact - gsw_cf.specvol_t_exact) >= gsw_cv.specvol_t_exact_ca); +if ~isempty(gsw_cf.Ispecvol_t_exact) try - cprintf('err','gsw_sigma4_CT: Failed\n'); + cprintf('err','gsw_specvol_t_exact: Failed\n'); catch - fprintf(2,'gsw_sigma4_CT: Failed\n'); + fprintf(2,'gsw_specvol_t_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -enthalpy_CT = gsw_enthalpy_CT(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Ienthalpy_CT] = find((gsw_cv.enthalpy_CT - enthalpy_CT) >= gsw_cv.enthalpy_CT_ca); -if ~isempty(Ienthalpy_CT) +gsw_cf.specvol_anom_t_exact = gsw_specvol_anom_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ispecvol_anom_t_exact] = find(abs(gsw_cv.specvol_anom_t_exact - gsw_cf.specvol_anom_t_exact) >= gsw_cv.specvol_anom_t_exact_ca); +if ~isempty(gsw_cf.Ispecvol_anom_t_exact) try - cprintf('err','gsw_enthalpy_CT: Failed\n'); + cprintf('err','gsw_specvol_anom_t_exact: Failed\n'); catch - fprintf(2,'gsw_enthalpy_CT: Failed\n'); + fprintf(2,'gsw_specvol_anom_t_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -if gsw_chks == 1 ; +if gsw_cf.gsw_chks == 1 ; try cprintf('text','.'); catch @@ -980,256 +1571,266 @@ end end -enthalpy_diff_CT = gsw_enthalpy_diff_CT(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast_shallow,gsw_cv.p_chck_cast_deep); -[Ienthalpy_diff_CT] = find((gsw_cv.enthalpy_diff_CT - enthalpy_diff_CT) >= gsw_cv.enthalpy_diff_CT_ca); -if ~isempty(Ienthalpy_diff_CT) + +gsw_cf.sound_speed_t_exact = gsw_sound_speed_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Isound_speed_t_exact] = find(abs(gsw_cv.sound_speed_t_exact - gsw_cf.sound_speed_t_exact) >= gsw_cv.sound_speed_t_exact_ca); +if ~isempty(gsw_cf.Isound_speed_t_exact) try - cprintf('err','gsw_enthalpy_diff_CT: Failed\n'); + cprintf('err','gsw_sound_speed_t_exact: Failed\n'); catch - fprintf(2,'gsw_enthalpy_diff_CT: Failed\n'); + fprintf(2,'gsw_sound_speed_t_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end - -entropy_from_pt = gsw_entropy_from_pt(SA_chck_cast,pt); -[Ientropy_from_pt] = find((gsw_cv.entropy_from_pt - entropy_from_pt) >= gsw_cv.entropy_from_pt_ca); -if ~isempty(Ientropy_from_pt) + +gsw_cf.kappa_t_exact = gsw_kappa_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ikappa_t_exact] = find(abs(gsw_cv.kappa_t_exact - gsw_cf.kappa_t_exact) >= gsw_cv.kappa_t_exact_ca); +if ~isempty(gsw_cf.Ikappa_t_exact) try - cprintf('err','gsw_entropy_from_pt: Failed\n'); + cprintf('err','gsw_kappa_t_exact: Failed\n'); catch - fprintf(2,'gsw_entropy_from_pt: Failed\n'); + fprintf(2,'gsw_kappa_t_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -entropy_from_CT = gsw_entropy_from_CT(SA_chck_cast,CT_chck_cast); -[Ientropy_from_CT] = find((gsw_cv.entropy_from_CT - entropy_from_CT) >= gsw_cv.entropy_from_CT_ca); -if ~isempty(Ientropy_from_CT) +gsw_cf.kappa_const_t_exact = gsw_kappa_const_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ikappa_const_t_exact] = find(abs(gsw_cv.kappa_const_t_exact - gsw_cf.kappa_const_t_exact) >= gsw_cv.kappa_const_t_exact_ca); +if ~isempty(gsw_cf.Ikappa_const_t_exact) try - cprintf('err','gsw_entropy_from_CT: Failed\n'); + cprintf('err','gsw_kappa_const_t_exact: Failed\n'); catch - fprintf(2,'gsw_entropy_from_CT: Failed\n'); + fprintf(2,'gsw_kappa_const_t_exact: Failed\n'); end gsw_chks = 0; end -CT_from_entropy = gsw_CT_from_entropy(SA_chck_cast,entropy); -[ICT_from_entropy] = find((gsw_cv.CT_from_entropy - CT_from_entropy) >= gsw_cv.CT_from_entropy_ca); -if ~isempty(ICT_from_entropy) +gsw_cf.internal_energy_t_exact = gsw_internal_energy_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Iinternal_energy_t_exact] = find(abs(gsw_cv.internal_energy_t_exact - gsw_cf.internal_energy_t_exact) >= gsw_cv.internal_energy_t_exact_ca); +if ~isempty(gsw_cf.Iinternal_energy_t_exact) try - cprintf('err','gsw_CT_from_entropy: Failed\n'); + cprintf('err','gsw_internal_energy_t_exact: Failed\n'); catch - fprintf(2,'gsw_CT_from_entropy: Failed\n'); + fprintf(2,'gsw_internal_energy_t_exact: Failed\n'); end gsw_chks = 0; end -pt_from_entropy = gsw_pt_from_entropy(SA_chck_cast,entropy); -[Ipt_from_entropy] = find((gsw_cv.pt_from_entropy - pt_from_entropy) >= gsw_cv.pt_from_entropy_ca); -if ~isempty(Ipt_from_entropy) +gsw_cf.enthalpy_t_exact = gsw_enthalpy_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ienthalpy_t_exact] = find(abs(gsw_cv.enthalpy_t_exact - gsw_cf.enthalpy_t_exact) >= gsw_cv.enthalpy_t_exact_ca); +if ~isempty(gsw_cf.Ienthalpy_t_exact) try - cprintf('err','gsw_pt_from_entropy: Failed\n'); + cprintf('err','gsw_enthalpy_t_exact: Failed\n'); catch - fprintf(2,'gsw_pt_from_entropy: Failed\n'); + fprintf(2,'gsw_enthalpy_t_exact: Failed\n'); end gsw_chks = 0; end -%% derivatives of enthalpy, entropy, CT and pt - -[CT_SA, CT_pt] = gsw_CT_first_derivatives(SA_chck_cast,pt); -[ICT_first_deriv] = find((gsw_cv.CT_SA - CT_SA) >= gsw_cv.CT_SA_ca | ... - (gsw_cv.CT_pt - CT_pt) >= gsw_cv.CT_pt_ca); -if ~isempty(ICT_first_deriv) +gsw_cf.dynamic_enthalpy_t_exact = gsw_dynamic_enthalpy_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Idynamic_enthalpy_t_exact] = find(abs(gsw_cv.dynamic_enthalpy_t_exact - gsw_cf.dynamic_enthalpy_t_exact) >= gsw_cv.dynamic_enthalpy_t_exact_ca); +if ~isempty(gsw_cf.Idynamic_enthalpy_t_exact) try - cprintf('err','gsw_CT_first_derivatives: Failed\n'); + cprintf('err','gsw_dynamic_enthalpy_t_exact: Failed\n'); catch - fprintf(2,'gsw_CT_first_derivatives: Failed\n'); + fprintf(2,'gsw_dynamic_enthalpy_t_exact: Failed\n'); end gsw_chks = 0; end -[CT_SA_SA, CT_SA_pt, CT_pt_pt] = gsw_CT_second_derivatives(SA_chck_cast,pt); -[ICT_second_deriv] = find((gsw_cv.CT_SA_SA - CT_SA_SA) >= gsw_cv.CT_SA_SA_ca | ... - (gsw_cv.CT_SA_pt - CT_SA_pt) >= gsw_cv.CT_SA_pt_ca | ... - (gsw_cv.CT_pt_pt - CT_pt_pt) >= gsw_cv.CT_pt_pt_ca); -if ~isempty(ICT_second_deriv) +gsw_cf.SA_from_rho_t_exact = gsw_SA_from_rho_t_exact(gsw_cf.rho_t_exact,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.ISA_from_rho_t_exact] = find(abs(gsw_cv.SA_from_rho_t_exact - gsw_cf.SA_from_rho_t_exact) >= gsw_cv.SA_from_rho_t_exact_ca); +if ~isempty(gsw_cf.ISA_from_rho_t_exact) try - cprintf('err','gsw_CT_second_derivatives: Failed\n'); + cprintf('err','gsw_SA_from_rho_t_exact: Failed\n'); catch - fprintf(2,'gsw_CT_second_derivatives: Failed\n'); + fprintf(2,'gsw_SA_from_rho_t_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -[h_SA, h_CT, h_P] = gsw_enthalpy_first_derivatives(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Ienthalpy_first_deriv] = find((gsw_cv.h_SA - h_SA) >= gsw_cv.h_SA_ca | ... - (gsw_cv.h_CT - h_CT) >= gsw_cv.h_CT_ca | ... - (gsw_cv.h_P - h_P) >= gsw_cv.h_P_ca); -if ~isempty(Ienthalpy_first_deriv) +gsw_cf.t_from_rho_exact = gsw_t_from_rho_exact(gsw_cf.rho_t_exact,gsw_cv.SA_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.It_from_rho_exact] = find(abs(gsw_cv.t_from_rho_exact - gsw_cf.t_from_rho_exact) >= gsw_cv.t_from_rho_exact_ca); +if ~isempty(gsw_cf.It_from_rho_exact) try - cprintf('err','gsw_enthalpy_first_derivatives: Failed\n'); + cprintf('err','gsw_t_from_rho_exact: Failed\n'); catch - fprintf(2,'gsw_enthalpy_first_derivatives: Failed\n'); + fprintf(2,'gsw_t_from_rho_exact: Failed\n'); end gsw_chks = 0; end -[h_SA_SA, h_SA_CT, h_CT_CT] = gsw_enthalpy_second_derivatives(SA_chck_cast,CT_chck_cast,gsw_cv.p_chck_cast); -[Ienthalpy_second_deriv] = find((gsw_cv.h_SA_SA - h_SA_SA) >= gsw_cv.h_SA_SA_ca | ... - (gsw_cv.h_SA_CT - h_SA_CT) >= gsw_cv.h_SA_CT_ca | ... - (gsw_cv.h_CT_CT - h_CT_CT) >= gsw_cv.h_CT_CT_ca); -if ~isempty(Ienthalpy_second_deriv) +gsw_cf.t_maxdensity_exact = gsw_t_maxdensity_exact(gsw_cv.SA_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.It_maxdensity_exact] = find(abs(gsw_cv.t_maxdensity_exact - gsw_cf.t_maxdensity_exact) >= gsw_cv.t_maxdensity_exact_ca); +if ~isempty(gsw_cf.It_maxdensity_exact) try - cprintf('err','gsw_enthalpy_second_derivatives: Failed\n'); + cprintf('err','gsw_t_maxdensity_exact: Failed\n'); catch - fprintf(2,'gsw_enthalpy_second_derivatives: Failed\n'); + fprintf(2,'gsw_t_maxdensity_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -[eta_SA, eta_CT] = gsw_entropy_first_derivatives(SA_chck_cast,CT_chck_cast); -[Ientropy_first_deriv] = find((gsw_cv.eta_SA - eta_SA) >= gsw_cv.eta_SA_ca | ... - (gsw_cv.eta_CT - eta_CT) >= gsw_cv.eta_CT_ca); -if ~isempty(Ientropy_first_deriv) +gsw_cf.entropy_t_exact = gsw_entropy_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ientropy_t_exact] = find(abs(gsw_cv.entropy_t_exact - gsw_cf.entropy_t_exact) >= gsw_cv.entropy_t_exact_ca); +if ~isempty(gsw_cf.Ientropy_t_exact) try - cprintf('err','Ienthalpy_second_deriv: Failed\n'); + cprintf('err','gsw_entropy_t_exact: Failed\n'); catch - fprintf(2,'Ienthalpy_second_deriv: Failed\n'); + fprintf(2,'gsw_entropy_t_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -if gsw_chks == 1 ; +gsw_cf.cp_t_exact = gsw_cp_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Icp_t_exact] = find(abs(gsw_cv.cp_t_exact - gsw_cf.cp_t_exact) >= gsw_cv.cp_t_exact_ca); +if ~isempty(gsw_cf.Icp_t_exact) try - cprintf('text','.'); + cprintf('err','gsw_cp_t_exact: Failed\n'); catch - fprintf(1,'.'); + fprintf(2,'gsw_cp_t_exact: Failed\n'); end + gsw_chks = 0; end -[eta_SA_SA, eta_SA_CT, eta_CT_CT] = gsw_entropy_second_derivatives(SA_chck_cast,CT_chck_cast); -[Ientropy_second_deriv] = find(((gsw_cv.eta_SA_SA - eta_SA_SA)) >= gsw_cv.eta_SA_SA_ca |... - (gsw_cv.eta_SA_CT - eta_SA_CT) >= gsw_cv.eta_SA_CT_ca |... - (gsw_cv.eta_CT_CT - eta_CT_CT) >= gsw_cv.eta_CT_CT_ca); -if ~isempty(Ientropy_second_deriv) +gsw_cf.isochoric_heat_cap_t_exact = gsw_isochoric_heat_cap_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Iisochoric_heat_cap_t_exact] = find(abs(gsw_cv.isochoric_heat_cap_t_exact - gsw_cf.isochoric_heat_cap_t_exact) >= gsw_cv.isochoric_heat_cap_t_exact_ca); +if ~isempty(gsw_cf.Iisochoric_heat_cap_t_exact) try - cprintf('err','gsw_entropy_second_derivatives: Failed\n'); + cprintf('err','gsw_isochoric_heat_cap_t_exact: Failed\n'); catch - fprintf(2,'gsw_entropy_second_derivatives: Failed\n'); + fprintf(2,'gsw_isochoric_heat_cap_t_exact: Failed\n'); end gsw_chks = 0; end -[pt_SA, pt_CT] = gsw_pt_first_derivatives(SA_chck_cast,CT_chck_cast); -[Ipt_first_deriv] = find((gsw_cv.pt_SA - pt_SA) >= gsw_cv.pt_SA_ca |... - (gsw_cv.pt_CT - pt_CT) >= gsw_cv.pt_CT_ca); -if ~isempty(Ipt_first_deriv) +gsw_cf.chem_potential_t_exact = gsw_chem_potential_relative_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ichem_potential_t_exact] = find(abs(gsw_cv.chem_potential_t_exact - gsw_cf.chem_potential_t_exact) >= gsw_cv.chem_potential_t_exact_ca); +if ~isempty(gsw_cf.Ichem_potential_t_exact) try - cprintf('err','gsw_pt_first_derivatives: Failed\n'); + cprintf('err','gsw_chem_potential_relative_t_exact: Failed\n'); catch - fprintf(2,'gsw_pt_first_derivatives: Failed\n'); + fprintf(2,'gsw_chem_potential_relative_t_exact: Failed\n'); end gsw_chks = 0; end -[pt_SA_SA, pt_SA_CT, pt_CT_CT] = gsw_pt_second_derivatives(SA_chck_cast,CT_chck_cast); -[Ipt_second_deriv] = find((gsw_cv.pt_SA_SA - pt_SA_SA) >= gsw_cv.pt_SA_SA_ca | ... - (gsw_cv.pt_SA_CT - pt_SA_CT) >= gsw_cv.pt_SA_CT_ca | ... - (gsw_cv.pt_CT_CT - pt_CT_CT) >= gsw_cv.pt_CT_CT_ca); -if ~isempty(Ipt_second_deriv) +gsw_cf.chem_potential_water_t_exact = gsw_chem_potential_water_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ichem_potential_water_t_exact] = find(abs(gsw_cv.chem_potential_water_t_exact - gsw_cf.chem_potential_water_t_exact) >= gsw_cv.chem_potential_water_t_exact_ca); +if ~isempty(gsw_cf.Ichem_potential_water_t_exact) try - cprintf('err','gsw_pt_second_derivatives: Failed\n'); + cprintf('err','gsw_chem_potential_water_t_exact: Failed\n'); catch - fprintf(2,'gsw_pt_second_derivatives: Failed\n'); + fprintf(2,'gsw_chem_potential_water_t_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -%% planet earth properties - -f = gsw_f(gsw_cv.lat_chck_cast); -[If] = find((gsw_cv.f - f) >= gsw_cv.f_ca); -if ~isempty(If) +if gsw_cf.gsw_chks == 1 ; try - cprintf('err','gsw_f: Failed\n'); + cprintf('text','.'); catch - fprintf(2,'gsw_f: Failed\n'); + fprintf(1,'.'); end - gsw_chks = 0; end -grav = gsw_grav(gsw_cv.lat_chck_cast,gsw_cv.p_chck_cast); -[Igrav] = find((gsw_cv.grav - grav) >= gsw_cv.grav_ca); -if ~isempty(Igrav) +gsw_cf.chem_potential_salt_t_exact = gsw_chem_potential_salt_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Ichem_potential_salt_t_exact] = find(abs(gsw_cv.chem_potential_salt_t_exact - gsw_cf.chem_potential_salt_t_exact) >= gsw_cv.chem_potential_salt_t_exact_ca); +if ~isempty(gsw_cf.Ichem_potential_salt_t_exact) try - cprintf('err','gsw_grav: Failed\n'); + cprintf('err','gsw_chem_potential_salt_t_exact: Failed\n'); catch - fprintf(2,'gsw_grav: Failed\n'); + fprintf(2,'gsw_chem_potential_salt_t_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -distance = gsw_distance(gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast,gsw_cv.p_chck_cast); -[Idistance] = find((gsw_cv.distance - distance) >= gsw_cv.distance_ca); -if ~isempty(Idistance) +gsw_cf.Helmholtz_energy_t_exact = gsw_Helmholtz_energy_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.IHelmholtz_energy_t_exact] = find(abs(gsw_cv.Helmholtz_energy_t_exact - gsw_cf.Helmholtz_energy_t_exact) >= gsw_cv.Helmholtz_energy_t_exact_ca); +if ~isempty(gsw_cf.IHelmholtz_energy_t_exact) try - cprintf('err','gsw_distance: Failed\n'); + cprintf('err','gsw_Helmholtz_energy_t_exact: Failed\n'); catch - fprintf(2,'gsw_distance: Failed\n'); + fprintf(2,'gsw_Helmholtz_energy_t_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -%% Absolute Salinity from direct density measurements:- a laboratory function +gsw_cf.adiabatic_lapse_rate_t_exact = gsw_adiabatic_lapse_rate_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Iadiabatic_lapse_rate_t_exact] = find(abs(gsw_cv.adiabatic_lapse_rate_t_exact - gsw_cf.adiabatic_lapse_rate_t_exact) >= gsw_cv.adiabatic_lapse_rate_t_exact_ca); +if ~isempty(gsw_cf.Iadiabatic_lapse_rate_t_exact) + try + cprintf('err','gsw_adiabatic_lapse_rate_t_exact: Failed\n'); + catch + fprintf(2,'gsw_adiabatic_lapse_rate_t_exact: Failed\n'); + end + gsw_cf.gsw_chks = 0; +end -SA_from_rho = gsw_SA_from_rho(rho,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[ISA_from_rho] = find((gsw_cv.SA_from_rho - SA_from_rho) >= gsw_cv.SA_from_rho_ca); -if ~isempty(ISA_from_rho) +gsw_cf.osmotic_coefficient_t_exact = gsw_osmotic_coefficient_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Iosmotic_coefficient_t_exact] = find(abs(gsw_cv.osmotic_coefficient_t_exact - gsw_cf.osmotic_coefficient_t_exact) >= gsw_cv.osmotic_coefficient_t_exact_ca); +if ~isempty(gsw_cf.Iosmotic_coefficient_t_exact) try - cprintf('err','gsw_SA_from_rho: Failed\n'); + cprintf('err','gsw_osmotic_coefficient_t_exact: Failed\n'); catch - fprintf(2,'gsw_SA_from_rho: Failed\n'); + fprintf(2,'gsw_osmotic_coefficient_t_exact: Failed\n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -sigma0_pt = gsw_sigma0_pt(SA_chck_cast,pt0); -[Isigma0_pt] = find((gsw_cv.sigma0_pt - sigma0_pt) >= gsw_cv.sigma0_pt_ca); -if ~isempty(Isigma0_pt) +gsw_cf.osmotic_pressure_t_exact = gsw_osmotic_pressure_t_exact(gsw_cv.SA_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); +[gsw_cf.Iosmotic_pressure_t_exact] = find(abs(gsw_cv.osmotic_pressure_t_exact - gsw_cf.osmotic_pressure_t_exact) >= gsw_cv.osmotic_pressure_t_exact_ca); +if ~isempty(gsw_cf.Iosmotic_pressure_t_exact) try - cprintf('err','gsw_sigma0_pt: Failed\n'); + cprintf('err','gsw_osmotic_pressure_t_exact: Failed\n'); catch - fprintf(2,'gsw_sigma0_pt: Failed\n'); + fprintf(2,'gsw_osmotic_pressure_t_exact: Failed\n'); end gsw_chks = 0; end -%% Practical Salinity (SP):- PSS-78 +if gsw_cf.gsw_chks == 1 ; + try + cprintf('text','.'); + catch + fprintf(1,'.'); + end +end -cndr = gsw_cndr_from_SP(gsw_cv.SP_chck_cast,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[Icndr] = find((gsw_cv.cndr - cndr) >= gsw_cv.cndr_ca); -if ~isempty(Icndr) +% library +gsw_cf.fdelta = gsw_Fdelta(gsw_cv.p_chck_cast,gsw_cv.long_chck_cast,gsw_cv.lat_chck_cast); +[gsw_cf.Ifdelta] = find(abs(gsw_cv.fdelta - gsw_cf.fdelta) >= gsw_cv.fdelta_ca); +if ~isempty(gsw_cf.Ifdelta) try - cprintf('err','gsw_cndr_from_SP: Failed\n'); + cprintf('err','gsw_Fdelta: Failed. \n'); catch - fprintf(2,'gsw_cndr_from_SP: Failed\n'); + fprintf(2,'gsw_Fdelta: Failed. \n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -SP_from_cndr = gsw_SP_from_cndr(cndr,gsw_cv.t_chck_cast,gsw_cv.p_chck_cast); -[ISP_from_cndr] = find((gsw_cv.SP_from_cndr - SP_from_cndr) >= gsw_cv.SP_from_cndr_ca); -if ~isempty(ISP_from_cndr) +for I = 1:45 + gsw_cf.long_chck_cast_temp(I,:) = gsw_cv.long_chck_cast(1,:); + gsw_cf.lat_chck_cast_temp(I,:) = gsw_cv.lat_chck_cast(1,:); +end +[I] = find(~isnan(gsw_cv.p_chck_cast)); +gsw_cf.delta_sa_ref = nan(45,3); +gsw_cf.delta_sa_ref(I) = gsw_delta_SA_ref(gsw_cv.p_chck_cast(I),gsw_cf.long_chck_cast_temp(I),gsw_cf.lat_chck_cast_temp(I)); +[gsw_cf.Idelta_sa_ref] = find(abs(gsw_cv.delta_sa_ref - gsw_cf.delta_sa_ref) >= gsw_cv.delta_sa_ref_ca); +if ~isempty(gsw_cf.Idelta_sa_ref) try - cprintf('err','gsw_SP_from_cndr: Failed\n'); + cprintf('err','gsw_delta_SA_ref: Failed. \n'); catch - fprintf(2,'gsw_SP_from_cndr: Failed\n'); + fprintf(2,'gsw_delta_SA_ref: Failed. \n'); end - gsw_chks = 0; + gsw_cf.gsw_chks = 0; end -if gsw_chks == 1 ; +clear I + +%% + +if gsw_cf.gsw_chks == 1 ; try cprintf('text',' Finished.\n'); cprintf('text',' \n'); @@ -1239,115 +1840,39 @@ end end -if gsw_chks == 0 +if gsw_cf.gsw_chks == 0 try cprintf('err','Your installation of the Gibbs SeaWater (GSW) Oceanographic Toolbox has errors !\n'); catch fprintf(2,'Your installation of the Gibbs SeaWater (GSW) Oceanographic Toolbox has errors !\n'); end + demo = 0; else try - cprintf('comment','Well done! The gsw_check_values function confirms that the \n') + cprintf('comment','Well done! The gsw_check_functions confirms that the \n'); cprintf('comment','Gibbs SeaWater (GSW) Oceanographic Toolbox is installed correctly.\n'); - cprintf('text',' \n') - cprintf('text','Press enter to continue. \n') + cprintf('text','\n'); + catch + fprintf(1,'Well done! The gsw_check_fuctions confirms that the \n'); + fprintf(1,'Gibbs SeaWater (GSW) Oceanographic Toolbox is installed correctly.\n'); + fprintf(1,'\n'); + end + demo = gsw_cf.gsw_chks; + clear gsw_cf gsw_cv gsw_data gsw_data_file +end + +if demo == 1 + try + cprintf('strings','A demo will now follow. \n'); + cprintf('text','Press enter to continue. \n'); pause - cprintf('text',' \n') - cprintf('keywords','A short demonstration of the GSW Oceanographic Toolbox now follows.\n'); - pause(3) - cprintf('comment','The following vertical profile, from the North Pacific, is of\n'); - cprintf('comment','Practical Salinity, SP, and in situ temperature, t, as a function\n'); - cprintf('comment','of pressure, p,\n'); - pause(6) - cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'SP = [',gsw_cv.SP_chck_cast([1,22,29:4:45],1)',']'); - cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'t = [',gsw_cv.t_chck_cast([1,22,29:4:45],1)',']'); - cprintf('text','%s %7.0f %7.0f %7.0f %7.0f %7.0f %7.0f %7.0f %s \n' ,'p = [',gsw_cv.p_chck_cast([1,22,29:4:45],1)',']'); - cprintf('comment','We have shown only seven bottles from the full vertical profile.\n'); - cprintf('text',' \n') - pause(6) - cprintf('comment','We now convert Practical Salinity, SP, into Absolute Salinity, SA,\n'); - cprintf('comment','using the function "gsw_SA_from_SP",\n'); - pause(6) - cprintf('text','SA = gsw_SA_from_SP(SP,p,long,lat)\n'); - cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'SA = [',SA_chck_cast([1,22,29:4:45],1)',']'); - cprintf('text',' \n') - pause(6) - cprintf('comment','We now convert in situ temperature, t, into Conservative Temperature, CT\n'); - cprintf('comment','using the function "gsw_CT_from_t",\n'); - pause(6) - cprintf('text','CT = gsw_CT_from_t(SA,t,p)\n'); - cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'CT = [',CT_chck_cast([1,22,29:4:45],1)',']'); - cprintf('text',' \n') - pause(6) - cprintf('keywords','We now plot the profile on the Absolute Salinity - Conservative Temperature diagram\n'); - cprintf('comment','Potential density anomaly contours are shown for two different reference\n'); - cprintf('comment','pressures; 0 dbar and 2000 dbar. These values are obtained by using the function\n') - cprintf('comment','"gsw_rho_CT" - 1000 kg/m3, as follows,\n') - cprintf('text','sigma_Theta = gsw_rho_CT(SA,CT,0) - 1000\n'); - cprintf('text','sigma_2 = gsw_rho_CT(SA,CT,2000) - 1000\n'); - pause(8) - catch - disp('Well done! The gsw_check_values function confirms that the') - disp('Gibbs SeaWater (GSW) Oceanographic Toolbox is installed correctly.'); - disp(' ') - disp('Press enter to continue.') + gsw_demo + catch + fprintf(1,'A demo will now follow. \n'); + fprintf(1,'Press enter to continue. \n'); pause - disp(' ') - disp('A short demonstation of the GSW Oceanographic Toolbox now follows.'); - pause(3) - disp('The following vertical profile, from the North Pacific, is of'); - disp('Practical Salinity, SP, and in situ temperature, t, as a function'); - disp('of pressure, p,'); - fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'SP = [',gsw_cv.SP_chck_cast([1,22,29:4:45],1)',']'); - fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'t = [',gsw_cv.t_chck_cast([1,22,29:4:45],1)',']'); - fprintf(1,'%s %7.0f %7.0f %7.0f %7.0f %7.0f %7.0f %7.0f %s \n' ,'p = [',gsw_cv.p_chck_cast([1,22,29:4:45],1)',']'); - disp('We have shown only seven bottles from the full vertical profile.'); - disp(' ') - pause(6) - disp('We now convert Practical Salinity, SP, into Absolute Salinity, SA,'); - disp('using the function "gsw_SA_from_SP",'); - disp('SA = gsw_SA_from_SP(SP,p,long,lat)'); - fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'SA = [',SA_chck_cast([1,22,29:4:45],1)',']'); - disp(' ') - pause(6) - disp('We now convert in situ temperature, t, into Conservative Temperature, CT'); - disp('using the function "gsw_CT_from_t",'); - disp('CT = gsw_CT_from_t(SA,t,p)'); - fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'CT = [',CT_chck_cast([1,22,29:4:45],1)',']'); - disp(' ') - pause(6) - disp('We now plot the profile on the Absolute Salinity - Conservative Temperature diagram'); - disp('Potential density anomaly contours are shown for two different reference'); - disp('pressures; 0 dbar and 2000 dbar. These values are obtained by using the function') - disp('"gsw_rho_CT" - 1000 kg/m3, as follows,') - disp('sigma_Theta = gsw_rho_CT(SA,CT,0) - 1000'); - disp('sigma_2 = gsw_rho_CT(SA,CT,2000) - 1000'); - pause(8) - end - pause(4) - try - SA_gridded = meshgrid([34:0.01:35.6],1:301); - CT_gridded = meshgrid([0:0.1:30],1:161)'; - isopycs_0 = gsw_rho_CT(SA_gridded,CT_gridded,0)-1000; - isopycs_2 = gsw_rho_CT(SA_gridded,CT_gridded,2000)-1000; - figure - [c0,h0]=contour(SA_gridded,CT_gridded,isopycs_0,[21:0.5:29],'k','linewidth',0.5); - hold on - [c2,h2]=contour(SA_gridded,CT_gridded,isopycs_2,[21:0.5:40],'r','linewidth',0.5); - clabel(c0,h0,'labelspacing',360); - clabel(c2,h2,'labelspacing',240,'color','r'); - plot(SA_chck_cast(:,1),CT_chck_cast(:,1),'b','linewidth',2) - plot(SA_chck_cast([1,22,29:4:45],1),CT_chck_cast([1,22,29:4:45],1),'co','linewidth',2,'Markersize',8) - xlabel('Absolute Salinity, S_A [g/kg]','fontsize',15) - ylabel('Conservative Temperature, {\Theta} [{\circ}C]','fontsize',15) - title(['S_A - {\Theta} for a profile at (',num2str(gsw_cv.long_chck_cast(1)),' {\circ}E, ',num2str(gsw_cv.lat_chck_cast(1)),' {\circ}N)'],'fontsize',15) - lh = plot(1:2,1:2,'k',1:2,1:2,'r'); - lh2 = legend(lh,'{\sigma^\Theta}','{\sigma_2}','Location','southEast'); - set(lh2,'FontSize',15); - catch - disp('It appears that you are running MATLAB without the desktop or display,') - disp('so we can not show the resulting figure.') - end - clear all + gsw_demo + end end +clear demo diff --git a/Toolbox/gsw_chem_potential_relative.m b/Toolbox/gsw_chem_potential_relative_t_exact.m similarity index 59% rename from Toolbox/gsw_chem_potential_relative.m rename to Toolbox/gsw_chem_potential_relative_t_exact.m index 0ab0155..4c6639d 100644 --- a/Toolbox/gsw_chem_potential_relative.m +++ b/Toolbox/gsw_chem_potential_relative_t_exact.m @@ -1,30 +1,31 @@ -function chem_potential_relative = gsw_chem_potential_relative(SA,t,p) +function chem_potential_relative_t_exact = gsw_chem_potential_relative_t_exact(SA,t,p) -% gsw_chem_potential_relative relative chemical potential +% gsw_chem_potential_relative_t_exact relative chemical potential %========================================================================== % % USAGE: -% chem_potential_relative = gsw_chem_potential_relative(SA,t,p) +% chem_potential_relative_t_exact = gsw_chem_potential_relative_t_exact(SA,t,p) % % DESCRIPTION: -% Calculates the relative chemical potential of seawater +% Calculates the relative chemical potential of seawater. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% chem_potential_relative = relative chemical potential [ J/kg ] +% chem_potential_relative_t_exact = relative chemical potential +% [ J/kg ] % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -41,7 +42,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_chem_potential_relative: Requires three inputs') + error('gsw_chem_potential_relative_t_exact: Requires three inputs') end %if [ms,ns] = size(SA); @@ -49,7 +50,7 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_chem_potential_relative: SA and t must have same dimensions') + error('gsw_chem_potential_relative_t_exact: SA and t must have same dimensions') end if (mp == 1) & (np == 1) % p is a scalar - fill to size of SA @@ -59,18 +60,18 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_chem_potential_relative: Inputs array dimensions arguments do not agree') + error('gsw_chem_potential_relative_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -83,10 +84,10 @@ n0 = 0; n1 = 1; -chem_potential_relative = gsw_gibbs(n1,n0,n0,SA,t,p); +chem_potential_relative_t_exact = gsw_gibbs(n1,n0,n0,SA,t,p); if transposed - chem_potential_relative = chem_potential_relative'; + chem_potential_relative_t_exact = chem_potential_relative_t_exact.'; end end diff --git a/Toolbox/gsw_chem_potential_salt.m b/Toolbox/gsw_chem_potential_salt_t_exact.m similarity index 58% rename from Toolbox/gsw_chem_potential_salt.m rename to Toolbox/gsw_chem_potential_salt_t_exact.m index be2dab7..cc7211b 100644 --- a/Toolbox/gsw_chem_potential_salt.m +++ b/Toolbox/gsw_chem_potential_salt_t_exact.m @@ -1,31 +1,32 @@ -function chem_potential_salt = gsw_chem_potential_salt(SA,t,p) +function chem_potential_salt_t_exact = gsw_chem_potential_salt_t_exact(SA,t,p) -% gsw_chem_potential_salt chemical potential of salt in seawater +% gsw_chem_potential_salt_t_exact chemical potential of salt +% in seawater %========================================================================== % % USAGE: -% chem_potential_salt = gsw_chem_potential_salt(SA,t,p) +% chem_potential_salt_t_exact = gsw_chem_potential_salt_t_exact(SA,t,p) % % DESCRIPTION: -% Calculates the chemical potential of salt in seawater +% Calculates the chemical potential of salt in seawater. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% chem_potential_salt = chemical potential of salt in seawater -% [ J/kg ] +% chem_potential_salt_t_exact = chemical potential of salt in seawater +% [ J/kg ] % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (28th September, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -42,7 +43,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_chemical_potential_salt: Requires three inputs') + error('gsw_chemical_potential_salt_t_exact: Requires three inputs') end %if [ms,ns] = size(SA); @@ -50,7 +51,7 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_chem_potential_salt: SA and t must have same dimensions') + error('gsw_chem_potential_salt_t_exact: SA and t must have same dimensions') end if (mp == 1) & (np == 1) % p is a scalar - fill to size of SA @@ -60,18 +61,18 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_chem_potential_salt: Inputs array dimensions arguments do not agree') + error('gsw_chem_potential_salt_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -81,11 +82,11 @@ % Start of the calculation %-------------------------------------------------------------------------- -chem_potential_salt = gsw_chem_potential_relative(SA,t,p) + ... - gsw_chem_potential_water(SA,t,p); +chem_potential_salt_t_exact = gsw_chem_potential_relative_t_exact(SA,t,p) ... + + gsw_chem_potential_water_t_exact(SA,t,p); if transposed - chem_potential_salt = chem_potential_salt'; + chem_potential_salt_t_exact = chem_potential_salt_t_exact.'; end end diff --git a/Toolbox/gsw_chem_potential_water.m b/Toolbox/gsw_chem_potential_water.m deleted file mode 100644 index 234522e..0000000 --- a/Toolbox/gsw_chem_potential_water.m +++ /dev/null @@ -1,145 +0,0 @@ -function chem_potential_water = gsw_chem_potential_water(SA,t,p) - -% gsw_chem_potential_water chemical potential of water in seawater -%========================================================================== -% -% USAGE: -% chem_potential_water = gsw_chem_potential_water(SA,t,p) -% -% DESCRIPTION: -% Calculates the chemical potential of water in seawater -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) -% -% SA & t need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. -% -% OUTPUT: -% chem_potential_water = chemical potential of water in seawater -% [ J/kg ] -% -% AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] -% -% VERSION NUMBER: 2.0 (28th September, 2010) -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 3) - error('gsw_chem_potential_water: Requires three inputs') -end %if - -[ms,ns] = size(SA); -[mt,nt] = size(t); -[mp,np] = size(p); - -if (mt ~= ms | nt ~= ns) - error('gsw_chem_potential_water: SA and t must have same dimensions') -end - -if (mp == 1) & (np == 1) % p is a scalar - fill to size of SA - p = p*ones(size(SA)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_chem_potential_water: Inputs array dimensions arguments do not agree') -end %if - -if ms == 1 - SA = SA'; - t = t'; - p = p'; - transposed = 1; -else - transposed = 0; -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -% These few lines ensure that SA is non-negative. -[I_neg_SA] = find(SA < 0); -if ~isempty(I_neg_SA) - SA(I_neg_SA) = 0; -end - -sfac = 0.0248826675584615; % sfac = 1/(40*(35.16504/35)). - -x2 = sfac.*SA; -x = sqrt(x2); -y = t.*0.025; -z = p.*1d-4; %Note that the input pressure (p) is sea pressure in units of dbar. - - g03_g = 101.342743139674 + z.*(100015.695367145 + ... - z.*(-2544.5765420363 + z.*(284.517778446287 + ... - z.*(-33.3146754253611 + (4.20263108803084 - 0.546428511471039.*z).*z)))) + ... - y.*(5.90578347909402 + z.*(-270.983805184062 + ... - z.*(776.153611613101 + z.*(-196.51255088122 + (28.9796526294175 - 2.13290083518327.*z).*z))) + ... - y.*(-12357.785933039 + z.*(1455.0364540468 + ... - z.*(-756.558385769359 + z.*(273.479662323528 + z.*(-55.5604063817218 + 4.34420671917197.*z)))) + ... - y.*(736.741204151612 + z.*(-672.50778314507 + ... - z.*(499.360390819152 + z.*(-239.545330654412 + (48.8012518593872 - 1.66307106208905.*z).*z))) + ... - y.*(-148.185936433658 + z.*(397.968445406972 + ... - z.*(-301.815380621876 + (152.196371733841 - 26.3748377232802.*z).*z)) + ... - y.*(58.0259125842571 + z.*(-194.618310617595 + ... - z.*(120.520654902025 + z.*(-55.2723052340152 + 6.48190668077221.*z))) + ... - y.*(-18.9843846514172 + y.*(3.05081646487967 - 9.63108119393062.*z) + ... - z.*(63.5113936641785 + z.*(-22.2897317140459 + 8.17060541818112.*z)))))))); - - g08_g = x2.*(1416.27648484197 + ... - x.*(-2432.14662381794 + x.*(2025.80115603697 + ... - y.*(543.835333000098 + y.*(-68.5572509204491 + ... - y.*(49.3667694856254 + y.*(-17.1397577419788 + 2.49697009569508.*y))) - 22.6683558512829.*z) + ... - x.*(-1091.66841042967 - 196.028306689776.*y + ... - x.*(374.60123787784 - 48.5891069025409.*x + 36.7571622995805.*y) + 36.0284195611086.*z) + ... - z.*(-54.7919133532887 + (-4.08193978912261 - 30.1755111971161.*z).*z)) + ... - z.*(199.459603073901 + z.*(-52.2940909281335 + (68.0444942726459 - 3.41251932441282.*z).*z)) + ... - y.*(-493.407510141682 + z.*(-175.292041186547 + (83.1923927801819 - 29.483064349429.*z).*z) + ... - y.*(-43.0664675978042 + z.*(383.058066002476 + z.*(-54.1917262517112 + 25.6398487389914.*z)) + ... - y.*(-10.0227370861875 - 460.319931801257.*z + y.*(0.875600661808945 + 234.565187611355.*z))))) + ... - y.*(168.072408311545)); - - g_SA_part = 8645.36753595126 + ... - x.*(-7296.43987145382 + x.*(8103.20462414788 + ... - y.*(2175.341332000392 + y.*(-274.2290036817964 + ... - y.*(197.4670779425016 + y.*(-68.5590309679152 + 9.98788038278032.*y))) - 90.6734234051316.*z) + ... - x.*(-5458.34205214835 - 980.14153344888.*y + ... - x.*(2247.60742726704 - 340.1237483177863.*x + 220.542973797483.*y) + 180.142097805543.*z) + ... - z.*(-219.1676534131548 + (-16.32775915649044 - 120.7020447884644.*z).*z)) + ... - z.*(598.378809221703 + z.*(-156.8822727844005 + (204.1334828179377 - 10.23755797323846.*z).*z)) + ... - y.*(-1480.222530425046 + z.*(-525.876123559641 + (249.57717834054571 - 88.449193048287.*z).*z) + ... - y.*(-129.1994027934126 + z.*(1149.174198007428 + z.*(-162.5751787551336 + 76.9195462169742.*z)) + ... - y.*(-30.0682112585625 - 1380.9597954037708.*z + y.*(2.626801985426835 + 703.695562834065.*z))))) + ... - y.*(1187.3715515697959); - -chem_potential_water = g03_g + g08_g - 0.5.*sfac.*SA.*g_SA_part; - -if transposed - chem_potential_water = chem_potential_water'; -end - -end diff --git a/Toolbox/gsw_chem_potential_water_t_exact.m b/Toolbox/gsw_chem_potential_water_t_exact.m new file mode 100644 index 0000000..d912068 --- /dev/null +++ b/Toolbox/gsw_chem_potential_water_t_exact.m @@ -0,0 +1,146 @@ +function chem_potential_water_t_exact = gsw_chem_potential_water_t_exact(SA,t,p) + +% gsw_chem_potential_water_t_exact chemical potential of water +% in seawater +%========================================================================== +% +% USAGE: +% chem_potential_water_t_exact = gsw_chem_potential_water_t_exact(SA,t,p) +% +% DESCRIPTION: +% Calculates the chemical potential of water in seawater. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & t need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% +% OUTPUT: +% chem_potential_water_t_exact = chemical potential of water in seawater +% [ J/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_chem_potential_water_t_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_chem_potential_water_t_exact: SA and t must have same dimensions') +end + +if (mp == 1) & (np == 1) % p is a scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_chem_potential_water_t_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +sfac = 0.0248826675584615; % sfac = 1/(40*(35.16504/35)). + +x2 = sfac.*SA; +x = sqrt(x2); +y = t.*0.025; +z = p.*1e-4; %Note that the input pressure (p) is sea pressure in units of dbar. + +g03_g = 101.342743139674 + z.*(100015.695367145 + ... + z.*(-2544.5765420363 + z.*(284.517778446287 + ... + z.*(-33.3146754253611 + (4.20263108803084 - 0.546428511471039.*z).*z)))) + ... + y.*(5.90578347909402 + z.*(-270.983805184062 + ... + z.*(776.153611613101 + z.*(-196.51255088122 + (28.9796526294175 - 2.13290083518327.*z).*z))) + ... + y.*(-12357.785933039 + z.*(1455.0364540468 + ... + z.*(-756.558385769359 + z.*(273.479662323528 + z.*(-55.5604063817218 + 4.34420671917197.*z)))) + ... + y.*(736.741204151612 + z.*(-672.50778314507 + ... + z.*(499.360390819152 + z.*(-239.545330654412 + (48.8012518593872 - 1.66307106208905.*z).*z))) + ... + y.*(-148.185936433658 + z.*(397.968445406972 + ... + z.*(-301.815380621876 + (152.196371733841 - 26.3748377232802.*z).*z)) + ... + y.*(58.0259125842571 + z.*(-194.618310617595 + ... + z.*(120.520654902025 + z.*(-55.2723052340152 + 6.48190668077221.*z))) + ... + y.*(-18.9843846514172 + y.*(3.05081646487967 - 9.63108119393062.*z) + ... + z.*(63.5113936641785 + z.*(-22.2897317140459 + 8.17060541818112.*z)))))))); + +g08_g = x2.*(1416.27648484197 + ... + x.*(-2432.14662381794 + x.*(2025.80115603697 + ... + y.*(543.835333000098 + y.*(-68.5572509204491 + ... + y.*(49.3667694856254 + y.*(-17.1397577419788 + 2.49697009569508.*y))) - 22.6683558512829.*z) + ... + x.*(-1091.66841042967 - 196.028306689776.*y + ... + x.*(374.60123787784 - 48.5891069025409.*x + 36.7571622995805.*y) + 36.0284195611086.*z) + ... + z.*(-54.7919133532887 + (-4.08193978912261 - 30.1755111971161.*z).*z)) + ... + z.*(199.459603073901 + z.*(-52.2940909281335 + (68.0444942726459 - 3.41251932441282.*z).*z)) + ... + y.*(-493.407510141682 + z.*(-175.292041186547 + (83.1923927801819 - 29.483064349429.*z).*z) + ... + y.*(-43.0664675978042 + z.*(383.058066002476 + z.*(-54.1917262517112 + 25.6398487389914.*z)) + ... + y.*(-10.0227370861875 - 460.319931801257.*z + y.*(0.875600661808945 + 234.565187611355.*z))))) + ... + y.*(168.072408311545)); + +g_SA_part = 8645.36753595126 + ... + x.*(-7296.43987145382 + x.*(8103.20462414788 + ... + y.*(2175.341332000392 + y.*(-274.2290036817964 + ... + y.*(197.4670779425016 + y.*(-68.5590309679152 + 9.98788038278032.*y))) - 90.6734234051316.*z) + ... + x.*(-5458.34205214835 - 980.14153344888.*y + ... + x.*(2247.60742726704 - 340.1237483177863.*x + 220.542973797483.*y) + 180.142097805543.*z) + ... + z.*(-219.1676534131548 + (-16.32775915649044 - 120.7020447884644.*z).*z)) + ... + z.*(598.378809221703 + z.*(-156.8822727844005 + (204.1334828179377 - 10.23755797323846.*z).*z)) + ... + y.*(-1480.222530425046 + z.*(-525.876123559641 + (249.57717834054571 - 88.449193048287.*z).*z) + ... + y.*(-129.1994027934126 + z.*(1149.174198007428 + z.*(-162.5751787551336 + 76.9195462169742.*z)) + ... + y.*(-30.0682112585625 - 1380.9597954037708.*z + y.*(2.626801985426835 + 703.695562834065.*z))))) + ... + y.*(1187.3715515697959); + +chem_potential_water_t_exact = g03_g + g08_g - 0.5.*sfac.*SA.*g_SA_part; + +if transposed + chem_potential_water_t_exact = chem_potential_water_t_exact.'; +end + +end diff --git a/Toolbox/gsw_cndr_from_SP.m b/Toolbox/gsw_cndr_from_SP.m deleted file mode 100644 index 88a739a..0000000 --- a/Toolbox/gsw_cndr_from_SP.m +++ /dev/null @@ -1,202 +0,0 @@ -function R = gsw_cndr_from_SP(SP,t,p) - -% gsw_cndr_from_SP conductivity ratio from Practical Salinity -%========================================================================== -% -% USAGE: -% R = gsw_cndr_from_SP(SP,t,p) -% -% DESCRIPTION: -% Calculates conductivity ratio (R) from (SP,t,p) using PSS-78. Note that -% the PSS-78 algorithm for Practical Salinity is only valid in the -% range 2 < SP < 42. -% -% INPUT: -% SP = Practical Salinity (PSS-78) [ unitless ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) -% -% SP & t need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SP & t are MxN. -% -% OUTPUT: -% R = conductivity ratio [ unitless ] -% -% AUTHOR: -% Phil Morgan [ help_gsw@csiro.au ] -% -% MODIFIED: -% 25th June 1999. Lindsay Pender, Fixed transpose of row vectors. -% 12 December 2003. Lindsay Pender, Converted to ITS-90. -% 16th August 2010. Paul Barker, Regrouped. -% -% VERSION NUMBER: 2.0 (16th August, 2010) -% -% REFERENCES: -% Fofonoff, P. and R.C .Millard, Jr, 1983: Algorithms for computation of -% fundamental properties of seawater, 1983. -% Unesco Tech. Pap. in Mar. Sci., No. 44, 53 pp. -% -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See appendix E of this TEOS-10 Manual. -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 3) - error('gsw_cndr_from_SP: Must have 3 input arguments') -end %if - -% These few lines ensure that SA is non-negative. -[I_neg_SP] = find(SP < 0); -if ~isempty(I_neg_SP) - error('gsw_cndr_from_SP: SP must be non-negative!') -end - -[ms,ns] = size(SP); -[mt,nt] = size(t); -[mp,np] = size(p); - -if (mt ~= ms | nt ~= ns) - error('gsw_cndr_from_SP: SP and t must have same dimensions') -end - -if mp==1 & np==1 % p is a scalar. Fill to size of SP - p = p(1)*ones(ms,ns); -elseif np==ns & mp==1 % p is row vector, - p = p(ones(1,ms),:); % copy down each column. -elseif mp==ms & np==1 % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif mp==ms & np==ns - % ok -else - error('gsw_cndr_from_SP: p has wrong dimensions') -end %if - -if ms == 1 - SP = SP'; - t = t'; - p = p'; - [ms,ns] = size(SP); - transposed = 1; -else - transposed = 0; -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -a0 = 0.0080; -a1 = -0.1692; -a2 = 25.3851; -a3 = 14.0941; -a4 = -7.0261; -a5 = 2.7081; - -b0 = 0.0005; -b1 = -0.0056; -b2 = -0.0066; -b3 = -0.0375; -b4 = 0.0636; -b5 = -0.0144; - -c0 = 0.6766097; -c1 = 2.00564e-2; -c2 = 1.104259e-4; -c3 = -6.9698e-7; -c4 = 1.0031e-9; - -d1 = 3.426e-2; -d2 = 4.464e-4; -d3 = 4.215e-1; -d4 = -3.107e-3; - -e1 = 2.070e-5; -e2 = -6.370e-10; -e3 = 3.989e-15; - -k = 0.0162; - -t68 = t.*1.00024; -d_t68 = t68 - 15; -Rx = nan(size(SP)); - -for i = 1:ms - for j = 1:ns - %--------------------------------------------------------------------- - %DO A NEWTON-RAPHSON ITERATION FOR INVERSE INTERPOLATION OF Rt FROM SP - %--------------------------------------------------------------------- - SP_ij = SP(i,j); % SP in the loop - d_t68_ij = d_t68(i,j); % t68 in the loop - Rx_ij = abs(SP_ij/35.0); % first guess at Rx = sqrt(Rt) - Rtx = Rx_ij; - - d_S = (d_t68_ij ./ (1+k*d_t68_ij) ) .* ... - ( b0 + (b1 + (b2+ (b3 + (b4 + b5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx); - S = a0 + (a1 + (a2 + (a3 + (a4 + a5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx; - SP_Inc = S + d_S; - - Iloop = 0; - end_ij = 0; - - while ~end_ij - Rtx = sqrt(Rx_ij); - dS = a1 + (2*a2 + (3*a3 + (4*a4 + 5*a5.*Rtx).*Rtx).*Rtx).*Rtx + ... - ((d_t68_ij)./(1+k*(d_t68_ij)))* ... - (b1 + (2*b2 + (3*b3 + (4*b4 + 5*b5.*Rtx).*Rtx).*Rtx).*Rtx); - Rx_ij = Rx_ij + (SP_ij - SP_Inc)./dS; - - Rtx = Rx_ij; - d_S = (d_t68_ij ./ (1+k*d_t68_ij) ) .* ... - (b0 + (b1 + (b2+ (b3 + (b4 + b5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx); - S = a0 + (a1 + (a2 + (a3 + (a4 + a5.*Rtx).*Rtx).*Rtx).*Rtx).*Rtx; - SP_Inc = S + d_S; - - Iloop = Iloop + 1; - dels = abs(SP_Inc-SP_ij); - if (dels>1.0e-10 & Iloop<100) - end_ij = 0; - else - end_ij = 1; - end %if - end %while - - Rx(i,j) = Rx_ij; - - end %for j -end %for i - -%-------------------------------------------------------------------------- -% ONCE Rt FOUND, CORRESPONDING TO EACH (SP,t) EVALUATE R. -% Eqn 4, p.8 (Unesco, 1983) -%-------------------------------------------------------------------------- - -A = (d3 + d4.*t68); -B = 1 + d1.*t68 + d2.*t68.^2; -C = p.*(e1 + e2.*p + e3.*p.^2); - -Rt = Rx.*Rx; % Eqn 6, p.9 (UNESCO, 1983). - -rt = c0 + (c1 + (c2 + (c3 + c4.*t68).*t68).*t68).*t68; - -D = B - A.*rt.*Rt; -E = rt.*Rt.*A.*(B+C); -Ra = sqrt(abs(D.^2+4*E)) - D; -R = 0.5*Ra./A; - -if transposed - R = R'; -end - -end - diff --git a/Toolbox/gsw_cp0.m b/Toolbox/gsw_cp0.m new file mode 100644 index 0000000..58e208f --- /dev/null +++ b/Toolbox/gsw_cp0.m @@ -0,0 +1,35 @@ +function cp0 = gsw_cp0 + +% gsw_cp0 the "specific heat" for use with CT +%========================================================================== +% +% USAGE: +% cp0 = gsw_cp0 +% +% DESCRIPTION: +% The "specific heat" for use with Conservative Temperature. cp0 is the +% ratio of potential enthalpy to Conservative Temperature. +% +% OUTPUT: +% cp0 = The "specific heat" for use [ J/(kg K) ] +% with Conservative Temperature +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. +% See Eqn. (3.3.3) and Table D.5 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +cp0 = 3991.86795711963; + +end diff --git a/Toolbox/gsw_cp.m b/Toolbox/gsw_cp_t_exact.m similarity index 62% rename from Toolbox/gsw_cp.m rename to Toolbox/gsw_cp_t_exact.m index b096c30..e85b07e 100644 --- a/Toolbox/gsw_cp.m +++ b/Toolbox/gsw_cp_t_exact.m @@ -1,30 +1,30 @@ -function cp = gsw_cp(SA,t,p) +function cp_t_exact = gsw_cp_t_exact(SA,t,p) -% gsw_cp isobaric heat capacity +% gsw_cp_t_exact isobaric heat capacity %========================================================================== % % USAGE: -% cp = gsw_cp(SA,t,p) +% cp_t_exact = gsw_cp_t_exact(SA,t,p) % % DESCRIPTION: % Calculates the isobaric heat capacity of seawater. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% cp = heat capacity of seawater [ J/(kg*K) ] +% cp_t_exact = heat capacity of seawater [ J/(kg*K) ] % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -41,7 +41,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_cp: Requires three inputs') + error('gsw_cp_t_exact: Requires three inputs') end %if [ms,ns] = size(SA); @@ -49,7 +49,7 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_cp: SA and t must have same dimensions') + error('gsw_cp_t_exact: SA and t must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -58,16 +58,19 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_cp: Inputs array dimensions arguments do not agree') + error('gsw_cp_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -80,10 +83,10 @@ n0 = 0; n2 = 2; -cp = -(t+273.15).*gsw_gibbs(n0,n2,n0,SA,t,p); +cp_t_exact = -(t+273.15).*gsw_gibbs(n0,n2,n0,SA,t,p); if transposed - cp = cp'; + cp_t_exact = cp_t_exact.'; end end \ No newline at end of file diff --git a/Toolbox/gsw_deltaSA_from_SP.m b/Toolbox/gsw_deltaSA_from_SP.m new file mode 100644 index 0000000..92782c5 --- /dev/null +++ b/Toolbox/gsw_deltaSA_from_SP.m @@ -0,0 +1,170 @@ +function deltaSA = gsw_deltaSA_from_SP(SP,p,long,lat) + +% gsw_deltaSA_from_SP Absolute Salinity Anomaly +% from Practical Salinity +%========================================================================== +% +% USAGE: +% deltaSA = gsw_deltaSA_from_SP(SP,p,long,lat) +% +% DESCRIPTION: +% Calculates Absolute Salinity Anomaly from Practical Salinity. Since SP +% is non-negative by definition, this function changes any negative input +% values of SP to be zero. +% +% INPUT: +% SP = Practical Salinity (PSS-78) [ unitless ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% long = longitude in decimal degrees [ 0 ... +360 ] +% or [ -180 ... +180 ] +% lat = latitude in decimal degrees north [ -90 ... +90 ] +% +% p, lat & long may have dimensions 1x1 or Mx1 or 1xN or MxN, +% where SP is MxN. +% +% OUTPUT: +% deltaSA = Absolute Salinity Anomaly [ g/kg ] +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (27th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 2.5 and appendices A.4 and A.5 of this TEOS-10 Manual. +% +% McDougall, T.J., D.R. Jackett and F.J. Millero, 2010: An algorithm +% for estimating Absolute Salinity in the global ocean. Submitted to +% Ocean Science. A preliminary version is available at Ocean Sci. Discuss., +% 6, 215-242. +% http://www.ocean-sci-discuss.net/6/215/2009/osd-6-215-2009-print.pdf +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin==4) + error('gsw_deltaSA_from_SP: Requires four inputs') +end %if + +[ms,ns] = size(SP); +[mp,np] = size(p); + +if (mp == 1) & (np == 1) % p is a scalar - fill to size of SP + p = p*ones(size(SP)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_deltaSA_from_SP: Inputs array dimensions arguments do not agree') +end %if + +[mla,nla] = size(lat); + +if (mla == 1) & (nla == 1) % lat is a scalar - fill to size of SP + lat = lat*ones(size(SP)); +elseif (ns == nla) & (mla == 1) % lat is a row vector, + lat = lat(ones(1,ms), :); % copy down each column. +elseif (ms == mla) & (nla == 1) % lat is a column vector, + lat = lat(:,ones(1,ns)); % copy across each row. +elseif (ns == mla) & (nla == 1) % lat is a transposed row vector, + lat = lat.'; % transposed then + lat = lat(ones(1,ms), :); % copy down each column. +elseif (ms == mla) & (ns == nla) + % ok +else + error('gsw_deltaSA_from_SP: Inputs array dimensions arguments do not agree') +end %if + +[mlo,nlo] = size(long); +[Iwest] =find(long < 0); +if ~isempty(Iwest) + long(Iwest) = long(Iwest) + 360; +end + +if (mlo == 1) & (nlo == 1) % long is a scalar - fill to size of SP + long = long*ones(size(SP)); +elseif (ns == nlo) & (mlo == 1) % long is a row vector, + long = long(ones(1,ms), :); % copy down each column. +elseif (ms == mlo) & (nlo == 1) % long is a column vector, + long = long(:,ones(1,ns)); % copy across each row. +elseif (ns == mlo) & (nlo == 1) % long is a transposed row vector, + long = long.'; % transposed then + long = long(ones(1,ms), :); % copy down each column. +elseif (ms == nlo) & (mlo == 1) % long is a transposed column vector, + long = long.'; % transposed then + long = long(:,ones(1,ns)); % copy down each column. +elseif (ms == mlo) & (ns == nlo) + % ok +else + error('gsw_deltaSA_from_SP: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SP = SP.'; + p = p.'; + lat = lat.'; + long = long.'; + transposed = 1; +else + transposed = 0; +end + +[Iout_of_range] = find(p < 100 & SP > 120); +SP(Iout_of_range) = NaN; +[Iout_of_range] = find(p >= 100 & SP > 42); +SP(Iout_of_range) = NaN; + +[Inan] = find(abs(SP) == 99999 | abs(SP) == 999999); +SP(Inan) = NaN; +[Inan] = find(abs(p) == 99999 | abs(p) == 999999); +p(Inan) = NaN; +[Inan] = find(abs(long) == 9999 | abs(long) == 99999); +long(Inan) = NaN; +[Inan] = find(abs(lat) == 9999 | abs(lat) == 99999); +lat(Inan) = NaN; + +if ~isempty(find(p < -1.5 | p > 12000)) + error('gsw_deltaSA_from_SP: pressure is out of range') +end +if ~isempty(find(long < 0 | long > 360)) + error('gsw_deltaSA_from_SP: longitude is out of range') +end +if ~isempty(find(abs(lat) > 90)) + error('gsw_deltaSA_from_SP: latitude is out of range') +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% These few lines ensure that SP is non-negative. +[I_neg_SP] = find(SP < 0); +if ~isempty(I_neg_SP) + SP(I_neg_SP) = 0; +end + +SA = gsw_SA_from_SP(SP,p,long,lat); +SR = gsw_SR_from_SP(SP); +deltaSA = SA - SR; + +if transposed + deltaSA = deltaSA.'; +end + +end diff --git a/Toolbox/gsw_demo.m b/Toolbox/gsw_demo.m new file mode 100644 index 0000000..4f4f6c5 --- /dev/null +++ b/Toolbox/gsw_demo.m @@ -0,0 +1,307 @@ +gsw_data = 'gsw_data_v3_0.mat'; +gsw_data_file = which(gsw_data); +load (gsw_data_file,'gsw_demo_data'); + +clear gsw_data gsw_data_file + +%test if Java Virtual Machine is running +try + JavaVirtMach = system_dependent('useJava','jvm'); +catch +% assume no Java Virtual Machine + JavaVirtMach = 0; +end + +try + cprintf('keywords','Welcome the Gibbs Seawater (GSW) Oceanographic Toolbox (version 3). \n'); + pause(3) + cprintf('comment','This is a short demonstration of some of the features of the \n'); + cprintf('comment','GSW Oceanographic Toolbox. \n'); + cprintf('text',' \n'); + cprintf('keywords','The most important functions are the first two functions. \n'); + cprintf('text',' \n'); + cprintf('comment','The following vertical profiles, from the North Pacific, are of \n'); + cprintf('comment','Practical Salinity, SP, and in-situ temperature, t, as a function \n'); + cprintf('comment','of pressure, p, \n'); + pause(6) + cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'SP = [',gsw_demo_data.SP([1,22,29:4:45],1)',']'); + cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'t = [',gsw_demo_data.t([1,22,29:4:45],1)',']'); + cprintf('text','%s %7.0f %7.0f %7.0f %7.0f %7.0f %7.0f %7.0f %s \n' ,'p = [',gsw_demo_data.p([1,22,29:4:45],1)',']'); + cprintf('comment','Note that, we have shown only seven bottles from the full vertical profile. \n'); + cprintf('text',' \n'); + pause(6) + cprintf('keywords','The first step under TEOS-10 is to convert Practical Salinity, SP, \n'); + cprintf('keywords','into Absolute Salinity, SA. This is done with the function "gsw_SA_from_SP" \n'); + pause(6) + cprintf('text','SA = gsw_SA_from_SP(SP,p,long,lat) \n'); + gsw_demo_data.SA = gsw_SA_from_SP(gsw_demo_data.SP,gsw_demo_data.p,gsw_demo_data.long,gsw_demo_data.lat); + cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'SA = [',gsw_demo_data.SA([1,22,29:4:45],1)',']'); + cprintf('text',' \n'); + pause(6) + cprintf('keywords','The second step is to convert in-situ temperature, t, into \n'); + cprintf('keywords','Conservative Temperature, CT, using the function \n'); + cprintf('keywords','"gsw_CT_from_t", \n'); + pause(6) + cprintf('text','CT = gsw_CT_from_t(SA,t,p) \n'); + gsw_demo_data.CT = gsw_CT_from_t(gsw_demo_data.SA,gsw_demo_data.t,gsw_demo_data.p); + cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'CT = [',gsw_demo_data.CT([1,22,29:4:45],1)',']'); + cprintf('text',' \n'); + cprintf('comment','At this point the data has been converted into SA and CT, which are \n'); + cprintf('comment','the TEOS-10 salinity and temperature variables. With these variables it \n'); + cprintf('comment','is possible to compute the complete range of water column properties. \n'); + cprintf('text',' \n'); + pause(6) + cprintf('comment','The first property to be demonstrated is density (rho) as a function \n'); + cprintf('comment','of SA and CT. This is computed by using the function "gsw_rho_CT". \n'); + cprintf('comment','The use of a single algorithm for seawater density (the 48-term computationally \n'); + cprintf('comment','efficient expression) ensures consistency between ocean modelling, observational \n'); + cprintf('comment','oceanography, and theoretical studies. Note that this is not been the case to \n'); + cprintf('comment','date under EOS-80. \n'); + cprintf('text','rho_CT = gsw_rho_CT(SA,CT,p) \n'); + gsw_demo_data.rho_CT = gsw_rho_CT(gsw_demo_data.SA,gsw_demo_data.CT,gsw_demo_data.p); + cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'rho_CT = [',gsw_demo_data.rho_CT([1,22,29:4:45],1)',']'); + cprintf('text',' \n'); + pause(6) + cprintf('comment','Using this same programme, gsw_rho_CT, it is possible to compute potential \n'); + cprintf('comment','density by replacing the in-situ pressure, p with the reference pressure, \n'); + cprintf('comment','p_ref. \n'); + cprintf('text',' \n'); + pause(2) + cprintf('comment','An example. We have set p_ref to be 2000 dbar, thus we have the potential \n'); + cprintf('comment','density referenced to 2000 dbars. \n'); + cprintf('text','pot_rho_CT_2 = gsw_rho_CT(SA,CT,p_ref) \n'); + gsw_demo_data.pot_rho_CT_2 = gsw_rho_CT(gsw_demo_data.SA,gsw_demo_data.CT,gsw_demo_data.p_ref); + cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'pot_rho_CT = [',gsw_demo_data.pot_rho_CT_2([1,22,29:4:45],1)',']'); + cprintf('text',' \n'); + pause(6) + cprintf('comment','The potential density anomaly can be obtained by using the function \n'); + cprintf('comment','"gsw_rho_CT" - 1000 kg/m^3. \n'); + cprintf('comment','Two examples of this are sigma_0 and sigma_2 which can be calculated \n'); + cprintf('comment','as follows \n'); + cprintf('text','sigma_0 = gsw_rho_CT(SA,CT,0) - 1000 \n'); + gsw_demo_data.sigma_0 = gsw_rho_CT(gsw_demo_data.SA,gsw_demo_data.CT,0) -1000; + cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'sigma_0 = [',gsw_demo_data.sigma_0([1,22,29:4:45],1)',']'); + cprintf('text',' \n'); + pause(6) + cprintf('text','sigma_2 = gsw_rho_CT(SA,CT,2000) - 1000 \n'); + gsw_demo_data.sigma_2 = gsw_rho_CT(gsw_demo_data.SA,gsw_demo_data.CT,2000) - 1000; + cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'sigma_2 = [',gsw_demo_data.sigma_2([1,22,29:4:45],1)',']'); + cprintf('text',' \n'); + pause(6) + cprintf('comment','However, there are alternatives to the last two calls, we have provided \n'); + cprintf('comment','some short-cuts for the standard oceaongraphic variables as functions of \n'); + cprintf('comment','SA and CT, the alternative short-cuts to the above two calls are: \n'); + cprintf('text','sigma_0 = gsw_sigma0_CT(SA,CT) \n'); + cprintf('comment',' and \n'); + cprintf('text','sigma_2 = gsw_sigma2_CT(SA,CT) \n'); + cprintf('text',' \n'); + pause(6) + cprintf('comment','Calculating the Conservative Temperature at which seawater freezes is \n'); + cprintf('comment','done with the function \n'); + cprintf('text','"gsw_CT_freezing" \n'); + cprintf('comment','This programme allows the user to choose the amount of air which the water \n'); + cprintf('comment','contains, at zero the water is unsaturated and at 1 it is completely \n'); + cprintf('comment','saturated, we have opted to set the default saturation level at maximum \n'); + cprintf('text','CT_freezing = gsw_CT_freezing(SA,p) \n'); + gsw_demo_data.CT_freezing = gsw_CT_freezing(gsw_demo_data.SA,gsw_demo_data.p); + cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'CT_freezing = [',gsw_demo_data.CT_freezing([1,22,29:4:45],1)',']'); + cprintf('text',' \n'); + cprintf('comment','Press enter to continue. \n'); + pause + cprintf('keywords','We now plot the profile on the Absolute Salinity - Conservative Temperature diagram\n'); + cprintf('comment','This can be done by calling "gsw_SA_CT_plot". This function plots the \n'); + cprintf('comment','Absolute Salinity and Conservative Temperature profile data on a SA-CT diagram \n'); + cprintf('comment','with user definied potential density contours and the Conservative Temperature \n'); + cprintf('comment','freezing line at p of 0 dbar. The potential density anomaly contours are \n'); + cprintf('comment','referenced to user supplied depth are also included. In this example we have \n'); + cprintf('comment','set the reference pressure to be 2000 dbar. \n'); + cprintf('comment','note that this plotting function relies on the functions \n'); + cprintf('comment','"gsw_rho_CT" and "gsw_CT_freezing" \n'); + cprintf('text',' \n'); + cprintf('text','p_ref = 2000 \n'); + cprintf('text','gsw_SA_CT_plot(SA,CT,p_ref,''\\itS_A - \\Theta plot'') \n'); + pause(6) + if JavaVirtMach == 1 + try + gsw_SA_CT_plot(gsw_demo_data.SA,gsw_demo_data.CT,gsw_demo_data.p_ref,[33:0.2:38],'\itS\rm_A - \Theta plot') + pause(6) + close all + catch + fprintf(1,' \n'); + fprintf(1,'It appears that you are running MATLAB without the Java Virtual Machine, \n'); + fprintf(1,'so we can not show the resulting figure. \n'); + end + else + fprintf(1,' \n'); + fprintf(1,'It appears that you are running MATLAB without the Java Virtual Machine, \n'); + fprintf(1,'so we can not show the resulting figure. \n'); + end + cprintf('text',' \n'); + pause(2) + cprintf('comment','The bouyancy (Brunt Vasaila) frequency squared (N^2) at the mid point \n'); + cprintf('comment','pressure (p_mid) between the "bottles" can be obtained by using the \n'); + cprintf('comment','function "gsw_Nsquared" \n'); + cprintf('text','[N2, p_mid] = gsw_Nsquared(SA,CT,p) \n'); + [gsw_demo_data.N2, gsw_demo_data.p_mid] = gsw_Nsquared(gsw_demo_data.SA,gsw_demo_data.CT,gsw_demo_data.p); + cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'N2 = [',1e5*gsw_demo_data.N2([1,22,29:4:44],1)','] (*1e-5)'); + cprintf('text',' \n'); + cprintf('text','%s %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %s \n' ,'p_mid = [',gsw_demo_data.p_mid([1,22,29:4:44],1)',']'); + cprintf('text',' \n'); + pause(6) + cprintf('comment','The dynamic height anomaly, commmonly shortened to "dynamic height", can be \n'); + cprintf('comment','calculated with the function "gsw_geo_strf_dyn_height". In this function \n'); + cprintf('comment','the user defines the the reference pressure that they want the dymanic height \n'); + cprintf('comment','relative to. In this example we set p_ref to be 2000 dbar. \n'); + gsw_demo_data.geo_strf_dyn_height = gsw_geo_strf_dyn_height(gsw_demo_data.SA,gsw_demo_data.CT,gsw_demo_data.p,gsw_demo_data.p_ref); + cprintf('text','geo_strf_dyn_height = gsw_geo_strf_dyn_height(SA,CT,p,p_ref) \n'); + cprintf('text','%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'geo_strf_dyn_height = [',gsw_demo_data.geo_strf_dyn_height([1,22,29:4:45],1)',']'); + pause(4) + cprintf('comment','The end. \n'); +catch + fprintf(1,'Welcome the Gibbs Seawater (GSW) Oceanographic Toolbox (version 3). \n'); + pause(3) + fprintf(1,'This is a short demonstration of some of the features of the \n'); + fprintf(1,'GSW Oceanographic toolbox. \n'); + fprintf(1,' \n'); + fprintf(1,'The most important functions are the first two functions. \n'); + fprintf(1,' \n'); + fprintf(1,'The following vertical profiles, from the North Pacific, are of \n'); + fprintf(1,'Practical Salinity, SP, and in-situ temperature, t, as a function \n'); + fprintf(1,'of pressure, p, \n'); + pause(6) + fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'SP = [',gsw_demo_data.SP([1,22,29:4:45],1)',']'); + fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'t = [',gsw_demo_data.t([1,22,29:4:45],1)',']'); + fprintf(1,'%s %7.0f %7.0f %7.0f %7.0f %7.0f %7.0f %7.0f %s \n' ,'p = [',gsw_demo_data.p([1,22,29:4:45],1)',']'); + fprintf(1,'Note that, we have shown only seven bottles from the full vertical profile. \n'); + fprintf(1,' \n'); + pause(6) + fprintf(1,'The first step under TEOS-10 is to convert Practical Salinity, SP, \n'); + fprintf(1,'into Absolute Salinity, SA. This is done with the function "gsw_SA_from_SP" \n'); + pause(6) + fprintf(1,'SA = gsw_SA_from_SP(SP,p,long,lat) \n'); + gsw_demo_data.SA = gsw_SA_from_SP(gsw_demo_data.SP,gsw_demo_data.p,gsw_demo_data.long,gsw_demo_data.lat); + fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'SA = [',gsw_demo_data.SA([1,22,29:4:45],1)',']'); + fprintf(1,' \n'); + pause(6) + fprintf(1,'The second step is to convert in-situ temperature, t, into \n'); + fprintf(1,'Conservative Temperature, CT, using the function \n'); + fprintf(1,'"gsw_CT_from_t", \n'); + pause(6) + fprintf(1,'CT = gsw_CT_from_t(SA,t,p) '); + gsw_demo_data.CT = gsw_CT_from_t(gsw_demo_data.SA,gsw_demo_data.t,gsw_demo_data.p); + fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'CT = [',gsw_demo_data.CT([1,22,29:4:45],1)',']'); + fprintf(1,' \n'); + fprintf(1,'At this point the data has been converted into SA and CT, which are \n'); + fprintf(1,'the TEOS-10 salinity and temperature variables. With these variables it \n'); + fprintf(1,'is possible to compute the complete range of water column properties. \n'); + fprintf(1,' \n'); + pause(6) + fprintf(1,'The first property to be demonstrated is density (rho) as a function \n'); + fprintf(1,'of SA and CT. This is computed by using the function "gsw_rho_CT". \n'); + fprintf(1,'The use of a single algorithm for seawater density (the 48-term computationally \n'); + fprintf(1,'efficient expression) ensures consistency between ocean modelling, observational \n'); + fprintf(1,'oceanography, and theoretical studies. Note that this is not been the case to \n'); + fprintf(1,'date under EOS-80. \n'); + fprintf(1,'rho_CT = gsw_rho_CT(SA,CT,p) \n'); + gsw_demo_data.rho_CT = gsw_rho_CT(gsw_demo_data.SA,gsw_demo_data.CT,gsw_demo_data.p); + fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'rho_CT = [',gsw_demo_data.rho_CT([1,22,29:4:45],1)',']'); + fprintf(1,' \n'); + pause(6) + fprintf(1,'Using this same programme, gsw_rho_CT, it is possible to compute potential \n'); + fprintf(1,'density by replacing the in-situ pressure, p with the reference pressure, \n'); + fprintf(1,'p_ref. \n'); + fprintf(1,' \n'); + pause(2) + fprintf(1,'An example. We have set p_ref to be 2000 dbar, thus we have the potential \n'); + fprintf(1,'density referenced to 2000 dbars. \n'); + fprintf(1,'pot_rho_CT_2 = gsw_rho_CT(SA,CT,p_ref) \n'); + gsw_demo_data.pot_rho_CT_2 = gsw_rho_CT(gsw_demo_data.SA,gsw_demo_data.CT,gsw_demo_data.p_ref); + fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'pot_rho_CT = [',gsw_demo_data.pot_rho_CT_2([1,22,29:4:45],1)',']'); + fprintf(1,' \n'); + pause(6) + fprintf(1,'The potential density anomaly can be obtained by using the function \n'); + fprintf(1,'"gsw_rho_CT" - 1000 kg/m^3. \n'); + fprintf(1,'Two examples of this are sigma_Theta and sigma_2 which can be calculated \n'); + fprintf(1,'as follows \n'); + fprintf(1,'sigma_0 = gsw_rho_CT(SA,CT,0) - 1000 \n'); + gsw_demo_data.sigma_0 = gsw_rho_CT(gsw_demo_data.SA,gsw_demo_data.CT,0) -1000; + fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'sigma_0 = [',gsw_demo_data.sigma_0([1,22,29:4:45],1)',']'); + fprintf(1,' \n'); + pause(6) + fprintf(1,'sigma_2 = gsw_rho_CT(SA,CT,2000) - 1000 \n'); + gsw_demo_data.sigma_2 = gsw_rho_CT(gsw_demo_data.SA,gsw_demo_data.CT,2000) - 1000; + fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'sigma_2 = [',gsw_demo_data.sigma_2([1,22,29:4:45],1)',']'); + fprintf(1,' \n'); + pause(6) + fprintf(1,'However, there are alternatives to the last two calls, we have provided \n'); + fprintf(1,'some short-cuts for the standard oceaongraphic variables as functions of \n'); + fprintf(1,'SA and CT, the alternative short-cuts to the above two calls are: \n'); + fprintf(1,'sigma_0 = gsw_sigma0_CT(SA,CT) \n'); + fprintf(1,' and \n'); + fprintf(1,'sigma_2 = gsw_sigma2_CT(SA,CT) \n'); + fprintf(1,' \n'); + pause(6) + fprintf(1,'Calculating the Conservative Temperature at which seawater freezes is \n'); + fprintf(1,'done with the function \n'); + fprintf(1,'"gsw_CT_freezing" \n'); + fprintf(1,'This programme allows the user to choose the amount of air which the water \n'); + fprintf(1,'contains, at zero the water is unsaturated and at 1 it is completely \n'); + fprintf(1,'saturated, we have opted to set the default saturation level at maximum \n'); + fprintf(1,'CT_freezing = gsw_CT_freezing(SA,p) \n'); + gsw_demo_data.CT_freezing = gsw_CT_freezing(gsw_demo_data.SA,gsw_demo_data.p); + fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'CT_freezing = [',gsw_demo_data.CT_freezing([1,22,29:4:45],1)',']'); + fprintf(1,' \n'); + fprintf(1,'Press enter to continue. \n'); + pause + fprintf(1,'We now plot the profile on the Absolute Salinity - Conservative Temperature diagram \n'); + fprintf(1,'This can be done by calling "gsw_SA_CT_plot". This function plots the \n'); + fprintf(1,'Absolute Salinity and Conservative Temperature profile data on a SA-CT diagram \n'); + fprintf(1,'with user definied potential density contours and the Conservative Temperature \n'); + fprintf(1,'freezing line at p of 0 dbar. The potential density anomaly contours are \n'); + fprintf(1,'referenced to user supplied depth are also included. In this example we have \n'); + fprintf(1,'set the reference pressure to be 2000 dbar. \n'); + fprintf(1,'note that this plotting function relies on the functions \n'); + fprintf(1,'"gsw_rho_CT" and "gsw_CT_freezing" \n'); + fprintf(1,' \n'); + fprintf(1,'p_ref = 2000 \n'); + fprintf(1,'gsw_SA_CT_plot(SA,CT,p_ref,''\\itS_A - \\Theta plot'') \n'); + pause(6) + if JavaVirtMach == 1 + try + gsw_SA_CT_plot(gsw_demo_data.SA,gsw_demo_data.CT,gsw_demo_data.p_ref,[33:0.2:38],'\itS\rm_A - \Theta plot') + pause(6) + close all + catch + fprintf(1,' \n'); + fprintf(1,'It appears that you are running MATLAB without the Java Virtual Machine, \n'); + fprintf(1,'so we can not show the resulting figure. \n'); + end + else + fprintf(1,' \n'); + fprintf(1,'It appears that you are running MATLAB without the Java Virtual Machine, \n'); + fprintf(1,'so we can not show the resulting figure. \n'); + end + fprintf(1,' \n'); + pause(2) + fprintf(1,'The bouyancy (Brunt Vasaila) frequency squared (N^2) at the mid point \n'); + fprintf(1,'pressure (p_mid) between the "bottles" can be obtained by using the \n'); + fprintf(1,'function "gsw_Nsquared" \n'); + fprintf(1,'[N2, p_mid] = gsw_Nsquared(SA,CT,p) \n'); + [gsw_demo_data.N2, gsw_demo_data.p_mid] = gsw_Nsquared(gsw_demo_data.SA,gsw_demo_data.CT,gsw_demo_data.p); + fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'N2 = [',1e5*gsw_demo_data.N2([1,22,29:4:44],1)','] (*1e-5)'); + fprintf(1,' \n'); + fprintf(1,'%s %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %s \n' ,'p_mid = [',gsw_demo_data.p_mid([1,22,29:4:44],1)',']'); + fprintf(1,' \n'); + pause(6) + fprintf(1,'The dynamic height anomaly, commmonly shortened to "dynamic height", can be \n'); + fprintf(1,'calculated with the function "gsw_geo_strf_dyn_height". In this function \n'); + fprintf(1,'the user defines the the reference pressure that they want the dymanic height \n'); + fprintf(1,'relative to. In this example we set p_ref to be 2000 dbar. \n'); + gsw_demo_data.geo_strf_dyn_height = gsw_geo_strf_dyn_height(gsw_demo_data.SA,gsw_demo_data.CT,gsw_demo_data.p,gsw_demo_data.p_ref); + fprintf(1,'geo_strf_dyn_height = gsw_geo_strf_dyn_height(SA,CT,p,p_ref) \n'); + fprintf(1,'%s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %s \n' ,'geo_strf_dyn_height = [',gsw_demo_data.geo_strf_dyn_height([1,22,29:4:45],1)',']'); + pause(4) + fprintf(1,'The end. \n'); +end + +clear gsw_demo_data JavaVirtMach diff --git a/Toolbox/gsw_depth_from_z.m b/Toolbox/gsw_depth_from_z.m new file mode 100644 index 0000000..2053197 --- /dev/null +++ b/Toolbox/gsw_depth_from_z.m @@ -0,0 +1,42 @@ +function depth = gsw_depth_from_z(z) + +% gsw_depth_from_z depth from height, z +%========================================================================== +% +% USAGE: +% depth = gsw_depth_from_z(z) +% +% DESCRIPTION: +% Calculates depth from height, z. Note that in general height is +% negative in the ocean. +% +% INPUT: +% z = height [ m ] +% +% OUTPUT: +% depth = depth [ m ] +% +% AUTHOR: +% Winston [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (26th March, 2011) +% +% This software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 1) + error('gsw_depth_from_z: Requires one input') +end %if + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +depth = -z; + +end diff --git a/Toolbox/gsw_distance.m b/Toolbox/gsw_distance.m index e67a3fc..90a8c3b 100644 --- a/Toolbox/gsw_distance.m +++ b/Toolbox/gsw_distance.m @@ -11,7 +11,7 @@ % Calculates the distance in metres between successive points in the % vectors long and lat, computed using the Haversine formula on a % spherical earth of radius 6,371 km, being the radius of a sphere having -% the same volume as Earth. For a sperical Earth of radius 6,371,000 m, +% the same volume as Earth. For a sperical Earth of radius 6,371,000 m, % one nautical mile is 1,853.2488 m, thus one degree of latitude is % 111,194.93 m. % Note. Distances are probably good to better than 1% of the "true" @@ -24,7 +24,7 @@ % % OPTIONAL: % p = sea pressure ( default is 0 ) [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% ( i.e. absolute pressure - 10.1325 dbar ) % % lat and long need to have the same dimensions, Mx1 or 1xN or MxN. % p, if provided, may have dimensions 1x1 or Mx1 or 1xN or MxN, @@ -32,18 +32,18 @@ % % OUTPUT: % distance = Distance between points on a spherical [ m ] -% Earth at pressure (p) +% Earth at pressure (p) % Note. The output is in m not km. % % AUTHOR: -% 6th November, 2000 by Rich Pawlowicz [ help_gsw@csiro.au ] +% 6th November, 2000 by Rich Pawlowicz [ help_gsw@csiro.au ] % Note. This function was extracted from Rich Pawlowicz's m_map package, % which is available from http://www.eos.ubc.ca/~rich/map.html % % MODIFIED: -% 28th July, 2010 by Paul Barker and Trevor McDougall. +% 4th April, 2011 by Paul Barker and Trevor McDougall. % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (4th April, 2011) % % REFERENCE: % http://www.eos.ubc.ca/~rich/map.html @@ -74,33 +74,37 @@ error('*** No, you need more than one point to find a distance! ***') end -if mla==1 & nla==1 % lat is a scalar. Fill to size of p +transposed = 0; + +if (mla == 1) & (nla == 1) % lat is a scalar. Fill to size of p lat = lat*ones(mp,np); long = long*ones(mp,np); -elseif nla==np & mla==1 % lat is row vector, +elseif (nla == np) & (mla == 1) % lat is row vector, lat = lat(ones(1,mp),:); % copy down each column. long = long(ones(1,mp),:); -elseif mla==mp & nla==1 % lat is column vector, - lat = p(:,ones(1,np)); % copy across each row. - long = long(:,ones(1,np)); -elseif mla==mp & nla==np +elseif (mla == mp) & (nla == 1) % lat is column vector. + lat = lat.'; + long = long.'; + transposed = 1; + lat = lat(ones(1,np),:); + long = long(ones(1,np),:); +elseif (mla == mp) & (nla == np) % ok -% else -% error('gsw_dist: p has wrong dimensions') end %if + [mla,nla] = size(lat); -[mlo,nlo] = size(long); -if mp==1 & np==1 % p is a scalar. Fill to size of lat - p = p(1)*ones(mla,nla); -elseif np==nla & mp==1 % p is row vector, +if (mp == 1) & (np == 1) % p is a scalar. Fill to size of lat + p = p*ones(mla,nla); +elseif (np == nla) & (mp == 1) % p is row vector, p = p(ones(1,mla),:); % copy down each column. -elseif mp==mla & np==1 % p is column vector, - p = p(:,ones(1,nla)); % copy across each row. -elseif mp==mla & np==nla +elseif (mp == mla) & (np == 1) % p is column vector. + p = p.'; + p = p(ones(1,nla),:); +elseif (mp == mla) & (np == nla) % ok else - error('gsw_dist: p has wrong dimensions') + error('gsw_distance: p has wrong dimensions') end %if %-------------------------------------------------------------------------- @@ -123,4 +127,8 @@ distance = (earth_radius + z).*angles; % Note. The output is in m not km. +if transposed + distance = distance.'; +end + end diff --git a/Toolbox/gsw_dynamic_enthalpy.m b/Toolbox/gsw_dynamic_enthalpy.m new file mode 100644 index 0000000..2421caf --- /dev/null +++ b/Toolbox/gsw_dynamic_enthalpy.m @@ -0,0 +1,210 @@ +function dynamic_enthalpy = gsw_dynamic_enthalpy(SA,CT,p) + +% gsw_dynamic_enthalpy dynamic enthalpy of seawater +% (48-term equation) +%========================================================================== +% +% USAGE: +% dynamic_enthalpy = gsw_dynamic_enthalpy(SA,CT,p) +% +% DESCRIPTION: +% Calculates dynamic enthalpy of seawater using the computationally- +% efficient 48-term expression for density in terms of SA, CT and p +% (McDougall et al., 2011). Dynamic enthalpy is defined as enthalpy minus +% potential enthalpy (Young, 2010). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% dynamic_enthalpy = dynamic enthalpy [ J/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (5th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 3.2 of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% Young, W.R., 2010: Dynamic enthalpy, Conservative Temperature, and the +% seawater Boussinesq approximation. Journal of Physical Oceanography, +% 40, 394-400. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_dynamic_enthalpy: requires three inputs') +end + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_dynamic_enthalpy: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_dynamic_enthalpy: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +db2Pa = 1e4; % factor to convert from dbar to Pa + +v01 = 9.998420897506056e+2; +v02 = 2.839940833161907; +v03 = -3.147759265588511e-2; +v04 = 1.181805545074306e-3; +v05 = -6.698001071123802; +v06 = -2.986498947203215e-2; +v07 = 2.327859407479162e-4; +v08 = -3.988822378968490e-2; +v09 = 5.095422573880500e-4; +v10 = -1.426984671633621e-5; +v11 = 1.645039373682922e-7; +v12 = -2.233269627352527e-2; +v13 = -3.436090079851880e-4; +v14 = 3.726050720345733e-6; +v15 = -1.806789763745328e-4; +v16 = 6.876837219536232e-7; +v17 = -3.087032500374211e-7; +v18 = -1.988366587925593e-8; +v19 = -1.061519070296458e-11; +v20 = 1.550932729220080e-10; +v21 = 1.0; +v22 = 2.775927747785646e-3; +v23 = -2.349607444135925e-5; +v24 = 1.119513357486743e-6; +v25 = 6.743689325042773e-10; +v26 = -7.521448093615448e-3; +v27 = -2.764306979894411e-5; +v28 = 1.262937315098546e-7; +v29 = 9.527875081696435e-10; +v30 = -1.811147201949891e-11; +v31 = -3.303308871386421e-5; +v32 = 3.801564588876298e-7; +v33 = -7.672876869259043e-9; +v34 = -4.634182341116144e-11; +v35 = 2.681097235569143e-12; +v36 = 5.419326551148740e-6; +v37 = -2.742185394906099e-5; +v38 = -3.212746477974189e-7; +v39 = 3.191413910561627e-9; +v40 = -1.931012931541776e-12; +v41 = -1.105097577149576e-7; +v42 = 6.211426728363857e-10; +v43 = -1.119011592875110e-10; +v44 = -1.941660213148725e-11; +v45 = -1.864826425365600e-14; +v46 = 1.119522344879478e-14; +v47 = -1.200507748551599e-15; +v48 = 6.057902487546866e-17; + +sqrtSA = sqrt(SA); + +a0 = v21 + CT.*(v22 + CT.*(v23 + CT.*(v24 + v25*CT))) ... + + SA.*(v26 + CT.*(v27 + CT.*(v28 + CT.*(v29 + v30*CT))) + v36*SA ... + + sqrtSA.*(v31 + CT.*(v32 + CT.*(v33 + CT.*(v34 + v35*CT))))); + +a1 = v37 + CT.*(v38 + CT.*(v39 + v40*CT)) + SA.*(v41 + v42*CT); + +a2 = v43 + CT.*(v44 + v45*CT + v46*SA); + +a3 = v47 + v48*CT; + +b0 = v01 + CT.*(v02 + CT.*(v03 + v04*CT)) ... + + SA.*(v05 + CT.*(v06 + v07*CT) ... + + sqrtSA.*(v08 + CT.*(v09 + CT.*(v10 + v11*CT)))); + +b1 = 0.5*(v12 + CT.*(v13 + v14*CT) + SA.*(v15 + v16*CT)); + +b2 = v17 + CT.*(v18 + v19*CT) + v20*SA; + +b1sq = b1.*b1; +sqrt_disc = sqrt(b1sq - b0.*b2); + +N = a0 + (2*a3.*b0.*b1./b2 - a2.*b0)./b2; + +M = a1 + (4*a3.*b1sq./b2 - a3.*b0 - 2*a2.*b1)./b2; + +A = b1 - sqrt_disc; +B = b1 + sqrt_disc; + +part = (N.*b2 - M.*b1)./(b2.*(B - A)); + +dynamic_enthalpy = db2Pa.*(p.*(a2 - 2*a3.*b1./b2 + 0.5*a3.*p)./b2 ... + + (M./(2*b2)).*log(1 + p.*(2*b1 + b2.*p)./b0) ... + + part.*log(1 + (b2.*p.*(B - A))./(A.*(B + b2.*p)))); + +%-------------------------------------------------------------------------- +% This function calculates dynamic_enthalpy using the computationally- +% efficient 48-term expression for density in terms of SA, CT and p. If +% one wanted to compute dynamic_enthalpy from SA, CT, and p with the full +% TEOS-10 Gibbs function, the following lines of code will enable this. +% +% dynamic_enthalpy = gsw_dynamic_enthalpy_CT_exact(SA,CT,p) +% +%-----------------This is the end of the alternative code------------------ + +if transposed + dynamic_enthalpy = dynamic_enthalpy.'; +end + +end diff --git a/Toolbox/gsw_dynamic_enthalpy_CT.m b/Toolbox/gsw_dynamic_enthalpy_CT.m new file mode 100644 index 0000000..010da8e --- /dev/null +++ b/Toolbox/gsw_dynamic_enthalpy_CT.m @@ -0,0 +1,115 @@ +function dynamic_enthalpy_CT = gsw_dynamic_enthalpy_CT(SA,CT,p) + +% gsw_dynamic_enthalpy_CT dynamic enthalpy of seawater +% (48-term equation) +%========================================================================== +% +% USAGE: +% dynamic_enthalpy_CT = gsw_dynamic_enthalpy_CT(SA,CT,p), or equivalently +% dynamic_enthalpy = gsw_dynamic_enthalpy(SA,CT,p) +% +% Note that gsw_dynamic_enthalpy(SA,CT,p) is identical to +% gsw_dynamic_enthalpy_CT(SA,CT,p). The extra "_CT" emphasises that the +% input temperature is Conservative Temperature, but the extra "_CT" part +% of the function name is not needed. +% +% DESCRIPTION: +% Calculates dynamic enthalpy of seawater using the computationally- +% efficient 48-term expression for density in terms of SA, CT and p +% (McDougall et al., 2011). Dynamic enthalpy is defined as enthalpy minus +% potential enthalpy (Young, 2010). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% dynamic_enthalpy_CT = dynamic enthalpy [ J/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (5th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 3.2 of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% Young, W.R., 2010: Dynamic enthalpy, Conservative Temperature, and the +% seawater Boussinesq approximation. Journal of Physical Oceanography, +% 40, 394-400. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_dynamic_enthalpy_CT: requires three inputs') +end + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_dynamic_enthalpy_CT: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_dynamic_enthalpy_CT: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +dynamic_enthalpy_CT = gsw_dynamic_enthalpy(SA,CT,p); + +if transposed + dynamic_enthalpy_CT = dynamic_enthalpy_CT.'; +end + +end diff --git a/Toolbox/gsw_dynamic_enthalpy_CT_exact.m b/Toolbox/gsw_dynamic_enthalpy_CT_exact.m new file mode 100644 index 0000000..67b57e9 --- /dev/null +++ b/Toolbox/gsw_dynamic_enthalpy_CT_exact.m @@ -0,0 +1,110 @@ +function dynamic_enthalpy_CT_exact = gsw_dynamic_enthalpy_CT_exact(SA,CT,p) + +% gsw_dynamic_enthalpy_CT_exact dyamic enthalpy of seawater +%========================================================================== +% +% USAGE: +% dynamic_enthalpy_CT_exact = gsw_dynamic_enthalpy_CT_exact(SA,CT,p) +% +% DESCRIPTION: +% Calculates the dynamic enthalpy of seawater from Absolute Salinity and +% Conservative Temperature and pressure. Dynamic enthalpy is defined +% as enthalpy minus potential enthalpy (Young, 2010). +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely +% gsw_dynamic_enthalpy(SA,CT,p), which uses the computationally +% efficient 48-term expression for density in terms of SA, CT and p +% (McDougall et al., 2011). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% dynamic_enthalpy_CT_exact = dynamic enthalpy [ J/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker. [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (5th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See apendix A.30 of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% Young, W.R., 2010: Dynamic enthalpy, Conservative Temperature, and the +% seawater Boussinesq approximation. Journal of Physical Oceanography, +% 40, 394-400. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_dynamic_enthalpy_CT_exact: requires three inputs') +end + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_dynamic_enthalpy_CT_exact: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_dynamic_enthalpy_CT_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +cp0 = 3991.86795711963; % from Eqn. (3.3.3) of IOC et al. (2010). + +t = gsw_t_from_CT(SA,CT,p); +dynamic_enthalpy_CT_exact = gsw_enthalpy_t_exact(SA,t,p) - cp0*CT; + +if transposed + dynamic_enthalpy_CT_exact = dynamic_enthalpy_CT_exact.'; +end + +end diff --git a/Toolbox/gsw_dynamic_enthalpy_t_exact.m b/Toolbox/gsw_dynamic_enthalpy_t_exact.m new file mode 100644 index 0000000..bc2e588 --- /dev/null +++ b/Toolbox/gsw_dynamic_enthalpy_t_exact.m @@ -0,0 +1,100 @@ +function dynamic_enthalpy_t_exact = gsw_dynamic_enthalpy_t_exact(SA,t,p) + +% gsw_dynamic_enthalpy_t_exact dyamic enthalpy of seawater +%========================================================================== +% +% USAGE: +% dynamic_enthalpy_t_exact = gsw_dynamic_enthalpy_t_exact(SA,t,p) +% +% DESCRIPTION: +% Calculates the dynamic enthalpy of seawater from Absolute Salinity, +% in situ temperature and pressure. Dynamic enthalpy was defined by +% Young (2010) as the difference between enthalpy and potential enthalpy. +% Note that this function uses the full TEOS-10 Gibbs function (i.e. the +% sum of the IAPWS-09 and IAPWS-08 Gibbs functions, see the TEOS-10 +% Manual, IOC et al. (2010)). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & t need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% +% OUTPUT: +% dynamic_enthalpy_t_exact = dynamic enthalpy [ J/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker. [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (11th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% +% Young, W.R., 2010: Dynamic enthalpy, Conservative Temperature, and the +% seawater Boussinesq approximation. Journal of Physical Oceanography, +% 40, 394-400. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_dynamic_enthalpy_t_exact: requires three inputs') +end + +[ms,ns] = size(SA); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_dynamic_enthalpy_t_exact: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_dynamic_enthalpy_t_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +cp0 = 3991.86795711963; % from Eqn. (3.3.3) of IOC et al. (2010). +CT = gsw_CT_from_t(SA,t,p); +dynamic_enthalpy_t_exact = gsw_enthalpy_t_exact(SA,t,p) - cp0*CT; + +if transposed + dynamic_enthalpy_t_exact = dynamic_enthalpy_t_exact.'; +end + +end diff --git a/Toolbox/gsw_enthalpy.m b/Toolbox/gsw_enthalpy.m index 30510ab..f89c063 100644 --- a/Toolbox/gsw_enthalpy.m +++ b/Toolbox/gsw_enthalpy.m @@ -1,36 +1,52 @@ -function enthalpy = gsw_enthalpy(SA,t,p) +function enthalpy = gsw_enthalpy(SA,CT,p) % gsw_enthalpy specific enthalpy of seawater +% (48-term equation) %========================================================================== % % USAGE: -% enthalpy = gsw_enthalpy(SA,t,p) +% enthalpy = gsw_enthalpy(SA,CT,p) % % DESCRIPTION: -% Calculates the specific enthalpy of seawater. +% Calculates specific enthalpy of seawater using the computationally- +% efficient 48-term expression for density in terms of SA, CT and p +% (McDougall et al., 2011) +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % -% SA & t need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. % % OUTPUT: -% enthalpy = specific enthalpy [ J/kg ] +% enthalpy = specific enthalpy [ J/kg ] % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker. [ help_gsw@csiro.au ] -% -% VERSION NUMBER: 2.0 (26th August, 2010) +% Trevor McDougall, David Jackett, Claire Roberts-Thomson and Paul Barker. +% [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (5th April, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of % seawater - 2010: Calculation and use of thermodynamic properties. % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (A.30.6) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -40,16 +56,16 @@ % Check variables and resize if necessary %-------------------------------------------------------------------------- -if ~(nargin==3) - error('gsw_enthalpy: Requires three inputs') -end %if +if ~(nargin == 3) + error('gsw_enthalpy: requires three inputs') +end [ms,ns] = size(SA); -[mt,nt] = size(t); +[mt,nt] = size(CT); [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_enthalpy: SA and t must have same dimensions') + error('gsw_enthalpy: SA and CT must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -58,16 +74,19 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_enthalpy: Inputs array dimensions arguments do not agree') + error('gsw_enthalpy_: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -77,13 +96,120 @@ % Start of the calculation %-------------------------------------------------------------------------- -n0 = 0; -n1 = 1; +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +db2Pa = 1e4; % factor to convert from dbar to Pa +cp0 = 3991.86795711963; % from Eqn. (3.3.3) of IOC et al. (2010). + +v01 = 9.998420897506056e+2; +v02 = 2.839940833161907; +v03 = -3.147759265588511e-2; +v04 = 1.181805545074306e-3; +v05 = -6.698001071123802; +v06 = -2.986498947203215e-2; +v07 = 2.327859407479162e-4; +v08 = -3.988822378968490e-2; +v09 = 5.095422573880500e-4; +v10 = -1.426984671633621e-5; +v11 = 1.645039373682922e-7; +v12 = -2.233269627352527e-2; +v13 = -3.436090079851880e-4; +v14 = 3.726050720345733e-6; +v15 = -1.806789763745328e-4; +v16 = 6.876837219536232e-7; +v17 = -3.087032500374211e-7; +v18 = -1.988366587925593e-8; +v19 = -1.061519070296458e-11; +v20 = 1.550932729220080e-10; +v21 = 1.0; +v22 = 2.775927747785646e-3; +v23 = -2.349607444135925e-5; +v24 = 1.119513357486743e-6; +v25 = 6.743689325042773e-10; +v26 = -7.521448093615448e-3; +v27 = -2.764306979894411e-5; +v28 = 1.262937315098546e-7; +v29 = 9.527875081696435e-10; +v30 = -1.811147201949891e-11; +v31 = -3.303308871386421e-5; +v32 = 3.801564588876298e-7; +v33 = -7.672876869259043e-9; +v34 = -4.634182341116144e-11; +v35 = 2.681097235569143e-12; +v36 = 5.419326551148740e-6; +v37 = -2.742185394906099e-5; +v38 = -3.212746477974189e-7; +v39 = 3.191413910561627e-9; +v40 = -1.931012931541776e-12; +v41 = -1.105097577149576e-7; +v42 = 6.211426728363857e-10; +v43 = -1.119011592875110e-10; +v44 = -1.941660213148725e-11; +v45 = -1.864826425365600e-14; +v46 = 1.119522344879478e-14; +v47 = -1.200507748551599e-15; +v48 = 6.057902487546866e-17; + +sqrtSA = sqrt(SA); + +a0 = v21 + CT.*(v22 + CT.*(v23 + CT.*(v24 + v25*CT))) ... + + SA.*(v26 + CT.*(v27 + CT.*(v28 + CT.*(v29 + v30*CT))) + v36*SA ... + + sqrtSA.*(v31 + CT.*(v32 + CT.*(v33 + CT.*(v34 + v35*CT))))); + +a1 = v37 + CT.*(v38 + CT.*(v39 + v40*CT)) + SA.*(v41 + v42*CT); + +a2 = v43 + CT.*(v44 + v45*CT + v46*SA); + +a3 = v47 + v48*CT; + +b0 = v01 + CT.*(v02 + CT.*(v03 + v04*CT)) ... + + SA.*(v05 + CT.*(v06 + v07*CT) ... + + sqrtSA.*(v08 + CT.*(v09 + CT.*(v10 + v11*CT)))); + +b1 = 0.5*(v12 + CT.*(v13 + v14*CT) + SA.*(v15 + v16*CT)); -enthalpy = gsw_gibbs(n0,n0,n0,SA,t,p) - (t+273.15).*gsw_gibbs(n0,n1,n0,SA,t,p); +b2 = v17 + CT.*(v18 + v19*CT) + v20*SA; + +b1sq = b1.*b1; +sqrt_disc = sqrt(b1sq - b0.*b2); + +N = a0 + (2*a3.*b0.*b1./b2 - a2.*b0)./b2; + +M = a1 + (4*a3.*b1sq./b2 - a3.*b0 - 2*a2.*b1)./b2; + +A = b1 - sqrt_disc; +B = b1 + sqrt_disc; + +part = (N.*b2 - M.*b1)./(b2.*(B - A)); + +enthalpy = cp0*CT + ... + db2Pa.*(p.*(a2 - 2*a3.*b1./b2 + 0.5*a3.*p)./b2 + ... + (M./(2*b2)).*log(1 + p.*(2*b1 + b2.*p)./b0) + ... + part.*log(1 + (b2.*p.*(B - A))./(A.*(B + b2.*p)))); + +%-------------------------------------------------------------------------- +% This function calculates enthalpy using the computationally-efficient +% 48-term expression for density in terms of SA, CT and p. If one wanted to +% compute enthalpy from SA, CT, and p with the full TEOS-10 Gibbs function, +% the following lines of code will enable this. +% +% pt = gsw_pt_from_CT(SA,CT); +% pr0 = zeros(size(SA)); +% t = gsw_pt_from_t(SA,pt,pr0,p); +% enthalpy = gsw_enthalpy_t_exact(SA,t,p); +% +% or call the following, it is identical to the lines above. +% +% enthalpy = gsw_enthalpy_CT_exact(SA,CT,p) +% +%-----------------This is the end of the alternative code------------------ if transposed - enthalpy = enthalpy'; + enthalpy = enthalpy.'; end -end \ No newline at end of file +end diff --git a/Toolbox/gsw_enthalpy_CT.m b/Toolbox/gsw_enthalpy_CT.m index d1d3cb7..dc4be22 100644 --- a/Toolbox/gsw_enthalpy_CT.m +++ b/Toolbox/gsw_enthalpy_CT.m @@ -1,53 +1,58 @@ -function enthalpy = gsw_enthalpy_CT(SA,CT,p) +function enthalpy_CT = gsw_enthalpy_CT(SA,CT,p) % gsw_enthalpy_CT specific enthalpy of seawater +% (48-term equation) %========================================================================== % % USAGE: -% enthalpy = gsw_enthalpy_CT(SA,CT,p) +% enthalpy_CT = gsw_enthalpy_CT(SA,CT,p), or equivalently +% enthalpy = gsw_enthalpy(SA,CT,p) +% +% Note that gsw_enthalpy(SA,CT,p) is identical to gsw_enthalpy_CT(SA,CT,p). +% The extra "_CT" emphasises that the input temperature is Conservative +% Temperature, but the extra "_CT" part of the function name is not +% needed. % % DESCRIPTION: -% Calculates specific enthalpy of seawater from Absolute Salinity and -% Conservative Temperature and pressure. +% Calculates specific enthalpy of seawater using the computationally- +% efficient 48-term expression for density in terms of SA, CT and p +% (McDougall et al., 2011) +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % -% Note that this function uses the full Gibbs function. There is an -% alternative to calling this function, namely gsw_enthalpy_CT25(SA,CT,p), -% which uses the computationally efficient 25-term expression for density -% in terms of SA, CT and p (McDougall et al., (2010)). For SA, CT and p -% values which fall inside the oceanographic "funnel" (McDougall et al., -% 2010), this computationally efficient (i. e. faster) 25-term version -% fits the underlying laboratory density data almost as well as does the -% density derived from the full TEOS-10 Gibbs function. -% % INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & CT need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. % % OUTPUT: -% enthalpy = specific enthalpy [ J/kg ] +% enthalpy_CT = specific enthalpy [ J/kg ] % % AUTHOR: -% Trevor McDougall and Paul Barker. [ help_gsw@csiro.au ] +% Trevor McDougall, David Jackett, Claire Roberts-Thomson and Paul Barker. +% [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (29th September, 2010) +% VERSION NUMBER: 3.0 (5th April, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of % seawater - 2010: Calculation and use of thermodynamic properties. % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See apendix A.11 of this TEOS-10 Manual. +% See Eqn. (A.30.6) of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -76,7 +81,7 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok @@ -85,9 +90,9 @@ end %if if ms == 1 - SA = SA'; - CT = CT'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -97,13 +102,10 @@ % Start of the calculation %-------------------------------------------------------------------------- -pt = gsw_pt_from_CT(SA,CT); -pr0 = zeros(size(SA)); -t = gsw_pt_from_t(SA,pt,pr0,p); -enthalpy = gsw_enthalpy(SA,t,p); +enthalpy_CT = gsw_enthalpy(SA,CT,p); if transposed - enthalpy = enthalpy'; + enthalpy_CT = enthalpy_CT.'; end end diff --git a/Toolbox/gsw_enthalpy_CT25.m b/Toolbox/gsw_enthalpy_CT25.m deleted file mode 100644 index 77fa637..0000000 --- a/Toolbox/gsw_enthalpy_CT25.m +++ /dev/null @@ -1,177 +0,0 @@ -function [enthalpy, in_funnel] = gsw_enthalpy_CT25(SA,CT,p) - -% gsw_enthalpy_CT25 specific enthalpy of seawater -% (25-term equation) -%========================================================================== -% -% USAGE: -% [enthalpy, in_funnel] = gsw_enthalpy_CT25(SA,CT,p) -% -% DESCRIPTION: -% Calculates specific enthalpy of seawater using the computationally- -% efficient 25-term expression for density in terms of SA, CT and p -% (McDougall et al., 2010) -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) -% -% SA & CT need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. -% -% OUTPUT: -% enthalpy = specific enthalpy [ J/kg ] -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). -% -% AUTHOR: -% Trevor McDougall, David Jackett, Claire Roberts-Thomson and Paul Barker. -% [ help_gsw@csiro.au ] -% -% VERSION NUMBER: 2.0 (26th August, 2010) -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See Eqn. (A.30.6) of this TEOS-10 Manual. -% -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 3) - error('gsw_enthalpy_CT25: requires three inputs') -end - -[ms,ns] = size(SA); -[mt,nt] = size(CT); -[mp,np] = size(p); - -if (mt ~= ms | nt ~= ns) - error('gsw_enthalpy_CT25: SA and CT must have same dimensions') -end - -if (mp == 1) & (np == 1) % p scalar - fill to size of SA - p = p*ones(size(SA)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_enthalpy_CT25: Inputs array dimensions arguments do not agree') -end %if - -if ms == 1 - SA = SA'; - CT = CT'; - p = p'; - transposed = 1; -else - transposed = 0; -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -% These few lines ensure that SA is non-negative. -[I_neg_SA] = find(SA < 0); -if ~isempty(I_neg_SA) - SA(I_neg_SA) = 0; -end - -in_funnel = gsw_infunnel(SA,CT,p); - -db2Pa = 1e4; -cp0 = 3991.86795711963; % from Eqn. (3.3.3) of IOC et al. (2010). - -CT2 = CT.*CT; -CT3 = CT.*CT2; - -a0 = 1 + CT.*( 7.0547681896071576e-3 +... - CT.*(-1.1753695605858647e-5 + ... - CT.*(5.9219809488274903e-7 + ... - CT.*3.4887902228012519e-10))) + ... - SA.*( 2.0777716085618458e-3 + ... - CT.*(-2.2210857293722998e-8 + ... - CT2.*-3.6628141067895282e-10) + ... - sqrt(SA).*(3.4688210757917340e-6 + ... - CT2.*8.0190541528070655e-10)); -a1 = 6.8314629554123324e-6; -a2 = CT3*-8.5294794834485446e-17; -a3 = CT*-9.2275325145038070e-18; - -b0 = 9.9984380290708214e2 + ... - CT.* (7.1188090678940910e0 + ... - CT.*(-1.9459922513379687e-2 + ... - CT.* 6.1748404455874641e-4)) + ... - SA.*(2.8925731541277653e0 + ... - CT.* 2.1471495493268324e-3 + ... - SA.* 1.9457531751183059e-3); -b1 = 0.5*(1.1930681818531748e-2 + ... - CT2.*2.6969148011830758e-7 + ... - SA.* 5.9355685925035653e-6); -b2 = CT2.*-7.2734111712822707e-12 - 2.5943389807429039e-8; - -b1sq = b1.*b1; -sqrt_disc = sqrt(b1sq - b0.*b2); - -N = a0 + (2*a3.*b0.*b1./b2 - a2.*b0)./b2; - -M = a1 + (4*a3.*b1sq./b2 - (a3.*b0 + 2*a2.*b1))./b2; - -A = b1 - sqrt_disc; -B = b1 + sqrt_disc; - -part = (N.*b2 - M.*b1)./(b2.*(B - A)); - -enthalpy = cp0*CT + ... - db2Pa.*(p.*(a2 - 2*a3.*b1./b2 + 0.5*a3.*p)./b2 + ... - (M./(2*b2)).*log(1 + p.*(2*b1 + b2.*p)./b0) + ... - part.*log(1 + (b2.*p.*(B - A))./(A.*(B + b2.*p)))); - -%-------------------------------------------------------------------------- -% This function calculates enthalpy_CT25 using the computationally-efficient -% 25-term expression for density in terms of SA, CT and p. If one wanted to -% compute enthalpy from SA, CT, and p with the full TEOS-10 Gibbs function, -% the following lines of code will enable this. -% -% pt = gsw_pt_from_CT(SA,CT); -% pr0 = zeros(size(SA)); -% t = gsw_pt_from_t(SA,pt,pr0,p); -% enthalpy = gsw_enthalpy(SA,t,p); -% -% or call the following, it is identical to the lines above. -% -% enthalpy = gsw_enthalpy_CT(SA,CT,p) -% -%-----------------This is the end of the alternative code------------------ - -if transposed - enthalpy = enthalpy'; - in_funnel = in_funnel'; -end - -end diff --git a/Toolbox/gsw_enthalpy_CT_exact.m b/Toolbox/gsw_enthalpy_CT_exact.m new file mode 100644 index 0000000..e57a8ee --- /dev/null +++ b/Toolbox/gsw_enthalpy_CT_exact.m @@ -0,0 +1,103 @@ +function enthalpy_CT_exact = gsw_enthalpy_CT_exact(SA,CT,p) + +% gsw_enthalpy_CT_exact specific enthalpy of seawater +%========================================================================== +% +% USAGE: +% enthalpy_CT_exact = gsw_enthalpy_CT_exact(SA,CT,p) +% +% DESCRIPTION: +% Calculates specific enthalpy of seawater from Absolute Salinity and +% Conservative Temperature and pressure. +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely gsw_enthalpy_CT(SA,CT,p), +% which uses the computationally-efficient 48-term expression for density +% in terms of SA, CT and p (McDougall et al., 2011). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% enthalpy_CT_exact = specific enthalpy [ J/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (6th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See apendix A.11 of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_enthalpy_CT_exact: requires three inputs') +end + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_enthalpy_CT_exact: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_enthalpy_CT_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + + +t = gsw_t_from_CT(SA,CT,p); +enthalpy_CT_exact = gsw_enthalpy_t_exact(SA,t,p); + +if transposed + enthalpy_CT_exact = enthalpy_CT_exact.'; +end + +end diff --git a/Toolbox/gsw_enthalpy_diff.m b/Toolbox/gsw_enthalpy_diff.m new file mode 100644 index 0000000..31e3f85 --- /dev/null +++ b/Toolbox/gsw_enthalpy_diff.m @@ -0,0 +1,246 @@ +function enthalpy_diff = gsw_enthalpy_diff(SA,CT,p_shallow,p_deep) + +% gsw_enthalpy_diff difference of enthalpy at two pressures +% (48-term equation) +%========================================================================== +% +% USAGE: +% enthalpy_diff = gsw_enthalpy_diff(SA,CT,p_shallow,p_deep) +% +% DESCRIPTION: +% Calculates the difference of the specific enthalpy of seawater between +% two different pressures, p_deep (the deeper pressure) and p_shallow +% (the shallower pressure), at the same values of SA and CT. This +% function uses the computationally-efficient 48-term expression for +% density in terms of SA, CT and p (McDougall et al., 2011). The output +% (enthalpy_diff_CT) is the specific enthalpy evaluated at (SA,CT,p_deep) +% minus the specific enthalpy at (SA,CT,p_shallow). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p_shallow = upper sea pressure [ dbar ] +% ( i.e. shallower absolute pressure - 10.1325 dbar ) +% p_deep = lower sea pressure [ dbar ] +% ( i.e. deeper absolute pressure - 10.1325 dbar ) +% +% p_shallow and p_deep may have dimensions Mx1 or 1xN or MxN, +% where SA and CT are MxN. +% +% OUTPUT: +% enthalpy_diff_CT = difference of specific enthalpy [ J/kg ] +% (deep minus shallow) +% +% AUTHOR: +% Trevor McDougall & Paul Barker. [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (21st March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqns. (3.32.2) and (A.30.6) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 4) + error('gsw_enthalpy_diff: requires four inputs') +end + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mpu,npu] = size(p_shallow); +[mpl,npl] = size(p_deep); + +if (ms~=mt) | (ns~=nt) + error('gsw_enthalpy_diff: SA & CT need to have the same dimensions') +end + +if (mpu == 1) & (npu == 1) % p_shallow is a scalar + p_shallow = p_shallow*ones(size(SA)); +elseif (ns == npu) & (mpu == 1) % p_shallow is row vector, + p_shallow = p_shallow(ones(1,ms), :); % copy down each column. +elseif (ms == mpu) & (npu == 1) % p_shallow is column vector, + p_shallow = p_shallow(:,ones(1,ns)); % copy across each row. +elseif (ns == mpu) & (npu == 1) % p_shallow is a transposed row vector, + p_shallow = p_shallow.'; % transposed then + p_shallow = p_shallow(ones(1,ms), :); % copy down each column. +elseif (ms == mpu) & (ns == npu) + % ok +end + +if (mpl == 1) & (npl == 1) % p_deep is a scalar + p_deep = p_deep*ones(size(SA)); +elseif (ns == npl) & (mpl == 1) % p_deep is row vector, + p_deep = p_deep(ones(1,ms), :); % copy down each column. +elseif (ms == mpl) & (npl == 1) % p_deep is column vector, + p_deep = p_deep(:,ones(1,ns)); % copy across each row. +elseif (ns == mpl) & (npl == 1) % p_deep is a transposed row vector, + p_deep = p_deep.'; % transposed then + p_deep = p_deep(ones(1,ms), :); % copy down each column. +elseif (ms == mpl) & (ns == npl) + % ok +else + error('gsw_enthalpy_diff: Inputs array dimensions arguments do not agree') +end %if + +if ~isempty(find(p_shallow - p_deep > 0)); + error('gsw_enthalpy_diff: p_deep needs to be greater than or equal to p_shallow') +end + +if ms == 1 + SA = SA.'; + CT = CT.'; + p_shallow = p_shallow.'; + p_deep = p_deep.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +db2Pa = 1e4; % factor to convert from dbar to Pa +%cp0 = 3991.86795711963; % from Eqn. (3.3.3) of IOC et al. (2010). + +v01 = 9.998420897506056e+2; +v02 = 2.839940833161907; +v03 = -3.147759265588511e-2; +v04 = 1.181805545074306e-3; +v05 = -6.698001071123802; +v06 = -2.986498947203215e-2; +v07 = 2.327859407479162e-4; +v08 = -3.988822378968490e-2; +v09 = 5.095422573880500e-4; +v10 = -1.426984671633621e-5; +v11 = 1.645039373682922e-7; +v12 = -2.233269627352527e-2; +v13 = -3.436090079851880e-4; +v14 = 3.726050720345733e-6; +v15 = -1.806789763745328e-4; +v16 = 6.876837219536232e-7; +v17 = -3.087032500374211e-7; +v18 = -1.988366587925593e-8; +v19 = -1.061519070296458e-11; +v20 = 1.550932729220080e-10; +v21 = 1.0; +v22 = 2.775927747785646e-3; +v23 = -2.349607444135925e-5; +v24 = 1.119513357486743e-6; +v25 = 6.743689325042773e-10; +v26 = -7.521448093615448e-3; +v27 = -2.764306979894411e-5; +v28 = 1.262937315098546e-7; +v29 = 9.527875081696435e-10; +v30 = -1.811147201949891e-11; +v31 = -3.303308871386421e-5; +v32 = 3.801564588876298e-7; +v33 = -7.672876869259043e-9; +v34 = -4.634182341116144e-11; +v35 = 2.681097235569143e-12; +v36 = 5.419326551148740e-6; +v37 = -2.742185394906099e-5; +v38 = -3.212746477974189e-7; +v39 = 3.191413910561627e-9; +v40 = -1.931012931541776e-12; +v41 = -1.105097577149576e-7; +v42 = 6.211426728363857e-10; +v43 = -1.119011592875110e-10; +v44 = -1.941660213148725e-11; +v45 = -1.864826425365600e-14; +v46 = 1.119522344879478e-14; +v47 = -1.200507748551599e-15; +v48 = 6.057902487546866e-17; + +sqrtSA = sqrt(SA); + + a0 = v21 + CT.*(v22 + CT.*(v23 + CT.*(v24 + v25*CT))) ... + + SA.*(v26 + CT.*(v27 + CT.*(v28 + CT.*(v29 + v30*CT))) + v36*SA ... + + sqrtSA.*(v31 + CT.*(v32 + CT.*(v33 + CT.*(v34 + v35*CT))))); + +a1 = v37 + CT.*(v38 + CT.*(v39 + v40*CT)) + SA.*(v41 + v42*CT); + +a2 = v43 + CT.*(v44 + v45*CT + v46*SA); + +a3 = v47 + v48*CT; + +b0 = v01 + CT.*(v02 + CT.*(v03 + v04*CT)) ... + + SA.*(v05 + CT.*(v06 + v07*CT) ... + + sqrtSA.*(v08 + CT.*(v09 + CT.*(v10 + v11*CT)))); + +b1 = 0.5*(v12 + CT.*(v13 + v14*CT) + SA.*(v15 + v16*CT)); + +b2 = v17 + CT.*(v18 + v19*CT) + v20*SA; + +b1sq = b1.*b1; +sqrt_disc = sqrt(b1sq - b0.*b2); + +N = a0 + (2*a3.*b0.*b1./b2 - a2.*b0)./b2; + +M = a1 + (4*a3.*b1sq./b2 - a3.*b0 - 2*a2.*b1)./b2; + +A = b1 - sqrt_disc; +B = b1 + sqrt_disc; +delta_p = p_deep - p_shallow; +p_sum = p_deep + p_shallow; +part1 = b0 + p_shallow.*(2*b1 + b2.*p_shallow); + +part2 = (B + b2.*p_deep).*(A + b2.*p_shallow); + +part3 = (N.*b2 - M.*b1)./(b2.*(B - A)); + +enthalpy_diff = db2Pa.*(delta_p.*(a2 - 2*a3.*b1./b2 + 0.5*a3.*p_sum)./b2 + ... + (M./(2*b2)).*log(1 + delta_p.*(2*b1 + b2.*p_sum)./part1) + ... + part3.*log(1 + delta_p.*b2.*(B - A)./part2)); + +%-------------------------------------------------------------------------- +% This function calculates enthalpy_diff using the computationally +% efficient 48-term expression for density in terms of SA, CT and p. If +% one wanted to compute the enthalpy difference using the full TEOS-10 +% Gibbs function, the following lines of code will enable this. +% +% pt = gsw_pt_from_CT(SA,CT); +% pr0 = zeros(size(SA)); +% t_shallow = gsw_pt_from_t(SA,pt,pr0,p_shallow); +% t_deep = gsw_pt_from_t(SA,pt,pr0,p_deep); +% enthalpy_diff = gsw_enthalpy_t_exact(SA,t_deep,p_deep) - ... +% gsw_enthalpy_t_exact(SA,t_shallow,p_shallow); +% +% or call the following, it is identical to the lines above. +% +% enthalpy_diff = gsw_enthalpy_diff_CT_exact(SA,CT,p_shallow,p_deep) +% +%-----------------This is the end of the alternative code------------------ + +if transposed + enthalpy_diff = enthalpy_diff.'; +end + +end diff --git a/Toolbox/gsw_enthalpy_diff_CT.m b/Toolbox/gsw_enthalpy_diff_CT.m index 4449860..73218a2 100644 --- a/Toolbox/gsw_enthalpy_diff_CT.m +++ b/Toolbox/gsw_enthalpy_diff_CT.m @@ -1,60 +1,64 @@ function enthalpy_diff_CT = gsw_enthalpy_diff_CT(SA,CT,p_shallow,p_deep) % gsw_enthalpy_diff_CT difference of enthalpy at two pressures +% (48-term equation) %========================================================================== % % USAGE: -% enthalpy_diff_CT = gsw_enthalpy_diff_CT(SA,CT,p_shallow,p_deep) +% enthalpy_diff_CT = gsw_enthalpy_diff_CT(SA,CT,p_shallow,p_deep), or +% equivalently enthalpy_diff = gsw_enthalpy_diff(SA,CT,p_shallow,p_deep) +% +% Note that gsw_enthalpy_diff(SA,CT,p_shallow,p_deep) is identical to +% gsw_enthalpy_diff_CT(SA,CT,p_shallow,p_deep). The extra "_CT" +% emphasises that the input temperature is Conservative Temperature, but +% the extra "_CT" part of the function name is not needed. % % DESCRIPTION: % Calculates the difference of the specific enthalpy of seawater between % two different pressures, p_deep (the deeper pressure) and p_shallow -% (the shallower pressure), at the same values of SA and CT. The output -% (enthalpy_diff) is the specific enthalpy evaluated at (SA,CT,p_deep) +% (the shallower pressure), at the same values of SA and CT. This +% function uses the computationally-efficient 48-term expression for +% density in terms of SA, CT and p (McDougall et al., 2011). The output +% (enthalpy_diff_CT) is the specific enthalpy evaluated at (SA,CT,p_deep) % minus the specific enthalpy at (SA,CT,p_shallow). % -% Note that this function uses the full Gibbs function. There is an -% alternative to calling this function, namely -% gsw_enthalpy_diff_CT25(SA,CT,p), which uses the computationally -% efficient 25-term expression for density in terms of SA, CT and p -% (McDougall et al., (2010)). For SA, CT and p values which fall inside -% the oceanographic "funnel" (McDougall et al., 2010), this -% computationally efficient (i. e. faster) 25-term version fits the -% underlying laboratory density data almost as well as does the density -% derived from the full TEOS-10 Gibbs function. +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: % SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % p_shallow = upper sea pressure [ dbar ] -% (ie. shallower absolute pressure - 10.1325 dbar) +% ( i.e. shallower absolute pressure - 10.1325 dbar ) % p_deep = lower sea pressure [ dbar ] -% (ie. deeper absolute pressure - 10.1325 dbar) +% ( i.e. deeper absolute pressure - 10.1325 dbar ) % % p_shallow and p_deep may have dimensions Mx1 or 1xN or MxN, -% where SA and CT are MxN. +% where SA and CT are MxN. % % OUTPUT: -% enthalpy_diff_CT = difference of specific enthalpy [ J/kg ] -% (deep minus shallow) +% enthalpy_diff_CT = difference of specific enthalpy [ J/kg ] +% (deep minus shallow) % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall & Paul Barker. [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (29th September, 2010) +% VERSION NUMBER: 3.0 (21st March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of % seawater - 2010: Calculation and use of thermodynamic properties. % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See Eqns. (3.32.2) of this TEOS-10 Manual. +% See Eqns. (3.32.2) and (A.30.6) of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -77,27 +81,27 @@ error('gsw_enthalpy_diff_CT: SA & CT need to have the same dimensions') end -if (mpu == 1) & (npu == 1) % p_shallowis a scalar - error('gsw_enthalpy_diff_CT: need more than one pressure') +if (mpu == 1) & (npu == 1) % p_shallow is a scalar + p_shallow = p_shallow*ones(size(SA)); elseif (ns == npu) & (mpu == 1) % p_shallow is row vector, p_shallow = p_shallow(ones(1,ms), :); % copy down each column. elseif (ms == mpu) & (npu == 1) % p_shallow is column vector, p_shallow = p_shallow(:,ones(1,ns)); % copy across each row. elseif (ns == mpu) & (npu == 1) % p_shallow is a transposed row vector, - p_shallow = p_shallow'; % transposed then + p_shallow = p_shallow.'; % transposed then p_shallow = p_shallow(ones(1,ms), :); % copy down each column. elseif (ms == mpu) & (ns == npu) % ok end if (mpl == 1) & (npl == 1) % p_deep is a scalar - error('gsw_enthalpy_diff_CT: need more than one pressure') + p_deep = p_deep*ones(size(SA)); elseif (ns == npl) & (mpl == 1) % p_deep is row vector, p_deep = p_deep(ones(1,ms), :); % copy down each column. elseif (ms == mpl) & (npl == 1) % p_deep is column vector, p_deep = p_deep(:,ones(1,ns)); % copy across each row. elseif (ns == mpl) & (npl == 1) % p_deep is a transposed row vector, - p_deep = p_deep'; % transposed then + p_deep = p_deep.'; % transposed then p_deep = p_deep(ones(1,ms), :); % copy down each column. elseif (ms == mpl) & (ns == npl) % ok @@ -105,11 +109,15 @@ error('gsw_enthalpy_diff_CT: Inputs array dimensions arguments do not agree') end %if +if ~isempty(find(p_shallow - p_deep > 0)); + error('gsw_enthalpy_diff_CT: p_deep needs to be greater than or equal to p_shallow') +end + if ms == 1 - SA = SA'; - CT = CT'; - p_shallow = p_shallow'; - p_deep = p_deep'; + SA = SA.'; + CT = CT.'; + p_shallow = p_shallow.'; + p_deep = p_deep.'; transposed = 1; else transposed = 0; @@ -119,15 +127,10 @@ % Start of the calculation %-------------------------------------------------------------------------- -pt = gsw_pt_from_CT(SA,CT); -pr0 = zeros(size(SA)); -t_shallow = gsw_pt_from_t(SA,pt,pr0,p_shallow); -t_deep = gsw_pt_from_t(SA,pt,pr0,p_deep); -enthalpy_diff_CT = gsw_enthalpy(SA,t_deep,p_deep) - ... - gsw_enthalpy(SA,t_shallow,p_shallow); +enthalpy_diff_CT = gsw_enthalpy_diff(SA,CT,p_shallow,p_deep); if transposed - enthalpy_diff_CT = enthalpy_diff_CT'; + enthalpy_diff_CT = enthalpy_diff_CT.'; end end diff --git a/Toolbox/gsw_enthalpy_diff_CT25.m b/Toolbox/gsw_enthalpy_diff_CT25.m deleted file mode 100644 index f37d713..0000000 --- a/Toolbox/gsw_enthalpy_diff_CT25.m +++ /dev/null @@ -1,204 +0,0 @@ -function [enthalpy_diff_CT25, in_funnel] = gsw_enthalpy_diff_CT25(SA,CT,p_shallow,p_deep) - -% gsw_enthalpy_diff_CT25 difference of enthalpy at two pressures -%========================================================================== -% -% USAGE: -% [enthalpy_diff, in_funnel] = gsw_enthalpy_diff_CT25(SA,CT,p_shallow,p_deep) -% -% DESCRIPTION: -% Calculates the difference of the specific enthalpy of seawater between -% two different pressures, p_deep (the deeper pressure) and p_shallow -% (the shallower pressure), at the same values of SA and CT. This -% function uses the computationally-efficient 25-term expression for -% density in terms of SA, CT and p (McDougall et al., 2010). The output -% (enthalpy_diff) is the specific enthalpy evaluated at (SA,CT,p_deep) -% minus the specific enthalpy at (SA,CT,p_shallow). -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p_shallow = upper sea pressure [ dbar ] -% (ie. shallower absolute pressure - 10.1325 dbar) -% p_deep = lower sea pressure [ dbar ] -% (ie. deeper absolute pressure - 10.1325 dbar) -% -% p_shallow and p_deep may have dimensions Mx1 or 1xN or MxN, -% where SA and CT are MxN. -% -% OUTPUT: -% enthalpy_diff_CT25 = difference of specific enthalpy [ J/kg ] -% (deep minus shallow) -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). -% -% AUTHOR: -% Trevor McDougall & Claire Roberts-Thomson. [ help_gsw@csiro.au ] -% -% VERSION NUMBER: 2.0 (26th August, 2010) -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See Eqns. (3.32.2) and (A.30.6) of this TEOS-10 Manual. -% -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 4) - error('gsw_enthalpy_diff_CT25: requires four inputs') -end - -[ms,ns] = size(SA); -[mt,nt] = size(CT); -[mpu,npu] = size(p_shallow); -[mpl,npl] = size(p_deep); - -if (ms~=mt) | (ns~=nt) - error('gsw_enthalpy_diff_CT25: SA & CT need to have the same dimensions') -end - -if (mpu == 1) & (npu == 1) % p_shallowis a scalar - error('gsw_enthalpy_diff_CT25: need more than one pressure') -elseif (ns == npu) & (mpu == 1) % p_shallow is row vector, - p_shallow = p_shallow(ones(1,ms), :); % copy down each column. -elseif (ms == mpu) & (npu == 1) % p_shallow is column vector, - p_shallow = p_shallow(:,ones(1,ns)); % copy across each row. -elseif (ns == mpu) & (npu == 1) % p_shallow is a transposed row vector, - p_shallow = p_shallow'; % transposed then - p_shallow = p_shallow(ones(1,ms), :); % copy down each column. -elseif (ms == mpu) & (ns == npu) - % ok -end - -if (mpl == 1) & (npl == 1) % p_deep is a scalar - error('gsw_enthalpy_diff_CT25: need more than one pressure') -elseif (ns == npl) & (mpl == 1) % p_deep is row vector, - p_deep = p_deep(ones(1,ms), :); % copy down each column. -elseif (ms == mpl) & (npl == 1) % p_deep is column vector, - p_deep = p_deep(:,ones(1,ns)); % copy across each row. -elseif (ns == mpl) & (npl == 1) % p_deep is a transposed row vector, - p_deep = p_deep'; % transposed then - p_deep = p_deep(ones(1,ms), :); % copy down each column. -elseif (ms == mpl) & (ns == npl) - % ok -else - error('gsw_enthalpy_diff_CT25: Inputs array dimensions arguments do not agree') -end %if - -if ms == 1 - SA = SA'; - CT = CT'; - p_shallow = p_shallow'; - p_deep = p_deep'; - transposed = 1; -else - transposed = 0; -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -% These few lines ensure that SA is non-negative. -[I_neg_SA] = find(SA < 0); -if ~isempty(I_neg_SA) - SA(I_neg_SA) = 0; -end - -in_funnel_shallow = gsw_infunnel(SA,CT,p_shallow); -in_funnel_deep = gsw_infunnel(SA,CT,p_deep); -in_funnel = in_funnel_shallow.*in_funnel_deep; - -db2Pa = 1e4; - -CT2 = CT.*CT; -CT3 = CT.*CT2; - -a0 = 1 + CT.*( 7.0547681896071576e-3 +... - CT.*(-1.1753695605858647e-5 + ... - CT.*(5.9219809488274903e-7 + ... - CT.*3.4887902228012519e-10))) + ... - SA.*( 2.0777716085618458e-3 + ... - CT.*(-2.2210857293722998e-8 + ... - CT2.*-3.6628141067895282e-10) + ... - sqrt(SA).*(3.4688210757917340e-6 + ... - CT2.*8.0190541528070655e-10)); -a1 = 6.8314629554123324e-6; -a2 = CT3*-8.5294794834485446e-17; -a3 = CT*-9.2275325145038070e-18; - -b0 = 9.9984380290708214e2 + ... - CT.* (7.1188090678940910e0 + ... - CT.*(-1.9459922513379687e-2 + ... - CT.* 6.1748404455874641e-4)) + ... - SA.*( 2.8925731541277653e0 + ... - CT.* 2.1471495493268324e-3 + ... - SA.* 1.9457531751183059e-3); -b1 = 0.5*(1.1930681818531748e-2 + ... - CT2.*2.6969148011830758e-7 + ... - SA.*5.9355685925035653e-6); -b2 = CT2.*-7.2734111712822707e-12 - 2.5943389807429039e-8; -b1sq = b1.*b1; -sqrt_disc = sqrt(b1sq - b0.*b2); - -N = a0 + (2*a3.*b0.*b1./b2 - a2.*b0)./b2; - -M = a1 + (4*a3.*b1sq./b2 - (a3.*b0 + 2*a2.*b1))./b2; - -A = b1 - sqrt_disc; -B = b1 + sqrt_disc; -delta_p = p_deep - p_shallow; -p_sum = p_deep + p_shallow; -part1 = b0 + p_shallow.*(2*b1 + b2.*p_shallow); - -part2 = (B + b2.*p_deep).*(A + b2.*p_shallow); - -part3 = (N.*b2 - M.*b1)./(b2.*(B - A)); - -enthalpy_diff_CT25 = db2Pa.*(delta_p.*(a2 - 2*a3.*b1./b2 + 0.5*a3.*p_sum)./b2 + ... - (M./(2*b2)).*log(1 + delta_p.*(2*b1 + b2.*p_sum)./part1) + ... - part3.*log(1 + delta_p.*b2.*(B - A)./part2)); - -%-------------------------------------------------------------------------- -% This function "gsw_enthalpy_diff_CT25.m" calculates enthalpy_diff_CT25 -% using the computationally-efficient 25-term expression for density in -% terms of SA, CT and p. If one wanted to compute the enthalpy difference -% using the full TEOS-10 Gibbs function, the following lines of code will -% enable this. -% -% pt = gsw_pt_from_CT(SA,CT); -% pr0 = zeros(size(SA)); -% t_shallow = gsw_pt_from_t(SA,pt,pr0,p_shallow); -% t_deep = gsw_pt_from_t(SA,pt,pr0,p_deep); -% enthalpy_diff = gsw_enthalpy(SA,t_deep,p_deep) - ... -% gsw_enthalpy(SA,t_shallow,p_shallow); -% -% or call the following, it is identical to the lines above. -% -% enthalpy_diff_CT = gsw_enthalpy_diff_CT(SA,CT,p_shallow,p_deep) -% -%-----------------This is the end of the alternative code------------------ - - if transposed - enthalpy_diff_CT25 = enthalpy_diff_CT25'; - in_funnel = in_funnel'; - end - -end diff --git a/Toolbox/gsw_enthalpy_diff_CT_exact.m b/Toolbox/gsw_enthalpy_diff_CT_exact.m new file mode 100644 index 0000000..c70a068 --- /dev/null +++ b/Toolbox/gsw_enthalpy_diff_CT_exact.m @@ -0,0 +1,126 @@ +function enthalpy_diff_CT_exact = gsw_enthalpy_diff_CT_exact(SA,CT,p_shallow,p_deep) + +% gsw_enthalpy_diff_CT_exact difference of enthalpy at two pressures +%========================================================================== +% +% USAGE: +% enthalpy_diff_CT_exact = gsw_enthalpy_diff_CT_exact(SA,CT,p_shallow,p_deep) +% +% DESCRIPTION: +% Calculates the difference of the specific enthalpy of seawater between +% two different pressures, p_deep (the deeper pressure) and p_shallow +% (the shallower pressure), at the same values of SA and CT. The output +% (enthalpy_diff_CT_exact) is the specific enthalpy evaluated at +% (SA,CT,p_deep) minus the specific enthalpy at (SA,CT,p_shallow). +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely +% gsw_enthalpy_diff_CT(SA,CT,p), which uses the computationally +% efficient 48-term expression for density in terms of SA, CT and p +% (McDougall et al., 2011). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p_shallow = upper sea pressure [ dbar ] +% ( i.e. shallower absolute pressure - 10.1325 dbar ) +% p_deep = lower sea pressure [ dbar ] +% ( i.e. deeper absolute pressure - 10.1325 dbar ) +% +% p_shallow and p_deep may have dimensions Mx1 or 1xN or MxN, +% where SA and CT are MxN. +% +% OUTPUT: +% enthalpy_diff_CT_exact = difference of specific enthalpy [ J/kg ] +% (deep minus shallow) +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (6th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqns. (3.32.2) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 4) + error('gsw_enthalpy_diff_CT_exact: requires four inputs') +end + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mpu,npu] = size(p_shallow); +[mpl,npl] = size(p_deep); + +if (ms~=mt) | (ns~=nt) + error('gsw_enthalpy_diff_CT_exact: SA & CT need to have the same dimensions') +end + +if (mpu == 1) & (npu == 1) % p_shallow is a scalar + p_shallow = p_shallow*ones(size(SA)); +elseif (ns == npu) & (mpu == 1) % p_shallow is row vector, + p_shallow = p_shallow(ones(1,ms), :); % copy down each column. +elseif (ms == mpu) & (npu == 1) % p_shallow is column vector, + p_shallow = p_shallow(:,ones(1,ns)); % copy across each row. +elseif (ns == mpu) & (npu == 1) % p_shallow is a transposed row vector, + p_shallow = p_shallow.'; % transposed then + p_shallow = p_shallow(ones(1,ms), :); % copy down each column. +elseif (ms == mpu) & (ns == npu) + % ok +end + +if (mpl == 1) & (npl == 1) % p_deep is a scalar + p_deep = p_deep*ones(size(SA)); +elseif (ns == npl) & (mpl == 1) % p_deep is row vector, + p_deep = p_deep(ones(1,ms), :); % copy down each column. +elseif (ms == mpl) & (npl == 1) % p_deep is column vector, + p_deep = p_deep(:,ones(1,ns)); % copy across each row. +elseif (ns == mpl) & (npl == 1) % p_deep is a transposed row vector, + p_deep = p_deep.'; % transposed then + p_deep = p_deep(ones(1,ms), :); % copy down each column. +elseif (ms == mpl) & (ns == npl) + % ok +else + error('gsw_enthalpy_diff_CT_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p_shallow = p_shallow.'; + p_deep = p_deep.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +t_shallow = gsw_t_from_CT(SA,CT,p_shallow); +t_deep = gsw_t_from_CT(SA,CT,p_deep); +enthalpy_diff_CT_exact = gsw_enthalpy_t_exact(SA,t_deep,p_deep) - ... + gsw_enthalpy_t_exact(SA,t_shallow,p_shallow); + +if transposed + enthalpy_diff_CT_exact = enthalpy_diff_CT_exact.'; +end + +end diff --git a/Toolbox/gsw_enthalpy_first_derivatives.m b/Toolbox/gsw_enthalpy_first_derivatives.m index b0599cb..5ca96e8 100644 --- a/Toolbox/gsw_enthalpy_first_derivatives.m +++ b/Toolbox/gsw_enthalpy_first_derivatives.m @@ -15,28 +15,29 @@ % SA and CT. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% (i.e. absolute pressure - 10.1325 dbar) +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & CT need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. % % OUTPUT: -% h_SA = The first derivative of specific enthalpy with respect to -% Absolute Salinity at constant CT and p. +% h_SA = The first derivative of specific enthalpy with respect to +% Absolute Salinity at constant CT and p. % [ J/(kg (g/kg))] i.e. [ J/g ] -% h_CT = The first derivative of specific enthalpy with respect to -% CT at constant SA and p. [ J/(kg K) ] -% h_P = The first partial derivative of specific enthalpy with -% respect to pressure (in Pa) at fixed SA and CT. Note that -% h_P is specific volume (1/rho). +% h_CT = The first derivative of specific enthalpy with respect to +% CT at constant SA and p. [ J/(kg K) ] +% h_P = The first partial derivative of specific enthalpy with +% respect to pressure (in Pa) at fixed SA and CT. Note that +% h_P is specific volume (1/rho). % % AUTHOR: -% Trevor McDougall. [ help_gsw@csiro.au ] +% Trevor McDougall. [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (17th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -75,6 +76,9 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else @@ -82,9 +86,9 @@ end %if if ms == 1 - SA = SA'; - CT = CT'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -97,23 +101,67 @@ cp0 = 3991.86795711963; % from Eqn. (3.3.3) of IOC et al. (2010). n0 = 0; n1 = 1; -pr0 = zeros(size(SA)); +t = gsw_t_from_CT(SA,CT,p); pt0 = gsw_pt_from_CT(SA,CT); -t = gsw_pt_from_t(SA,pt0,pr0,p); + temp_ratio = (273.15 + t)./(273.15 + pt0); h_CT = cp0.*temp_ratio; % from Eqn. (A.11.15) of IOC et al. (2010). -h_SA = gsw_gibbs(n1,n0,n0,SA,t,p) - ... - temp_ratio.*gsw_gibbs(n1,n0,n0,SA,pt0,pr0); - % from Eqn. (A.11.18) of IOC et al. (2010). -h_P = gsw_gibbs(n0,n0,n1,SA,t,p); - % from Eqn. (A.11.12) of IOC et al. (2010). +h_P = gsw_gibbs(n0,n0,n1,SA,t,p); %from Eqn. (A.11.12) of IOC et al. (2010). + +db2Pa = 1e-4; +sfac = 0.0248826675584615; % sfac = 1/(40*(35.16504/35)). + +x = sqrt(sfac.*SA); +y = 0.025*t; +z = db2Pa*p; %Note.The input pressure (p) is sea pressure in units of dbar. + +g_SA_mod_t = 8645.36753595126 + z.*(-6620.98308089678 + ... + z.*(769.588305957198 + z.*(-193.0648640214916 + (31.6816345533648 - 5.24960313181984.*z).*z))) + ... + x.*(-7296.43987145382 + x.*(8103.20462414788 + ... + y.*(2175.341332000392 + y.*(-274.2290036817964 + ... + y.*(197.4670779425016 + y.*(-68.5590309679152 + 9.98788038278032.*y))) - 90.6734234051316.*z) + ... + x.*(-5458.34205214835 - 980.14153344888.*y + ... + x.*(2247.60742726704 - 340.1237483177863.*x + 220.542973797483.*y) + 180.142097805543.*z) + ... + z.*(-219.1676534131548 + (-16.32775915649044 - 120.7020447884644.*z).*z)) + ... + z.*(598.378809221703 + z.*(-156.8822727844005 + (204.1334828179377 - 10.23755797323846.*z).*z)) + ... + y.*(-1480.222530425046 + z.*(-525.876123559641 + (249.57717834054571 - 88.449193048287.*z).*z) + ... + y.*(-129.1994027934126 + z.*(1149.174198007428 + z.*(-162.5751787551336 + 76.9195462169742.*z)) + ... + y.*(-30.0682112585625 - 1380.9597954037708.*z + y.*(2.626801985426835 + 703.695562834065.*z))))) + ... + y.*(1187.3715515697959 + z.*(1458.233059470092 + ... + z.*(-687.913805923122 + z.*(249.375342232496 + z.*(-63.313928772146 + 14.09317606630898.*z)))) + ... + y.*(1760.062705994408 + y.*(-450.535298526802 + ... + y.*(182.8520895502518 + y.*(-43.3206481750622 + 4.26033941694366.*y) + ... + z.*(-595.457483974374 + (149.452282277512 - 72.9745838003176.*z).*z)) + ... + z.*(1388.489628266536 + z.*(-409.779283929806 + (227.123395681188 - 22.2565468652826.*z).*z))) + ... + z.*(-1721.528607567954 + z.*(674.819060538734 + ... + z.*(-356.629112415276 + (88.4080716616 - 15.84003094423364.*z).*z))))); + +g_SA_mod_t = 0.5.*sfac.*g_SA_mod_t; + +y_pt = 0.025*pt0; + +g_SA_mod_pt = 8645.36753595126 + ... + x.*(-7296.43987145382 + x.*(8103.20462414788 + ... + y_pt.*(2175.341332000392 + y_pt.*(-274.2290036817964 + ... + y_pt.*(197.4670779425016 + y_pt.*(-68.5590309679152 + 9.98788038278032.*y_pt)))) + ... + x.*(-5458.34205214835 - 980.14153344888.*y_pt + ... + x.*(2247.60742726704 - 340.1237483177863.*x + 220.542973797483.*y_pt))) + ... + y_pt.*(-1480.222530425046 + y_pt.*(-129.1994027934126 + ... + y_pt.*(-30.0682112585625 + y_pt.*2.626801985426835)))) + ... + y_pt.*(1187.3715515697959 + y_pt.*(1760.062705994408 + y_pt.*(-450.535298526802 + ... + y_pt.*(182.8520895502518 + y_pt.*(-43.3206481750622 + 4.26033941694366.*y_pt))))); + +g_SA_mod_pt = 0.5*sfac*g_SA_mod_pt; + +h_SA = g_SA_mod_t - temp_ratio.*g_SA_mod_pt; + if transposed - h_CT = h_CT'; - h_SA = h_SA'; - h_P = h_P'; + h_CT = h_CT.'; + h_SA = h_SA.'; + h_P = h_P.'; end end \ No newline at end of file diff --git a/Toolbox/gsw_enthalpy_second_derivatives.m b/Toolbox/gsw_enthalpy_second_derivatives.m index ef27591..a26de77 100644 --- a/Toolbox/gsw_enthalpy_second_derivatives.m +++ b/Toolbox/gsw_enthalpy_second_derivatives.m @@ -18,9 +18,9 @@ % % INPUT: % SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% (i.e. absolute pressure - 10.1325 dbar) +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & CT need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. @@ -34,9 +34,10 @@ % CT at constant SA and p. [ J/(kg K^2) ] % % AUTHOR: -% Trevor McDougall and Paul Barker. [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker. [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -44,11 +45,10 @@ % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % This software is available from http://www.TEOS-10.org % @@ -80,6 +80,9 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else @@ -87,9 +90,9 @@ end %if if ms == 1 - SA = SA'; - CT = CT'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -116,24 +119,42 @@ gST_t = gsw_gibbs(n1,n1,n0,SA,t,p); gS_pt0 = gsw_gibbs(n1,n0,n0,SA,pt0,pr0); +% h_CT_CT is naturally well-behaved as SA approaches zero. h_CT_CT = cp0.*cp0.* ... (temp_ratio.*rec_gTT_pt0 - rec_gTT_t)./(abs_pt0.*abs_pt0); part = (temp_ratio.*gST_pt0.*rec_gTT_pt0 - gST_t.*rec_gTT_t)./(abs_pt0); factor = gS_pt0./cp0; -h_SA_CT = cp0.*part - factor.*h_CT_CT; +% h_SA_SA has a singularity at SA = 0, and blows up as SA approaches zero. +h_SA_SA = gsw_gibbs(n2,n0,n0,SA,t,p) ... + - temp_ratio.*gsw_gibbs(n2,n0,n0,SA,pt0,pr0) ... + + temp_ratio.*gST_pt0.*gST_pt0.*rec_gTT_pt0 ... + - gST_t.*gST_t.*rec_gTT_t ... + - 2.0.*gS_pt0.*part + (factor.*factor).*h_CT_CT; + +% h_SA_CT should not blow up as SA approaches zero. The following lines +% of code ensure that the h_SA_CT output of this function does not blow +% up in this limit. That is, when SA < 1e-100 g/kg, we force the h_SA_CT +% output to be the same as if SA = 1e-100 g/kg. +[Ismall_SA] = find(SA < 1e-100); +if ~isempty(Ismall_SA) + SA(Ismall_SA) = 1e-100; + rec_gTT_pt0 = ones(size(SA))./gsw_gibbs(n0,n2,n0,SA,pt0,pr0); + rec_gTT_t = ones(size(SA))./gsw_gibbs(n0,n2,n0,SA,t,p); + gST_pt0 = gsw_gibbs(n1,n1,n0,SA,pt0,pr0); + gST_t = gsw_gibbs(n1,n1,n0,SA,t,p); + gS_pt0 = gsw_gibbs(n1,n0,n0,SA,pt0,pr0); + part = (temp_ratio.*gST_pt0.*rec_gTT_pt0 - gST_t.*rec_gTT_t)./(abs_pt0); + factor = gS_pt0./cp0; +end -h_SA_SA = gsw_gibbs(n2,n0,n0,SA,t,p) - ... - temp_ratio.*gsw_gibbs(n2,n0,n0,SA,pt0,pr0) + ... - temp_ratio.*gST_pt0.*gST_pt0.*rec_gTT_pt0 - ... - gST_t.*gST_t.*rec_gTT_t - ... - 2.0.*gS_pt0.*part + (factor.*factor).*h_CT_CT; +h_SA_CT = cp0.*part - factor.*h_CT_CT; if transposed - h_SA_SA = h_SA_SA'; - h_SA_CT = h_SA_CT'; - h_CT_CT = h_CT_CT'; + h_SA_SA = h_SA_SA.'; + h_SA_CT = h_SA_CT.'; + h_CT_CT = h_CT_CT.'; end end diff --git a/Toolbox/gsw_Helmholtz_energy.m b/Toolbox/gsw_enthalpy_t_exact.m similarity index 65% rename from Toolbox/gsw_Helmholtz_energy.m rename to Toolbox/gsw_enthalpy_t_exact.m index f37c960..13c4615 100644 --- a/Toolbox/gsw_Helmholtz_energy.m +++ b/Toolbox/gsw_enthalpy_t_exact.m @@ -1,37 +1,36 @@ -function Helmholtz_energy = gsw_Helmholtz_energy(SA,t,p) +function enthalpy_t_exact = gsw_enthalpy_t_exact(SA,t,p) -% gsw_Helmholtz_energy Helmholtz energy of seawater +% gsw_enthalpy_t_exact specific enthalpy of seawater %========================================================================== % % USAGE: -% Helmholtz_energy = gsw_Helmholtz_energy(SA,t,p) +% enthalpy_t_exact = gsw_enthalpy_t_exact(SA,t,p) % % DESCRIPTION: -% Calculates the Helmholtz energy of seawater +% Calculates the specific enthalpy of seawater. % % INPUT: % SA = Absolute Salinity [ g/kg ] % t = in-situ temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% Helmholtz_energy = Helmholtz energy [ J/kg ] +% enthalpy_t_exact = specific enthalpy [ J/kg ] % % AUTHOR: -% Trevor McDougall [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of % seawater - 2010: Calculation and use of thermodynamic properties. % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See section 2.13 of this TEOS-10 Manual. % % The software is available from http://www.TEOS-10.org % @@ -42,7 +41,7 @@ %-------------------------------------------------------------------------- if ~(nargin==3) - error('gsw_Helmholtz_energy: Requires three inputs') + error('gsw_enthalpy_t_exact: Requires three inputs') end %if [ms,ns] = size(SA); @@ -50,7 +49,7 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_Helmholtz_energy: SA and t must have same dimensions') + error('gsw_enthalpy_t_exact: SA and t must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -59,16 +58,19 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_Helmholtz_energy: Inputs array dimensions arguments do not agree') + error('gsw_enthalpy_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -78,15 +80,14 @@ % Start of the calculation %-------------------------------------------------------------------------- -db2Pa = 1e4; -n0 = 0; +n0 = 0; n1 = 1; -Helmholtz_energy = gsw_gibbs(n0,n0,n0,SA,t,p) - ... - (db2Pa*p + 101325).*gsw_gibbs(n0,n0,n1,SA,t,p); +enthalpy_t_exact = gsw_gibbs(n0,n0,n0,SA,t,p) ... + - (t+273.15).*gsw_gibbs(n0,n1,n0,SA,t,p); if transposed - Helmholtz_energy = Helmholtz_energy'; + enthalpy_t_exact = enthalpy_t_exact.'; end end \ No newline at end of file diff --git a/Toolbox/gsw_entropy_first_derivatives.m b/Toolbox/gsw_entropy_first_derivatives.m index 46458ef..3bf200e 100644 --- a/Toolbox/gsw_entropy_first_derivatives.m +++ b/Toolbox/gsw_entropy_first_derivatives.m @@ -15,24 +15,25 @@ % constant Absolute Salinity. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % % SA & CT need to have the same dimensions. % % OUTPUT: % eta_SA = The derivative of specific entropy with respect to -% Absolute Salinity (in units of g/kg) at constant Conservative -% Temperature. The eta_SA output has units of: -% [ J/(kg K(g/kg))] or [ J/(g K) ] +% Absolute Salinity (in units of g kg^-1) at constant +% Conservative Temperature. +% eta_SA has units of: [ J/(kg K(g/kg))] or [ J/(g K) ] % eta_CT = The derivative of specific entropy with respect to % Conservative Temperature at constant Absolute Salinity. -% The eta_CT output has units of: [ J/(kg K^2) ] +% eta_CT has units of: [ J/(kg K^2) ] % % AUTHOR: -% Trevor McDougall. [ help_gsw@csiro.au ] +% Trevor McDougall. [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (21th August, 2010). +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -64,8 +65,8 @@ error('gsw_entropy_first_derivatives: SA and CT must have same dimensions') end if ms == 1 - SA = SA'; - CT = CT'; + SA = SA.'; + CT = CT.'; transposed = 1; else transposed = 0; @@ -86,8 +87,8 @@ eta_CT = (cp0*ones(size(pt)))./(273.15 + pt); if transposed - eta_SA = eta_SA'; - eta_CT = eta_CT'; + eta_SA = eta_SA.'; + eta_CT = eta_CT.'; end end diff --git a/Toolbox/gsw_entropy_from_CT.m b/Toolbox/gsw_entropy_from_CT.m index 491bc6d..d071207 100644 --- a/Toolbox/gsw_entropy_from_CT.m +++ b/Toolbox/gsw_entropy_from_CT.m @@ -1,7 +1,7 @@ function entropy = gsw_entropy_from_CT(SA,CT) -% gsw_entropy_from_CT specific entropy of seawater with Conservative -% Temperature as the input temperature +% gsw_entropy_from_CT specific entropy of seawater with +% Conservative Temperature as the input temperature %========================================================================== % % USAGE: @@ -11,7 +11,7 @@ % Calculates specific entropy of seawater. % % INPUT: -% SA = Absolute Salinity [ g/kg ] +% SA = Absolute Salinity [ g kg^-1 ] % CT = Conservative Temperature (ITS-90) [ deg C ] % % SA & CT need to have the same dimensions. @@ -20,9 +20,9 @@ % entropy = specific entropy [ J/(kg*K) ] % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (13 October, 2010) +% VERSION NUMBER: 3.0 (4th April, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -51,8 +51,8 @@ end if ms == 1 - SA = SA'; - CT = CT'; + SA = SA.'; + CT = CT.'; transposed = 1; else transposed = 0; @@ -73,10 +73,10 @@ pt0 = gsw_pt_from_CT(SA,CT); pr0 = zeros(size(SA)); -entropy = -1*gsw_gibbs(n0,n1,n0,SA,pt0,pr0); +entropy = -gsw_gibbs(n0,n1,n0,SA,pt0,pr0); if transposed - entropy = entropy'; + entropy = entropy.'; end end \ No newline at end of file diff --git a/Toolbox/gsw_entropy_from_pt.m b/Toolbox/gsw_entropy_from_pt.m index 0528543..b502b6d 100644 --- a/Toolbox/gsw_entropy_from_pt.m +++ b/Toolbox/gsw_entropy_from_pt.m @@ -20,9 +20,9 @@ % entropy = specific entropy [ J/(kg*K) ] % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (13 October, 2010) +% VERSION NUMBER: 3.0 (3rd April, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -51,8 +51,8 @@ end if ms == 1 - SA = SA'; - pt = pt'; + SA = SA.'; + pt = pt.'; transposed = 1; else transposed = 0; @@ -75,7 +75,7 @@ entropy = -gsw_gibbs(n0,n1,n0,SA,pt,pr0); if transposed - entropy = entropy'; + entropy = entropy.'; end end \ No newline at end of file diff --git a/Toolbox/gsw_entropy_second_derivatives.m b/Toolbox/gsw_entropy_second_derivatives.m index 1cf01d1..7136556 100644 --- a/Toolbox/gsw_entropy_second_derivatives.m +++ b/Toolbox/gsw_entropy_second_derivatives.m @@ -17,28 +17,28 @@ % Temperature at constant Absolute Salinity. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % % SA & CT need to have the same dimensions. % % OUTPUT: % eta_SA_SA = The second derivative of specific entropy with respect -% to Absolute Salinity (in units of g/kg) at constant -% Conservative Temperature. eta_SA_SA has units of: -% [ J/(kg K(g/kg)^2)] +% to Absolute Salinity (in units of g kg^-1) at constant +% Conservative Temperature. +% eta_SA_SA has units of: [ J/(kg K(g/kg)^2)] % eta_SA_CT = The second derivative of specific entropy with respect % to Conservative Temperature at constant Absolute % Salinity. eta_SA_CT has units of: [ J/(kg (g/kg) K^2) ] -% % eta_CT_CT = The second derivative of specific entropy with respect % to Conservative Temperature at constant Absolute % Salinity. eta_CT_CT has units of: [ J/(kg K^3) ] % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -71,8 +71,8 @@ end if ms == 1 - SA = SA'; - CT = CT'; + SA = SA.'; + CT = CT.'; transposed = 1; else transposed = 0; @@ -102,9 +102,9 @@ eta_SA_SA = - gsw_gibbs(n2,n0,n0,SA,pt,pr0)./abs_pt - CT_SA.*eta_SA_CT; if transposed - eta_CT_CT = eta_CT_CT'; - eta_SA_CT = eta_SA_CT'; - eta_SA_SA = eta_SA_SA'; + eta_CT_CT = eta_CT_CT.'; + eta_SA_CT = eta_SA_CT.'; + eta_SA_SA = eta_SA_SA.'; end end diff --git a/Toolbox/gsw_entropy.m b/Toolbox/gsw_entropy_t_exact.m similarity index 68% rename from Toolbox/gsw_entropy.m rename to Toolbox/gsw_entropy_t_exact.m index b7d748d..c3d88f1 100644 --- a/Toolbox/gsw_entropy.m +++ b/Toolbox/gsw_entropy_t_exact.m @@ -1,10 +1,10 @@ -function entropy = gsw_entropy(SA,t,p) +function entropy_t_exact = gsw_entropy_t_exact(SA,t,p) -% gsw_entropy specific entropy of seawater +% gsw_entropy_t_exact specific entropy of seawater %========================================================================== % % USAGE: -% entropy = gsw_entropy(SA,t,p) +% entropy_t_exact = gsw_entropy_t_exact(SA,t,p) % % DESCRIPTION: % Calculates specific entropy of seawater. @@ -13,18 +13,18 @@ % SA = Absolute Salinity [ g/kg ] % t = in-situ temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% entropy = specific entropy [ J/(kg*K) ] +% entropy_t_exact = specific entropy [ J/(kg*K) ] % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -41,7 +41,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_entropy: Requires three inputs') + error('gsw_entropy_t_exact: Requires three inputs') end %if [ms,ns] = size(SA); @@ -49,7 +49,7 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_entropy: SA and t must have same dimensions') + error('gsw_entropy_t_exact: SA and t must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -58,16 +58,19 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_entropy: Inputs array dimensions arguments do not agree') + error('gsw_entropy_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -80,10 +83,10 @@ n0 = 0; n1 = 1; -entropy = -gsw_gibbs(n0,n1,n0,SA,t,p); +entropy_t_exact = -gsw_gibbs(n0,n1,n0,SA,t,p); if transposed - entropy = entropy'; + entropy_t_exact = entropy_t_exact.'; end end \ No newline at end of file diff --git a/Toolbox/gsw_f.m b/Toolbox/gsw_f.m index 2bf40ad..2b25be1 100644 --- a/Toolbox/gsw_f.m +++ b/Toolbox/gsw_f.m @@ -13,28 +13,29 @@ % omega = 7.292115e-5 (Groten, 2004) [ radians/s ] % % INPUT: -% lat = latitude in decimal degrees north [ -90 ... +90 ] +% lat = latitude in decimal degrees North [ -90 ... +90 ] % % OUTPUT: % f = Coriolis parameter [ radians/s ] % % AUTHOR: -% 20th April 1993. Phil Morgan [ help_gsw@csiro.au ] +% 20th April 1993. Phil Morgan [ help_gsw@csiro.au ] % % MODIFIED: % 28th July, 2010 by Paul Barker % -% VERSION NUMBER: 2.0 (28th July, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (28th July, 2010). % % REFERENCE: % Groten, E., 2004: Fundamental Parameters and Current (2004) Best -% Estimates of the Parameters of Common Relevance to Astronomy, Geodesy, -% and Geodynamics. Journal of Geodesy, 77, pp. 724-797. +% Estimates of the Parameters of Common Relevance to Astronomy, Geodesy, +% and Geodynamics. Journal of Geodesy, 77, pp. 724-797. % % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % % The software is available from http://www.TEOS-10.org % @@ -53,7 +54,7 @@ %-------------------------------------------------------------------------- DEG2RAD = pi/180; -OMEGA = 7.292115e-5; %(s^-1) (Groten, 2004) +OMEGA = 7.292115e-5; %(1/s) (Groten, 2004) f = 2*OMEGA*sin(lat*DEG2RAD); end diff --git a/Toolbox/gsw_front_page.m b/Toolbox/gsw_front_page.m new file mode 100644 index 0000000..1531163 --- /dev/null +++ b/Toolbox/gsw_front_page.m @@ -0,0 +1,21 @@ +function gsw_front_page + +% Front page to the Gibbs SeaWater (GSW) Oceanographic Toolbox of TEOS-10 + +if exist('showdemo.m','file') == 2 + showdemo gsw_front_page +else + [html_file] = which('gsw_front_page.html'); + try + web ([html_file],' -helpbrowser') + catch + try + web ([html_file],' -browser') + catch + disp('Enter the following address into your web browser:') + disp([html_file]) + end + end +end + +end \ No newline at end of file diff --git a/Toolbox/gsw_geo_strf_Cunningham.m b/Toolbox/gsw_geo_strf_Cunningham.m index b67af34..7733d9e 100644 --- a/Toolbox/gsw_geo_strf_Cunningham.m +++ b/Toolbox/gsw_geo_strf_Cunningham.m @@ -1,58 +1,54 @@ -function [geo_strf_Cunningham, in_funnel] = gsw_geo_strf_Cunningham(SA,CT,p,interp_style) +function geo_strf_Cunningham = gsw_geo_strf_Cunningham(SA,CT,p,p_ref) % gsw_geo_strf_Cunningham Cunningham geostrophic streamfunction +% (48-term equation) %========================================================================== % % USAGE: -% [geo_strf_Cunningham, in_funnel] = gsw_geo_strf_Cunningham(SA,CT,p,interp_style) +% geo_strf_Cunningham = gsw_geo_strf_Cunningham(SA,CT,p,p_ref) % % DESCRIPTION: % Calculates the Cunningham geostrophic streamfunction (see Eqn. (3.29.2) % of IOC et al. (2010)). This is the geostrophic streamfunction for the % difference between the horizontal velocity at the pressure concerned, -% p, and the horizontal velocity at the sea surface. This function -% calculates specific volume anomaly using the computationally efficient -% 25-term expression for specific volume of McDougall et al. (2010). -% Under the default setting, this function evaluates the pressure integral -% of specific volume using SA and CT “interploted” with respect to pressure -% using a scheme based on the method of Reiniger and Ross (1968). Our -% method uses a weighted mean of (i) values obtained from linear -% interpolation of the two nearest data points, and (ii) a linear -% extrapolation of the pairs of data above and below. This "curve fitting" -% method resembles the use of cubic splines. If the option “linear” is -% chosen, the function interpolates Absolute Salinity and Conservative -% Temperature linearly with presure in the vertical between “bottles”. +% p, and the horizontal velocity on the pressure surface, p_ref. This +% function calculates specific volume anomaly using the computationally +% efficient 48-term expression for specific volume of McDougall et al. +% (2011). +% +% Note that p_ref, is the reference pressure to which the streamfunction +% is referenced. When p_ref is zero, "gsw_geo_strf_Cunningham" returns +% the Cunningham geostrophic streamfunction with respect to the sea +% surface, otherwise, the function returns the geostrophic streamfunction +% with respect to the (deep) reference pressure p_ref. +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) -% -% OPTIONAL: -% interp_style = interpolation technique. -% = if nothing is entered the programme defaults to "curved" -% interpolation between bottles in the vertical. -% = if "linear" or "lin" is entered then the programme -% interpolates linearly between bottles in the -% vertical. +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% p_ref = reference pressure [ dbar ] +% ( i.e. reference absolute pressure - 10.1325 dbar ) % % SA & CT need to have the same dimensions. % p may have dimensions Mx1 or 1xN or MxN, where SA & CT are MxN. +% p_ref needs to be a single value, it can have dimensions 1x1 or Mx1 or +% 1xN or MxN. % % OUTPUT: -% geo_strf_Cunningham = Cunningham geostrophic streamfunction [ m^2/s^2 ] -% -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). +% geo_strf_Cunningham = Cunningham geostrophic [ m^2/s^2 ] +% streamfunction % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (18th March, 2011) % % REFERENCES: % Cunningham, S.A., 2000: Circulation and volume flux of the North @@ -65,11 +61,10 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See section 3.29 of this TEOS-10 Manual. % -% McDougall T.J., D.R. Jackett, P.M. Barker, C. Roberts-Thomson, R. -% Feistel and R.W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -79,10 +74,17 @@ % Check variables and resize if necessary %-------------------------------------------------------------------------- -if ~(nargin == 3| nargin == 4) - error('gsw_geo_strf_Cunningham: Requires three or four inputs') +if ~(nargin == 4) + error('gsw_geo_strf_Cunningham: Requires four inputs') end %if +unique_p_ref = unique(p_ref); +if ~isscalar(unique_p_ref) + error('gsw_geo_strf_Cunningham: The reference pressure p_ref must be unique') +end +clear p_ref +p_ref = unique_p_ref; + [ms,ns] = size(SA); [mt,nt] = size(CT); [mp,np] = size(p); @@ -92,28 +94,24 @@ end if (mp == 1) & (np == 1) % p scalar - fill to size of SA - error('gsw_geo_strf_Cunningham : need more than one pressure'); + error('gsw_geo_strf_Cunningham: need more than one pressure'); elseif (ns == np) & (mp == 1) % p is row vector, p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_geo_strf_Cunningham : Inputs array dimensions arguments do not agree') + error('gsw_geo_strf_Cunningham: Inputs array dimensions arguments do not agree') end %if -if ~exist('interp_style','var') - interp_style = 'curve'; -elseif strcmpi('interp_style','linear') == 1 | strcmpi('interp_style','lin') == 1 |... - strcmpi('interp_style','linaer') == 1 | strcmpi('interp_style','lnear') == 1 - interp_style = 'linear'; -end - if ms == 1 - SA = SA'; - CT = CT'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -125,31 +123,28 @@ cp0 = 3991.86795711963; % from Eqn. (3.3.3) of IOC et al. (2010). -delta_p = 1; % This is the maximum distance between bottles in the vertical. - -[dyn_height, in_funnel] = gsw_geo_strf_dyn_height(SA,CT,p,delta_p,interp_style); +dyn_height = gsw_geo_strf_dyn_height(SA,CT,p,p_ref); -geo_strf_Cunningham = dyn_height - gsw_enthalpy_SSO_0_CT25(p) + ... - gsw_enthalpy_CT25(SA,CT,p) - cp0*CT; +geo_strf_Cunningham = dyn_height - gsw_enthalpy_SSO_0_p(p) + ... + gsw_enthalpy(SA,CT,p) - cp0*CT; %-------------------------------------------------------------------------- % This function calculates the Cunningham streamfunction using the -% computationally efficient 25-term expression for density in terms of SA, +% computationally-efficient 48-term expression for density in terms of SA, % CT and p. If one wanted to compute this with the full TEOS-10 Gibbs % function expression for density, the following lines of code will enable % this. Note that dynamic height will also need to be evaluated using the % full Gibbs function. % -% SA_SO = 35.16504*ones(size(SA)); +% SA_SSO = 35.16504*ones(size(SA)); % CT_0 = zeros(size(CT)); -% geo_strf_Cunningham = dyn_height - gsw_enthalpy_CT(SA_SO,CT_0,p) + ... -% gsw_enthalpy_CT(SA,CT,p) - cp0*CT; +% geo_strf_Cunningham = dyn_height - gsw_enthalpy_CT_exact(SA_SSO,CT_0,p) + ... +% gsw_enthalpy_CT_exact(SA,CT,p) - cp0*CT; % %---------------This is the end of the alternative code-------------------- if transposed - geo_strf_Cunningham = geo_strf_Cunningham'; - in_funnel = in_funnel'; -end %if + geo_strf_Cunningham = geo_strf_Cunningham.'; +end end diff --git a/Toolbox/gsw_geo_strf_McD_Klocker.m b/Toolbox/gsw_geo_strf_McD_Klocker.m deleted file mode 100644 index 11acb53..0000000 --- a/Toolbox/gsw_geo_strf_McD_Klocker.m +++ /dev/null @@ -1,246 +0,0 @@ -function [geo_strf_McD_Klocker, in_funnel] = gsw_geo_strf_McD_Klocker(SA,CT,p,Neutral_Density,p_Neutral_Density,A) - -% gsw_geo_strf_McD_Klocker McDougall-Klocker geostrophic streamfunction -%========================================================================== -% -% USAGE: -% [geo_strf_McD_Klocker, in_funnel] = gsw_geo_strf_McD_Klocker(SA,CT,p,Neutral_Density,p_Neutral_Density,A) -% -% DESCRIPTION: -% Calculates the McDougall-Klocker geostrophic streamfunction (see Eqn. -% (3.30.1) of IOC et al. (2010)). This is the geostrophic streamfunction -% for the difference between the horizontal velocity at the pressure -% concerned, p, and the horizontal velocity at the sea surface. It is -% designed to be used as the geostrophic streamfunction in an -% approximately neutral surface (such as a Neutral Density surface, a -% potential density surface or an omega surface (Klocker et al. (2009)). -% Reference values of Absolute Salinity, Conservative Temperature and -% pressure are found by interpolation of a one-dimensional look-up table, -% with the interpolating variable being Neutral Density (gamma_n). This -% function calculates specific volume anomaly using the computationally -% efficient 25-term expression for specific volume in terms of SA, CT and -% p (McDougall et al., 2010). -% -% The first three input arguments are a series of vertical profiles, while -% the last two argumnents pertain to the (usually relatively few) surfaces -% on which the McDougall-Klocker geostrophic streamfunction is to be -% calculated. These last two input arguments, Neutral_Density and -% p_Neutral_Density, are the Neutral density label and the pressure of -% each of the (usually relately few) surfaces. p_Neutral_Density is the -% series of pressures where the surfaces intersect the vertical profiles. -% These surfaces do not have to be the very best approximately neutral -% surfaces; rather the onus is on the user to use a surface that is -% sufficiently neutral for his/her purpose. The input variable -% "Neutral_Density" is used to find reference values of SA, CT and p -% by vertcal interpolation down a single reference cast. As an -% alternative to the user supplying Neutral Density for this purpose, -% the code allows for sigma_2 to be used as the vertical interpolating -% variable instead of Neutral Density. -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) -% -% Neutral_Density = Neutral Density anomaly [ kg/m^3 ] -% (ie. Neutral Density minus 1000 kg/m^3) -% p_Neutral_Density = pressure of the Neutral_Density surface. -% -% A = if nothing is entered the programme defaults to "Neutral -% Density" as the vertical interpolating variable. -% = 's2' or 'sigma2', for sigma_2 as the vertical interpolating -% variable. -% -% SA & CT need to have the same dimensions. -% p may have dimensions Mx1 or 1xN or MxN, where SA & CT are MxN. -% Neutral_Density & p_Neutral_Density need to have the same dimensions, -% and they need to have dimensions BxN, where B is the number of surfaces. -% -% OUTPUT: -% geo_strf_McD_Klocker = McDougall & Klocker (2010) [ m^2/s^2 ] -% geostrophic streamfunction -% -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). -% -% AUTHOR: Trevor McDougall and Paul Barker -% -% VERSION NUMBER: 2.0 (1st September, 2010) -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See section 3.30 of this TEOS-10 Manual. -% -% Jackett, D. R. and T. J. McDougall, 1997: A neutral density variable -% for the world’s oceans. Journal of Physical Oceanography, 27, 237-263. -% -% Klocker, A., T. J. McDougall and D. R. Jackett, 2009: A new method -% for forming approximately neutral surfaces. Ocean Sci., 5, 155-172. -% -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. -% -% McDougall, T. J. and A. Klocker, 2010: An approximate geostrophic -% streamfunction for use in density surfaces. Ocean Modelling, 32, -% 105-117. -% The McDougall-Klocker geostrophic streamfunction is defined in -% Eqn. (62) of this paper. -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 5 | nargin == 6 ) - error('gsw_geo_strf_McD_Klocker: Requires five or six inputs') -end %if - -if ~exist('A','var') - A = 'gn'; -elseif ~ischar(A) - A = 'gn'; -end %if - -[ms,ns] = size(SA); -[mt,nt] = size(CT); -[mp,np] = size(p); - -if (ms~=mt) | (ns~=nt) - error('gsw_geo_strf_McD_Klocker: SA & CT need to have the same dimensions') -end - -if (mp == 1) & (np == 1) % p scalar - fill to size of SA - error('gsw_geo_strf_McD_Klocker: needs more than one pressure'); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_geo_strf_McD_Klocker: Inputs array dimensions arguments do not agree') -end %if - -[mgn,ngn] = size(Neutral_Density); -[mpgn,npgn] = size(p_Neutral_Density); - -if (mgn~=mpgn) | (ngn~=npgn) - error('gsw_geo_strf_McD_Klocker: Neutral_Density & p_Neutral_Density need to have the same dimensions') -end - -if mgn == 1 & ms == 1 - Neutral_Density = Neutral_Density(:); - p_Neutral_Density = p_Neutral_Density(:); -end - -if ms == 1 % row vector - p = p(:); - CT = CT(:); - SA = SA(:); - Neutral_Density = Neutral_Density(:); - p_Neutral_Density = p_Neutral_Density(:); - transposed = 1; -else - transposed = 0; -end - -[ms,ns] = size(SA); -[mt,nt] = size(CT); -[mp,np] = size(p); -[mgn,ngn] = size(Neutral_Density); -[mpgn,npgn] = size(p_Neutral_Density); - -if ngn ~= ns - error('gsw_geo_strf_McD_Klocker: SA & Neutral_Density need to have the same number of profiles') -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -db2Pa = 1e4; -cp0 = 3991.86795711963; % from Eqn. (3.3.3) of IOC et al. (2010). - -SA_iref_cast = nan(size(Neutral_Density)); -CT_iref_cast = nan(size(Neutral_Density)); -p_iref_cast = nan(size(Neutral_Density)); - -[Inn] = find(~isnan(Neutral_Density)); -[SA_iref_cast(Inn),CT_iref_cast(Inn),p_iref_cast(Inn)] = gsw_interp_McD_Klocker(Neutral_Density(Inn),A); - -dummy = cat(1,p,p_Neutral_Density); % this combines the profile pressures with the neutral density pressures -p_plusnd = sort(dummy); % this sorts the pressures down the profile into decending order - -dyn_height_nd = nan(mpgn,ns); -SA_nd = nan(mpgn,ns); -CT_nd = nan(mpgn,ns); -in_funnel= nan(mpgn,ns); - -for Iprofile = 1:ns - [Inn] = ~isnan(p_plusnd(:,Iprofile)); - p_plus = unique(p_plusnd(Inn,Iprofile)); - [InnSACT] = ~isnan(SA(:,Iprofile)) & ~isnan(CT(:,Iprofile)); - [SA_plus, CT_plus] = gsw_interp_SA_CT(SA(InnSACT,Iprofile),CT(InnSACT,Iprofile),p(InnSACT,Iprofile),p_plus); - [dyn_height,in_funnel_plus] = gsw_geo_strf_dyn_height(SA_plus(:),CT_plus(:),p_plus); - [dummy, Idata] = intersect(p_plus,p_Neutral_Density(:,Iprofile)); - dyn_height_nd(1:mpgn,Iprofile) = dyn_height(Idata); - SA_nd(1:mpgn,Iprofile) = SA_plus(Idata); - CT_nd(1:mpgn,Iprofile) = CT_plus(Idata); - in_funnel(1:mpgn,Iprofile) = in_funnel_plus(Idata); -end - -[Isurface] = find(p_Neutral_Density == 0); -p_Neutral_Density(Isurface) = NaN; - -part1 = 0.5*db2Pa*(p_Neutral_Density -p_iref_cast).*(gsw_specvol_CT25(SA_nd,CT_nd,p_Neutral_Density) - ... - gsw_specvol_CT25(SA_iref_cast,CT_iref_cast,p_Neutral_Density)); - -part2 = -0.225e-15*db2Pa*db2Pa*(CT_nd-CT_iref_cast).*(p_Neutral_Density-p_iref_cast).*(p_Neutral_Density-p_iref_cast); - -part3 = dyn_height_nd - gsw_enthalpy_SSO_0_CT25(p_Neutral_Density) + ... - gsw_enthalpy_CT25(SA_iref_cast,CT_iref_cast,p_Neutral_Density) - cp0*CT_iref_cast; - -%-------------------------------------------------------------------------- -% This function calculates the McDougall-Klocker streamfunction using the -% computationally efficient 25-term expression for density in terms of SA, -% CT and p. If one wanted to compute this with the full TEOS-10 Gibbs -% function expression for density, the following lines of code will enable -% this. Note that dynamic height will also need to be evaluated using the -% full Gibbs function. -% -% part1 = 0.5*db2Pa*(p_Neutral_Density -p_iref_cast).*(gsw_specvol_CT(SA_nd,CT_nd,p_Neutral_Density) - ... -% gsw_specvol_CT(SA_iref_cast,CT_iref_cast,p_Neutral_Density)); -% part2 = -0.225e-15*db2Pa*db2Pa*(CT_nd-CT_iref_cast).*(p_Neutral_Density-p_iref_cast).*(p_Neutral_Density-p_iref_cast); -% SA_SO = 35.16504*ones(size(SA)); -% CT_0 = zeros(size(CT)); -% part3 = dyn_height_nd - gsw_enthalpy_CT(SA_SO,CT_0,p_Neutral_Density) + ... -% gsw_enthalpy_CT(SA_iref_cast,CT_iref_cast,p_Neutral_Density) - cp0*CT_iref_cast; -% -%---------------This is the end of the alternative code-------------------- - -geo_strf_McD_Klocker = part1 + part2 + part3; - -if transposed - geo_strf_McD_Klocker= geo_strf_McD_Klocker'; - in_funnel = in_funnel'; -end %if - -end - - diff --git a/Toolbox/gsw_geo_strf_McD_Klocker_pc.m b/Toolbox/gsw_geo_strf_McD_Klocker_pc.m deleted file mode 100644 index 245c9d8..0000000 --- a/Toolbox/gsw_geo_strf_McD_Klocker_pc.m +++ /dev/null @@ -1,208 +0,0 @@ -function [geo_strf_McD_Klocker_pc, p_mid, in_funnel] = gsw_geo_strf_McD_Klocker_pc(SA,CT,delta_p,gamma_n,layer_index,A) - -% gsw_geo_strf_McD_Klocker_pc McDougall-Klocker geostrophic -% streamfunction -%========================================================================== -% -% USAGE: -% [geo_strf_McD_Klocker_pc, p_mid, in_funnel] = gsw_geo_strf_McD_Klocker_pc(SA,CT,delta_p,gamma_n,layer_index,A) -% -% DESCRIPTION: -% Calculates the McDougall-Klocker geostrophic streamfunction -% (see Eqn. (3.30.1) of IOC et al. (2010). This function is to used -% when the Absolute Salinity and Conservative Temperature are piecewise -% constant in the vertical over sucessive pressure intervals of delta_p -% (such as in a forward "z-coordinate" ocean model, and in isopycnal -% layered ocean models). The McDougall-Klocker geostrpohic streamfunction -% is designed to be used as the geostrophic streamfunction in an -% approximately neutral surface (such as a Neutral Density surface, -% a potential density surface or an omega surface (Klocker et al. (2009)). -% Reference values of Absolute Salinity, Conservative Temperature and -% pressure are found by interpolation of a one-dimensional look-up table, -% with the interpolating variable being Neutral Density (gamma_n) or -% sigma_2. -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% delta_p = difference in sea pressure between the deep and shallow -% extents of each layer in which SA and CT are vertically -% constant. delta_p must be positive. [ dbar ] -% Note. Sea pressure is absolute pressure minus 10.1325 dbar. -% -% gamma_n = Neutral Density anomaly [ kg/m^3 ] -% (ie. Neutral Density minus 1000 kg/m^3) -% layer_index = Index of the layers of the gamma_n surfaces -% A = if nothing is entered the programme defaults to "Neutral -% Density" as the vertical interpolating variable. -% = 's2' or 'sigma2', for sigma_2 as the vertical -% interpolating variable. -% -% SA, CT & delta_p need to have the same dimensions. -% gamma_n & layer_indx need to have the same dimensions, there should be -% only one "gamma_n" or "sigma_2" value per level of interest. -% A needs to be 1x1. -% -% OUTPUT: -% geo_strf_McD_Klocker_pc = McDougall & Klocker (2010) [ m^2/s^2 ] -% geostrophic streamfunction -% -% p_mid = mid-point pressure in each layer [ dbar ] -% -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). -% -% AUTHOR: Trevor McDougall and Paul Barker -% -% VERSION NUMBER: 2.0 (17th September, 2010) -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See section 3.30 of this TEOS-10 Manual. -% -% Jackett, D. R. and T. J. McDougall, 1997: A neutral density variable -% for the world’s oceans. Journal of Physical Oceanography, 27, 237-263. -% -% Klocker, A., T. J. McDougall and D. R. Jackett, 2009: A new method -% for forming approximately neutral surfaces. Ocean Sci., 5, 155-172. -% -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. -% -% McDougall, T. J. and A. Klocker, 2010: An approximate geostrophic -% streamfunction for use in density surfaces. Ocean Modelling, 32, -% 105-117. -% The McDougall-Klocker geostrophic streamfunction is defined in -% Eqn. (62) of this paper. -% See section 8 of this paper for a discussion of this piecewise- -% constant version of the McDougall-Klocker geostrophic streamfunction. -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 5 | nargin == 6) - error('gsw_geo_strf_McD_Klocker_pc: Requires five or six inputs') -end %if - -if ~(nargout == 2 | nargout == 3) - error('gsw_geo_strf_McD_Klocker_pc: Requires two or three outputs') -end %if - -if ~exist('A','var') - A = 'gn'; -elseif ~ischar(A) - A = 'gn'; -end %if - -[ms,ns] = size(SA); -[mt,nt] = size(CT); -[mp,np] = size(delta_p); - -if (ms~=mt) | (ns~=nt) - error('gsw_geo_strf_McD_Klocker_pc: SA & CT need to have the same dimensions') -end - -if (mp == 1) & (np == 1) % delta_p scalar - fill to size of SA - error('gsw_geo_strf_McD_Klocker_pc: needs more than one pressure'); -elseif (ns == np) & (mp == 1) % delta_p is row vector, - delta_p = delta_p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % delta_p is column vector, - delta_p = delta_p(:,ones(1,ns)); % copy across each row. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_geo_strf_McD_Klocker_pc: Inputs array dimensions arguments do not agree') -end %if - -[mgn,ngn] = size(gamma_n); -[mli,nli] = size(layer_index); - -if (mgn~=mli) | (ngn~=nli) - error('gsw_geo_strf_McD_Klocker_pc: Inputs array (layers) dimensions arguments do not agree') -end - -if ms == 1 % row vector - delta_p = delta_p(:); - CT = CT(:); - SA = SA(:); - transposed = 1; -else - transposed = 0; -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -db2Pa = 1e4; -cp0 = 3991.86795711963; % from Eqn. (3.3.3) of IOC et al. (2010). - -SA_iref_cast = nan(size(gamma_n)); -CT_iref_cast = nan(size(gamma_n)); -p_iref_cast = nan(size(gamma_n)); - -[Inn] = find(~isnan(gamma_n)); -[SA_iref_cast(Inn),CT_iref_cast(Inn),p_iref_cast(Inn)] = gsw_interp_McD_Klocker(gamma_n(Inn),A); - -[dyn_height_pc, p_mid_fine, in_funnel_fine] = gsw_geo_strf_dyn_height_pc(SA,CT,delta_p); - -[Isurface] = find(p_mid_fine == 0); -p_mid_fine(Isurface) = NaN; -p_mid = p_mid_fine(layer_index,:); -in_funnel = in_funnel_fine(layer_index,:); - -SA_iref_cast_nd = SA_iref_cast.* ones(size(p_mid)); -CT_iref_cast_nd = CT_iref_cast.* ones(size(p_mid)); - -part1 = 0.5*db2Pa*(p_mid_fine(layer_index,:) - p_iref_cast).*(gsw_specvol_CT25(SA(layer_index,:),CT(layer_index,:),p_mid_fine(layer_index,:)) - ... - gsw_specvol_CT25(SA_iref_cast_nd,CT_iref_cast_nd,p_mid_fine(layer_index,:))); - -part2 = -0.225e-15*db2Pa*db2Pa*(CT(layer_index,:)-CT_iref_cast).*... - (p_mid_fine(layer_index,:)-p_iref_cast).*(p_mid_fine(layer_index,:)-p_iref_cast); - -part3 = dyn_height_pc(layer_index,:) - gsw_enthalpy_SSO_0_CT25(p_mid_fine(layer_index,:)) + ... - gsw_enthalpy_CT25(SA_iref_cast_nd,CT_iref_cast_nd,p_mid_fine(layer_index,:)) - cp0*CT_iref_cast; - -%-------------------------------------------------------------------------- -% This function calculates the McDougall-Klocker piecewise constant -% streamfunction using the computationally efficient 25-term expression for -% density in terms of SA, CT and p. If one wanted to compute this with the -% full TEOS-10 Gibbs function expression for density, the following lines -% of code will enable this. Note that dynamic height will also need to be -% evaluated using the full Gibbs function. -% -% part1 = 0.5*db2Pa*(p_mid_fine(layer_index,:) - p_iref_cast).*(gsw_specvol_CT(SA(layer_index,:),CT(layer_index,:),p_mid_fine(layer_index,:)) - ... -% gsw_specvol_CT(SA_iref_cast,CT_iref_cast,p_mid_fine(layer_index,:))); -% part2 = -0.225e-15*db2Pa*db2Pa*(CT(layer_index,:)-CT_iref_cast).*... -% (p_mid_fine(layer_index,:)-p_iref_cast).*(p_mid_fine(layer_index,:)-p_iref_cast); -% SA_SO = 35.16504*ones(size(SA)); -% CT_0 = zeros(size(CT)); -% part3 = dyn_height_pc(layer_index,:) - gsw_enthalpy_CT(SA_SO,CT_0,p_mid_fine(layer_index,:)) + ... -% gsw_enthalpy_CT(SA_iref_cast_nd,CT_iref_cast_nd,p_mid_fine(layer_index,:)) - cp0*CT_iref_cast; -% -%---------------This is the end of the alternative code-------------------- - -geo_strf_McD_Klocker_pc = part1 + part2 + part3; - -if transposed - geo_strf_McD_Klocker_pc = geo_strf_McD_Klocker_pc'; - in_funnel = in_funnel'; - p_mid = p_mid'; -end %if - -end - diff --git a/Toolbox/gsw_geo_strf_Montgomery.m b/Toolbox/gsw_geo_strf_Montgomery.m index fd1f3a1..f56160f 100644 --- a/Toolbox/gsw_geo_strf_Montgomery.m +++ b/Toolbox/gsw_geo_strf_Montgomery.m @@ -1,61 +1,57 @@ -function [geo_strf_Montgomery, in_funnel] = gsw_geo_strf_Montgomery(SA,CT,p,interp_style) +function geo_strf_Montgomery = gsw_geo_strf_Montgomery(SA,CT,p,p_ref) -% gsw_geo_strf_Montgomery Montgomery geostrophic streamfunction +% gsw_geo_strf_Montgomery Montgomery geostrophic +% streamfunction (48-term equation) %========================================================================== % % USAGE: -% [geo_strf_Montgomery, in_funnel] = gsw_geo_strf_Montgomery(SA,CT,p,interp_style) +% geo_strf_Montgomery = gsw_geo_strf_Montgomery(SA,CT,p,p_ref) % % DESCRIPTION: % Calculates the Montgomery geostrophic streamfunction (see Eqn. (3.28.1) % of IOC et al. (2010)). This is the geostrophic streamfunction for the % difference between the horizontal velocity at the pressure concerned, p, -% and the horizontal velocity at the sea surface. The Montgomery -% geostrophic streamfunction is the geostrophic streamfunction for flow in -% a specifc volume anomaly surface. The reference values used for the -% specific volume anomaly are SA = SSO = 35.16504 g/kg and CT = 0 deg C. -% This function calculates specific volume anomaly using the -% computationally efficient 25-term expression for specific volume of -% McDougall et al. (2010). -% Under the default setting, this function evaluates the pressure integral -% of specific volume using SA and CT “interploted” with respect to pressure -% using a scheme based on the method of Reiniger and Ross (1968). Our -% method uses a weighted mean of (i) values obtained from linear -% interpolation of the two nearest data points, and (ii) a linear -% extrapolation of the pairs of data above and below. This "curve fitting" -% method resembles the use of cubic splines. If the option “linear” is -% chosen, the function interpolates Absolute Salinity and Conservative -% Temperature linearly with presure in the vertical between “bottles”. +% and the horizontal velocity on the pressure surface, p_ref. The +% Montgomery geostrophic streamfunction is the geostrophic streamfunction +% for flow in a specifc volume anomaly surface. The reference values used +% for the specific volume anomaly are SA = SSO = 35.16504 g/kg and +% CT = 0 deg C. This function calculates specific volume anomaly using +% the computationally efficient 48-term expression for specific volume of +% McDougall et al. (2011). +% +% Note that p_ref, is the reference pressure to which the streamfunction +% is referenced. When p_ref is zero, "gsw_geo_strf_Montgomery" returns +% the Montgomery geostrophic streamfunction with respect to the sea +% surface, otherwise, the function returns the geostrophic streamfunction +% with respect to the (deep) reference pressure p_ref. +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) -% -% OPTIONAL: -% interp_style = interpolation technique. -% = if nothing is entered the programme defaults to "curved" -% interpolation between bottles in the vertical. -% = if "linear" or "lin" is entered then the programme -% interpolates linearly between bottles in the -% vertical. +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% p_ref = reference pressure [ dbar ] +% ( i.e. reference absolute pressure - 10.1325 dbar ) % % SA & CT need to have the same dimensions. % p may have dimensions Mx1 or 1xN or MxN, where SA & CT are MxN. +% p_ref needs to be a single value, it can have dimensions 1x1 or Mx1 or +% 1xN or MxN. % % OUTPUT: -% geo_strf_Montgomery = Montgomery geostrophic streamfunction [ m^2/s^2 ] -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). +% geo_strf_Montgomery = Montgomery geostrophic [ m^2/s^2 ] +% streamfunction % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (26th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -64,11 +60,10 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See section 3.28 of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % Montgomery, R. B., 1937: A suggested method for representing gradient % flow in isentropic surfaces. Bull. Amer. Meteor. Soc. 18, 210-212. @@ -81,10 +76,17 @@ % Check variables and resize if necessary %-------------------------------------------------------------------------- -if ~(nargin == 3 | nargin == 4) - error('gsw_geo_strf_Montgomery: Requires three or four inputs') +if ~(nargin == 4) + error('gsw_geo_strf_Montgomery: Requires four inputs') end %if +unique_p_ref = unique(p_ref); +if ~isscalar(unique_p_ref) + error('gsw_geo_strf_Montgomery: The reference pressure p_ref must be unique') +end +clear p_ref +p_ref = unique_p_ref; + [ms,ns] = size(SA); [mt,nt] = size(CT); [mp,np] = size(p); @@ -99,19 +101,15 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else error('gsw_geo_strf_Montgomery: Inputs array dimensions arguments do not agree') end %if -if ~exist('interp_style','var') - interp_style = 'curve'; -elseif strcmpi('interp_style','linear') == 1 | strcmpi('interp_style','lin') == 1 |... - strcmpi('interp_style','linaer') == 1 | strcmpi('interp_style','lnear') == 1 - interp_style = 'linear'; -end - transposed = 0; if ms == 1 p = p(:); @@ -126,31 +124,28 @@ db2Pa = 1e4; -delta_p = 1; % This is the maximum distance between bottles in the vertical. - -[dyn_height,in_funnel] = gsw_geo_strf_dyn_height(SA,CT,p,delta_p,interp_style); +dyn_height = gsw_geo_strf_dyn_height(SA,CT,p,p_ref); -geo_strf_Montgomery = db2Pa*p.*(gsw_specvol_CT25(SA,CT,p) - ... - gsw_specvol_SSO_0_CT25(p)) + dyn_height; +geo_strf_Montgomery = db2Pa*p.*(gsw_specvol(SA,CT,p) - ... + gsw_specvol_SSO_0_p(p)) + dyn_height; %-------------------------------------------------------------------------- % This function calculates the Montgomery streamfunction using the -% computationally efficient 25-term expression for density in terms of SA, -% CT and p. If one wanted to compute this with the full TEOS-10 Gibbs +% computationally efficient 48-term expression for density in terms of SA, +% CT and p. If one wanted to compute this with the full TEOS-10 Gibbs % function expression for density, the following lines of code will enable -% this. Note that dynamic height will also need to be evaluated using the +% this. Note that dynamic height will also need to be evaluated using the % full Gibbs function. % -% SA_SO = 35.16504*ones(size(SA)); +% SA_SSO = 35.16504*ones(size(SA)); % CT_0 = zeros(size(CT)); -% geo_strf_Montgomery = db2Pa*p.*(gsw_specvol_CT(SA,CT,p) - ... -% gsw_enthalpy_CT(SA_SO,CT_0,p)) + dyn_height; +% geo_strf_Montgomery = db2Pa*p.*(gsw_specvol_CT_exact(SA,CT,p) - ... +% gsw_enthalpy_CT_exact(SA_SSO,CT_0,p)) + dyn_height; % %---------------This is the end of the alternative code-------------------- if transposed - geo_strf_Montgomery = geo_strf_Montgomery'; - in_funnel = in_funnel'; + geo_strf_Montgomery = geo_strf_Montgomery.'; end %if end diff --git a/Toolbox/gsw_geo_strf_dyn_height.m b/Toolbox/gsw_geo_strf_dyn_height.m index c88094f..38f305b 100644 --- a/Toolbox/gsw_geo_strf_dyn_height.m +++ b/Toolbox/gsw_geo_strf_dyn_height.m @@ -1,64 +1,66 @@ -function [geo_strf_dyn_height, in_funnel] = gsw_geo_strf_dyn_height(SA,CT,p,delta_p,interp_style) +function geo_strf_dyn_height = gsw_geo_strf_dyn_height(SA,CT,p,p_ref) % gsw_geo_strf_dyn_height dynamic height anomaly +% (48-term equation) %========================================================================== % % USAGE: -% [geo_strf_dyn_height, in_funnel] = gsw_geo_strf_dyn_height(SA,CT,p,delta_p,interp_style) +% geo_strf_dyn_height = gsw_geo_strf_dyn_height(SA,CT,p,p_ref) % % DESCRIPTION: -% Calculates dynamic height anomaly as the integral of specific volume -% anomaly from the the sea surface pressure (0 Pa) to the pressure p. -% Hence, geo_strf_dyn_height is the dynamic height anomaly with respect to -% the sea surface. This is the geostrophic streamfunction for the -% difference between the horizontal velocity at the pressure concerned, p, -% and the horizontal velocity at the sea surface. Dynamic height anomaly -% is the geostrophic streamfunction in an isobaric surface. The reference -% values used for the specific volume anomaly are SA = SSO = 35.16504 g/kg -% and CT = 0 deg C. This function calculates specific volume anomaly -% using the computationally efficient 25-term expression for specific -% volume of McDougall et al. (2010). -% Under the default setting, this function evaluates the pressure integral -% of specific volume using SA and CT “interploted” with respect to pressure -% using a scheme based on the method of Reiniger and Ross (1968). Our -% method uses a weighted mean of (i) values obtained from linear -% interpolation of the two nearest data points, and (ii) a linear -% extrapolation of the pairs of data above and below. This "curve fitting" -% method resembles the use of cubic splines. If the option “linear” is -% chosen, the function interpolates Absolute Salinity and Conservative -% Temperature linearly with presure in the vertical between “bottles”. +% Calculates dynamic height anomaly as the integral of specific volume +% anomaly from the pressure p of the “bottle” to the reference pressure +% p_ref. +% +% Hence, geo_strf_dyn_height is the dynamic height anomaly with respect +% to a given reference pressure. This is the geostrophic streamfunction +% for the difference between the horizontal velocity at the pressure +% concerned, p, and the horizontal velocity at p_ref. Dynamic height +% anomaly is the geostrophic streamfunction in an isobaric surface. The +% reference values used for the specific volume anomaly are +% SSO = 35.16504 g/kg and CT = 0 deg C. This function calculates +% specific volume anomaly using the computationally efficient 48-term +% expression for specific volume of McDougall et al. (2011). +% +% This function evaluates the pressure integral of specific volume using +% SA and CT “interpolated” with respect to pressure using a scheme based +% on the method of Reiniger and Ross (1968). Our method uses a weighted +% mean of (i) values obtained from linear interpolation of the two nearest +% data points, and (ii) a linear extrapolation of the pairs of data above +% and below. This "curve fitting" method resembles the use of cubic +% splines. +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). For dynamical oceanography we may +% take the 48-term rational function expression for density as essentially +% reflecting the full accuracy of TEOS-10. The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% p_ref = reference pressure [ dbar ] +% ( i.e. reference absolute pressure - 10.1325 dbar ) % % SA & CT need to have the same dimensions. % p may have dimensions Mx1 or 1xN or MxN, where SA & CT are MxN. +% p_ref needs to be a single value, it can have dimensions 1x1 or Mx1 or +% 1xN or MxN. % -% OPTIONAL: -% delta_p = maximum interpolation distance between bottles. -% interp_style = interpolation technique. -% = if nothing is entered the programme defaults to "curved" -% interpolation between bottles in the vertical. -% = if "linear" or "lin" is entered then the programme -% interpolates linearly between bottles in the -% vertical. -% % OUTPUT: -% geo_strf_dyn_height = dynamic height anomaly [ m^2/s^2 ] -% -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). +% geo_strf_dyn_height = dynamic height anomaly [ m^2/s^2 ] +% Note. If p_ref exceeds the pressure of the deepest “bottle” on a +% vertical profile, the dynamic height anomaly for each “bottle” +% on the whole vertical profile is returned as NaN. % % AUTHOR: -% Paul Barker, Jeff Dunn and Trevor McDougall [ help_gsw@csiro.au ] +% Paul Barker, Jeff Dunn and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0, 25th August, 2010 +% VERSION NUMBER: 3.0 (7th April, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -67,11 +69,10 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See Eqn. (3.7.3) and section 3.27 of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % Reiniger, R. F. and C. K. Ross, 1968: A method of interpolation with % application to oceanographic data. Deep-Sea Res. 15, 185-193. @@ -84,10 +85,26 @@ % Check variables and resize if necessary %-------------------------------------------------------------------------- -if ~(nargin == 3 | nargin == 4 | nargin == 5) - error('gsw_geo_strf_dyn_height: Requires three, four or five inputs') +if ~(nargin == 4) + error('gsw_geo_strf_dyn_height: Requires four inputs') end %if +unique_p_ref = unique(p_ref); +if ~isscalar(unique_p_ref) + error('gsw_geo_strf_dyn_height: The reference pressure p_ref must be unique') +end +clear p_ref +p_ref = unique_p_ref; + +if p_ref < 0 + error('gsw_geo_strf_dyn_height: The reference pressure p_ref must be positive') +end + +[InegSA] = find(SA < 0); +if ~isempty(InegSA) + error('gsw_geo_strf_dyn_height: The Absolute Salinity must be positive!') +end + [ms,ns] = size(SA); [mt,nt] = size(CT); [mp,np] = size(p); @@ -105,7 +122,7 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok @@ -113,21 +130,15 @@ error('gsw_geo_strf_dyn_height: Inputs array dimensions arguments do not agree') end %if -if ~exist('delta_p','var') - delta_p = 1; -end - -if ~exist('interp_style','var') - interp_style = 'curve'; -elseif strcmpi('interp_style','linear') == 1 | strcmpi('interp_style','lin') == 1 |... - strcmpi('interp_style','linaer') == 1 | strcmpi('interp_style','lnear') == 1 - interp_style = 'linear'; -end +[Inan] = find(isnan(SA.*CT.*p)); +SA(Inan) = NaN; +CT(Inan) = NaN; +p(Inan) = NaN; if ms == 1 - SA = SA'; - CT = CT'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -138,7 +149,18 @@ % Start of the calculation %-------------------------------------------------------------------------- -in_funnel = gsw_infunnel(SA,CT,p); +if max(p(:)) < p_ref + error('gsw_geo_strf_dyn_height: The reference pressure p_ref is deeper than all bottles') +end + +%-------------------------------------------------------------------------- +% This max_dp_i is the limit we choose for the evaluation of specific +% volume in the pressure integration. That is, the vertical integration +% of specific volume with respet to pressure is perfomed with the pressure +% increment being no more than max_dp_i, with the default value being 1 +% dbar. +max_dp_i = 1; +%-------------------------------------------------------------------------- db2Pa = 1e4; @@ -151,142 +173,266 @@ end geo_strf_dyn_height = nan(size(SA)); + +%-------------------------------------------------------------------------- +% The index [Ibg] (Index-bottle-gaps) indicates where the vertical gaps +% between adjacent "bottles" is greater than max_dp_i. +[Ibg] = find(d_p > max_dp_i); +%-------------------------------------------------------------------------- -[Ibg] = find(d_p > delta_p); +% The index [Inz] (Index-not-zero) indicates when the shallowest +% "bottle" is not at p = 0 dbar. [Inz] = find(p(1,:) ~=0); +%-------------------------------------------------------------------------- -if isempty(Ibg) & isempty(Inz) - % resolution is ok & profile extends to the surface. - B = gsw_specvol_CT25(SA,CT,p); - C = gsw_enthalpy_SSO_0_CT25(p); +% The index [Ibp_ref] (Index-bottle-at-p_ref) indicates when there is a +% cast which does not have a "bottle" at exactly p_ref, and that cast is +% deeper than p_ref. +Ibp_ref = []; +Icount = 1; +Iprofile = 1; +Idha = nan(1,np); +test_p_ref = 1; +while test_p_ref == 1 + if Iprofile <= np + [Ibrp] = find(p(:,Iprofile) == p_ref); + if isempty(Ibrp) & (p_ref < max(p(:,Iprofile))) + Ibp_ref = 1; + test_p_ref = 0; + elseif ~isempty(Ibrp) + Idha(Icount) = Iprofile; + Icount = Icount + 1; + end + if Iprofile == np + if Icount < np + Idha(Icount:np) = []; + end + test_p_ref = 0; + end + Iprofile = Iprofile + 1; + end +end + +%-------------------------------------------------------------------------- + +if isempty(Ibg) & isempty(Inz) & isempty(Ibp_ref) + % vertical resolution is good (bottle gap is no larger than max_dp_i) + % & vertical profile begins at the surface (i.e. at p = 0 dbar) + % & each vertical profile contains a "bottle" at exactly p_ref. + geo_strf_dyn_height0 = nan(size(SA)); + geo_strf_dyn_height_p_ref = nan(size(SA)); + B = gsw_specvol(SA(:,Idha),CT(:,Idha),p(:,Idha)); + C = gsw_enthalpy_SSO_0_p(p(:,Idha)); %-------------------------------------------------------------------------- % This function calculates dynamic height anomaly using the computationally -% efficient 25-term expression for density in terms of SA, CT and p. If one +% efficient 48-term expression for density in terms of SA, CT and p. If one % wanted to compute dynamic height anomaly with the full TEOS-10 Gibbs % function expression for density, the following lines of code will enable % this. % -% B = gsw_specvol_CT(SA,CT,p); -% SA_SO = 35.16504*ones(size(SA)); +% B = gsw_specvol_CT_exact(SA(:,Idha),CT(:,Idha),p(:,Idha)); +% SA_SSO = 35.16504*ones(size(SA)); % CT_0 = zeros(size(CT)); -% C = gsw_enthalpy_CT(SA_SO,CT_0,p); +% C = gsw_enthalpy_CT_exact(SA_SSO(:,Idha),CT_0(:,Idha),p(:,Idha)); % % Further down the page is a second section which also needs to be % activated in order to compute dynamic height anomaly with the full % TEOS-10 Gibbs function expression for density. +% %---------------This is the end of the alternative code-------------------- - B_av = zeros(size(SA)); + B_av = zeros(size(SA(:,Idha))); B_av(2:mp,:) = 0.5*(B(1:(end-1),:) + B(2:end,:)); - dp = zeros(size(SA)); - dp(2:mp,:) = d_p; + dp = zeros(size(SA(:,Idha))); + dp(2:mp,:) = d_p(:,Idha); D = B_av.*dp.*db2Pa; - geo_strf_dyn_height = C - cumsum(D); + + geo_strf_dyn_height0(:,Idha) = C - cumsum(D); +% "geo_strf_dyn_height0" is the dynamic height anomaly with respect +% to p_ref = 0 (the surface). + + [I_rp] = find(p == p_ref); + geo_strf_dyn_height_p_ref(:,Idha) = meshgrid(geo_strf_dyn_height0(I_rp),[1:mp]); +% "geo_strf_dyn_height_p_ref" is the dynamic height anomaly at p_ref +% with respect to the surface. + + geo_strf_dyn_height = geo_strf_dyn_height0 - geo_strf_dyn_height_p_ref; +% "geo_strf_dyn_height" is the dynamic height anomaly with respect +% to p_ref, and is returned. The code will have gotten to here iff the +% data is "perfect" in the sense that +% (i) it has very fine vertical resolution, +% (ii) each cast starts at p = 0, and +% (iii) every cast contains a bottle at exactly p_ref. + else - % will need to interplolate profiles, but will check each profile. + % will need to interpolate profiles, doing so one profile at a time. for Iprofile = 1:np [Inn] = find(~isnan(p(:,Iprofile))); - [Ibg_i] = find(d_p(:,Iprofile) > delta_p); - if isempty(Ibg_i) - if min(p(Inn,Iprofile)) > 0 - SA_i = SA(Inn(1),Iprofile); - SA_i(2:length(Inn)+1) = SA(Inn,Iprofile); - CT_i = CT(Inn(1),Iprofile); - CT_i(2:length(Inn)+1) = CT(Inn,Iprofile); - p_i = 0; - p_i(2:length(Inn)+1) = p(Inn,Iprofile); - [dummy Iidata Ibdata] = intersect(p_i(2:end),p(:,Iprofile)); - Intrp = 2:length(p_i); - else - SA_i = SA(Inn,Iprofile); - CT_i = CT(Inn,Iprofile); - p_i = p(Inn,Iprofile); - [dummy Iidata Ibdata] = intersect(p_i,p(:,Iprofile)); - Intrp = 1:length(p_i); - end - else - p_i = nan(2*round(max(p(Inn,Iprofile)/delta_p)),1); - if p(Inn,Iprofile) > 0 - p_i(1) = 0; - p_i(2) = min(p(Inn,Iprofile)); - top_pad = 1; - p_cnt = 2; - else - p_i(1) = min(p(Inn,Iprofile)); - top_pad = 0; - p_cnt = 1; - end - for Ibottle = 1:(length(Inn)-1) - dp_iIbottle = p(Inn(Ibottle+1),Iprofile) - p(Inn(Ibottle),Iprofile); - p_iIbottle = p(Inn(Ibottle),Iprofile):dp_iIbottle/ceil(dp_iIbottle/delta_p):p(Inn(Ibottle+1),Iprofile); - p_cnt_ld = p_cnt+1; - p_cnt = p_cnt + length(p_iIbottle(2:length(p_iIbottle))); - p_i(p_cnt_ld:p_cnt) = p_iIbottle(2:length(p_iIbottle)); - end - p_i(p_cnt+1:end) = []; - p_i = p_i(:); - - if top_pad ==1 - Intrp = 2:length(p_i); - SA_i = SA(Inn,Iprofile); - CT_i = CT(Inn,Iprofile); - else - Intrp = 1:length(p_i); - end - [dummy Iidata Ibdata] = intersect(p_i(Intrp),p(:,Iprofile)); - - if ~exist('interp_style','var') - SA_i(Intrp) = pinterp_from_p(p(:,Iprofile),SA(:,Iprofile),p_i(Intrp)); - CT_i(Intrp) = pinterp_from_p(p(:,Iprofile),CT(:,Iprofile),p_i(Intrp)); - [Inan] = find(isnan(SA_i)); - if ~isempty(Inan) - [SA_i(Inan), CT_i(Inan)] = gsw_interp_SA_CT(SA(:,Iprofile),CT(:,Iprofile),p(:,Iprofile),p_i(Inan)); - end - elseif exist('interp_style','var') & strcmpi(interp_style,'linear') - [SA_i(Intrp), CT_i(Intrp)] = gsw_interp_SA_CT(SA(:,Iprofile),CT(:,Iprofile),p(:,Iprofile),p_i(Intrp)); + +% Test if the depth of the cast extends to the reference pressure + if (max(p(Inn,Iprofile)) >= p_ref) +% p_ref is shallower than the pressure of the deepest “bottle” on the +% vertical profile, thus the dynamic height can be calculated. + +% Test if there are vertical gaps between adjacent "bottles" which are +% greater than max_dp_i, and that there is a "bottle" exactly at the +% reference pressure. + [Ibg_i] = find(d_p(:,Iprofile) > max_dp_i); + [Ibrp] = find(p(Inn,Iprofile) == p_ref); + if isempty(Ibg_i) & isempty(Ibrp) +% Vertical resultion is already good (no larger than max_dp_i, and on this +% vertical profile there is a "bottle" at exactly p_ref. + + %Test if the the shallowest "bottle" is not at p = 0 dbar. + if min(p(Inn,Iprofile)) > 0 + %resolution is fine and there is a bottle at p_ref, but + %there is not a bottle at p =0 + SA_i = SA(Inn(1),Iprofile); + SA_i(2:length(Inn)+1) = SA(Inn,Iprofile); + CT_i = CT(Inn(1),Iprofile); + CT_i(2:length(Inn)+1) = CT(Inn,Iprofile); + p_i = 0; + p_i(2:length(Inn)+1) = p(Inn,Iprofile); + [dummy Iidata Ibdata] = intersect(p_i,p(:,Iprofile)); + [Ibpr] = find(p_i == p_ref); + else + %resolution is fine, there is a bottle at p_ref, and + %there is a bottle at p =0 + SA_i = SA(Inn,Iprofile); + CT_i = CT(Inn,Iprofile); + p_i = p(Inn,Iprofile); + [dummy Iidata Ibdata] = intersect(p_i,p(:,Iprofile)); + [Ibpr] = find(p_i == p_ref); + end else + % interpolation is needed. + p_i = nan(2*round(max(p(Inn,Iprofile)/max_dp_i)),1); + +% Test if there is a bottle at p = 0. + if min(p(Inn,Iprofile)) > 0 + % there is not a bottle at p = 0. +% Test if p_ref is shallower than the minimum bottle pressure of the profile + if p_ref < min(p(Inn,Iprofile)) + % p_ref is shallower than the minimum bottle pressure. + dp_iIbottle1 = p_ref; + dp_iIbottle2 = p(Inn(1),Iprofile) - p_ref; + p_iIbottle1 = 0:dp_iIbottle1/ceil(dp_iIbottle1/max_dp_i):p_ref; + p_iIbottle2 = p_ref:dp_iIbottle2/ceil(dp_iIbottle2/max_dp_i):p(Inn(1),Iprofile); + p_iIbottle = p_iIbottle1(1:end-1); + p_iIbottle((length(p_iIbottle1)):length(p_iIbottle1)+length(p_iIbottle2)-1) = p_iIbottle2; + p_cnt = length(p_iIbottle); + p_i(1:p_cnt) = p_iIbottle; + top_pad = p_cnt; + else + % p_ref is deeper than the minimum bottle pressure. + p_i(1) = 0; + p_i(2) = min(p(Inn,Iprofile)); + top_pad = 2; + p_cnt = 2; + end + else + % there is a bottle at p = 0. + p_i(1) = min(p(Inn,Iprofile)); + top_pad = 1; + p_cnt = 1; + end + +% Test for bottle at p_ref, if it does not exist then the reference +% pressure will need to be an interpolated pressure. + [Irb] = find(p - p_ref == 0); + if ~isempty(Irb) + %There is a bottle at p_ref. Define interpolation + %pressures. + for Ibottle = 1:(length(Inn)-1) + dp_iIbottle = p(Inn(Ibottle+1),Iprofile) - p(Inn(Ibottle),Iprofile); + p_iIbottle = p(Inn(Ibottle),Iprofile):dp_iIbottle/ceil(dp_iIbottle/max_dp_i):p(Inn(Ibottle+1),Iprofile); + p_cnt_ld = p_cnt+1; + p_cnt = p_cnt + length(p_iIbottle(2:length(p_iIbottle))); + p_i(p_cnt_ld:p_cnt) = p_iIbottle(2:length(p_iIbottle)); + end + else + %There is not a bottle at p_ref. Define interpolation + %pressures to include p_ref. + for Ibottle = 1:(length(Inn)-1) +% Test if the bottle pair spans the reference pressure + dp_iIbottle = p(Inn(Ibottle+1),Iprofile) - p(Inn(Ibottle),Iprofile); + if (p(Inn(Ibottle+1),Iprofile) - p_ref > 0) & (p(Inn(Ibottle),Iprofile) - p_ref < 0) + %reference pressure is spanned by bottle pairs, + %need to include p_ref as an interpolated + %pressure. + dp_iIbottle1 = p_ref - p(Inn(Ibottle),Iprofile); + dp_iIbottle2 = p(Inn(Ibottle+1),Iprofile) - p_ref; + p_iIbottle1 = p(Inn(Ibottle),Iprofile):dp_iIbottle1/ceil(dp_iIbottle1/max_dp_i):p_ref; + p_iIbottle2 = p_ref:dp_iIbottle2/ceil(dp_iIbottle2/max_dp_i):p(Inn(Ibottle+1),Iprofile); + p_iIbottle = p_iIbottle1(1:end-1); + p_iIbottle((length(p_iIbottle1)):length(p_iIbottle1)+length(p_iIbottle2)-1) = p_iIbottle2; + else + %reference pressure is not spanned by bottle pairs. + p_iIbottle = p(Inn(Ibottle),Iprofile):dp_iIbottle/ceil(dp_iIbottle/max_dp_i):p(Inn(Ibottle+1),Iprofile); + end + p_cnt_ld = p_cnt+1; + p_cnt = p_cnt + length(p_iIbottle(2:length(p_iIbottle))); + p_i(p_cnt_ld:p_cnt) = p_iIbottle(2:length(p_iIbottle)); + end + end + p_i(p_cnt+1:end) = []; + p_i = p_i(:); + SA_i = nan(size(p_i)); + CT_i = nan(size(p_i)); + + [dummy, Iidata, Ibdata] = intersect(p_i,p(:,Iprofile)); + [Ibpr] = find(p_i == p_ref); + +%--------------------------------------------------------------------------- +% "Cowboy/cowgirl" oceanographers would not action the next 7 lines of +% code. Instead these "rough & ready" oceanographers would implement the +% one line of code which linearly interpolates. + [Intrp] = top_pad:length(p_i); SA_i(Intrp) = pinterp_from_p(p(:,Iprofile),SA(:,Iprofile),p_i(Intrp)); CT_i(Intrp) = pinterp_from_p(p(:,Iprofile),CT(:,Iprofile),p_i(Intrp)); [Inan] = find(isnan(SA_i)); if ~isempty(Inan) [SA_i(Inan), CT_i(Inan)] = gsw_interp_SA_CT(SA(:,Iprofile),CT(:,Iprofile),p(:,Iprofile),p_i(Inan)); - end - end - end - - p_i = p_i(:); - B_i = gsw_specvol_CT25(SA_i(:),CT_i(:),p_i(:)); - C_i = gsw_enthalpy_SSO_0_CT25(p_i(2:end)); - + end + +% The linear interpolation below is for use by "cowboy/cowgirl" oceanographers only +% (i.e. those "rough & ready" oceanographers who do not care about accuracy). +% [SA_i, CT_i] = gsw_interp_SA_CT(SA(:,Iprofile),CT(:,Iprofile),p(:,Iprofile),p_i); +%--------------------------------------------------------------------------- + end + + p_i = p_i(:); + B_i = gsw_specvol(SA_i(:),CT_i(:),p_i(:)); + C_i = gsw_enthalpy_SSO_0_p(p_i(2:end)); + %-------------------------------------------------------------------------- % This function calculates dynamic height anomaly using the computationally -% efficient 25-term expression for density in terms of SA, CT and p. If one -% wanted to compute dynamic height anomaly with the full TEOS-10 Gibbs -% function expression for density, the following lines of code will enable +% efficient 48-term expression for density in terms of SA, CT and p. If +% one wanted to compute dynamic height anomaly with the full TEOS-10 Gibbs +% function expression for density, the following lines of code will enable % this. % -% B_i = gsw_specvol_CT(SA_i,CT_i,p_i); +% B_i = gsw_specvol_CT_exact(SA_i,CT_i,p_i); % B_i = B_i(:); -% SA_SO = 35.16504*ones(size(SA_i)); +% SA_SSO = 35.16504*ones(size(SA_i)); % CT_0 = zeros(size(CT_i)); -% C_i = gsw_enthalpy_CT(SA_SO(2:end),CT_0(2:end),p_i(2:end)); +% C_i = gsw_enthalpy_CT_exact(SA_SSO(2:end),CT_0(2:end),p_i(2:end)); % C_i = C_i(:); % %---------------This is the end of the alternative code-------------------- - - B_i_av = 0.5*(B_i(1:(end-1)) + B_i(2:end)); - Da_i = (B_i_av.*diff(p_i).*db2Pa); - D_i(2:length(C_i)+1) = C_i - cumsum(Da_i); - geo_strf_dyn_height(Ibdata,Iprofile) = D_i(Intrp(Iidata)); - - clear SA_i CT_i p_i + + B_i_av = 0.5*(B_i(1:(end-1)) + B_i(2:end)); + Da_i = (B_i_av.*diff(p_i).*db2Pa); + D_i(2:length(C_i)+1) = C_i - cumsum(Da_i); + geo_strf_dyn_height(Ibdata,Iprofile) = D_i(Iidata) - D_i(Ibpr); + clear SA_i CT_i p_i + end end end if transposed - geo_strf_dyn_height = geo_strf_dyn_height'; - in_funnel = in_funnel'; + geo_strf_dyn_height = geo_strf_dyn_height.'; end %if end @@ -304,12 +450,13 @@ % sdep - pressure to interpolate to. % OUTPUT: % sdat - interpolated values on at the required pressures. -% Jeff Dunn. Copyright CSIRO Division of Marine Research. +% AUTHOR: Jeff Dunn. %========================================================================== global rr_int_cnt lin_int_cnt dir_sub_cnt r_extrp_cnt; grad_lim = []; maxdis = rr_int([],[],sdep); +%keyboard odep = odep(:); obs = obs(:); sdep = sdep(:); @@ -320,7 +467,7 @@ far_lim = 2*near_lim; dir_lim = near_lim/5; sdat = repmat(NaN,nlvl,1); -jj = find(isnan(obs) | isnan(odep) | odep<0 | odep>8000); +jj = find(isnan(obs) | isnan(odep) | odep<0 | odep>12000); if ~isempty(jj) obs(jj) = []; odep(jj) = []; @@ -343,78 +490,78 @@ if ndeps < 4 | maxdis == -1 sidx = (1:nlvl)'; else - % RR INTERPOLATION + % Reiniger & Ross INTERPOLATION (Reiniger and Ross, 1968) sdat = rr_int(obs,odep,sdep,1,maxdis); sidx = find(isnan(sdat)); rr_int_cnt = rr_int_cnt + nlvl - length(sidx); end -if ~isempty(sidx) & ndeps >= 2 - idx = sidx(find(sdep(sidx)>odep(1) & sdep(sidx) 1.5 - jll = find(abs(odep-sdj) < far_lim(sidx(jj))); - if x > 0 - jll = flipud(jll); - end - if length(jll)<2 | max(abs(odep(jll)-odj)) < abs(x) - jll = []; - elseif any(abs(diff(odep(jll))) < 1.5) - ll = jll(1); - for mm = jll(2:end)' - if abs(odep(ll(end))-odep(mm))>1.5 & ... - (length(ll) < 4 | abs(odj-odep(mm)) < abs(x)) - ll = [ll mm]; - end - end - jll = ll; - end - if length(jll) >= 2 - if abs(max(obs(jll))-min(obs(jll)))<.005 - new = obs(jll(1)); - else - xog = min(odep(jll)); - cc = ([ones([length(jll) 1]) odep(jll)-xog]) \ obs(jll); - new = cc(1) + (sdj-xog)*cc(2); - end - r_extrp_cnt = r_extrp_cnt + 1; - if ~isempty(grad_lim) - ofset = abs(obs(idx(jj))-new); - if ofset>abs(x*grad_lim) | ofset>offlim - new = nan; - end - end - sdat(sidx(jj)) = new; - end - end - if isnan(new) & abs(x)= 2 +% idx = sidx(find(sdep(sidx)>odep(1) & sdep(sidx) 1.5 +% jll = find(abs(odep-sdj) < far_lim(sidx(jj))); +% if x > 0 +% jll = flipud(jll); +% end +% if length(jll)<2 | max(abs(odep(jll)-odj)) < abs(x) +% jll = []; +% elseif any(abs(diff(odep(jll))) < 1.5) +% ll = jll(1); +% for mm = jll(2:end)' +% if abs(odep(ll(end))-odep(mm))>1.5 & ... +% (length(ll) < 4 | abs(odj-odep(mm)) < abs(x)) +% ll = [ll mm]; +% end +% end +% jll = ll; +% end +% if length(jll) >= 2 +% if abs(max(obs(jll))-min(obs(jll)))<.005 +% new = obs(jll(1)); +% else +% xog = min(odep(jll)); +% cc = ([ones([length(jll) 1]) odep(jll)-xog]) \ obs(jll); +% new = cc(1) + (sdj-xog)*cc(2); +% end +% r_extrp_cnt = r_extrp_cnt + 1; +% if ~isempty(grad_lim) +% ofset = abs(obs(idx(jj))-new); +% if ofset>abs(x*grad_lim) | ofset>offlim +% new = nan; +% end +% end +% sdat(sidx(jj)) = new; +% end +% end +% if isnan(new) & abs(x) 180); -long2(Iwest2) = long2(Iwest2) - 360; +if ~isempty(Iwest2) + long2(Iwest2) = long2(Iwest2) - 360; +end mid_long2 = 0.5*(long2(:,1:ng-1) + long2(:,2:ng)); diff_long2 = (long2(1,1:ng-1) - long2(1,2:ng)); diff --git a/Toolbox/gsw_grav.m b/Toolbox/gsw_grav.m index 23eaa36..d1c8900 100644 --- a/Toolbox/gsw_grav.m +++ b/Toolbox/gsw_grav.m @@ -13,21 +13,21 @@ % INPUT: % lat = latitude in decimal degress north [ -90 ... +90 ] % -% Optional -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% Optional: +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % (If pressure is not given then it is assumed that pressure = 0 dbar.) % % p (if provided) may have dimensions 1x1 or Mx1 or 1xN or MxN, % where lat is MxN. % % OUTPUT: -% grav = gravitational acceleration [ m/s^2 ] +% grav = gravitational acceleration [ m s^-2 ] % % AUTHOR: -% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -48,7 +48,7 @@ %-------------------------------------------------------------------------- % Check variables and resize if necessary %-------------------------------------------------------------------------- -if ~(nargin==1 | nargin == 2) +if ~(nargin == 1 | nargin == 2) error('gsw_grav: Requires either one or two inputs, latitude and pressure') end %if @@ -60,35 +60,39 @@ [ml,nl] = size(lat); [mp,np] = size(p); -if ml==1 & nl==1 % lat is a scalar. Fill to size of p - lat = lat*ones(mp,np); -elseif nl==np & ml==1 % lat is row vector, +if (ml == 1) & (nl == 1) % lat is a scalar. Fill to size of p + lat = lat*ones(size(p)); +elseif (nl == np) & (ml == 1) % lat is row vector, lat = lat(ones(1,mp),:); % copy down each column. -elseif ml==mp & nl==1 % lat is column vector, +elseif (ml == mp) & (nl == 1) % lat is column vector, lat = lat(:,ones(1,np)); % copy across each row. -elseif ml==mp & nl==np +elseif (nl == mp) & (nl == 1) % p is a transposed row vector, + lat = lat.'; % transposed then + lat = lat(ones(1,mp), :); % copy down each column. +elseif (ml == mp) & (nl == np) % ok -% else -% error('gsw_grav: p has wrong dimensions') end %if [ml,nl] = size(lat); -if mp==1 & np==1 % p is a scalar. Fill to size of lat +if (mp == 1) & (np == 1) % p is a scalar. Fill to size of lat p = p(1)*ones(ml,nl); -elseif np==nl & mp==1 % p is row vector, +elseif (np == nl) & (mp == 1) % p is row vector, p = p(ones(1,ml),:); % copy down each column. -elseif mp==ml & np==1 % p is column vector, +elseif (mp == ml) & (np == 1) % p is column vector, p = p(:,ones(1,nl)); % copy across each row. -elseif mp==ml & np==nl +elseif (np == ml) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ml), :); % copy down each column. +elseif (mp == ml) & (np == nl) % ok else error('gsw_grav: p has wrong dimensions') end %if if ml == 1 - lat = lat'; - p = p'; + lat = lat.'; + p = p.'; transposed = 1; else transposed = 0; @@ -109,7 +113,7 @@ grav = gs.*(1 - gamma*z); % z is the height corresponding to p. % Note. In the ocean z is negative. if transposed - grav = grav'; + grav = grav.'; end end diff --git a/Toolbox/gsw_internal_energy.m b/Toolbox/gsw_internal_energy.m index 8fe66d3..7f2f1b6 100644 --- a/Toolbox/gsw_internal_energy.m +++ b/Toolbox/gsw_internal_energy.m @@ -1,37 +1,50 @@ -function internal_energy = gsw_internal_energy(SA,t,p) +function internal_energy = gsw_internal_energy(SA,CT,p) -% gsw_internal_energy specific internal energy of seawater +% gsw_internal_energy specific interal energy of seawater +% (48-term equation) %========================================================================== % % USAGE: -% internal_energy = gsw_internal_energy(SA,t,p) +% internal_energy = gsw_internal_energy(SA,CT,p) % % DESCRIPTION: -% Calculates the specific internal energy of seawater +% Calculates specific internal energy of seawater using the +% computationally-efficient 48-term expression for density in terms of SA, +% CT and p (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: % SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] +% CT = Conservative Temperature [ deg C ] % p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% ( i.e. absolute pressure - 10.1325 dbar ) % -% SA & t need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. % % OUTPUT: -% internal_energy (u) = specific internal energy [ J/kg ] +% internal_energy = specific internal energy [ J/kg ] % % AUTHOR: -% Trevor McDougall [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker. [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (22nd August, 2010) +% VERSION NUMBER: 3.0 (4th April, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of % seawater - 2010: Calculation and use of thermodynamic properties. % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See Eqn. (2.11.1) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -41,25 +54,27 @@ % Check variables and resize if necessary %-------------------------------------------------------------------------- -if ~(nargin==3) - error('gsw_internal_energy: Requires three inputs') -end %if +if ~(nargin == 3) + error('gsw_internal_energy: requires three inputs') +end [ms,ns] = size(SA); -[mt,nt] = size(t); +[mt,nt] = size(CT); [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_internal_energy: SA and t must have same dimensions') + error('gsw_internal_energy: SA and CT must have same dimensions') end - if (mp == 1) & (np == 1) % p scalar - fill to size of SA p = p*ones(size(SA)); elseif (ns == np) & (mp == 1) % p is row vector, p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else @@ -67,9 +82,9 @@ end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -79,16 +94,30 @@ % Start of the calculation %-------------------------------------------------------------------------- -db2Pa = 1e4; -n0 = 0; -n1 = 1; +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +P0 = 101325; % Pressure (in Pa) of one standard atmosphere +db2Pa = 1e+4; % dbar to Pa conversion factor + +enthalpy = gsw_enthalpy(SA,CT,p); +internal_energy = enthalpy - (P0 + db2Pa*p).*gsw_specvol(SA,CT,p); -internal_energy = gsw_gibbs(n0,n0,n0,SA,t,p) - ... - (273.15 + t).*gsw_gibbs(n0,n1,n0,SA,t,p) - ... - (db2Pa*p + 101325).*gsw_gibbs(n0,n0,n1,SA,t,p); +%-------------------------------------------------------------------------- +% This function calculates enthalpy using the computationally-efficient +% 48-term expression for density in terms of SA, CT and p. If one wanted to +% compute enthalpy from SA, CT, and p with the full TEOS-10 Gibbs function, +% the following line of code will enable this. +% +% internal_energy = gsw_internal_energy_CT_exact(SA,CT,p); +% +%-----------------This is the end of the alternative code------------------ if transposed - internal_energy = internal_energy'; + internal_energy = internal_energy.'; end -end \ No newline at end of file +end diff --git a/Toolbox/gsw_internal_energy_CT.m b/Toolbox/gsw_internal_energy_CT.m new file mode 100644 index 0000000..65d938d --- /dev/null +++ b/Toolbox/gsw_internal_energy_CT.m @@ -0,0 +1,109 @@ +function internal_energy_CT = gsw_internal_energy_CT(SA,CT,p) + +% gsw_internal_energy_CT specific interal energy of seawater +% (48-term equation) +%========================================================================== +% +% USAGE: +% internal_energy_CT = gsw_internal_energy_CT(SA,CT,p), or equivalently +% internal_energy = gsw_internal_energy(SA,CT,p) +% +% Note that gsw_internal_energy(SA,CT,p) is identical to +% gsw_internal_energy_CT(SA,CT,p). The extra "_CT" emphasises that the +% input temperature is Conservative Temperature, but the extra "_CT" part +% of the function name is not needed. +% +% DESCRIPTION: +% Calculates specific internal energy of seawater using the +% computationally-efficient 48-term expression for density in terms of SA, +% CT and p (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% internal_energy_CT = specific internal energy [ J/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker. [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (4th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_internal_energy_CT: requires three inputs') +end + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_internal_energy_CT: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_internal_energy_CT: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +internal_energy_CT = gsw_internal_energy(SA,CT,p); + +if transposed + internal_energy_CT = internal_energy_CT.'; +end + +end diff --git a/Toolbox/gsw_internal_energy_CT_exact.m b/Toolbox/gsw_internal_energy_CT_exact.m new file mode 100644 index 0000000..083adb7 --- /dev/null +++ b/Toolbox/gsw_internal_energy_CT_exact.m @@ -0,0 +1,92 @@ +function internal_energy_CT_exact = gsw_internal_energy_CT_exact(SA,CT,p) + +% gsw_internal_energy_CT_exact specific internal energy of seawater +%========================================================================== +% +% USAGE: +% internal_energy_CT_exact = gsw_internal_energy_CT_exact(SA,CT,p) +% +% DESCRIPTION: +% Calculates the specific internal energy of seawater from Absolute +% Salinity, Conservative Temperature and pressure. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% +% OUTPUT: +% internal_energy_CT_exact = specific internal energy (u) [ J/kg ] +% +% AUTHOR: +% Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (5th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (2.11.1) of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin==3) + error('gsw_internal_energy_CT_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_internal_energy_CT_exact: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_internal_energy_CT_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +t = gsw_t_from_CT(SA,CT,p); +internal_energy_CT_exact = gsw_internal_energy_t_exact(SA,t,p); + +if transposed + internal_energy_CT_exact = internal_energy_CT_exact.'; +end + +end \ No newline at end of file diff --git a/Toolbox/gsw_internal_energy_t_exact.m b/Toolbox/gsw_internal_energy_t_exact.m new file mode 100644 index 0000000..18a7883 --- /dev/null +++ b/Toolbox/gsw_internal_energy_t_exact.m @@ -0,0 +1,97 @@ +function internal_energy_t_exact = gsw_internal_energy_t_exact(SA,t,p) + +% gsw_internal_energy_t_exact specific internal energy of seawater +%========================================================================== +% +% USAGE: +% internal_energy_t_exact = gsw_internal_energy_t_exact(SA,t,p) +% +% DESCRIPTION: +% Calculates the specific internal energy of seawater. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & t need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% +% OUTPUT: +% internal_energy_t_exact = specific internal energy (u) [ J/kg ] +% +% AUTHOR: +% Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (2.11.1) of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin==3) + error('gsw_internal_energy_t_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_internal_energy_t_exact: SA and t must have same dimensions') +end + + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_internal_energy_t_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +db2Pa = 1e4; +n0 = 0; +n1 = 1; + +internal_energy_t_exact = gsw_gibbs(n0,n0,n0,SA,t,p) ... + - (273.15 + t).*gsw_gibbs(n0,n1,n0,SA,t,p) ... + - (db2Pa*p + 101325).*gsw_gibbs(n0,n0,n1,SA,t,p); + +if transposed + internal_energy_t_exact = internal_energy_t_exact.'; +end + +end \ No newline at end of file diff --git a/Toolbox/gsw_introduction.m b/Toolbox/gsw_introduction.m deleted file mode 100644 index 1f6a22a..0000000 --- a/Toolbox/gsw_introduction.m +++ /dev/null @@ -1,7 +0,0 @@ -function gsw_introduction - -% Front page to the Gibbs SeaWater (GSW) Oceanographic Toolbox of TEOS-10 - -showdemo gsw_introduction - -end \ No newline at end of file diff --git a/Toolbox/gsw_ionic_strength.m b/Toolbox/gsw_ionic_strength_from_SA.m similarity index 63% rename from Toolbox/gsw_ionic_strength.m rename to Toolbox/gsw_ionic_strength_from_SA.m index dee7a3d..9b29631 100644 --- a/Toolbox/gsw_ionic_strength.m +++ b/Toolbox/gsw_ionic_strength_from_SA.m @@ -1,13 +1,13 @@ -function ionic_strength = gsw_ionic_strength(SA) +function ionic_strength = gsw_ionic_strength_from_SA(SA) -% gsw_ionic_strength ionic strength of seawater +% gsw_ionic_strength_from_SA ionic strength of seawater %========================================================================== % % USAGE: -% ionic_strength = gsw_ionic_strength(SA) +% ionic_strength = gsw_ionic_strength_from_SA(SA) % % DESCRIPTION: -% Calculates the ionic strength of seawater +% Calculates the ionic strength of seawater from Absolute Salinity. % % INPUT: % SA = Absolute Salinity [ g/kg ] @@ -16,9 +16,9 @@ % ionic_strength = ionic strength of seawater [ mol/kg ] % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (28th September, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -41,23 +41,25 @@ %-------------------------------------------------------------------------- if ~(nargin == 1) - error('gsw_ionic_strength: Requires one input') + error('gsw_ionic_strength_from_SA: Requires one input') end %if %-------------------------------------------------------------------------- % Start of the calculation %-------------------------------------------------------------------------- -M_S = 0.0314038218; % mole-weighted average atomic weight of the elements -% of sea salt, in units of kg/mol. - -Z_2 = 1.2452898; % the valence factor of sea salt +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end -[Isalty] = find(SA >= 0); +M_S = 0.0314038218; % mole-weighted average atomic weight of the elements + % of sea salt, in units of kg/mol. -molality = nan(size(SA)); +Z_2 = 1.2452898; % the valence factor of sea salt -molality(Isalty) = SA(Isalty)./(M_S*(1000 - SA(Isalty))); % molality of seawater in mol/kg +molality = SA./(M_S*(1000 - SA)); % molality of seawater in mol/kg ionic_strength = 0.5*Z_2*molality; diff --git a/Toolbox/gsw_isochoric_heat_cap.m b/Toolbox/gsw_isochoric_heat_cap_t_exact.m similarity index 63% rename from Toolbox/gsw_isochoric_heat_cap.m rename to Toolbox/gsw_isochoric_heat_cap_t_exact.m index 97b9f84..8d4dff6 100644 --- a/Toolbox/gsw_isochoric_heat_cap.m +++ b/Toolbox/gsw_isochoric_heat_cap_t_exact.m @@ -1,30 +1,30 @@ -function isochoric_heat_cap = gsw_isochoric_heat_cap(SA,t,p) +function isochoric_heat_cap_t_exact = gsw_isochoric_heat_cap_t_exact(SA,t,p) -% gsw_isochoric_heat_cap isochoric heat capacity of seawater +% gsw_isochoric_heat_cap_t_exact isochoric heat capacity of seawater % ========================================================================= % % USAGE: -% isochoric_heat_cap = gsw_isochoric_heat_cap(SA,t,p) +% isochoric_heat_cap_t_exact = gsw_isochoric_heat_cap_t_exact(SA,t,p) % % DESCRIPTION: -% Calculates the isochoric heat capacity of seawater +% Calculates the isochoric heat capacity of seawater. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% isochoric_heat_cap = isochoric heat capacity [ J/(kg K) ] +% isochoric_heat_cap_t_exact = isochoric heat capacity [ J/(kg K) ] % % AUTHOR: -% Trevor McDougall [ help_gsw@csiro.au ] +% Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -42,7 +42,7 @@ %-------------------------------------------------------------------------- if ~(nargin==3) - error('gsw_isochoric_heat_cap: Requires three inputs') + error('gsw_isochoric_heat_cap_t_exact: Requires three inputs') end %if [ms,ns] = size(SA); @@ -50,7 +50,7 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_isochoric_heat_cap: SA and t must have same dimensions') + error('gsw_isochoric_heat_cap_t_exact: SA and t must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -60,18 +60,18 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_isochoric_heat_cap: Inputs array dimensions arguments do not agree') + error('gsw_isochoric_heat_cap_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -89,10 +89,10 @@ g_tp = gsw_gibbs(n0,n1,n1,SA,t,p); g_pp = gsw_gibbs(n0,n0,n2,SA,t,p); -isochoric_heat_cap = -(273.15 + t).*(g_tt - g_tp.*g_tp./g_pp); +isochoric_heat_cap_t_exact = -(273.15 + t).*(g_tt - g_tp.*g_tp./g_pp); if transposed - isochoric_heat_cap = isochoric_heat_cap'; + isochoric_heat_cap_t_exact = isochoric_heat_cap_t_exact.'; end end \ No newline at end of file diff --git a/Toolbox/gsw_isopycnal_slope_ratio.m b/Toolbox/gsw_isopycnal_slope_ratio.m new file mode 100644 index 0000000..a6b8c08 --- /dev/null +++ b/Toolbox/gsw_isopycnal_slope_ratio.m @@ -0,0 +1,152 @@ +function isopycnal_slope_ratio = gsw_isopycnal_slope_ratio(SA,CT,p,p_ref) + +% gsw_isopycnal_slope_ratio ratio of the slopes of isopycnals +% on the SA-CT diagram for p and p_ref +% (48-term equation) +% ========================================================================= +% +% USAGE: +% isopycnal_slope_ratio = gsw_isopycnal_slope_ratio(SA,CT,p,p_ref) +% +% DESCRIPTION: +% Calculates the ratio of alpha/beta at pressure, p, to that at reference +% pressure, p_ref. This function uses the computationally-efficient 48-term +% expression for density in terms of SA, CT & p (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% pr = reference pressure [ dbar ] +% ( i.e. absolute reference pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p and p_ref may have dimensions 1x1 or Mx1 or 1xN or MxN, where +% SA and CT are MxN +% +% OUTPUT: +% isopycnal_slope_ratio +% = The ratio of alpha/beta evaluated at [ unitless ] +% pressure, p, to that at reference pressure, p_ref. +% +% AUTHOR: +% Trevor McDougall, Paul Barker & David Jackett [ gsw_help@csiro.au ] +% +% VERSION NUMBER: 3.0 (26th March, 2011). +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. +% See Eqn. (3.17.2) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% This software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 4) + error('gsw_isopycnal_slope_ratio: Requires four inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); +[mpr,npr] = size(p_ref); + +if (mt ~= ms | nt ~= ns) + error('gsw_isopycnal_slope_ratio: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_isopycnal_slope_ratio: Inputs array dimensions arguments do not agree') +end %if + +if (mpr == 1) & (npr == 1) % p_ref scalar - fill to size of SA + p_ref = p_ref*ones(size(SA)); +elseif (ns == npr) & (mpr == 1) % p_ref is row vector, + p_ref = p_ref(ones(1,ms), :); % copy down each column. +elseif (ms == mpr) & (npr == 1) % p_ref is column vector, + p_ref = p_ref(:,ones(1,ns)); % copy across each row. +elseif (ns == mpr) & (npr == 1) % p_ref is a transposed row vector, + p_ref = p_ref.'; % transposed then + p_ref = p_ref(ones(1,ms), :); % copy down each column. +elseif (ms == mpr) & (ns == npr) + % ok +else + error('gsw_isopycnal_slope_ratio: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + p_ref = p_ref.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +[dummy, alpha, beta] = gsw_rho_alpha_beta(SA,CT,p); +[dummy, alpha_pref, beta_pref] = gsw_rho_alpha_beta(SA,CT,p_ref); + +%-------------------------------------------------------------------------- +% This function calculates isopycnal_slope_ratio using the computationally +% efficient 48-term expression for density as a function of SA, CT and p. +% If one wanted to compute this with the full TEOS-10 Gibbs function +% expression for density, the following lines of code will enable this. +% +% pt = gsw_pt_from_CT(SA,CT); +% p_ref0 = zeros(size(SA)); +% t = gsw_pt_from_t(SA,pt,pr0,p); +% alpha = gsw_alpha_wrt_CT_t_exact(SA,t,p); +% beta = gsw_beta_const_CT_t_exact(SA,t,p); +% tr = gsw_pt_from_t(SA,pt,p_ref0,p_ref); +% alpha_pref = gsw_alpha_wrt_CT_t_exact(SA,tr,p_ref); +% beta_pref = gsw_beta_const_CT_t_exact(SA,tr,p_ref); +% +%--------------This is the end of the alternative code--------------------- + +isopycnal_slope_ratio = nan(size(SA)); +[I] = find(alpha_pref ~= 0); +if ~isempty(I) + isopycnal_slope_ratio(I) = (alpha(I).*beta_pref(I))./ ... + (alpha_pref(I).*beta(I)); +end + +if transposed + isopycnal_slope_ratio = isopycnal_slope_ratio.'; +end + +end diff --git a/Toolbox/gsw_isopycnal_slope_ratio_CT25.m b/Toolbox/gsw_isopycnal_slope_ratio_CT25.m deleted file mode 100644 index 625e5ee..0000000 --- a/Toolbox/gsw_isopycnal_slope_ratio_CT25.m +++ /dev/null @@ -1,150 +0,0 @@ -function [isopycnal_slope_ratio_CT25, in_funnel] = gsw_isopycnal_slope_ratio_CT25(SA,CT,p,pr) - -% gsw_isopycnal_slope_ratio_CT25 ratio of the slopes of isopycnals -% on the SA-CT diagram for p and pr -% (25-term equation) -% ========================================================================= -% -% USAGE: -% [isopycnal_slope_ratio_CT25, in_funnel] = gsw_isopycnal_slope_ratio_CT25(SA,CT,p,pr) -% -% DESCRIPTION: -% Calculates the ratio of alpha_CT/beta_CT at pressure p to that at -% pressure pr. This function uses the computationally-efficient 25-term -% expression for density in terms of SA, CT & p (McDougall et al., 2010). -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) -% pr = reference pressure [ dbar ] -% (ie. absolute reference pressure - 10.1325 dbar) -% -% SA & CT need to have the same dimensions. -% p & pr may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN -% -% OUTPUT: -% isopycnal_slope_ratio_CT25 -% = The ratio of alpha_CT/beta_CT evaluated at -% pressure p to that at pressure pr. -% [ unitless ] -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). -% -% AUTHOR: -% Trevor McDougall, Paul Barker & David Jackett [ gsw_help@csiro.au ] -% -% VERSION NUMBER: 2.0 (26th August, 2010). -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. -% See Eqn. (3.17.2) of this TEOS-10 Manual. -% -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. -% -% This software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 4) - error('gsw_isopycnal_slope_ratio_CT25: Requires four inputs') -end %if - -[ms,ns] = size(SA); -[mt,nt] = size(CT); -[mp,np] = size(p); -[mpr,npr] = size(pr); - -if (mt ~= ms | nt ~= ns) - error('gsw_isopycnal_slope_ratio_CT25: SA and CT must have same dimensions') -end - -if (mp == 1) & (np == 1) % p scalar - fill to size of SA - p = p*ones(size(SA)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_isopycnal_slope_ratio_CT25: Inputs array dimensions arguments do not agree') -end %if - -if (mpr == 1) & (npr == 1) % pr scalar - fill to size of SA - pr = pr*ones(size(SA)); -elseif (ns == npr) & (mpr == 1) % pr is row vector, - pr = pr(ones(1,ms), :); % copy down each column. -elseif (ms == mpr) & (npr == 1) % pr is column vector, - pr = pr(:,ones(1,ns)); % copy across each row. -elseif (ms == mpr) & (ns == npr) - % ok -else - error('gsw_isopycnal_slope_ratio_CT25: Inputs array dimensions arguments do not agree') -end %if - -if ms == 1 - SA = SA'; - CT = CT'; - p = p'; - pr = pr'; - transposed = 1; -else - transposed = 0; -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -in_funnel = gsw_infunnel(SA,CT,p); - -[dummy, alpha_CT, beta_CT, dummy2] = gsw_rho_alpha_beta_CT25(SA,CT,p); -[dummy, alpha_CT_pr, beta_CT_pr, dummy2] = gsw_rho_alpha_beta_CT25(SA,CT,pr); - -%------------------------------------------------------------------------- -% This function calculates isopycnal_slope_ratio_CT25 using the -% computationally-efficient 25-term expression for density as a function of -% SA, CT and p. If one wanted to compute this with the full TEOS-10 Gibbs -% function expression for density, the following lines of code will enable -% this. -% -% pt = gsw_pt_from_CT(SA,CT); -% pr0 = zeros(size(SA)); -% t = gsw_pt_from_t(SA,pt,pr0,p); -% beta_CT = gsw_beta_const_CT(SA,t,p); -% alpha_CT = gsw_alpha_wrt_CT(SA,t,p); -% tr = gsw_pt_from_t(SA,pt,pr0,pr); -% beta_CT_pr = gsw_beta_const_CT(SA,tr,pr); -% alpha_CT_pr = gsw_alpha_wrt_CT(SA,tr,pr); -% -%--------------This is the end of the alternative code--------------------- - -isopycnal_slope_ratio_CT25 = nan(size(SA)); -[I] = find(alpha_CT_pr ~= 0); -if ~isempty(I) - isopycnal_slope_ratio_CT25 (I) = (alpha_CT(I).*beta_CT_pr(I))./ ... - (alpha_CT_pr(I).*beta_CT(I)); -end - -if transposed - isopycnal_slope_ratio_CT25 = isopycnal_slope_ratio_CT25'; - in_funnel = in_funnel'; -end - -end diff --git a/Toolbox/gsw_isopycnal_vs_ntp_CT_ratio.m b/Toolbox/gsw_isopycnal_vs_ntp_CT_ratio.m new file mode 100644 index 0000000..3dae9df --- /dev/null +++ b/Toolbox/gsw_isopycnal_vs_ntp_CT_ratio.m @@ -0,0 +1,181 @@ +function [G_CT, p_mid] = gsw_isopycnal_vs_ntp_CT_ratio(SA,CT,p,p_ref) + +% gsw_isopycnal_vs_ntp_CT_ratio ratio of the gradient of +% Conservative Temperature in a potential density surface +% to that in a neutral tangent plane (i.e. in a locally +% referenced potential density surface) (48-term equation) +%========================================================================== +% +% USAGE: +% [G_CT, p_mid] = gsw_isopycnal_vs_ntp_CT_ratio(SA,CT,p,p_ref) +% +% DESCRIPTION: +% Calculates the ratio of the two-dimensional gradient of Conservative +% Temperature in a potential density surface (with reference sea pressure +% (p_ref)) versus that in the neutral tangent plane (see Eqns. (3.17.3) +% and (3.17.4) of IOC et al. (2010)). This ratio has been called the +% "isopycnal Conservative Temperature gradient ratio". This ratio is +% evaluated at the mid pressure between the individual data points in the +% vertical. The reference sea pressure of the potential density surface +% must have a constant value. This function uses the computationally +% efficient 48-term expression for density in terms of SA, CT and p +% (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% p_ref = reference sea pressure of the potential density surface [ dbar ] +% ( i.e. absolute reference pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p & p_ref may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT +% are MxN +% +% OUTPUT: +% G_CT = the ratio of the gradient of CT in a potential density surface +% to that in a neutral tangent plane. G_CT is output on the +% same vertical (M-1)xN grid as p_mid, where M & N are the +% dimensions of SA. G_CT is dimensionless. [ unitless ] +% p_mid = mid pressure between the individual points of the p grid. +% That is, p_mid is on a (M-1)xN grid. +% p_mid has units of: [ dbar ] +% +% AUTHOR: +% Trevor McDougall, Paul Barker & David Jackett [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (23rd March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqns. (3.17.3) and (3.17.4) of this TEOS-10 Manual. +% +% McDougall, T. J., 1987: Neutral surfaces. Journal of Physical +% Oceanography, 17, 1950-1964. See Eqn. (29) of this paper. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3 | nargin == 4) + error('gsw_isopycnal_vs_ntp_CT_ratio: Requires three or four inputs') +end %if + +if ~(nargout == 2) + error('gsw_isopycnal_vs_ntp_CT_ratio: Requires two outputs') +end + +if nargin == 3 +% Assume reference pressure is 0 dbar. + p_ref = 0; +end %if + +if ~isscalar(unique(p_ref)) + error('gsw_isopycnal_vs_ntp_CT_ratio: The reference pressures differ, they should be unique') +end + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_isopycnal_vs_ntp_CT_ratio: SA and CT must have same dimensions, p can be a vector') +end + +if (ms*ns == 1) + error('gsw_isopycnal_vs_ntp_CT_ratio: There must be at least 2 values') +end + +if (mp == 1) & (np == 1) % p scalar - must be two bottles + error('gsw_isopycnal_vs_ntp_CT_ratio: There must be at least 2 values') +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_isopycnal_vs_ntp_CT_ratio: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + [mp,np] = size(p); + transposed = 1; +else + transposed = 0; +end + +p_ref = unique(p_ref)*ones(mp-1,np); %resize the reference pressure + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +Ishallow = 1:(mp-1); +Ideep = 2:mp; +p_mid = 0.5*(p(Ishallow,:) + p(Ideep,:)); +SA_mid = 0.5*(SA(Ishallow,:) + SA(Ideep,:)); +CT_mid = 0.5*(CT(Ishallow,:) + CT(Ideep,:)); + +dSA = SA(Ishallow,:) - SA(Ideep,:); +dCT = CT(Ishallow,:) - CT(Ideep,:); + +[dummy, alpha, beta] = gsw_rho_alpha_beta(SA_mid,CT_mid,p_mid); +[dummy, alpha_pref, beta_pref] = gsw_rho_alpha_beta(SA_mid,CT_mid,p_ref); + +%-------------------------------------------------------------------------- +% This function calculates G_CT using the computationally-efficient +% 48-term expression for density as a function of SA, CT and p. If one +% wanted to compute this with the full TEOS-10 Gibbs function expression +% for density, the following lines of code will enable this. +% +% pt_mid = gsw_pt_from_CT(SA_mid,CT_mid); +% pref0 = zeros(size(SA_mid)); +% t_mid = gsw_pt_from_t(SA_mid,pt_mid,pref0,p_mid); +% alpha = gsw_alpha_wrt_CT_t_exact(SA_mid,t_mid,p_mid); +% beta = gsw_beta_const_CT_t_exact(SA_mid,t_mid,p_mid); +% alpha_pref = gsw_alpha_wrt_CT_t_exact(SA_mid,t_mid,p_ref); +% beta_pref = gsw_beta_const_CT_t_exact(SA_mid,t_mid,p_ref); +% +%------------This is the end of the alternative code----------------------- + +numerator = dCT.*alpha./beta - dSA; +denominator = dCT.*alpha_pref./beta_pref - dSA; + +G_CT = nan(size(SA_mid)); +[I] = find(denominator ~= 0); +if ~isempty(I) + G_CT(I) = numerator(I)./denominator(I); +end + +if transposed + G_CT = G_CT.'; + p_mid = p_mid.'; +end + +end diff --git a/Toolbox/gsw_isopycnal_vs_ntp_CT_ratio_CT25.m b/Toolbox/gsw_isopycnal_vs_ntp_CT_ratio_CT25.m deleted file mode 100644 index d829fa4..0000000 --- a/Toolbox/gsw_isopycnal_vs_ntp_CT_ratio_CT25.m +++ /dev/null @@ -1,182 +0,0 @@ -function [G_CT, p_mid, in_funnel] = gsw_isopycnal_vs_ntp_CT_ratio_CT25(SA,CT,p,pr) - -% gsw_isopycnal_vs_ntp_CT_ratio_CT25 ratio of the gradient of -% Conservative Temperature in a potential density surface -% to that in a neutral tangent plane (i.e. in a locally -% referenced potential density surface) (25-term equation) -%========================================================================== -% -% USAGE: -% [G_CT, p_mid, in_funnel] = gsw_isopycnal_vs_ntp_CT_ratio_CT25(SA,CT,p,pr) -% -% DESCRIPTION: -% Calculates the ratio of the two-dimensional gradient of Conservative -% Temperature in a potential density surface (with reference sea pressure -% (pr)) versus that in the neutral tangent plane (see Eqns. (3.17.3) and -% (3.17.4) of IOC et al. (2010)). This ratio has been called the -% "isopycnal Conservative Temperature gradient ratio". This ratio is -% evaluated at the mid pressure between the individual data points in the -% vertical. The reference sea pressure of the potential density surface -% must have a constant value. This function uses the computationally -% efficient 25-term expression for density in terms of SA, CT and p -% (McDougall et al., 2010). -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) -% pr = reference sea pressure of the potential density surface -% (ie. absolute reference pressure - 10.1325 dbar) [ dbar ] -% -% SA & CT need to have the same dimensions. -% p & pr may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT -% are MxN -% -% OUTPUT: -% G_CT = the ratio of the gradient of CT in a potential density -% surface to that in a neutral tangent plane. -% G_CT is output on the same vertical (M-1)xN grid -% as p_mid, where M & N are the dimensions of SA. -% G_CT is dimensionless. [ unitless ] -% p_mid = mid pressure between the individual points of the p grid. -% That is, p_mid is on a (M-1)xN grid. -% p_mid has units of: [ dbar ] -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). -% -% AUTHOR: -% Trevor McDougall, Paul Barker & David Jackett [ help_gsw@csiro.au ] -% -% VERSION NUMBER: 2.0 (23rd August, 2010) -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See Eqns. (3.17.3) and (3.17.4) of this TEOS-10 Manual. -% -% McDougall, T. J., 1987: Neutral surfaces. Journal of Physical -% Oceanography, 17, 1950-1964. See Eqn. (29) of this paper. -% -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 3 | nargin == 4) - error('gsw_isopycnal_vs_ntp_CT_ratio_CT25: Requires three or four inputs') -end %if - -if ~(nargout == 2 | nargout == 3) - error('gsw_isopycnal_vs_ntp_CT_ratio_CT25: Requires two or three outputs') -end - -if nargin == 3 -% Assume reference pressure is 0 dbar. - pr = 0; -end %if - -if ~isscalar(unique(pr)) - error('gsw_IPV_vs_fNsquared_ratio_CT25: The reference pressures differ, they should be unique') -end - -[ms,ns] = size(SA); -[mt,nt] = size(CT); -[mp,np] = size(p); - -if (mt ~= ms | nt ~= ns) - error('SA and CT must have same dimensions, p can be a vector') -end - -if (ms*ns == 1) - error('There must be at least 2 values') -end - -if (mp == 1) & (np == 1) % p scalar - must be two bottles - error('There must be at least 2 values') -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_isopycnal_vs_ntp_CT_ratio_CT25: Inputs array dimensions arguments do not agree') -end %if - -if ms == 1 - SA = SA'; - CT = CT'; - p = p'; - [mp,np] = size(p); - transposed = 1; -else - transposed = 0; -end - -pr = unique(pr)*ones(mp-1,np); %resize the reference pressure - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -in_funnel = gsw_infunnel(SA,CT,p); - -Ishallow = 1:(mp-1); -Ideep = 2:mp; -p_mid = 0.5*(p(Ishallow,:) + p(Ideep,:)); -SA_mid = 0.5*(SA(Ishallow,:) + SA(Ideep,:)); -CT_mid = 0.5*(CT(Ishallow,:) + CT(Ideep,:)); - -dSA = SA(Ishallow,:) - SA(Ideep,:); -dCT = CT(Ishallow,:) - CT(Ideep,:); - -[dummy, alpha, beta, dummy2] = gsw_rho_alpha_beta_CT25(SA_mid,CT_mid,p_mid); -[dummy, alpha_pr, beta_pr, dummy2] = gsw_rho_alpha_beta_CT25(SA_mid,CT_mid,pr); - -%-------------------------------------------------------------------------- -% This function calculates G_CT using the computationally-efficient -% 25-term expression for density as a function of SA, CT and p. If one -% wanted to compute this with the full TEOS-10 Gibbs function expression -% for density, the following lines of code will enable this. -% -% pt_mid = gsw_pt_from_CT(SA_mid,CT_mid); -% pr0 = zeros(size(SA_mid)); -% t_mid = gsw_pt_from_t(SA_mid,pt_mid,pr0,p_mid); -% beta = gsw_beta_const_CT(SA_mid,t_mid,p_mid); -% alpha = gsw_alpha_wrt_CT(SA_mid,t_mid,p_mid); -% beta_pr = gsw_beta_const_CT(SA_mid,t_mid,pr); -% alpha_pr = gsw_alpha_wrt_CT(SA_mid,t_mid,pr); -% -%------------This is the end of the alternative code----------------------- - -anum = dCT.*alpha./beta - dSA; -adenom = dCT.*alpha_pr./beta_pr - dSA; - -G_CT = nan(size(SA_mid)); -[I] = find(adenom ~= 0); -if ~isempty(I) - G_CT(I) = anum(I)./adenom(I); -end - -if transposed - G_CT = G_CT'; - p_mid = p_mid'; - in_funnel = in_funnel'; -end - -end diff --git a/Toolbox/gsw_kappa_const_t.m b/Toolbox/gsw_kappa_const_t_exact.m similarity index 65% rename from Toolbox/gsw_kappa_const_t.m rename to Toolbox/gsw_kappa_const_t_exact.m index 4947727..4650509 100644 --- a/Toolbox/gsw_kappa_const_t.m +++ b/Toolbox/gsw_kappa_const_t_exact.m @@ -1,10 +1,10 @@ -function kappa_const_t = gsw_kappa_const_t(SA,t,p) +function kappa_const_t_exact = gsw_kappa_const_t_exact(SA,t,p) -% gsw_kappa_const_t isothermal compressibility +% gsw_kappa_const_t_exact isothermal compressibility %========================================================================== % % USAGE: -% kappa_const_t = gsw_kappa_const_t(SA,t,p) +% kappa_const_t_exact = gsw_kappa_const_t_exact(SA,t,p) % % DESCRIPTION: % Calculates isothermal compressibility of seawater. @@ -12,22 +12,22 @@ % TEMPERATURE % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% kappa_const_t = Isothermal compressibility [ 1/Pa ] -% Note. The output units are 1/Pa not 1/dbar. +% kappa_const_t_exact = isothermal compressibility [ 1/Pa ] +% Note. The output units are 1/Pa not 1/dbar. % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -45,7 +45,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_kappa_const_t: Requires three inputs') + error('gsw_kappa_const_t_exact: Requires three inputs') end %if [ms,ns] = size(SA); @@ -53,7 +53,7 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_kappa_const_t: SA and t must have same dimensions') + error('gsw_kappa_const_t_exact: SA and t must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -63,18 +63,18 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_kappa_const_t: Inputs array dimensions arguments do not agree') + error('gsw_kappa_const_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -88,10 +88,10 @@ n1 = 1; n2 = 2; -kappa_const_t = - gsw_gibbs(n0,n0,n2,SA,t,p)./gsw_gibbs(n0,n0,n1,SA,t,p); +kappa_const_t_exact = -gsw_gibbs(n0,n0,n2,SA,t,p)./gsw_gibbs(n0,n0,n1,SA,t,p); if transposed - kappa_const_t = kappa_const_t'; + kappa_const_t_exact = kappa_const_t_exact.'; end end \ No newline at end of file diff --git a/Toolbox/gsw_kappa.m b/Toolbox/gsw_kappa_t_exact.m similarity index 60% rename from Toolbox/gsw_kappa.m rename to Toolbox/gsw_kappa_t_exact.m index bfc4fd1..5ba4df8 100644 --- a/Toolbox/gsw_kappa.m +++ b/Toolbox/gsw_kappa_t_exact.m @@ -1,31 +1,31 @@ -function kappa = gsw_kappa(SA,t,p) +function kappa_t_exact = gsw_kappa_t_exact(SA,t,p) -% gsw_kappa isentropic compressibility +% gsw_kappa_t_exact isentropic compressibility %========================================================================== % % USAGE: -% kappa = gsw_kappa(SA,t,p) +% kappa_t_exact = gsw_kappa_t_exact(SA,t,p) % % DESCRIPTION: -% Calculates the isentropic compressibility of seawater +% Calculates the isentropic compressibility of seawater. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% kappa = Isentropic compressibility [ 1/Pa ] +% kappa_t_exact = isentropic compressibility [ 1/Pa ] % Note. The output units are 1/Pa not 1/dbar. % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (23rd March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -33,7 +33,7 @@ % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See Eqns. (2.16.1) and the row for kappa in Table P.1 of appendix P -% of this TEOS-10 Manual. +% of this TEOS-10 Manual. % % The software is available from http://www.TEOS-10.org % @@ -44,7 +44,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_kappa: Requires three inputs') + error('gsw_kappa_t_exact: Requires three inputs') end %if [ms,ns] = size(SA); @@ -52,7 +52,7 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_kappa: SA and t must have same dimensions') + error('gsw_kappa_t_exact: SA and t must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -61,16 +61,19 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_kappa: Inputs array dimensions arguments do not agree') + error('gsw_kappa_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -87,11 +90,11 @@ g_tt = gsw_gibbs(n0,n2,n0,SA,t,p); g_tp = gsw_gibbs(n0,n1,n1,SA,t,p); -kappa = (g_tp.*g_tp - g_tt.*gsw_gibbs(n0,n0,n2,SA,t,p))./ ... - (gsw_gibbs(n0,n0,n1,SA,t,p).*g_tt); +kappa_t_exact = (g_tp.*g_tp - g_tt.*gsw_gibbs(n0,n0,n2,SA,t,p))./ ... + (gsw_gibbs(n0,n0,n1,SA,t,p).*g_tt); if transposed - kappa = kappa'; + kappa_t_exact = kappa_t_exact.'; end end \ No newline at end of file diff --git a/Toolbox/gsw_latentheat_evap_CT.m b/Toolbox/gsw_latentheat_evap_CT.m new file mode 100644 index 0000000..98ea7fa --- /dev/null +++ b/Toolbox/gsw_latentheat_evap_CT.m @@ -0,0 +1,110 @@ +function latentheat_evap_CT = gsw_latentheat_evap_CT(SA,CT) + +% gsw_latentheat_evap_CT latent heat of evaporation +%========================================================================== +% +% USAGE: +% latentheat_evap_CT = gsw_latentheat_evap_CT(SA,CT) +% +% DESCRIPTION: +% Calculates latent heat, or enthalpy, of evaporation at p = 0 (the +% surface). It is defined as a function of Absolute Salinity, SA, and +% Conservative Temperature, CT, and is valid in the ranges +% 0 < SA < 42 g/kg and 0 < CT < 40 deg C. The errors range between +% -0.4 and 0.6 J/kg. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% +% SA & CT need to have the same dimensions. +% +% OUTPUT: +% latentheat_evap_CT = latent heat of evaporation [ J/kg ] +% +% AUTHOR: +% Paul Barker, Trevor McDougall & Rainer Feistel [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 3.39 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_latentheat_evap_CT: Requires two input arguments') +end %if +[ms,ns] = size(SA); +[mt,nt] = size(CT); + +if (mt ~= ms | nt ~= ns) + error('gsw_latentheat_evap_CT: SA and CT must have same dimensions') +end + +if ms == 1 + SA = SA.'; + CT = CT.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +c0 = 2.499065844825125e6; +c1 = -1.544590633515099e-1; +c2 = -9.096800915831875e4; +c3 = 1.665513670736000e2; +c4 = 4.589984751248335e1; +c5 = 1.894281502222415e1; +c6 = 1.192559661490269e3; +c7 = -6.631757848479068e3; +c8 = -1.104989199195898e2; +c9 = -1.207006482532330e3; +c10 = -3.148710097513822e3; +c11 = 7.437431482069087e2; +c12 = 2.519335841663499e3; +c13 = 1.186568375570869e1; +c14 = 5.731307337366114e2; +c15 = 1.213387273240204e3; +c16 = 1.062383995581363e3; +c17 = -6.399956483223386e2; +c18 = -1.541083032068263e3; +c19 = 8.460780175632090e1; +c20 = -3.233571307223379e2; +c21 = -2.031538422351553e2; +c22 = 4.351585544019463e1; +c23 = -8.062279018001309e2; +c24 = 7.510134932437941e2; +c25 = 1.797443329095446e2; +c26 = -2.389853928747630e1; +c27 = 1.021046205356775e2; + +S_u = 40*(35.16504/35); +x = sqrt(SA./S_u); +y = CT./40; + +latentheat_evap_CT = c0 + x.*(c1 + c4*y + x.*(c3 ... + + y.*(c7 + c12*y) + x.*(c6 + y.*(c11 + y.*(c17 + c24*y)) ... + + x.*(c10 + y.*(c16 + c23*y) + x.*(c15 + c22*y + c21*x))))) ... + + y.*(c2 + y.*(c5 + c8*x + y.*(c9 + x.*(c13 + c18*x) ... + + y.*(c14 + x.*(c19 + c25*x) + y.*(c20 + c26*x + c27*y))))); + +if transposed + latentheat_evap_CT = latentheat_evap_CT.'; +end + +end diff --git a/Toolbox/gsw_latentheat_evap_t.m b/Toolbox/gsw_latentheat_evap_t.m new file mode 100644 index 0000000..b892070 --- /dev/null +++ b/Toolbox/gsw_latentheat_evap_t.m @@ -0,0 +1,75 @@ +function latentheat_evap_t = gsw_latentheat_evap_t(SA,t) + +% gsw_latentheat_evap_t latent heat of evaporation +%========================================================================== +% +% USAGE: +% latentheat_evap_t = gsw_latentheat_evap_t(SA,t) +% +% DESCRIPTION: +% Calculates latent heat, or enthalpy, of evaporation at p = 0 (the +% surface). It is defined as a function of Absolute Salinity, SA, and +% in-situ temperature, t, and is valid in the ranges 0 < SA < 40 g/kg +% and 0 < CT < 42 deg C. The errors range between -0.4 and 0.6 J/kg. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% +% SA & CT need to have the same dimensions. +% +% OUTPUT: +% latentheat_evap_t = latent heat of evaporation [ J/kg ] +% +% AUTHOR: +% Paul Barker, Trevor McDougall & Rainer Feistel [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 3.39 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_latentheat_evap_t: Requires two input arguments') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(t); + +if (mt ~= ms | nt ~= ns) + error('gsw_latentheat_evap_t: SA and t must have same dimensions') +end + +if ms == 1 + SA = SA.'; + t = t.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +CT = gsw_CT_from_pt(SA,t); + +latentheat_evap_t = gsw_latentheat_evap_CT(SA,CT); + +if transposed + latentheat_evap_t = latentheat_evap_t.'; +end + +end diff --git a/Toolbox/gsw_latentheat_melting.m b/Toolbox/gsw_latentheat_melting.m new file mode 100644 index 0000000..a5cce30 --- /dev/null +++ b/Toolbox/gsw_latentheat_melting.m @@ -0,0 +1,117 @@ +function latentheat_melting = gsw_latentheat_melting(SA,p) + +% gsw_latentheat_melting latent heat of melting +%========================================================================== +% +% USAGE: +% latentheat_melting = gsw_latentheat_melting(SA,p) +% +% DESCRIPTION: +% Calculates latent heat, or enthalpy, of melting. It is defined in terms +% of Absolute Salinity, SA, and sea pressure, p, and is valid in the +% ranges 0 < SA < 42 g kg^-1 and 0 < p < 10,000 dbar. The errors range +% between -0.4 and 0.3 J kg^-1. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & p need to have the same dimensions. +% +% OUTPUT: +% latentheat_melting = latent heat of melting [ J/kg ] +% +% AUTHOR: +% Paul Barker, Trevor McDougall & Rainer Feistel [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 3.34 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_latentheat_melting: Requires two input arguments') +end %if + +[ms,ns] = size(SA); +[mp,np] = size(p); + +if (mp ~= ms | np ~= ns) + error('gsw_latentheat_melting: SA and p must have same dimensions') +end + +if ms == 1 + SA = SA.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +c0 = 3.334265169240710e5; +c1 = -2.789444646733159; +c2 = -1.822150156453350e4; +c3 = -4.984585692734338e3; +c4 = -7.371966528571920e1; +c5 = -7.605802553358546e3; +c6 = 1.195857305019339e3; +c7 = 1.233720336206392e3; +c8 = 2.294798676591890e2; +c9 = 9.655751370889338e2; +c10 = -5.792068522727968e2; +c11 = -1.649446955902331e3; +c12 = -1.029021448430547e3; +c13 = -3.171558017172501e2; +c14 = -1.751401389905041e2; +c15 = 6.836527214265952e2; +c16 = 1.078283734113611e3; +c17 = 5.613896351265648e2; +c18 = 6.968934948667265e2; +c19 = 1.793032021946783e2; +c20 = 8.692558481134256e1; +c21 = -2.371103254714944e2; +c22 = -5.775033277201674e2; +c23 = -3.019749254648732e2; +c24 = -6.420420579160927e2; +c25 = -2.657570848596042e2; +c26 = -1.646738151143109e1; +c27 = 4.618228988300871; + +S_u = 40*(35.16504/35); +x = sqrt(SA./S_u); +y = p.*1e-4; + +latentheat_melting = c0 + x.*(c1 + c4*y + x.*(c3 ... + + y.*(c7 + c12*y) + x.*(c6 + y.*(c11 + y.*(c17 + c24*y)) ... + + x.*(c10 + y.*(c16 + c23*y) + x.*(c15 + c22*y + c21*x))))) ... + + y.*(c2 + y.*(c5 + c8*x + y.*(c9 + x.*(c13 + c18*x) ... + + y.*(c14 + x.*(c19 + c25*x) + y.*(c20 + c26*x + c27*y))))); + +% Note that the computed latent heat of melting from this function has +% errors which range between -0.4 and 0.3 J kg^-1, when compared with the +% latent heats of melting derived from the Gibbs functions of ice and of +% seawater (using the SIA code of TEOS-10), however, the underlying data to +% the Gibbs function contains uncertainities of 200 J kg^-1 (IOC et al., 2010). + +if transposed + latentheat_melting = latentheat_melting.'; +end + +end diff --git a/Toolbox/gsw_licence.m b/Toolbox/gsw_licence.m deleted file mode 100644 index 371b3ad..0000000 --- a/Toolbox/gsw_licence.m +++ /dev/null @@ -1,26 +0,0 @@ -function gsw_licence - -% The Gibbs SeaWater (GSW) Oceanographic Toolbox of TEOS-10 is distributed -% under a "creative commons" licence which is available as an attached -% document. -% -% In summary, the computer software comes with no warranty of any kind, -% and it is to be used on an "as is" basis. The software -% -% (1) may not be changed in any way, -% (2) it may used for commercial purposes, and -% (3) it may be forwarded to third parties, -% -% so long as the software toolbox remains called the "Gibbs SeaWater (GSW) -% Oceanographic Toolbox" and so long as it is acknowledged as such in works -% resulting from its use. -% -% That is, this licence lets others distribute, display and perform -% only verbatim copies of this software. They may not adapt or change the work -% in any way. Any variation of these conditions must be confirmed in writing -% after enquiring to [ help_gsw@csiro.au ]. -% - -help gsw_licence - -end diff --git a/Toolbox/gsw_molality_from_SA.m b/Toolbox/gsw_molality_from_SA.m new file mode 100644 index 0000000..1be7576 --- /dev/null +++ b/Toolbox/gsw_molality_from_SA.m @@ -0,0 +1,62 @@ +function molality = gsw_molality_from_SA(SA) + +% gsw_molality_from_SA molality of seawater +%========================================================================== +% +% USAGE: +% molality = gsw_molality_from_SA(SA) +% +% DESCRIPTION: +% Calculates the molality of seawater from Absolute Salinity. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% +% OUTPUT: +% molality = molality of seawater [ mol/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 1) + error('gsw_molality_from_SA: Requires just one input') +end %if + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +M_S = 0.0314038218; % mole-weighted average atomic weight of the elements + % of Reference-Composition sea salt, in units of + % kg mol^-1. Strictly speaking, the formula below + % applies only to seawater of Reference Composition. + % If molality is required to an accuracy of better + % than 0.1% we suggest you contact the authors for + % further guidance. + + +molality = SA./(M_S*(1000 - SA)); % molality of seawater in mol kg^-1 + +end diff --git a/Toolbox/gsw_ntp_pt_vs_CT_ratio.m b/Toolbox/gsw_ntp_pt_vs_CT_ratio.m new file mode 100644 index 0000000..8d7422e --- /dev/null +++ b/Toolbox/gsw_ntp_pt_vs_CT_ratio.m @@ -0,0 +1,130 @@ +function ntp_pt_vs_CT_ratio = gsw_ntp_pt_vs_CT_ratio(SA,CT,p) + +% gsw_ntp_pt_vs_CT_ratio ratio of gradients of potential +% temperature and Conservative Temperature in a +% neutral tangent plane (in a locally-referenced +% potential density surface)(48-term equation) +% ========================================================================= +% +% USAGE: +% ntp_pt_vs_CT_ratio = gsw_ntp_pt_vs_CT_ratio(SA,CT,p) +% +% DESCRIPTION: +% Calculates the ratio of the two-dimensional gradient of potential +% temperature versus that of Conservative Temperature, CT, along the +% neutral tangent plane. The potential temperature is the regular one +% which has a reference sea pressure of 0 dbar. Part of the calculation +% uses the computationally-efficient 48-term expression for density in +% terms of SA, CT and p (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% ntp_pt_vs_CT_ratio = The ratio of the spatial gradient of +% potential temperature versus that of +% Conservative Temperature in the +% neutral tangent plane (ntp). [ unitless ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ gsw_help@csiro.au ] +% +% VERSION NUMBER: 3.0 (23rd March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. +% See Eqn. (A.14.5) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% This software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_ntp_pt_vs_CT_ratio: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_ntp_pt_vs_CT_ratio: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_ntp_pt_vs_CT_ratio: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +[dummy, alpha, beta] = gsw_rho_alpha_beta(SA,CT,p); + +%-------------------------------------------------------------------------- +% This function calculates the ntp_pt_vs_CT_ratio using the computationally +% efficient 48-term expression for density in terms of SA, CT and p. If +% one wanted to compute this with the full TEOS-10 Gibbs function +% expression for density, the following lines of code will enable this. +% +% pt = gsw_pt_from_CT(SA,CT); +% pref0 = zeros(size(SA)); +% t = gsw_pt_from_t(SA,pt,pref0,p); +% beta = gsw_beta_const_CT_t_exact(SA,t,p); +% alpha = gsw_alpha_wrt_CT_t_exact(SA,t,p); +% +%--------- This is the end of the alternative code------------------------- + +[pt_SA, pt_CT] = gsw_pt_first_derivatives(SA,CT); + +ntp_pt_vs_CT_ratio = pt_CT + pt_SA.*(alpha./beta); + +if transposed + ntp_pt_vs_CT_ratio = ntp_pt_vs_CT_ratio.'; +end + +end diff --git a/Toolbox/gsw_ntp_pt_vs_CT_ratio_CT25.m b/Toolbox/gsw_ntp_pt_vs_CT_ratio_CT25.m deleted file mode 100644 index 1233302..0000000 --- a/Toolbox/gsw_ntp_pt_vs_CT_ratio_CT25.m +++ /dev/null @@ -1,131 +0,0 @@ -function [ntp_pt_vs_CT_ratio_CT25, in_funnel] = gsw_ntp_pt_vs_CT_ratio_CT25(SA,CT,p) - -% gsw_ntp_pt_vs_CT_ratio_CT25 ratio of gradients of potential -% temperature and Conservative Temperature in a -% neutral tangent plane (in a locally-referenced -% potential density surface)(25-term equation) -% ========================================================================= -% -% USAGE: -% [ntp_pt_vs_CT_ratio_CT25, in_funnel] = gsw_ntp_pt_vs_CT_ratio_CT25(SA,CT,p) -% -% DESCRIPTION: -% Calculates the ratio of the two-dimensional gradient of potential -% temperature versus that of Conservative Temperature, CT, along the -% neutral tangent plane. The potential temperature is the regular one -% which has a reference sea pressure of 0 dbar. Part of the calculation -% uses the computationally-efficient 25-term expression for density in -% terms of SA, CT and p (McDougall et al., 2010). -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) -% -% SA & CT need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. -% -% OUTPUT: -% ntp_pt_vs_CT_ratio_CT25 = The ratio of the spatial gradient of -% potential temperature versus that of -% Conservative Temperature in the -% neutral tangent plane (ntp). [ unitless ] -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). -% -% AUTHOR: -% Trevor McDougall and Paul Barker [ gsw_help@csiro.au ] -% -% VERSION NUMBER: 2.0 (26th August, 2010) -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. -% See Eqn. (A.14.5) of this TEOS-10 Manual. -% -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. -% -% This software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 3) - error('gsw_ntp_pt_vs_CT_ratio_CT25: Requires three inputs') -end %if - -[ms,ns] = size(SA); -[mt,nt] = size(CT); -[mp,np] = size(p); - -if (mt ~= ms | nt ~= ns) - error('gsw_ntp_pt_vs_CT_ratio_CT25: SA and CT must have same dimensions') -end - -if (mp == 1) & (np == 1) % p scalar - fill to size of SA - p = p*ones(size(SA)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_ntp_pt_vs_CT_ratio_CT25: Inputs array dimensions arguments do not agree') -end %if - -if ms == 1 - SA = SA'; - CT = CT'; - p = p'; - transposed = 1; -else - transposed = 0; -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -in_funnel = gsw_infunnel(SA,CT,p); - -[dummy, alpha_CT, beta_CT, dummy2] = gsw_rho_alpha_beta_CT25(SA,CT,p); - -%-------------------------------------------------------------------------- -% This function calculates the ntp_pt_vs_CT_ratio_CT25 using the -% computationally-efficient 25-term expression for density in terms of SA, -% CT and p. If one wanted to compute this with the full TEOS-10 Gibbs -% function expression for density, the following lines of code will enable -% this. -% -% pt = gsw_pt_from_CT(SA,CT); -% pr0 = zeros(size(SA)); -% t = gsw_pt_from_t(SA,pt,pr0,p); -% beta_CT = gsw_beta_const_CT(SA,t,p); -% alpha_CT = gsw_alpha_wrt_CT(SA,t,p); -% -%--------- This is the end of the alternative code------------------------- - -[pt_SA, pt_CT] = gsw_pt_first_derivatives(SA,CT); - -ntp_pt_vs_CT_ratio_CT25 = pt_CT + pt_SA.*(alpha_CT./beta_CT); - -if transposed - ntp_pt_vs_CT_ratio_CT25 = ntp_pt_vs_CT_ratio_CT25'; - in_funnel = in_funnel'; -end - -end diff --git a/Toolbox/gsw_osmotic_coefficient.m b/Toolbox/gsw_osmotic_coefficient.m deleted file mode 100644 index 3a3ca1a..0000000 --- a/Toolbox/gsw_osmotic_coefficient.m +++ /dev/null @@ -1,108 +0,0 @@ -function osmotic_coefficient = gsw_osmotic_coefficient(SA,t,p) - -% gsw_osmotic_coefficient osmotic coefficient -%========================================================================== -% -% USAGE: -% osmotic_coefficient = gsw_osmotic_coefficient(SA,t,p) -% -% DESCRIPTION: -% Calculates the osmotic coefficient of seawater -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) -% -% SA & t need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. -% -% OUTPUT: -% osmotic coefficient = osmotic coefficient of seawater [ unitless ] -% -% AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] -% -% VERSION NUMBER: 2.0 (28th September, 2010) -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 3) - error('gsw_osmotic_coefficient: Requires three inputs') -end %if - -[ms,ns] = size(SA); -[mt,nt] = size(t); -[mp,np] = size(p); - -if (mt ~= ms | nt ~= ns) - error('gsw_osmotic_coefficient: SA and t must have same dimensions') -end - -if (mp == 1) & (np == 1) % p is a scalar - fill to size of SA - p = p*ones(size(SA)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_osmotic_coefficient: Inputs array dimensions arguments do not agree') -end %if - -if ms == 1 - SA = SA'; - t = t'; - p = p'; - transposed = 1; -else - transposed = 0; -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -n0 = 0; - -R = 8.314472; % molar gas constant - -M_S = 0.0314038218; % mole-weighted average atomic weight of the elements - % of sea salt, in units of kg/mol. -[Isalty] = find(SA >= 0); - -molality = nan(size(SA)); - -molality(Isalty) = SA(Isalty)./(M_S*(1000 - SA(Isalty))); % molality of seawater in mol/kg - -part = molality.*R.*(273.15 + t); - -SAzero = zeros(size(SA)); -[Inn] = find(~isnan(SA) & ~isnan(t) & ~isnan(p) & ~isnan(part) & part ~= 0); -osmotic_coefficient = nan(size(SA)); - -osmotic_coefficient(Inn) = (gsw_gibbs(n0,n0,n0,SAzero(Inn),t(Inn),p(Inn)) - ... - gsw_chem_potential_water(SA(Inn),t(Inn),p(Inn)))./part(Inn); - -if transposed - osmotic_coefficient = osmotic_coefficient'; -end - -end diff --git a/Toolbox/gsw_osmotic_coefficient_t_exact.m b/Toolbox/gsw_osmotic_coefficient_t_exact.m new file mode 100644 index 0000000..a0d2092 --- /dev/null +++ b/Toolbox/gsw_osmotic_coefficient_t_exact.m @@ -0,0 +1,164 @@ +function osmotic_coefficient_t_exact = gsw_osmotic_coefficient_t_exact(SA,t,p) + +% gsw_osmotic_coefficient_t_exact osmotic coefficient +%========================================================================== +% +% USAGE: +% osmotic_coefficient_t_exact = gsw_osmotic_coefficient_t_exact(SA,t,p) +% +% DESCRIPTION: +% Calculates the osmotic coefficient of seawater. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & t need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% +% OUTPUT: +% osmotic_coefficient_t_exact = osmotic coefficient of seawater +% [ unitless ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (1st April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_osmotic_coefficient_t_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_osmotic_coefficient_t_exact: SA and t must have same dimensions') +end + +if (mp == 1) & (np == 1) % p is a scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_osmotic_coefficient_t_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +%R = 8.314472; % molar gas constant + + +%M_S = 0.0314038218; % mole-weighted average atomic weight of the elements + % of Reference-Composition sea salt, in units of + % kg mol^-1. Strictly speaking, the formula below + % applies only to seawater of Reference Composition. + % If molality and the osmotic coefficienit is + % required to an accuracy of better than 0.1% we + % suggest you contact the authors for further + % guidance. + + +k = 3.777007343340624e-3; % k = M_S/R + +part = k.*(1000 - SA)./(273.15 + t); + +sfac = 0.0248826675584615; % sfac = 1/(40*(35.16504/35)). + +x2 = sfac.*SA; +x = sqrt(x2); +y = t.*0.025; +z = p.*1e-4; %Note that the input pressure (p) is sea pressure in units of dbar. + +oc01 = 7.231916621570606e1; +oc02 = 1.059039593127674e1; +oc03 = -3.025914794694813e1; +oc04 = 5.040733670521486e1; +oc05 = -4.074543321119333e1; +oc06 = 1.864215613820487e1; +oc07 = -3.022566485046178; +oc08 = -6.138647522851840; +oc09 = 1.353207379758663e1; +oc10 = -7.316560781114737; +oc11 = 1.829232499785750; +oc12 = -5.358042980767074e-1; +oc13 = -1.705887283375562; +oc14 = -1.246962174707332e-1; +oc15 = 1.228376913546017; +oc16 = 1.089364009088042e-2; +oc17 = -4.264828939262248e-1; +oc18 = 6.213127679460041e-2; +oc19 = 2.481543497315280; +oc20 = -1.363368964861909; +oc21 = -5.640491627443773e-1; +oc22= 1.344724779893754; +oc23 = -2.180866793244492; +oc24 = 4.765753255963401; +oc25 = -5.726993916772165; +oc26 = 2.918303792060746; +oc27 = -6.506082399183509e-1; +oc28 = -1.015695507663942e-1; +oc29 = 1.035024326471108; +oc30 = -6.742173543702397e-1; +oc31 = 8.465642650849419e-1; +oc32 = -7.508472135244717e-1; +oc33 = -3.668086444057845e-1; +oc34 = 3.189939162107803e-1; +oc35 = -4.245629194309487e-2; + +tl = oc01 + oc02*y ... + + x.*(oc03 + x.*(oc04 + x.*(oc05 + x.*(oc06 + oc07*x))) ... + + y.*(oc08 + x.*(oc09 + x.*(oc10 + oc11*x))... + + y.*(oc12 + oc13*x + y.*(oc14 + oc15*x + y.*(oc16 + x.*(oc17 + oc18*y))))) ... + + z.*(oc19 + x.*(oc20 + oc21*y + oc22*x) + y.*(oc23 + y.*(oc24 + y.*(oc25 + oc26*y))) ... + + z.*(oc27 + oc28*x + y.*(oc29 + oc30*y) ... + + z.*(oc31 + oc32*x + y.*(oc33 + oc34*y) + oc35*z)))); + +osmotic_coefficient_t_exact = tl.*part; + +if transposed + osmotic_coefficient_t_exact = osmotic_coefficient_t_exact.'; +end + +end diff --git a/Toolbox/gsw_osmotic_pressure_t_exact.m b/Toolbox/gsw_osmotic_pressure_t_exact.m new file mode 100644 index 0000000..8feabff --- /dev/null +++ b/Toolbox/gsw_osmotic_pressure_t_exact.m @@ -0,0 +1,116 @@ +function osmotic_pressure_t_exact = gsw_osmotic_pressure_t_exact(SA,t,pw) + +% gsw_osmotic_pressure_t_exact osmotic pressure +%========================================================================== +% +% USAGE: +% osmotic_pressure_t_exact = gsw_osmotic_pressure_t_exact(SA,t,pw) +% +% DESCRIPTION: +% Calculates the osmotic pressure of seawater. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% pw = sea pressure of the pure water side [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & t need to have the same dimensions. +% pw may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% +% OUTPUT: +% osmotic_pressure_t_exact = osmotic pressure of seawater [ dbar ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (26th May, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 3.41 of this TEOS-10 Manual +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_osmotic_pressure_t_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(t); +[mp,np] = size(pw); + +if (mt ~= ms | nt ~= ns) + error('gsw_osmotic_pressure_t_exact: SA and t must have same dimensions') +end + +if (mp == 1) & (np == 1) % pw is a scalar - fill to size of SA + pw = pw*ones(size(SA)); +elseif (ns == np) & (mp == 1) % pw is row vector, + pw = pw(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % pw is column vector, + pw = pw(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % pw is a transposed row vector, + pw = pw.'; % transposed then + pw = pw(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_osmotic_pressure_t_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + t = t.'; + pw = pw.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +db2Pa = 1e4; % conversion factor from dbar to Pa + +gibbs_pure_water = gsw_gibbs(0,0,0,0,t,pw); + +p = pw + 235.4684; % Initial guess of p, in dbar + +df_dp = -db2Pa*(gsw_gibbs(0,0,1,SA,t,p) - SA.*gsw_gibbs(1,0,1,SA,t,p)); % Inital guess of df/dp + +for Number_of_iterations = 1:2 + p_old = p; + f = gibbs_pure_water - gsw_chem_potential_water_t_exact(SA,t,p_old); + p = p_old - f./df_dp; % this is half way through the modified N-R method + p_mean = 0.5*(p + p_old); + df_dp = -db2Pa*(gsw_gibbs(0,0,1,SA,t,p_mean) - SA.*gsw_gibbs(1,0,1,SA,t,p_mean)) ; + p = p_old - f./df_dp; +end + +% After two iterations though the modified Newton-Raphson technique the +% maximum error is 6x10^-12 dbar. + +osmotic_pressure_t_exact = p - pw; % osmotic pressure of seawater, in dbar. + +if transposed + osmotic_pressure_t_exact = osmotic_pressure_t_exact.'; +end + +end diff --git a/Toolbox/gsw_p_from_Abs_Pressure.m b/Toolbox/gsw_p_from_Abs_Pressure.m new file mode 100644 index 0000000..fab5a2c --- /dev/null +++ b/Toolbox/gsw_p_from_Abs_Pressure.m @@ -0,0 +1,43 @@ +function p = gsw_p_from_Abs_Pressure(Absolute_Pressure) + +% gsw_p_from_Abs_Pressure sea pressure +%========================================================================== +% +% USAGE: +% p = gsw_p_from_Abs_Pressure(Absolute_Pressure) +% +% DESCRIPTION: +% Calculates sea pressure from Absolute Pressure. Note that Absolute +% Pressure is in Pa NOT dbar. +% +% INPUT: +% Absolute_Pressure = Absolute Pressure [ Pa ] +% +% OUTPUT: +% p = sea pressure [ dbar ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. +% See Eqn. (2.2.1) of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +if ~(nargin == 1) + error('gsw_p_from_Abs_Pressure: Requires one input') +end %if + +Pa2db = 1e-4; + +p = (Absolute_Pressure - 101325)*Pa2db; + +end diff --git a/Toolbox/gsw_p_from_z.m b/Toolbox/gsw_p_from_z.m index 31f2f42..21044c4 100644 --- a/Toolbox/gsw_p_from_z.m +++ b/Toolbox/gsw_p_from_z.m @@ -1,55 +1,69 @@ -function p = gsw_p_from_z(z,lat) +function p = gsw_p_from_z(z,lat,geo_strf_dyn_height) % gsw_p_from_z pressure from height %========================================================================== % % USAGE: -% p = gsw_p_from_z(z,lat) +% p = gsw_p_from_z(z,lat,{geo_strf_dyn_height}) % % DESCRIPTION: % Calculates sea pressure from height using computationally-efficient -% 25-term expression for density, in terms of SA, CT and p -% (McDougall et al., 2010). +% 48-term expression for density, in terms of SA, CT and p (McDougall et +% al., 2011). Dynamic height anomaly, geo_strf_dyn_height, if provided, +% must be computed with its p_ref = 0 (the surface). +% % Note. Height (z) is NEGATIVE in the ocean. Depth is -z. % Depth is not used in the GSW computer software library. % +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% % INPUT: -% z = height [ m ] +% z = height [ m ] % Note. At sea level z = 0, and since z (HEIGHT) is defined % to be positive upwards, it follows that while z is % positive in the atmosphere, it is NEGATIVE in the ocean. -% lat = latitude in decimal degrees north [ -90 ... +90 ] +% lat = latitude in decimal degrees north [ -90 ... +90 ] % +% OPTIONAL: +% geo_strf_dyn_height = dynamic height anomaly [ m^2/s^2 ] +% Note that the reference pressure, p_ref, of geo_strf_dyn_height must +% be zero (0) dbar. +% % lat may have dimensions 1x1 or Mx1 or 1xN or MxN, where z is MxN. +% geo_strf_dyn_height, if provided, must have dimensions MxN, which is +% the same as z. % % OUTPUT: % p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% ( i.e. absolute pressure - 10.1325 dbar ) % % AUTHOR: % Trevor McDougall, Claire Roberts-Thomson and Paul Barker. -% [ help_gsw@csiro.au ] +% [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (26th March, 2011) % % REFERENCES: -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % -% Saunders, P. M., 1981: Practical conversion of pressure to depth. -% Journal of Physical Oceanography, 11, 573-574. +% Moritz (2000) Goedetic reference system 1980. J. Geodesy, 74, 128-133. % -% Moritz (2000) Goedetic reference system 1980. J. Geodesy, 74, 128-133. +% Saunders, P. M., 1981: Practical conversion of pressure to depth. +% Journal of Physical Oceanography, 11, 573-574. % -% This software is available from http://www.TEOS-10.org +% This software is available from http://www.TEOS-10.org % %========================================================================== @@ -57,12 +71,21 @@ % Check variables and resize if necessary %-------------------------------------------------------------------------- -if ~(nargin == 2) - error('gsw_p_from_z: Requires two inputs, latitude and pressure') +if ~(nargin == 2 | nargin == 3) + error('gsw_p_from_z: Requires two or three inputs') end %if +if ~exist('geo_strf_dyn_height','var') + geo_strf_dyn_height = zeros(size(z)); +end + [mz,nz] = size(z); [ml,nl] = size(lat); +[mdh,ndh] = size(geo_strf_dyn_height); + +if (mz ~= mdh) | (nz ~= ndh) + error('gsw_p_from_z: height & dynamic height anomaly need to have the same dimensions') +end if (ml == 1) & (nl == 1) % lat is a scalar - fill to size of z lat = lat*ones(size(z)); @@ -70,6 +93,9 @@ lat = lat(ones(1,mz), :); % copy down each column. elseif (mz == ml) & (nl == 1) % lat is column vector, lat = lat(:,ones(1,nz)); % copy across each row. +elseif (nz == ml) & (nl == 1) % lat is a transposed row vector, + lat = lat.'; % transposed then + lat= lat(ones(1,mz), :); % copy down each column. elseif (mz == ml) & (nz == nl) % ok else @@ -77,15 +103,16 @@ end %if if mz == 1 - z = z'; - lat = lat'; + z = z.'; + lat = lat.'; + geo_strf_dyn_height = geo_strf_dyn_height.'; transposed = 1; else transposed = 0; end %-------------------------------------------------------------------------- -% Start of the caclulation +% Start of the calculation %-------------------------------------------------------------------------- db2Pa = 1e4; @@ -97,24 +124,24 @@ % get the first estimate of p from Saunders (1981) c1 = 5.25e-3*sin2 + 5.92e-3; -p = -2.*z./((1-c1) + sqrt((1-c1).*(1-c1) + 8.84e-6.*z)); +p = -2.*z./((1-c1) + sqrt((1-c1).*(1-c1) + 8.84e-6.*z)) ; % end of the first estimate from Saunders (1981) -df_dp = db2Pa * gsw_specvol_SSO_0_CT25(p); % initial value of the derivative of f +df_dp = db2Pa * gsw_specvol_SSO_0_p(p); % initial value of the derivative of f -f = gsw_enthalpy_SSO_0_CT25(p) + gs.*(z - 0.5*gamma*(z.*z)); +f = gsw_enthalpy_SSO_0_p(p) + gs.*(z - 0.5*gamma*(z.*z)) - geo_strf_dyn_height; p_old = p; -p = p_old - f./df_dp; -pm = 0.5*(p + p_old); -df_dp = db2Pa * gsw_specvol_SSO_0_CT25(pm); -p = p_old - f./df_dp; +p = p_old - f./df_dp; +p_mid = 0.5*(p + p_old); +df_dp = db2Pa * gsw_specvol_SSO_0_p(p_mid); +p = p_old - f./df_dp; % After this one iteration through this modified Newton-Raphson iterative % procedure, the remaining error in p is at computer machine precision, % being no more than 1.6e-10 dbar. if transposed - p = p'; + p = p.'; end end diff --git a/Toolbox/gsw_pot_enthalpy_from_pt.m b/Toolbox/gsw_pot_enthalpy_from_pt.m index b7a9209..943bed7 100644 --- a/Toolbox/gsw_pot_enthalpy_from_pt.m +++ b/Toolbox/gsw_pot_enthalpy_from_pt.m @@ -11,8 +11,8 @@ % temperature (whose reference sea pressure is zero dbar). % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% pt = potential temperature (ITS-90) [ deg C ] +% SA = Absolute Salinity [ g/kg ] +% pt = potential temperature (ITS-90) [ deg C ] % % SA & pt need to have the same dimensions. % @@ -20,9 +20,10 @@ % pot_enthalpy = potential enthalpy [ J/kg ] % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -51,8 +52,8 @@ end if ms == 1 - SA = SA'; - pt = pt'; + SA = SA.'; + pt = pt.'; transposed = 1; else transposed = 0; @@ -109,7 +110,7 @@ %-----------------This is the end of the alternative code------------------ if transposed - pot_enthalpy = pot_enthalpy'; + pot_enthalpy = pot_enthalpy.'; end end diff --git a/Toolbox/gsw_pot_rho.m b/Toolbox/gsw_pot_rho_t_exact.m similarity index 54% rename from Toolbox/gsw_pot_rho.m rename to Toolbox/gsw_pot_rho_t_exact.m index ca1b9be..d1b2b21 100644 --- a/Toolbox/gsw_pot_rho.m +++ b/Toolbox/gsw_pot_rho_t_exact.m @@ -1,10 +1,10 @@ -function pot_rho = gsw_pot_rho(SA,t,p,pr) +function pot_rho_t_exact = gsw_pot_rho_t_exact(SA,t,p,p_ref) -% gsw_pot_rho potential density +% gsw_pot_rho_t_exact potential density %========================================================================== % % USAGE: -% pot_rho = gsw_pot_rho(SA,t,p,pr) +% pot_rho_t_exact = gsw_pot_rho_t_exact(SA,t,p,p_ref) % % DESCRIPTION: % Calculates potential density of seawater. Note. This function outputs @@ -12,25 +12,25 @@ % is not subtracted. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) -% pr = reference pressure [ dbar ] -% ( ie. reference absolute pressure - 10.1325 dbar ) +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% p_ref = reference pressure [ dbar ] +% ( i.e. reference absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. -% p & pr may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t +% p & p_ref may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t % are MxN % % OUTPUT: -% pot_rho = potential density (not potential density anomaly) +% pot_rho_t_exact = potential density (not potential density anomaly) % [ kg/m^3 ] % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -48,7 +48,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 4 ) - error('gsw_pot_rho: Requires four inputs') + error('gsw_pot_rho_t_exact: Requires four inputs') end %if [ms,ns] = size(SA); @@ -56,11 +56,11 @@ [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_pot_rho: SA and t must have same dimensions') + error('gsw_pot_rho_t_exact: SA and t must have same dimensions') end -if ~isscalar(unique(pr)) - error('gsw_pot_rho: The reference pressures differ, they should be unique') +if ~isscalar(unique(p_ref)) + error('gsw_pot_rho_t_exact: The reference pressures differ, they should be unique') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -69,46 +69,37 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_pot_rho: Inputs array dimensions arguments do not agree') -end %if - -[mpr,npr] = size(pr); - -if mpr == 1 & npr == 1 % pr scalar - fill to size of SA - pr = pr*ones(size(SA)); -elseif (ns == np) & (mp == 1) % pr is row vector, - pr = pr(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % pr is column vector, - pr = pr(:,ones(1,ns)); % copy across each row. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_pot_rho: Inputs array dimensions arguments do not agree') + error('gsw_pot_rho_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; - pr = pr'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; end +upr = unique(p_ref); +p_ref = upr*ones(size(SA)); + %-------------------------------------------------------------------------- % Start of the calculation %-------------------------------------------------------------------------- -pt = gsw_pt_from_t(SA,t,p,pr); +pt = gsw_pt_from_t(SA,t,p,p_ref); -pot_rho = gsw_rho(SA,pt,pr); +pot_rho_t_exact = gsw_rho_t_exact(SA,pt,p_ref); if transposed - pot_rho = pot_rho'; + pot_rho_t_exact = pot_rho_t_exact.'; end end diff --git a/Toolbox/gsw_pt0_from_t.m b/Toolbox/gsw_pt0_from_t.m index 5e16209..251f8cf 100644 --- a/Toolbox/gsw_pt0_from_t.m +++ b/Toolbox/gsw_pt0_from_t.m @@ -5,35 +5,36 @@ % ========================================================================= % % USAGE: -% pt0 = gsw_pt0_from_t(SA,t,p) +% pt0 = gsw_pt0_from_t(SA,t,p) % % DESCRIPTION: -% Calculates potential temperature with reference pressure, pr = 0 dbar. +% Calculates potential temperature with reference pressure, p_ref = 0 dbar. % The present routine is computationally faster than the more general -% function "gsw_pt_from_t(SA,t,p,pr)" which can be used for any -% reference pressure value. +% function "gsw_pt_from_t(SA,t,p,p_ref)" which can be used for any reference +% pressure value. % This subroutine calls "gsw_entropy_part(SA,t,p)", % "gsw_entropy_part_zerop(SA,pt0)" and "gsw_gibbs_pt0_pt0(SA,pt0)". % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & t need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% pt0 = potential temperature [ deg C ] -% with reference sea pressure (pr) = 0 dbar. +% pt0 = potential temperature [ deg C ] +% with reference sea pressure (p_ref) = 0 dbar. % Note. The reference sea pressure of the output, pt0, is zero dbar. % % AUTHOR: % Trevor McDougall, David Jackett, Claire Roberts-Thomson and Paul Barker. -% [ help_gsw@csiro.au ] +% [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -42,11 +43,10 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See section 3.1 of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -61,8 +61,8 @@ end %if [ms,ns] = size(SA); -[mt,nt] = size(t); -[mp,np] = size(p); +[mt,nt] = size(t); +[mp,np] = size(p); if (ms ~= mt | ns ~= nt ) error('gsw_pt0_from_t: Input arguments do not have the same dimensions') @@ -74,6 +74,9 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else @@ -81,9 +84,9 @@ end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -104,13 +107,13 @@ s1 = SA*(35./SSO); -pt0 = t + p.*( 8.65483913395442d-6 - ... - s1.* 1.41636299744881d-6 - ... - p.* 7.38286467135737d-9 + ... - t.*(-8.38241357039698d-6 + ... - s1.* 2.83933368585534d-8 + ... - t.* 1.77803965218656d-8 + ... - p.* 1.71155619208233d-10)); +pt0 = t + p.*( 8.65483913395442e-6 - ... + s1.* 1.41636299744881e-6 - ... + p.* 7.38286467135737e-9 + ... + t.*(-8.38241357039698e-6 + ... + s1.* 2.83933368585534e-8 + ... + t.* 1.77803965218656e-8 + ... + p.* 1.71155619208233e-10)); dentropy_dt = cp0./((273.15 + pt0).*(1-0.05.*(1 - SA./SSO))); @@ -126,13 +129,13 @@ end if transposed - pt0 = pt0'; + pt0 = pt0.'; end % maximum error of 6.3x10^-9 degrees C for one iteration. % maximum error is 1.8x10^-14 degrees C for two iterations % (two iterations is the default, "for Number_of_iterations = 1:2"). % These errors are over the full "oceanographic funnel" of -% McDougall et al. (2010), which reaches down to p = 8000 dbar. +% McDougall et al. (2011), which reaches down to p = 8000 dbar. end diff --git a/Toolbox/gsw_pt_first_derivatives.m b/Toolbox/gsw_pt_first_derivatives.m index bb6b2d8..71640e4 100644 --- a/Toolbox/gsw_pt_first_derivatives.m +++ b/Toolbox/gsw_pt_first_derivatives.m @@ -4,19 +4,19 @@ % ========================================================================= % % USAGE: -% [pt_SA, pt_CT] = gsw_pt_first_derivatives(SA,CT) +% [pt_SA, pt_CT] = gsw_pt_first_derivatives(SA,CT) % % DESCRIPTION: -% Calculates the following two partial derivatives of potential temperature -% (the regular potential temperature whose reference sea pressure is 0 dbar) -% (1) pt_SA, the derivative with respect to Absolute Salinity at +% Calculates the following two partial derivatives of potential temperature +% (the regular potential temperature whose reference sea pressure is 0 dbar) +% (1) pt_SA, the derivative with respect to Absolute Salinity at % constant Conservative Temperature, and -% (2) pt_CT, the derivative with respect to Conservative Temperature at +% (2) pt_CT, the derivative with respect to Conservative Temperature at % constant Absolute Salinity. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % % SA & CT need to have the same dimensions. % @@ -29,7 +29,10 @@ % pt_CT is dimensionless. [ unitless ] % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -38,11 +41,10 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. % See Eqns. (A.12.6), (A.12.3), (P.6) and (P.8) of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % This software is available from http://www.TEOS-10.org % @@ -68,8 +70,8 @@ end if ms == 1 - SA = SA'; - CT = CT'; + SA = SA.'; + CT = CT.'; transposed = 1; else transposed = 0; @@ -97,8 +99,8 @@ pt_CT = ones(size(CT_pt))./CT_pt; if transposed - pt_SA = pt_SA'; - pt_CT = pt_CT'; + pt_SA = pt_SA.'; + pt_CT = pt_CT.'; end end diff --git a/Toolbox/gsw_pt_from_CT.m b/Toolbox/gsw_pt_from_CT.m index d9de28c..b1aa61b 100644 --- a/Toolbox/gsw_pt_from_CT.m +++ b/Toolbox/gsw_pt_from_CT.m @@ -14,20 +14,21 @@ % for both pt and dCT_dpt. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % % SA & CT need to have the same dimensions. % % OUTPUT: -% pt = potential temperature referenced to a sea pressure -% of zero dbar (ITS-90) [ deg C ] +% pt = potential temperature referenced to a sea pressure +% of zero dbar (ITS-90) [ deg C ] % % AUTHOR: % Trevor McDougall, David Jackett, Claire Roberts-Thomson and Paul Barker. -% [ help_gsw@csiro.au ] +% [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -36,11 +37,10 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See sections 3.1 and 3.3 of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -62,8 +62,8 @@ end if ms == 1 - SA = SA'; - CT = CT'; + SA = SA.'; + CT = CT.'; transposed = 1; else transposed = 0; @@ -115,13 +115,13 @@ % of the Gibbs function with respect to temperature at zero sea pressure. dCT_dpt = -(ptm + 273.15).*gsw_gibbs_pt0_pt0(SA,ptm)./cp0; -pt = pt_old - (CT_diff)./dCT_dpt; % end of 1st full modified N-R iteration +pt = pt_old - (CT_diff)./dCT_dpt; % end of 1st full modified N-R iteration CT_diff = gsw_CT_from_pt(SA,pt) - CT; pt_old = pt; pt = pt_old - (CT_diff)./dCT_dpt; % 1.5 iterations of the modified N-R method if transposed - pt = pt'; + pt = pt.'; end % abs max error of result is 1.42e-14 deg C diff --git a/Toolbox/gsw_pt_from_entropy.m b/Toolbox/gsw_pt_from_entropy.m index 6da4ba0..67b2be6 100644 --- a/Toolbox/gsw_pt_from_entropy.m +++ b/Toolbox/gsw_pt_from_entropy.m @@ -6,27 +6,27 @@ % ========================================================================= % % USAGE: -% pt = gsw_pt_from_entropy(SA,entropy) +% pt = gsw_pt_from_entropy(SA,entropy) % % DESCRIPTION: -% Calculates potential temperature with reference pressure pr = 0 dbar and -% with entropy as an input variable. +% Calculates potential temperature with reference pressure p_ref = 0 dbar +% and with entropy as an input variable. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% entropy = specific entropy [ deg C ] +% SA = Absolute Salinity [ g/kg ] +% entropy = specific entropy [ deg C ] % % SA & entropy need to have the same dimensions. % % OUTPUT: % pt = potential temperature [ deg C ] -% with reference sea pressure (pr) = 0 dbar. +% with reference sea pressure (p_ref) = 0 dbar. % Note. The reference sea pressure of the output, pt, is zero dbar. % % AUTHOR: -% Trevor McDougall and Paul Barker. [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (13th October, 2010) +% VERSION NUMBER: 3.0 (3rd April, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -44,7 +44,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 2) - error('gsw_pt_from_entropy: Requires 2 inputs - Absolute Salinity and entropy') + error('gsw_pt_from_entropy: Requires 2 inputs, Absolute Salinity and entropy') end %if [ms,ns] = size(SA); @@ -55,8 +55,8 @@ end %if if ms == 1 - SA = SA'; - entropy = entropy'; + SA = SA.'; + entropy = entropy.'; transposed = 1; else transposed = 0; @@ -93,7 +93,7 @@ end if transposed - pt = pt'; + pt = pt.'; end % maximum error of 2.2x10^-6 degrees C for one iteration. diff --git a/Toolbox/gsw_pt_from_t.m b/Toolbox/gsw_pt_from_t.m index 7be0d80..60cb976 100644 --- a/Toolbox/gsw_pt_from_t.m +++ b/Toolbox/gsw_pt_from_t.m @@ -1,42 +1,43 @@ -function pt = gsw_pt_from_t(SA,t,p,pr) +function pt = gsw_pt_from_t(SA,t,p,p_ref) % gsw_pt_from_t potential temperature % ========================================================================= % % USAGE: -% pt = gsw_pt_from_t(SA,t,p,pr) +% pt = gsw_pt_from_t(SA,t,p,p_ref) % % DESCRIPTION: % Calculates potential temperature with the general reference pressure, -% pr, from in-situ temperature, t. This function calls "gsw_entropy_part" -% which evaluates entropy except for the parts which are a function of -% Absolute Salinity alone. -% A faster gsw routine exists if pr is indeed zero dbar. This routine +% p_ref, from in-situ temperature, t. This function calls +% "gsw_entropy_part" which evaluates entropy except for the parts which +% are a function of Absolute Salinity alone. +% A faster gsw routine exists if p_ref is indeed zero dbar. This routine % is "gsw_pt0_from_t(SA,t,p)". % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % % OPTIONAL: -% pr = reference pressure [ dbar ] +% p_ref = reference pressure [ dbar ] % (If reference pressure is not given then it is assumed that reference % pressure is zero). % -% SA & t need to have the same dimensions. p & pr (if provided) may -% have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% SA & t need to have the same dimensions. p & p_ref (if provided) may +% have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. % % OUTPUT: -% pt = potential temperature with reference pressure, pr, on the -% ITS-90 temperature scale [ deg C ] +% pt = potential temperature with reference pressure, p_ref, on the +% ITS-90 temperature scale [ deg C ] % % AUTHOR: % Trevor McDougall, David Jackett, Claire Roberts-Thomson and Paul Barker. -% [ help_gsw@csiro.au ] +% [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -45,11 +46,10 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See section 3.1 of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -59,20 +59,20 @@ % Check variables and resize if necessary %-------------------------------------------------------------------------- -if ~(nargin==3 | nargin == 4) +if ~(nargin == 3 | nargin == 4) error(['gsw_pt_from_t: Requires either three or four inputs, Absolute '... 'Salinity, temperature, pressure and (optional) reference pressure']) end %if if nargin == 3 % Assume reference pressure is 0 dbar. - pr = zeros(size(SA)); + p_ref = zeros(size(SA)); end %if [ms,ns] = size(SA); [mt,nt] = size(t); [mp,np] = size(p); -[mpr,npr] = size(pr); +[mpr,npr] = size(p_ref); if (ms ~= mt | ns ~= nt ) error('gsw_pt_from_t: Input arguments do not have the same dimensions') @@ -85,7 +85,7 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok @@ -93,15 +93,15 @@ error('gsw_pt_from_t: Inputs array dimensions arguments do not agree') end %if -if (mpr == 1) & (npr == 1) % pr scalar - fill to size of SA - pr = pr*ones(size(SA)); -elseif (ns == npr) & (mpr == 1) % pr is row vector, - pr = pr(ones(1,ms), :); % copy down each column. -elseif (ms == mpr) & (npr == 1) % pr is column vector, - pr = pr(:,ones(1,ns)); % copy across each row. -elseif (ns == mpr) & (npr == 1) % pr is a transposed row vector, - pr = pr'; % transposed then - pr = pr(ones(1,ms), :); % copy down each column. +if (mpr == 1) & (npr == 1) % p_ref scalar - fill to size of SA + p_ref = p_ref*ones(size(SA)); +elseif (ns == npr) & (mpr == 1) % p_ref is row vector, + p_ref = p_ref(ones(1,ms), :); % copy down each column. +elseif (ms == mpr) & (npr == 1) % p_ref is column vector, + p_ref = p_ref(:,ones(1,ns)); % copy across each row. +elseif (ns == mpr) & (npr == 1) % p_ref is a transposed row vector, + p_ref = p_ref.'; % transposed then + p_ref = p_ref(ones(1,ms), :); % copy down each column. elseif (ms == mpr) & (ns == npr) % ok else @@ -109,10 +109,10 @@ end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; - pr = pr'; + SA = SA.'; + t = t.'; + p = p.'; + p_ref = p_ref.'; transposed = 1; else transposed = 0; @@ -135,13 +135,13 @@ s1 = SA*35./SSO; -pt = t + (p-pr).*( 8.65483913395442d-6 - ... - s1 .* 1.41636299744881d-6 - ... - (p+pr).* 7.38286467135737d-9 + ... - t .*(-8.38241357039698d-6 + ... - s1 .* 2.83933368585534d-8 + ... - t .* 1.77803965218656d-8 + ... - (p+pr).* 1.71155619208233d-10)); +pt = t + (p-p_ref).*( 8.65483913395442e-6 ... + - s1 .* 1.41636299744881e-6 ... + - (p+p_ref).* 7.38286467135737e-9 ... + + t .*(-8.38241357039698e-6 ... + + s1 .* 2.83933368585534e-8 ... + + t .* 1.77803965218656e-8 ... + + (p+p_ref).* 1.71155619208233e-10)); dentropy_dt = cp0./((273.15 + pt).*(1-0.05.*(1 - SA./SSO))); @@ -149,21 +149,21 @@ for Number_of_iterations = 1:2 pt_old = pt; - dentropy = gsw_entropy_part(SA,pt_old,pr) - true_entropy_part; + dentropy = gsw_entropy_part(SA,pt_old,p_ref) - true_entropy_part; pt = pt_old - dentropy./dentropy_dt ; % this is half way through the modified method ptm = 0.5*(pt + pt_old); - dentropy_dt = -gsw_gibbs(n0,n2,n0,SA,ptm,pr); + dentropy_dt = -gsw_gibbs(n0,n2,n0,SA,ptm,p_ref); pt = pt_old - dentropy./dentropy_dt; end if transposed - pt = pt'; + pt = pt.'; end % maximum error of 6.3x10^-9 degrees C for one iteration. % maximum error is 1.8x10^-14 degrees C for two iterations % (two iterations is the default, "for Number_of_iterations = 1:2"). % These errors are over the full "oceanographic funnel" of -% McDougall et al. (2010), which reaches down to p = 8000 dbar. +% McDougall et al. (2011), which reaches down to p = 8000 dbar. end diff --git a/Toolbox/gsw_pt_second_derivatives.m b/Toolbox/gsw_pt_second_derivatives.m index abd52cd..5fd9de2 100644 --- a/Toolbox/gsw_pt_second_derivatives.m +++ b/Toolbox/gsw_pt_second_derivatives.m @@ -18,8 +18,8 @@ % Temperature at constant Absolute Salinity. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % % SA & CT need to have the same dimensions. % @@ -31,16 +31,17 @@ % pt_SA_SA has units of: [ K/((g/kg)^2) ] % pt_SA_CT = The derivative of potential temperature with respect % to Absolute Salinity and Conservative Temperature. -% pt_SA_CT has units of: [ (g/kg)^-1 ] +% pt_SA_CT has units of: [ 1/(g/kg) ] % pt_CT_CT = The second derivative of potential temperature (the -% regular one with pr = 0 dbar) with respect to +% regular one with p_ref = 0 dbar) with respect to % Conservative Temperature at constant SA. -% pt_CT_CT has units of: [ K^-1 ] +% pt_CT_CT has units of: [ 1/K ] % % AUTHOR: -% Trevor McDougall and Paul Barker. [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker. [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -49,11 +50,10 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. % See Eqns. (A.12.9) and (A.12.10) of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % This software is available from http://www.TEOS-10.org % @@ -74,21 +74,13 @@ [ms,ns] = size(SA); [mt,nt] = size(CT); -if (mt == 1) & (nt == 1) % CT scalar - fill to size of SA - CT = CT*ones(size(SA)); -elseif (ns == nt) & (mt == 1) % CT is row vector, - CT = CT(ones(1,ms), :); % copy down each column. -elseif (ms == mt) & (nt == 1) % CT is column vector, - CT = CT(:,ones(1,ns)); % copy across each row. -elseif (ms == mt) & (ns == nt) - % ok -else - error('gsw_pt_second_derivatives: The dimensions of CT do not agree') -end %if +if (mt ~= ms | nt ~= ns) + error('gsw_pt_second_derivatives: SA and CT must have same dimensions') +end if ms == 1 - SA = SA'; - CT = CT'; + SA = SA.'; + CT = CT.'; transposed = 1; else transposed = 0; @@ -127,8 +119,8 @@ pt_CT_CT = (pt_CT_u - pt_CT_l)./(CT_u - CT_l); if transposed - pt_SA_CT = pt_SA_CT'; - pt_CT_CT = pt_CT_CT'; + pt_SA_CT = pt_SA_CT.'; + pt_CT_CT = pt_CT_CT.'; end end diff --git a/Toolbox/gsw_rho.m b/Toolbox/gsw_rho.m index 0faac2c..aacd11b 100644 --- a/Toolbox/gsw_rho.m +++ b/Toolbox/gsw_rho.m @@ -1,41 +1,56 @@ -function rho = gsw_rho(SA,t,p) +function rho = gsw_rho(SA,CT,p) -% gsw_rho density of seawater +% gsw_rho in-situ density (48-term equation) %========================================================================== -% +% % USAGE: -% rho = gsw_rho(SA,t,p) +% rho = gsw_rho(SA,CT,p) % % DESCRIPTION: -% Calculates in-situ density of seawater from Absolute Salinity and -% in-situ temperature. Note that the output, rho, is density, -% not density anomaly; that is, 1000 kg/m^3 is not subracted from it. +% Calculates in-situ density from Absolute Salinity and Conservative +% Temperature, using the computationally-efficient 48-term expression for +% density in terms of SA, CT and p (McDougall et al., 2011). +% +% Note that potential density with respect to reference pressure, pr, is +% obtained by calling this function with the pressure argument being pr +% (i.e. "gsw_rho(SA,CT,pr)"). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % -% SA & t need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. % % OUTPUT: -% rho = in-situ density (not density anomaly) [ kg/m^3 ] -% +% rho = in-situ density [ kg/m ] +% % AUTHOR: -% David Jackett, Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (18th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of % seawater - 2010: Calculation and use of thermodynamic properties. % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See section 2.8 of this TEOS-10 Manual. +% See appendix A.20 and appendix K of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % -% The software is available from http://www.TEOS-10.org +% The software is available from http://www.TEOS-10.org % %========================================================================== @@ -48,19 +63,22 @@ end %if [ms,ns] = size(SA); -[mt,nt] = size(t); +[mt,nt] = size(CT); [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_rho: SA and t must have same dimensions') + error('gsw_rho: SA and CT must have same dimensions') end -if (mp == 1) & (np == 1) % p scalar - fill to size of SA +if (mp == 1) & (np == 1) % p scalar - fill to size of SA p = p*ones(size(SA)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else @@ -69,7 +87,7 @@ if ms == 1 SA = SA'; - t = t'; + CT = CT'; p = p'; transposed = 1; else @@ -80,13 +98,103 @@ % Start of the calculation %-------------------------------------------------------------------------- -n0 = 0; -n1 = 1; +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +v01 = 9.998420897506056e+2; +v02 = 2.839940833161907; +v03 = -3.147759265588511e-2; +v04 = 1.181805545074306e-3; +v05 = -6.698001071123802; +v06 = -2.986498947203215e-2; +v07 = 2.327859407479162e-4; +v08 = -3.988822378968490e-2; +v09 = 5.095422573880500e-4; +v10 = -1.426984671633621e-5; +v11 = 1.645039373682922e-7; +v12 = -2.233269627352527e-2; +v13 = -3.436090079851880e-4; +v14 = 3.726050720345733e-6; +v15 = -1.806789763745328e-4; +v16 = 6.876837219536232e-7; +v17 = -3.087032500374211e-7; +v18 = -1.988366587925593e-8; +v19 = -1.061519070296458e-11; +v20 = 1.550932729220080e-10; +v21 = 1.0; +v22 = 2.775927747785646e-3; +v23 = -2.349607444135925e-5; +v24 = 1.119513357486743e-6; +v25 = 6.743689325042773e-10; +v26 = -7.521448093615448e-3; +v27 = -2.764306979894411e-5; +v28 = 1.262937315098546e-7; +v29 = 9.527875081696435e-10; +v30 = -1.811147201949891e-11; +v31 = -3.303308871386421e-5; +v32 = 3.801564588876298e-7; +v33 = -7.672876869259043e-9; +v34 = -4.634182341116144e-11; +v35 = 2.681097235569143e-12; +v36 = 5.419326551148740e-6; +v37 = -2.742185394906099e-5; +v38 = -3.212746477974189e-7; +v39 = 3.191413910561627e-9; +v40 = -1.931012931541776e-12; +v41 = -1.105097577149576e-7; +v42 = 6.211426728363857e-10; +v43 = -1.119011592875110e-10; +v44 = -1.941660213148725e-11; +v45 = -1.864826425365600e-14; +v46 = 1.119522344879478e-14; +v47 = -1.200507748551599e-15; +v48 = 6.057902487546866e-17; + +sqrtSA = sqrt(SA); + +v_hat_denominator = v01 + CT.*(v02 + CT.*(v03 + v04*CT)) ... + + SA.*(v05 + CT.*(v06 + v07*CT) ... + + sqrtSA.*(v08 + CT.*(v09 + CT.*(v10 + v11*CT)))) ... + + p.*(v12 + CT.*(v13 + v14*CT) + SA.*(v15 + v16*CT) ... + + p.*(v17 + CT.*(v18 + v19*CT) + v20*SA)); + +v_hat_numerator = v21 + CT.*(v22 + CT.*(v23 + CT.*(v24 + v25*CT))) ... + + SA.*(v26 + CT.*(v27 + CT.*(v28 + CT.*(v29 + v30*CT))) + v36*SA ... + + sqrtSA.*(v31 + CT.*(v32 + CT.*(v33 + CT.*(v34 + v35*CT))))) ... + + p.*(v37 + CT.*(v38 + CT.*(v39 + v40*CT)) ... + + SA.*(v41 + v42*CT) ... + + p.*(v43 + CT.*(v44 + v45*CT + v46*SA) ... + + p.*(v47 + v48*CT))); -rho = ones(size(SA))./gsw_gibbs(n0,n0,n1,SA,t,p); +rho = v_hat_denominator./v_hat_numerator; + +%-------------------------------------------------------------------------- +% This function calculates rho using the computationally-efficient +% 48-term expression for density in terms of SA, CT and p. If one wanted to +% compute rho from SA, CT, and p with the full TEOS-10 Gibbs function, +% the following lines of code will enable this. +% +% pt0 = gsw_pt_from_CT(SA,CT); +% pr0 = zeros(size(SA)); +% t = gsw_pt_from_t(SA,pt0,pr0,p); +% rho = gsw_rho_t_exact(SA,t,p); +% +% or call the following, it is identical to the lines above. +% +% rho = gsw_rho_CT_exact(SA,CT,p) +% +% or call the following, it is identical to the lines above. +% +% [rho, ~, ~] = gsw_rho_alpha_beta_CT_exact(SA,CT,p) +% +%-----------------This is the end of the alternative code------------------ if transposed - rho = rho'; + rho = rho.'; end end + diff --git a/Toolbox/gsw_rho_CT.m b/Toolbox/gsw_rho_CT.m index 13bfd91..1a1d682 100644 --- a/Toolbox/gsw_rho_CT.m +++ b/Toolbox/gsw_rho_CT.m @@ -1,51 +1,60 @@ function rho_CT = gsw_rho_CT(SA,CT,p) -% gsw_rho_CT In-situ density +% gsw_rho_CT in-situ density (48-term equation) %========================================================================== % % USAGE: -% rho_CT = gsw_rho_CT(SA,CT,p) +% rho_CT = gsw_rho_CT(SA,CT,p), or equivalently +% rho = gsw_rho(SA,CT,p) +% +% Note that gsw_rho(SA,CT,p) is identical to gsw_rho_CT(SA,CT,p). +% The extra "_CT" emphasises that the input temperature is Conservative +% Temperature, but the extra "_CT" part of the function name is not +% needed. % % DESCRIPTION: % Calculates in-situ density from Absolute Salinity and Conservative -% Temperature. +% Temperature, using the computationally-efficient 48-term expression for +% density in terms of SA, CT and p (McDougall et al., 2011). % -% Note that potential density with respect to reference pressure, pr, is -% obtained by calling this function with the pressure argument being pr -% (i.e. "gsw_rho_CT(SA,CT,pr)"). +% Note that potential density with respect to reference pressure, p_ref, is +% obtained by calling this function with the pressure argument being p_ref +% (i.e. "gsw_rho_CT(SA,CT,p_ref)"). % -% Note that this function uses the full Gibbs function. There is an -% alternative to calling this function, namely gsw_rho_CT25(SA,CT,p), -% which uses the computationally efficient 25-term expression for density -% in terms of SA, CT and p (McDougall et al., (2010)). For SA, CT and p -% values which fall inside the oceanographic "funnel" (McDougall et al., -% 2010), this computationally efficient (i. e. faster) 25-term version -% fits the underlying laboratory density data almost as well as does the -% density derived from the full TEOS-10 Gibbs function. +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: % SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% (i.e. absolute pressure - 10.1325 dbar) +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & CT need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. % % OUTPUT: -% rho_CT = in-situ density [ kg m^-3 ] +% rho_CT = in-situ density [ kg/m^3 ] % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (18th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of % seawater - 2010: Calculation and use of thermodynamic properties. % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See Eqn. (2.8.2) of this TEOS-10 Manual. +% See appendix A.20 and appendix K of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -67,15 +76,15 @@ error('gsw_rho_CT: SA and CT must have same dimensions') end -if (mp == 1) & (np == 1) % p scalar - fill to size of SA +if (mp == 1) & (np == 1) % p scalar - fill to size of SA p = p*ones(size(SA)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then - p = p(ones(1,ms), :); % copy down each column. +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else @@ -83,9 +92,9 @@ end %if if ms == 1 - SA = SA'; - CT = CT'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -95,13 +104,11 @@ % Start of the calculation %-------------------------------------------------------------------------- -pt0 = gsw_pt_from_CT(SA,CT); -pr0 = zeros(size(SA)); -t = gsw_pt_from_t(SA,pt0,pr0,p); -rho_CT = gsw_rho(SA,t,p); +rho_CT = gsw_rho(SA,CT,p); if transposed - rho_CT = rho_CT'; + rho_CT = rho_CT.'; end end + diff --git a/Toolbox/gsw_rho_CT25.m b/Toolbox/gsw_rho_CT25.m deleted file mode 100644 index 1da2e50..0000000 --- a/Toolbox/gsw_rho_CT25.m +++ /dev/null @@ -1,162 +0,0 @@ -function [rho_CT25, in_funnel] = gsw_rho_CT25(SA,CT,p) - -% gsw_rho_CT25 In-situ density (25-term equation) -%========================================================================== -% -% USAGE: -% rho_CT25 = gsw_rho_CT25(SA,CT,p) -% -% DESCRIPTION: -% Calculates in-situ density from Absolute Salinity and Conservative -% Temperature, using the computationally-efficient 25-term expression -% for density in terms of SA, CT and p (McDougall et al., 2010). -% -% Note that potential density with respect to reference pressure, pr, is -% obtained by calling this function with the pressure argument being pr -% (i.e. "gsw_rho_CT25(SA,CT,pr)"). -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% (i.e. absolute pressure - 10.1325 dbar) -% -% SA & CT need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. -% -% OUTPUT: -% rho_CT25 = in-situ density [ kg m^-3 ] -% in_funnel = 0, if (SA, CT and p) are outside the "funnel" -% = 1, if (SA, CT and p) are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). -% -% AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] -% -% VERSION NUMBER: 2.0 (23rd July, 2010) -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See appendix A.20 and appendix K of this TEOS-10 Manual. -% -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 3) - error('gsw_rho_CT25: Requires three inputs') -end %if - -[ms,ns] = size(SA); -[mt,nt] = size(CT); -[mp,np] = size(p); - -if (mt ~= ms | nt ~= ns) - error('gsw_rho_CT25: SA and CT must have same dimensions') -end - -if (mp == 1) & (np == 1) % p scalar - fill to size of SA - p = p*ones(size(SA)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_rho_CT25: Inputs array dimensions arguments do not agree') -end %if - -if ms == 1 - SA = SA'; - CT = CT'; - p = p'; - transposed = 1; -else - transposed = 0; -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -% These few lines ensure that SA is non-negative. -[I_neg_SA] = find(SA < 0); -if ~isempty(I_neg_SA) - SA(I_neg_SA) = 0; -end - -in_funnel = gsw_infunnel(SA,CT,p); - -CT2 = CT.*CT; - -anum = 9.9984380290708214e+002 + ... - CT.*( 7.1188090678940910e+000 + ... - CT.*(-1.9459922513379687e-002 + ... - CT * 6.1748404455874641e-004)) + ... - SA.*( 2.8925731541277653e+000 + ... - CT * 2.1471495493268324e-003 + ... - SA * 1.9457531751183059e-003) + ... - p.*( 1.1930681818531748e-002 + ... - CT2 * 2.6969148011830758e-007 + ... - SA * 5.9355685925035653e-006 + ... - p.*(-2.5943389807429039e-008 + ... - CT2 * -7.2734111712822707e-012)); - -adenom = 1.00000000d+00 + ... - CT.*( 7.0547681896071576e-003 + ... - CT.*(-1.1753695605858647e-005 + ... - CT.*( 5.9219809488274903e-007 + ... - CT * 3.4887902228012519e-010))) + ... - SA.*( 2.0777716085618458e-003 + ... - CT.*(-2.2210857293722998e-008 + ... - CT2 * -3.6628141067895282e-010) + ... - sqrt(SA).*( 3.4688210757917340e-006 + ... - CT2 * 8.0190541528070655e-010)) + ... - p.*( 6.8314629554123324e-006 + ... - (p.*CT).*(CT2 * -8.5294794834485446e-017 + ... - p * -9.2275325145038070e-018)); - -rho_CT25 = anum./adenom; - -%-------------------------------------------------------------------------- -% This function calculates rho_CT25 using the computationally-efficient -% 25-term expression for density in terms of SA, CT and p. If one wanted to -% compute rho from SA, CT, and p with the full TEOS-10 Gibbs function, -% the following lines of code will enable this. -% -% pt0 = gsw_pt_from_CT(SA,CT); -% pr0 = zeros(size(SA)); -% t = gsw_pt_from_t(SA,pt0,pr0,p); -% rho = gsw_rho(SA,t,p); -% -% or call the following, it is identical to the lines above. -% -% rho = gsw_rho_CT(SA,CT,p) -% -% or call the following, it is identical to the lines above. -% -% [rho, ~, ~] = gsw_rho_alpha_beta_CT(SA,CT,p) -% -%-----------------This is the end of the alternative code------------------ - -if transposed - rho_CT25 = rho_CT25'; -end - -end diff --git a/Toolbox/gsw_rho_CT_exact.m b/Toolbox/gsw_rho_CT_exact.m new file mode 100644 index 0000000..bae2281 --- /dev/null +++ b/Toolbox/gsw_rho_CT_exact.m @@ -0,0 +1,106 @@ +function rho_CT_exact = gsw_rho_CT_exact(SA,CT,p) + +% gsw_rho_CT_exact in-situ density +%========================================================================== +% +% USAGE: +% rho_CT_exact = gsw_rho_CT_exact(SA,CT,p) +% +% DESCRIPTION: +% Calculates in-situ density from Absolute Salinity and Conservative +% Temperature. +% +% Note that potential density with respect to reference pressure, p_ref, is +% obtained by calling this function with the pressure argument being p_ref +% (i.e. "gsw_rho_CT_exact(SA,CT,p_ref)"). +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely gsw_rho_CT(SA,CT,p), +% which uses the computationally efficient 48-term expression for density +% in terms of SA, CT and p (McDougall et al., 2011). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% rho_CT_exact = in-situ density [ kg/m^3 ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (3rd April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (2.8.2) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_rho_CT_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_rho_CT_exact: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_rho_CT_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +t = gsw_t_from_CT(SA,CT,p); +rho_CT_exact = gsw_rho_t_exact(SA,t,p); + +if transposed + rho_CT_exact = rho_CT_exact.'; +end + +end diff --git a/Toolbox/gsw_rho_alpha_beta.m b/Toolbox/gsw_rho_alpha_beta.m new file mode 100644 index 0000000..35a45bd --- /dev/null +++ b/Toolbox/gsw_rho_alpha_beta.m @@ -0,0 +1,298 @@ +function [rho, alpha, beta] = gsw_rho_alpha_beta(SA,CT,p) + +% gsw_rho_alpha_beta in-situ density, thermal expansion & saline +% contraction coefficient (48-term equation) +%========================================================================== +% +% USAGE: +% [rho, alpha, beta] = gsw_rho_alpha_beta(SA,CT,p) +% +% DESCRIPTION: +% Calculates in-situ density, the appropiate thermal expansion coefficient +% and the appropriate saline contraction coefficient of seawater from +% Absolute Salinity and Conservative Temperature. This function uses the +% computationally-efficient 48-term expression for density in terms of +% SA, CT and p (McDougall et al., 2011). +% +% Note that potential density (pot_rho) with respect to reference pressure +% p_ref is obtained by calling this function with the pressure argument +% being p_ref as in [pot_rho, ~, ~] = gsw_rho_alpha_beta(SA,CT,p_ref). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% rho = in-situ density [ kg/m ] +% alpha = thermal expansion coefficient [ 1/K ] +% with respect to Conservative Temperature +% beta = saline (i.e. haline) contraction [ kg/g ] +% coefficient at constant Conservative Temperature +% +% AUTHOR: +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (3rd April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See appendix A.20 and appendix K of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_rho_alpha_beta: Requires three inputs') +end %if +if ~(nargout == 3 | nargout == 4) + error('gsw_rho_alpha_beta: Requires three outputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_rho_alpha_beta: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_rho_alpha_beta: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +v01 = 9.998420897506056e+2; +v02 = 2.839940833161907; +v03 = -3.147759265588511e-2; +v04 = 1.181805545074306e-3; +v05 = -6.698001071123802; +v06 = -2.986498947203215e-2; +v07 = 2.327859407479162e-4; +v08 = -3.988822378968490e-2; +v09 = 5.095422573880500e-4; +v10 = -1.426984671633621e-5; +v11 = 1.645039373682922e-7; +v12 = -2.233269627352527e-2; +v13 = -3.436090079851880e-4; +v14 = 3.726050720345733e-6; +v15 = -1.806789763745328e-4; +v16 = 6.876837219536232e-7; +v17 = -3.087032500374211e-7; +v18 = -1.988366587925593e-8; +v19 = -1.061519070296458e-11; +v20 = 1.550932729220080e-10; +v21 = 1.0; +v22 = 2.775927747785646e-3; +v23 = -2.349607444135925e-5; +v24 = 1.119513357486743e-6; +v25 = 6.743689325042773e-10; +v26 = -7.521448093615448e-3; +v27 = -2.764306979894411e-5; +v28 = 1.262937315098546e-7; +v29 = 9.527875081696435e-10; +v30 = -1.811147201949891e-11; +v31 = -3.303308871386421e-5; +v32 = 3.801564588876298e-7; +v33 = -7.672876869259043e-9; +v34 = -4.634182341116144e-11; +v35 = 2.681097235569143e-12; +v36 = 5.419326551148740e-6; +v37 = -2.742185394906099e-5; +v38 = -3.212746477974189e-7; +v39 = 3.191413910561627e-9; +v40 = -1.931012931541776e-12; +v41 = -1.105097577149576e-7; +v42 = 6.211426728363857e-10; +v43 = -1.119011592875110e-10; +v44 = -1.941660213148725e-11; +v45 = -1.864826425365600e-14; +v46 = 1.119522344879478e-14; +v47 = -1.200507748551599e-15; +v48 = 6.057902487546866e-17; + +a01 = 2.839940833161907; +a02 = -6.295518531177023e-2; +a03 = 3.545416635222918e-3; +a04 = -2.986498947203215e-2; +a05 = 4.655718814958324e-4; +a06 = 5.095422573880500e-4; +a07 = -2.853969343267241e-5; +a08 = 4.935118121048767e-7; +a09 = -3.436090079851880e-4; +a10 = 7.452101440691467e-6; +a11 = 6.876837219536232e-7; +a12 = -1.988366587925593e-8; +a13 = -2.123038140592916e-11; + +a14 = 2.775927747785646e-3; +a15 = -4.699214888271850e-5; +a16 = 3.358540072460230e-6; +a17 = 2.697475730017109e-9; +a18 = -2.764306979894411e-5; +a19 = 2.525874630197091e-7; +a20 = 2.858362524508931e-9; +a21 = -7.244588807799565e-11; +a22 = 3.801564588876298e-7; +a23 = -1.534575373851809e-8; +a24 = -1.390254702334843e-10; +a25 = 1.072438894227657e-11; +a26 = -3.212746477974189e-7; +a27 = 6.382827821123254e-9; +a28 = -5.793038794625329e-12; +a29 = 6.211426728363857e-10; +a30 = -1.941660213148725e-11; +a31 = -3.729652850731201e-14; +a32 = 1.119522344879478e-14; +a33 = 6.057902487546866e-17; + +b01 = -6.698001071123802; +b02 = -2.986498947203215e-2; +b03 = 2.327859407479162e-4; +b04 = -5.983233568452735e-2; +b05 = 7.643133860820750e-4; +b06 = -2.140477007450431e-5; +b07 = 2.467559060524383e-7; +b08 = -1.806789763745328e-4; +b09 = 6.876837219536232e-7; +b10 = 1.550932729220080e-10; +b11 = -7.521448093615448e-3; +b12 = -2.764306979894411e-5; +b13 = 1.262937315098546e-7; +b14 = 9.527875081696435e-10; +b15 = -1.811147201949891e-11; +b16 = -4.954963307079632e-5; +b17 = 5.702346883314446e-7; +b18 = -1.150931530388857e-8; +b19 = -6.951273511674217e-11; +b20 = 4.021645853353715e-12; +b21 = 1.083865310229748e-5; +b22 = -1.105097577149576e-7; +b23 = 6.211426728363857e-10; +b24 = 1.119522344879478e-14; + +sqrtSA = sqrt(SA); + +v_hat_denominator = v01 + CT.*(v02 + CT.*(v03 + v04*CT)) ... + + SA.*(v05 + CT.*(v06 + v07*CT) ... + + sqrtSA.*(v08 + CT.*(v09 + CT.*(v10 + v11*CT)))) ... + + p.*(v12 + CT.*(v13 + v14*CT) + SA.*(v15 + v16*CT) ... + + p.*(v17 + CT.*(v18 + v19*CT) + v20*SA)); + +v_hat_numerator = v21 + CT.*(v22 + CT.*(v23 + CT.*(v24 + v25*CT))) ... + + SA.*(v26 + CT.*(v27 + CT.*(v28 + CT.*(v29 + v30*CT))) + v36*SA ... + + sqrtSA.*(v31 + CT.*(v32 + CT.*(v33 + CT.*(v34 + v35*CT))))) ... + + p.*(v37 + CT.*(v38 + CT.*(v39 + v40*CT)) ... + + SA.*(v41 + v42*CT) ... + + p.*(v43 + CT.*(v44 + v45*CT + v46*SA) ... + + p.*(v47 + v48*CT))); + +rec_num = ones(size(v_hat_numerator))./v_hat_numerator; + +rho = rec_num.*v_hat_denominator; + +spec_vol = v_hat_numerator./v_hat_denominator; + +dvhatden_dCT = a01 + CT.*(a02 + a03*CT) ... + + SA.*(a04 + a05*CT ... + + sqrtSA.*(a06 + CT.*(a07 + a08*CT))) ... + + p.*(a09 + a10*CT + a11*SA ... + + p.*(a12 + a13*CT)); + +dvhatnum_dCT = a14 + CT.*(a15 + CT.*(a16 + a17*CT)) ... + + SA.*(a18 + CT.*(a19 + CT.*(a20 + a21*CT)) ... + + sqrtSA.*(a22 + CT.*(a23 + CT.*(a24 + a25*CT)))) ... + + p.*(a26 + CT.*(a27 + a28*CT) + a29*SA ... + + p.*(a30 + a31*CT + a32*SA + a33*p)); + +alpha = rec_num.*(dvhatnum_dCT - dvhatden_dCT.*spec_vol); + +dvhatden_dSA = b01 + CT.*(b02 + b03*CT) ... + + sqrtSA.*(b04 + CT.*(b05 + CT.*(b06 + b07*CT))) ... + + p.*(b08 + b09*CT + b10*p) ; + +dvhatnum_dSA = b11 + CT.*(b12 + CT.*(b13 + CT.*(b14 + b15*CT))) ... + + sqrtSA.*(b16 + CT.*(b17 + CT.*(b18 + CT.*(b19 + b20*CT)))) + b21*SA ... + + p.*(b22 + CT.*(b23 + b24*p)); + +beta = rec_num.*(dvhatden_dSA.*spec_vol - dvhatnum_dSA); + +%-------------------------------------------------------------------------- +% This function calculates rho, alpha and beta using the computationally- +% efficient 48-term expression for density in terms of SA, CT and p. If +% one wanted to compute rho, alpha and beta with the full TEOS-10 Gibbs +% function expression for density, the following lines of code will do +% this. +% +% pt0 = gsw_pt_from_CT(SA,CT); +% pr0 = zeros(size(SA)); +% t = gsw_pt_from_t(SA,pt0,pr0,p); +% rho = gsw_rho_t_exact(SA,t,p); +% alpha = gsw_alpha_wrt_CT_t_exact(SA,t,p); +% beta = gsw_beta_const_CT_t_exact(SA,t,p); +% +% or call the following, it is identical to the lines above. +% +% [rho, alpha, beta] = gsw_rho_alpha_beta_CT_exact(SA,CT,p) +% +%--------------This is the end of the alternative code--------------------- + +if transposed + rho = rho.'; + alpha = alpha.'; + beta = beta.'; +end + +end diff --git a/Toolbox/gsw_rho_alpha_beta_CT.m b/Toolbox/gsw_rho_alpha_beta_CT.m index 5aeaf6f..e878dd4 100644 --- a/Toolbox/gsw_rho_alpha_beta_CT.m +++ b/Toolbox/gsw_rho_alpha_beta_CT.m @@ -1,60 +1,68 @@ -function [rho, alpha_wrt_CT, beta_const_CT] = gsw_rho_alpha_beta_CT(SA,CT,p) +function [rho_CT, alpha_CT, beta_CT] = gsw_rho_alpha_beta_CT(SA,CT,p) -% gsw_rho_alpha_beta_CT25 in-situ density, thermal expansion -% & saline contraction coefficient from CT +% gsw_rho_alpha_beta_CT in-situ density, thermal expansion & saline +% contraction coefficient (48-term equation) %========================================================================== % % USAGE: -% [rho, alpha_wrt_CT, beta_const_CT] = gsw_rho_alpha_beta_CT(SA,CT,p) +% [rho_CT, alpha_CT, beta_CT] = gsw_rho_alpha_beta_CT(SA,CT,p), +% or equivalently +% [rho, alpha, beta] = gsw_rho_alpha_beta(SA,CT,p) +% +% Note that gsw_rho_alpha_beta(SA,CT,p) is identical to +% gsw_rho_alpha_beta_CT(SA,CT,p). The extra "_CT" emphasises that the +% input temperature is Conservative Temperature, but the extra "_CT" part +% of the function name is not needed. % % DESCRIPTION: % Calculates in-situ density, the appropiate thermal expansion coefficient % and the appropriate saline contraction coefficient of seawater from -% Absolute Salinity and Conservative Temperature. +% Absolute Salinity and Conservative Temperature. This function uses the +% computationally-efficient 48-term expression for density in terms of +% SA, CT and p (McDougall et al., 2011). +% +% Note that potential density (pot_rho) with respect to reference pressure +% p_ref is obtained by calling this function with the pressure argument +% being p_ref as in [pot_rho, ~, ~] = gsw_rho_alpha_beta(SA,CT,p_ref). % -% Note that this function uses the full Gibbs function. There is an -% alternative to calling this function, namely -% gsw_rho_alpha_beta_CT25(SA,CT,p), which uses the computationally -% efficient 25-term expression for density in terms of SA, CT and p -% (McDougall et al., (2010)). For SA, CT and p values which fall inside -% the oceanographic "funnel" (McDougall et al., 2010), this -% computationally efficient (i. e. faster) 25-term version fits the -% underlying laboratory density data almost as well as does the density -% derived from the full TEOS-10 Gibbs function. +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: % SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & CT need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. % % OUTPUT: -% rho = in-situ density [ kg m^-3 ] -% alpha_wrt_CT = thermal expansion coefficient [ 1/K ] +% rho_CT = in-situ density [ kg/m ] +% alpha_CT = thermal expansion coefficient [ 1/K ] % with respect to Conservative Temperature -% beta_const_CT = saline contraction coefficient [ kg/g ] -% at constant Conservative Temperature +% beta_CT = saline (i.e. haline) contraction [ kg/g ] +% coefficient at constant Conservative Temperature % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (30th September, 2010) +% VERSION NUMBER: 3.0 (3rd April, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of % seawater - 2010: Calculation and use of thermodynamic properties. % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See sections (2.8), (2.18) and (2.19) of this TEOS-10 Manual. +% See appendix A.20 and appendix K of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -67,7 +75,7 @@ if ~(nargin == 3) error('gsw_rho_alpha_beta_CT: Requires three inputs') end %if -if ~(nargout == 3) +if ~(nargout == 3 | nargout == 4) error('gsw_rho_alpha_beta_CT: Requires three outputs') end %if @@ -86,7 +94,7 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok @@ -95,9 +103,9 @@ end %if if ms == 1 - SA = SA'; - CT = CT'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -107,17 +115,12 @@ % Start of the calculation %-------------------------------------------------------------------------- -pt0 = gsw_pt_from_CT(SA,CT); -pr0 = zeros(size(SA)); -t = gsw_pt_from_t(SA,pt0,pr0,p); -rho = gsw_rho(SA,t,p); -alpha_wrt_CT = gsw_alpha_wrt_CT(SA,t,p); -beta_const_CT = gsw_beta_const_CT(SA,t,p); +[rho_CT, alpha_CT, beta_CT] = gsw_rho_alpha_beta(SA,CT,p); if transposed - rho = rho'; - alpha_wrt_CT = alpha_wrt_CT'; - beta_const_CT = beta_const_CT'; + rho_CT = rho_CT.'; + alpha_CT = alpha_CT.'; + beta_CT = beta_CT.'; end end diff --git a/Toolbox/gsw_rho_alpha_beta_CT25.m b/Toolbox/gsw_rho_alpha_beta_CT25.m deleted file mode 100644 index c0edb1e..0000000 --- a/Toolbox/gsw_rho_alpha_beta_CT25.m +++ /dev/null @@ -1,215 +0,0 @@ -function [rho, alpha_wrt_CT, beta_const_CT, in_funnel] = gsw_rho_alpha_beta_CT25(SA,CT,p) - -% gsw_rho_alpha_beta_CT25 In-situ density, thermal expansion & saline -% contraction coefficient (25-term equation) -%========================================================================== -% -% USAGE: -% [rho, alpha_wrt_CT, beta_const_CT, in_funnel] = gsw_rho_alpha_beta_CT25(SA,CT,p) -% -% DESCRIPTION: -% Calculates in-situ density, the appropiate thermal expansion coefficient -% and the appropriate saline contraction coefficient of seawater from -% Absolute Salinity and Conservative Temperature. This function uses the -% computationally-efficient 25-term expression for density in terms of -% SA, CT and p (McDougall et al., 2010). -% -% Note that potential density (pot_rho) with respect to reference pressure -% pr is obtained by calling this function with the pressure argument being -% pr as in [pot_rho, ~, ~, in_funnel] = gsw_rho_alpha_beta_CT25(SA,CT,pr). -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) -% -% SA & CT need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. -% -% OUTPUT: -% rho = in-situ density [ kg m^-3 ] -% alpha_wrt_CT = thermal expansion coefficient [ 1/K ] -% with respect to Conservative Temperature -% beta_const_CT = saline (i.e. haline) contraction coefficient [ kg/g ] -% at constant Conservative Temperature -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). -% -% AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] -% -% VERSION NUMBER: 2.0 (23rd July, 2010) -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See appendix A.20 and appendix K of this TEOS-10 Manual. -% -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 3) - error('gsw_rho_alpha_beta_CT25: Requires three inputs') -end %if -if ~(nargout == 3 | nargout == 4) - error('gsw_rho_alpha_beta_CT25: Requires three or four outputs') -end %if - -[ms,ns] = size(SA); -[mt,nt] = size(CT); -[mp,np] = size(p); - -if (mt ~= ms | nt ~= ns) - error('gsw_rho_alpha_beta_CT25: SA and CT must have same dimensions') -end - -if (mp == 1) & (np == 1) % p scalar - fill to size of SA - p = p*ones(size(SA)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_rho_alpha_beta_CT25: Inputs array dimensions arguments do not agree') -end %if - -if ms == 1 - SA = SA'; - CT = CT'; - p = p'; - transposed = 1; -else - transposed = 0; -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -% These few lines ensure that SA is non-negative. -[I_neg_SA] = find(SA < 0); -if ~isempty(I_neg_SA) - SA(I_neg_SA) = 0; -end - -in_funnel = gsw_infunnel(SA,CT,p); - -CT2 = CT.*CT; -sqrtSA = sqrt(SA); -pCT = p.*CT; - -anum = 9.9984380290708214e+002 + ... - CT.*( 7.1188090678940910e+000 + ... - CT.*(-1.9459922513379687e-002 + ... - CT * 6.1748404455874641e-004)) + ... - SA.*( 2.8925731541277653e+000 + ... - CT * 2.1471495493268324e-003 + ... - SA * 1.9457531751183059e-003) + ... - p.*( 1.1930681818531748e-002+ ... - CT2 * 2.6969148011830758e-007 + ... - SA * 5.9355685925035653e-006 + ... - p.*(-2.5943389807429039e-008 + ... - CT2 * -7.2734111712822707e-012)); - -adenom = 1.00000000e+00 + ... - CT.*( 7.0547681896071576e-003 + ... - CT.*(-1.1753695605858647e-005 + ... - CT.*( 5.9219809488274903e-007 + ... - CT * 3.4887902228012519e-010))) + ... - SA.*( 2.0777716085618458e-003 + ... - CT.*(-2.2210857293722998e-008 + ... - CT2 * -3.6628141067895282e-010) + ... - sqrtSA.*( 3.4688210757917340e-006 + ... - CT2.* 8.0190541528070655e-010))+ ... - p.*( 6.8314629554123324e-006 + ... - pCT.*(CT2.* -8.5294794834485446e-017 + ... - p.* -9.2275325145038070e-018)); - -rec_adenom = ones(size(adenom))./adenom; - -rho = anum.*rec_adenom; - -rec_rho = ones(size(rho))./rho; - -anum_CT = 7.118809067894091e+00 + ... - CT.*(-3.8919845026759374e-02 + ... - CT.* 1.8524521336762394e-03) + ... - SA.* 2.1471495493268324e-03 + ... - pCT.*( 5.393829602366152e-07 - ... - p.* 1.454682234256454e-11); - -adenom_CT = 7.0547681896071576d-03 + ... - CT.*(-2.35073912117172980d-05 + ... - CT.*( 1.7765942846482467d-06 + ... - CT.* 1.3955160891205007d-09)) + ... - SA.*(-2.2210857293722998d-08 - ... - CT2.* 1.09884423203685860d-09 + ... - CT.*sqrtSA.* 1.6038108305614131d-09) - ... - p.*p.*(CT2.* 2.5588438450345636d-16 + ... - p.* 9.227532514503807d-18); - -alpha_wrt_CT = (adenom_CT - anum_CT.*rec_rho).*rec_adenom; - -anum_SA = 2.8925731541277653 + ... - CT.* 2.1471495493268324e-03 + ... - SA.* 3.8915063502366117e-03 + ... - p.* 5.935568592503565e-06; - -adenom_SA = 2.077771608561846e-03 + ... - CT.*(-2.2210857293722998e-08 - ... - CT2.* 3.6628141067895287e-10) + ... - sqrtSA.*( 5.203231613687601e-06 + ... - CT2.* 1.2028581229210597e-09); - -beta_const_CT = (anum_SA.*rec_rho - adenom_SA).*rec_adenom; - -%-------------------------------------------------------------------------- -% This function calculates rho, alpha_wrt_CT and beta_const_CT using the -% computationally-efficient 25-term expression for density in terms of SA, -% CT and p. If one wanted to compute rho, alpha_wrt_CT and beta_const_CT -% with the full TEOS-10 Gibbs function expression for density, the -% following lines of code will do this. -% -% pt0 = gsw_pt_from_CT(SA,CT); -% pr0 = zeros(size(SA)); -% t = gsw_pt_from_t(SA,pt0,pr0,p); -% rho = gsw_rho(SA,t,p); -% alpha_wrt_CT = gsw_alpha_wrt_CT(SA,t,p); -% beta_const_CT = gsw_beta_const_CT(SA,t,p); -% -% or call the following, it is identical to the lines above. -% -% [rho, alpha_wrt_CT, beta_const_CT] = gsw_rho_alpha_beta_CT(SA,CT,p) -% -%--------------This is the end of the alternative code--------------------- - -if transposed - rho = rho'; - alpha_wrt_CT = alpha_wrt_CT'; - beta_const_CT = beta_const_CT'; - in_funnel = in_funnel'; -end - -end diff --git a/Toolbox/gsw_rho_alpha_beta_CT_exact.m b/Toolbox/gsw_rho_alpha_beta_CT_exact.m new file mode 100644 index 0000000..fc82a30 --- /dev/null +++ b/Toolbox/gsw_rho_alpha_beta_CT_exact.m @@ -0,0 +1,116 @@ +function [rho_CT_exact, alpha_CT_exact, beta_CT_exact] = gsw_rho_alpha_beta_CT_exact(SA,CT,p) + +% gsw_rho_alpha_beta_CT_exact in-situ density, thermal expansion +% & saline contraction coefficient from CT +%========================================================================== +% +% USAGE: +% [rho_CT_exact, alpha_CT_exact, beta_CT_exact] = gsw_rho_alpha_beta_CT_exact(SA,CT,p) +% +% DESCRIPTION: +% Calculates in-situ density, the appropiate thermal expansion coefficient +% and the appropriate saline contraction coefficient of seawater from +% Absolute Salinity and Conservative Temperature. +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely +% gsw_rho_alpha_beta(SA,CT,p), which uses the computationally-efficient +% 48-term expression for density in terms of SA, CT and p (McDougall et +% al., 2011). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% rho_CT_exact = in-situ density [ kg/m^3 ] +% alpha_CT_exact = thermal expansion coefficient [ 1/K ] +% with respect to Conservative Temperature +% beta_CT_exact = saline contraction coefficient [ kg/g ] +% at constant Conservative Temperature +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (23rd March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See sections (2.8), (2.18) and (2.19) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_rho_alpha_beta_CT_exact: Requires three inputs') +end %if +if ~(nargout == 3) + error('gsw_rho_alpha_beta_CT_exact: Requires three outputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_rho_alpha_beta_CT_exact: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_rho_alpha_beta_CT_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +t = gsw_t_from_CT(SA,CT,p); +rho_CT_exact = gsw_rho_t_exact(SA,t,p); +alpha_CT_exact = gsw_alpha_wrt_CT_t_exact(SA,t,p); +beta_CT_exact = gsw_beta_const_CT_t_exact(SA,t,p); + +if transposed + rho_CT_exact = rho_CT_exact.'; + alpha_CT_exact = alpha_CT_exact.'; + beta_CT_exact = beta_CT_exact.'; +end + +end diff --git a/Toolbox/gsw_rho_t_exact.m b/Toolbox/gsw_rho_t_exact.m new file mode 100644 index 0000000..406abd3 --- /dev/null +++ b/Toolbox/gsw_rho_t_exact.m @@ -0,0 +1,95 @@ +function rho_t_exact = gsw_rho_t_exact(SA,t,p) + +% gsw_rho_t_exact density of seawater +%========================================================================== +% +% USAGE: +% rho_t_exact = gsw_rho_t_exact(SA,t,p) +% +% DESCRIPTION: +% Calculates in-situ density of seawater from Absolute Salinity and +% in-situ temperature. Note that the output, rho, is density, +% not density anomaly; that is, 1000 kg/m^3 is not subracted from it. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & t need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% +% OUTPUT: +% rho_t_exact = in-situ density (not density anomaly) [ kg/m^3 ] +% +% AUTHOR: +% Paul Barker, David Jackett & Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 2.8 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_rho_t_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_rho_t_exact: SA and t must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_rho_t_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +n0 = 0; +n1 = 1; + +rho_t_exact = ones(size(SA))./gsw_gibbs(n0,n0,n1,SA,t,p); + +if transposed + rho_t_exact = rho_t_exact.'; +end + +end diff --git a/Toolbox/gsw_sigma0.m b/Toolbox/gsw_sigma0.m new file mode 100644 index 0000000..742ae6a --- /dev/null +++ b/Toolbox/gsw_sigma0.m @@ -0,0 +1,149 @@ +function sigma0 = gsw_sigma0(SA,CT) + +% gsw_sigma0 potential density anomaly with reference +% sea pressure of 0 dbar (48-term equation) +%========================================================================== +% +% USAGE: +% sigma0 = gsw_sigma0(SA,CT,p) +% +% DESCRIPTION: +% Calculates potential density anomaly with reference pressure of 0 dbar, +% this being this particular potential density minus 1000 kg/m^3. This +% function has inputs of Absolute Salinity and Conservative Temperature. +% This function uses the computationally-efficient 48-term expression for +% density in terms of SA, CT and p (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% +% SA & CT need to have the same dimensions. +% +% OUTPUT: +% sigma0 = potential density anomaly with [ kg/m^3 ] +% respect to a reference pressure of 0 dbar, +% that is, this potential density - 1000 kg/m^3. +% +% AUTHOR: +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (30th July, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (A.30.1) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_sigma0: Requires two inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); + +if (mt ~= ms | nt ~= ns) + error('gsw_sigma0: SA and CT must have same dimensions') +end + +if ms == 1 + SA = SA.'; + CT = CT.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +v01 = 9.998420897506056e+2; +v02 = 2.839940833161907; +v03 = -3.147759265588511e-2; +v04 = 1.181805545074306e-3; +v05 = -6.698001071123802; +v06 = -2.986498947203215e-2; +v07 = 2.327859407479162e-4; +v08 = -3.988822378968490e-2; +v09 = 5.095422573880500e-4; +v10 = -1.426984671633621e-5; +v11 = 1.645039373682922e-7; + +% + +v21 = 1.0; +v22 = 2.775927747785646e-3; +v23 = -2.349607444135925e-5; +v24 = 1.119513357486743e-6; +v25 = 6.743689325042773e-10; +v26 = -7.521448093615448e-3; +v27 = -2.764306979894411e-5; +v28 = 1.262937315098546e-7; +v29 = 9.527875081696435e-10; +v30 = -1.811147201949891e-11; +v31 = -3.303308871386421e-5; +v32 = 3.801564588876298e-7; +v33 = -7.672876869259043e-9; +v34 = -4.634182341116144e-11; +v35 = 2.681097235569143e-12; +v36 = 5.419326551148740e-6; + +sqrtSA = sqrt(SA); + +v_hat_denominator = v01 + CT.*(v02 + CT.*(v03 + v04*CT)) ... + + SA.*(v05 + CT.*(v06 + v07*CT) ... + + sqrtSA.*(v08 + CT.*(v09 + CT.*(v10 + v11*CT)))); + +v_hat_numerator = v21 + CT.*(v22 + CT.*(v23 + CT.*(v24 + v25*CT))) ... + + SA.*(v26 + CT.*(v27 + CT.*(v28 + CT.*(v29 + v30*CT))) + v36*SA ... + + sqrtSA.*(v31 + CT.*(v32 + CT.*(v33 + CT.*(v34 + v35*CT))))); + +sigma0 = v_hat_denominator./v_hat_numerator - 1000; + +%-------------------------------------------------------------------------- +% This function calculates sigma0 using the computationally-efficient +% 48-term expression for density in terms of SA, CT and p. If one wanted +% to compute sigma0 with the full TEOS-10 Gibbs function expression for +% density, the following lines of code will enable this. +% +% pr0 = zeros(size(SA)); +% sigma0 = gsw_rho_CT_exact(SA,CT,pr0) - 1000; +% +%---------------This is the end of the alternative code-------------------- + +if transposed + sigma0 = sigma0.'; +end + +% The output, being potential density anomaly, has units of kg/m^3 and is +% potential density with 1000 kg/m^3 subtracted from it. + +end diff --git a/Toolbox/gsw_sigma0_CT.m b/Toolbox/gsw_sigma0_CT.m index 7c4fb7f..4c4e108 100644 --- a/Toolbox/gsw_sigma0_CT.m +++ b/Toolbox/gsw_sigma0_CT.m @@ -1,20 +1,34 @@ function sigma0_CT = gsw_sigma0_CT(SA,CT) -% gsw_sigma0_CT potential density anomaly with -% reference sea pressure of 0 dbar. +% gsw_sigma0_CT potential density anomaly with reference +% sea pressure of 0 dbar (48-term equation) %========================================================================== % % USAGE: -% sigma0_CT = gsw_sigma0_CT(SA,CT) +% sigma0_CT = gsw_sigma0_CT(SA,CT), or equivalently +% sigma0 = gsw_sigma0(SA,CT) +% +% Note that gsw_sigma0(SA,CT) is identical to gsw_sigma0_CT(SA,CT). +% The extra "_CT" emphasises that the input temperature is Conservative +% Temperature, but the extra "_CT" part of the function name is not +% needed. % % DESCRIPTION: % Calculates potential density anomaly with reference pressure of 0 dbar, % this being this particular potential density minus 1000 kg/m^3. This % function has inputs of Absolute Salinity and Conservative Temperature. +% This function uses the computationally-efficient 48-term expression for +% density in terms of SA, CT and p (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: % SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % % SA & CT need to have the same dimensions. % @@ -24,9 +38,9 @@ % that is, this potential density - 1000 kg/m^3. % % AUTHOR: -% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (26th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -35,6 +49,11 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See Eqn. (A.30.1) of this TEOS-10 Manual. % +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% % The software is available from http://www.TEOS-10.org % %========================================================================== @@ -55,8 +74,8 @@ end if ms == 1 - SA = SA'; - CT = CT'; + SA = SA.'; + CT = CT.'; transposed = 1; else transposed = 0; @@ -66,18 +85,10 @@ % Start of the calculation %-------------------------------------------------------------------------- -pr0 = zeros(size(SA)); -pt = gsw_pt_from_CT(SA,CT); - -n0 = 0; -n1 = 1; - -rho_0 = ones(size(SA))./gsw_gibbs(n0,n0,n1,SA,pt,pr0); - -sigma0_CT = rho_0 - 1000; +sigma0_CT = gsw_sigma0(SA,CT); if transposed - sigma0_CT = sigma0_CT'; + sigma0_CT = sigma0_CT.'; end % The output, being potential density anomaly, has units of kg/m^3 and is diff --git a/Toolbox/gsw_sigma0_CT_exact.m b/Toolbox/gsw_sigma0_CT_exact.m new file mode 100644 index 0000000..a6b471e --- /dev/null +++ b/Toolbox/gsw_sigma0_CT_exact.m @@ -0,0 +1,89 @@ +function sigma0_CT_exact = gsw_sigma0_CT_exact(SA,CT) + +% gsw_sigma0_CT_exact potential density anomaly with +% reference sea pressure of 0 dbar. +%========================================================================== +% +% USAGE: +% sigma0_CT_exact = gsw_sigma0_CT_exact(SA,CT) +% +% DESCRIPTION: +% Calculates potential density anomaly with reference pressure of 0 dbar, +% this being this particular potential density minus 1000 kg/m^3. This +% function has inputs of Absolute Salinity and Conservative Temperature. +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely gsw_sigma0_CT(SA,CT,p), +% which uses the computationally efficient 48-term expression for density +% in terms of SA, CT and p (McDougall et al., 2011). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% +% SA & CT need to have the same dimensions. +% +% OUTPUT: +% sigma0_CT_exact = potential density anomaly with [ kg/m^3 ] +% respect to a reference pressure of 0 dbar, +% that is, this potential density - 1000 kg/m^3. +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (3rd April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (A.30.1) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_sigma0_CT_exact: Requires two inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); + +if (mt ~= ms | nt ~= ns) + error('gsw_sigma0_CT_exact: SA and CT must have same dimensions') +end + +if ms == 1 + SA = SA.'; + CT = CT.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +pt0 = gsw_pt_from_CT(SA,CT); +sigma0_CT_exact = gsw_sigma0_pt0_exact(SA,pt0); + +if transposed + sigma0_CT_exact = sigma0_CT_exact.'; +end + +% The output, being potential density anomaly, has units of kg/m^3 and is +% potential density with 1000 kg/m^3 subtracted from it. + +end diff --git a/Toolbox/gsw_sigma0_pt.m b/Toolbox/gsw_sigma0_pt0_exact.m similarity index 63% rename from Toolbox/gsw_sigma0_pt.m rename to Toolbox/gsw_sigma0_pt0_exact.m index 21238c2..a42efc1 100644 --- a/Toolbox/gsw_sigma0_pt.m +++ b/Toolbox/gsw_sigma0_pt0_exact.m @@ -1,11 +1,11 @@ -function sigma0_pt = gsw_sigma0_pt(SA,pt0) +function sigma0_pt0_exact = gsw_sigma0_pt0_exact(SA,pt0) -% gsw_sigma0 Potential density anomaly, +% gsw_sigma0_pt0_exact potential density anomaly, % being potential density minus 1000 kg/m^3 -% ========================================================================= +%========================================================================== % % USAGE: -% sigma0_pt = gsw_sigma0(SA,pt0) +% sigma0_pt0_exact = gsw_sigma0_pt0_exact(SA,pt0) % % DESCRIPTION: % Calculates potential density anomaly with reference sea pressure of @@ -13,21 +13,21 @@ % temperature referenced to zero dbar. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% pt0 = potential temperature with respect to a -% reference sea pressure of 0 dbar (ITS-90) [ deg C ] +% SA = Absolute Salinity [ g/kg ] +% pt0 = potential temperature with respect to a +% reference sea pressure of 0 dbar (ITS-90) [ deg C ] % % SA & pt0 need to have the same dimensions. % % OUTPUT: -% sigma0_pt = potential density anomaly with [ kg/m^3 ] -% respect to a reference pressure of 0 dbar, -% that is, potential density minus 1000 kg/m^3. +% sigma0_pt0_exact = potential density anomaly with [ kg/m^3 ] +% respect to a reference pressure of 0 dbar, +% that is, potential density minus 1000 kg/m^3. % % AUTHOR: -% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -45,19 +45,19 @@ %-------------------------------------------------------------------------- if ~(nargin == 2) - error('gsw_sigma0: Requires two inputs') + error('gsw_sigma0_pt0_exact: Requires two inputs') end %if [ms,ns] = size(SA); [mt,nt] = size(pt0); if (mt ~= ms | nt ~= ns) - error('gsw_sigma0: SA and pt0 must have same dimensions') + error('gsw_sigma0_pt0_exact: SA and pt0 must have same dimensions') end if ms == 1 - SA = SA'; - pt0 = pt0'; + SA = SA.'; + pt0 = pt0.'; transposed = 1; else transposed = 0; @@ -73,7 +73,7 @@ SA(I_neg_SA) = 0; end -sfac = 0.0248826675584615; % sfac = 1/(40*(35.16504/35)); +sfac = 0.0248826675584615; % sfac = 1/(40*(35.16504/35)); x2 = sfac.*SA; x = sqrt(x2); y = pt0.*0.025d0; @@ -101,14 +101,22 @@ y.*(694.244814133268 + ... y.*(-297.728741987187))))); -sigma0_pt = 100000000./(g03 + g08) - 1000.0; +sigma0_pt0_exact = 100000000./(g03 + g08) - 1000.0; + +%-------------------------------------------------------------------------- +% The above code is exactly the same as the following two lines of code. +% +% pr0 = zeros(size(SA)); +% sigma0_pt_exact = gsw_rho_t_exact(SA,pt0,pr0) - 1000; +% +%---------------This is the end of the alternative code-------------------- if transposed - sigma0_pt = sigma0_pt'; + sigma0_pt0_exact = sigma0_pt0_exact.'; end % The output, being potential density anomaly, has units of kg/m^3 and is -% this particular potential density (with referece pressure (pr) = 0 dbar) +% this particular potential density (with referece pressure (p_ref) = 0 dbar) % and with 1000 kg/m^3 subtracted from it. end diff --git a/Toolbox/gsw_sigma1.m b/Toolbox/gsw_sigma1.m new file mode 100644 index 0000000..1006624 --- /dev/null +++ b/Toolbox/gsw_sigma1.m @@ -0,0 +1,104 @@ +function sigma1 = gsw_sigma1(SA,CT) + +% gsw_sigma1 potential density anomaly with reference +% sea pressure of 1000 dbar (48-term equation) +%========================================================================== +% +% USAGE: +% sigma1 = gsw_sigma1(SA,CT) +% +% DESCRIPTION: +% Calculates potential density anomaly with reference pressure of 1000 +% dbar, this being this particular potential density minus 1000 kg/m^3. +% This function has inputs of Absolute Salinity and Conservative +% Temperature. +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% +% SA & CT need to have the same dimensions. +% +% OUTPUT: +% sigma1 = potential density anomaly with [ kg/m^3 ] +% respect to a reference pressure of 1000 dbar, +% that is, this potential density - 1000 kg/m^3. +% +% AUTHOR: +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (24th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (A.30.1) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_sigma1: Requires two inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); + +if (mt ~= ms | nt ~= ns) + error('gsw_sigma1: SA and CT must have same dimensions') +end + +if ms == 1 + SA = SA.'; + CT = CT.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +pr1000 = 1000*ones(size(SA)); + +rho1 = gsw_rho(SA,CT,pr1000); + +%-------------------------------------------------------------------------- +% This function calculates rho using the computationally-efficient +% 48-term expression for density in terms of SA, CT and p. If one wanted +% to compute rho with the full TEOS-10 Gibbs function expression for +% density, the following lines of code will enable this. +% +% rho1 = gsw_rho_CT_exact(SA,CT,pr1000); +% +%---------------This is the end of the alternative code ------------------- + +sigma1 = rho1 - 1000; + +if transposed + sigma1 = sigma1.'; +end + +% The output, being potential density anomaly, has units of kg/m^3 and is +% potential density with 1000 kg/m^3 subtracted from it. + +end diff --git a/Toolbox/gsw_sigma1_CT.m b/Toolbox/gsw_sigma1_CT.m index 9bf4456..e749b20 100644 --- a/Toolbox/gsw_sigma1_CT.m +++ b/Toolbox/gsw_sigma1_CT.m @@ -1,11 +1,17 @@ function sigma1_CT = gsw_sigma1_CT(SA,CT) -% gsw_sigma1_CT potential density anomaly with -% reference sea pressure of 1000 dbar. +% gsw_sigma1_CT potential density anomaly with reference +% sea pressure of 1000 dbar (48-term equation) %========================================================================== % % USAGE: -% sigma1_CT = gsw_sigma1_CT(SA,CT) +% sigma1_CT = gsw_sigma1_CT(SA,CT), or equivalently +% sigma1 = gsw_sigma1(SA,CT) +% +% Note that gsw_sigma1(SA,CT) is identical to gsw_sigma1_CT(SA,CT). +% The extra "_CT" emphasises that the input temperature is Conservative +% Temperature, but the extra "_CT" part of the function name is not +% needed. % % DESCRIPTION: % Calculates potential density anomaly with reference pressure of 1000 @@ -13,9 +19,15 @@ % This function has inputs of Absolute Salinity and Conservative % Temperature. % +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% % INPUT: % SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % % SA & CT need to have the same dimensions. % @@ -25,9 +37,9 @@ % that is, this potential density - 1000 kg/m^3. % % AUTHOR: -% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (24th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -36,6 +48,11 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See Eqn. (A.30.1) of this TEOS-10 Manual. % +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% % The software is available from http://www.TEOS-10.org % %========================================================================== @@ -56,8 +73,8 @@ end if ms == 1 - SA = SA'; - CT = CT'; + SA = SA.'; + CT = CT.'; transposed = 1; else transposed = 0; @@ -67,19 +84,10 @@ % Start of the calculation %-------------------------------------------------------------------------- -pr0 = zeros(size(SA)); -pr1000 = 1000*ones(size(SA)); -pt0 = gsw_pt_from_CT(SA,CT); -t1000 = gsw_pt_from_t(SA,pt0,pr0,pr1000); - -n0 = 0; -n1 = 1; - -sigma1_CT = ones(size(SA))./gsw_gibbs(n0,n0,n1,SA,t1000,pr1000) ... - - 1000; +sigma1_CT = gsw_sigma1(SA,CT); if transposed - sigma1_CT = sigma1_CT'; + sigma1_CT = sigma1_CT.'; end % The output, being potential density anomaly, has units of kg/m^3 and is diff --git a/Toolbox/gsw_sigma1_CT_exact.m b/Toolbox/gsw_sigma1_CT_exact.m new file mode 100644 index 0000000..e2e59d6 --- /dev/null +++ b/Toolbox/gsw_sigma1_CT_exact.m @@ -0,0 +1,91 @@ +function sigma1_CT_exact = gsw_sigma1_CT_exact(SA,CT) + +% gsw_sigma1_CT_exact potential density anomaly with +% reference sea pressure of 1000 dbar +%========================================================================== +% +% USAGE: +% sigma1_CT_exact = gsw_sigma1_CT_exact(SA,CT) +% +% DESCRIPTION: +% Calculates potential density anomaly with reference pressure of 1000 +% dbar, this being this particular potential density minus 1000 kg/m^3. +% This function has inputs of Absolute Salinity and Conservative +% Temperature. +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely gsw_sigma1_CT(SA,CT,p), +% which uses the computationally efficient 48-term expression for density +% in terms of SA, CT and p (McDougall et al., 2011). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% +% SA & CT need to have the same dimensions. +% +% OUTPUT: +% sigma1_CT_exact = potential density anomaly with [ kg/m^3 ] +% respect to a reference pressure of 1000 dbar, +% that is, this potential density - 1000 kg/m^3. +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (3rd April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (A.30.1) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_sigma1_CT_exact: Requires two inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); + +if (mt ~= ms | nt ~= ns) + error('gsw_sigma1_CT_exact: SA and CT must have same dimensions') +end + +if ms == 1 + SA = SA.'; + CT = CT.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +pr1000 = 1000*ones(size(SA)); +t = gsw_t_from_CT(SA,CT,pr1000); +sigma1_CT_exact = gsw_rho_t_exact(SA,t,pr1000) - 1000; + +if transposed + sigma1_CT_exact = sigma1_CT_exact.'; +end + +% The output, being potential density anomaly, has units of kg/m^3 and is +% potential density with 1000 kg/m^3 subtracted from it. + +end diff --git a/Toolbox/gsw_sigma2.m b/Toolbox/gsw_sigma2.m new file mode 100644 index 0000000..799f7a4 --- /dev/null +++ b/Toolbox/gsw_sigma2.m @@ -0,0 +1,104 @@ +function sigma2 = gsw_sigma2(SA,CT) + +% gsw_sigma2 potential density anomaly with reference +% sea pressure of 2000 dbar (48-term equation) +%========================================================================== +% +% USAGE: +% sigma2 = gsw_sigma2(SA,CT) +% +% DESCRIPTION: +% Calculates potential density anomaly with reference pressure of 2000 +% dbar, this being this particular potential density minus 1000 kg/m^3. +% This function has inputs of Absolute Salinity and Conservative +% Temperature. +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% +% SA & CT need to have the same dimensions. +% +% OUTPUT: +% sigma2 = potential density anomaly with [ kg/m^3 ] +% respect to a reference pressure of 2000 dbar, +% that is, this potential density - 1000 kg/m^3. +% +% AUTHOR: +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (24th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (A.30.1) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_sigma2: Requires two inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); + +if (mt ~= ms | nt ~= ns) + error('gsw_sigma2: SA and CT must have same dimensions') +end + +if ms == 1 + SA = SA.'; + CT = CT.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +pr2000 = 2000*ones(size(SA)); + +rho2 = gsw_rho(SA,CT,pr2000); + +%-------------------------------------------------------------------------- +% This function calculates rho using the computationally-efficient +% 48-term expression for density in terms of SA, CT and p. If one wanted +% to compute rho with the full TEOS-10 Gibbs function expression for +% density, the following lines of code will enable this. +% +% rho2 = gsw_rho_CT_exact(SA,CT,pr2000); +% +%---------------This is the end of the alternative code ------------------- + +sigma2 = rho2 - 1000; + +if transposed + sigma2 = sigma2.'; +end + +% The output, being potential density anomaly, has units of kg/m^3 and is +% potential density with 1000 kg/m^3 subtracted from it. + +end diff --git a/Toolbox/gsw_sigma2_CT.m b/Toolbox/gsw_sigma2_CT.m index 6ae61e9..f8852fa 100644 --- a/Toolbox/gsw_sigma2_CT.m +++ b/Toolbox/gsw_sigma2_CT.m @@ -1,11 +1,17 @@ function sigma2_CT = gsw_sigma2_CT(SA,CT) -% gsw_sigma2_CT potential density anomaly with -% reference sea pressure of 2000 dbar. +% gsw_sigma2_CT potential density anomaly with reference +% sea pressure of 2000 dbar (48-term equation) %========================================================================== % % USAGE: -% sigma2_CT = gsw_sigma2_CT(SA,CT) +% sigma2_CT = gsw_sigma2_CT(SA,CT), or equivalently +% sigma2 = gsw_sigma2(SA,CT) +% +% Note that gsw_sigma2(SA,CT) is identical to gsw_sigma2_CT(SA,CT). +% The extra "_CT" emphasises that the input temperature is Conservative +% Temperature, but the extra "_CT" part of the function name is not +% needed. % % DESCRIPTION: % Calculates potential density anomaly with reference pressure of 2000 @@ -13,9 +19,15 @@ % This function has inputs of Absolute Salinity and Conservative % Temperature. % +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% % INPUT: % SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % % SA & CT need to have the same dimensions. % @@ -25,9 +37,9 @@ % that is, this potential density - 1000 kg/m^3. % % AUTHOR: -% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (24th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -36,6 +48,11 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See Eqn. (A.30.1) of this TEOS-10 Manual. % +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% % The software is available from http://www.TEOS-10.org % %========================================================================== @@ -56,8 +73,8 @@ end if ms == 1 - SA = SA'; - CT = CT'; + SA = SA.'; + CT = CT.'; transposed = 1; else transposed = 0; @@ -67,19 +84,10 @@ % Start of the calculation %-------------------------------------------------------------------------- -pr0 = zeros(size(SA)); -pr2000 = 2000*ones(size(SA)); -pt0 = gsw_pt_from_CT(SA,CT); -t2000 = gsw_pt_from_t(SA,pt0,pr0,pr2000); - -n0 = 0; -n1 = 1; - -sigma2_CT = ones(size(SA))./gsw_gibbs(n0,n0,n1,SA,t2000,pr2000) ... - - 1000; +sigma2_CT = gsw_sigma2(SA,CT); if transposed - sigma2_CT = sigma2_CT'; + sigma2_CT = sigma2_CT.'; end % The output, being potential density anomaly, has units of kg/m^3 and is diff --git a/Toolbox/gsw_sigma2_CT_exact.m b/Toolbox/gsw_sigma2_CT_exact.m new file mode 100644 index 0000000..f014773 --- /dev/null +++ b/Toolbox/gsw_sigma2_CT_exact.m @@ -0,0 +1,91 @@ +function sigma2_CT_exact = gsw_sigma2_CT_exact(SA,CT) + +% gsw_sigma2_CT_exact potential density anomaly with +% reference sea pressure of 2000 dbar +%========================================================================== +% +% USAGE: +% sigma2_CT_exact = gsw_sigma2_CT_exact(SA,CT) +% +% DESCRIPTION: +% Calculates potential density anomaly with reference pressure of 2000 +% dbar, this being this particular potential density minus 1000 kg/m^3. +% This function has inputs of Absolute Salinity and Conservative +% Temperature. +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely gsw_sigma2_CT(SA,CT,p), +% which uses the computationally efficient 48-term expression for density +% in terms of SA, CT and p (McDougall et al., 2011). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% +% SA & CT need to have the same dimensions. +% +% OUTPUT: +% sigma2_CT_exact = potential density anomaly with [ kg/m^3 ] +% respect to a reference pressure of 2000 dbar, +% that is, this potential density - 1000 kg/m^3. +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (3rd April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (A.30.1) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_sigma2_CT_exact: Requires two inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); + +if (mt ~= ms | nt ~= ns) + error('gsw_sigma2_CT_exact: SA and CT must have same dimensions') +end + +if ms == 1 + SA = SA.'; + CT = CT.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +pr2000 = 2000*ones(size(SA)); +t = gsw_t_from_CT(SA,CT,pr2000); +sigma2_CT_exact = gsw_rho_t_exact(SA,t,pr2000) - 1000; + +if transposed + sigma2_CT_exact = sigma2_CT_exact.'; +end + +% The output, being potential density anomaly, has units of kg/m^3 and is +% potential density with 1000 kg/m^3 subtracted from it. + +end diff --git a/Toolbox/gsw_sigma3.m b/Toolbox/gsw_sigma3.m new file mode 100644 index 0000000..f334b3d --- /dev/null +++ b/Toolbox/gsw_sigma3.m @@ -0,0 +1,104 @@ +function sigma3 = gsw_sigma3(SA,CT) + +% gsw_sigma3 potential density anomaly with reference +% sea pressure of 3000 dbar (48-term equation) +%========================================================================== +% +% USAGE: +% sigma3 = gsw_sigma3(SA,CT) +% +% DESCRIPTION: +% Calculates potential density anomaly with reference pressure of 3000 +% dbar, this being this particular potential density minus 1000 kg/m^3. +% This function has inputs of Absolute Salinity and Conservative +% Temperature. +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% +% SA & CT need to have the same dimensions. +% +% OUTPUT: +% sigma3 = potential density anomaly with [ kg/m^3 ] +% respect to a reference pressure of 3000 dbar, +% that is, this potential density - 1000 kg/m^3. +% +% AUTHOR: +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (24th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (A.30.1) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_sigma3: Requires two inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); + +if (mt ~= ms | nt ~= ns) + error('gsw_sigma3: SA and CT must have same dimensions') +end + +if ms == 1 + SA = SA.'; + CT = CT.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +pr3000 = 3000*ones(size(SA)); + +rho3 = gsw_rho(SA,CT,pr3000); + +%-------------------------------------------------------------------------- +% This function calculates rho using the computationally-efficient +% 48-term expression for density in terms of SA, CT and p. If one wanted +% to compute rho with the full TEOS-10 Gibbs function expression for +% density, the following lines of code will enable this. +% +% rho3 = gsw_rho_CT_exact(SA,CT,pr3000); +% +%---------------This is the end of the alternative code ------------------- + +sigma3 = rho3 - 1000; + +if transposed + sigma3 = sigma3.'; +end + +% The output, being potential density anomaly, has units of kg/m^3 and is +% potential density with 1000 kg/m^3 subtracted from it. + +end diff --git a/Toolbox/gsw_sigma3_CT.m b/Toolbox/gsw_sigma3_CT.m index 6763e6c..e3e19a0 100644 --- a/Toolbox/gsw_sigma3_CT.m +++ b/Toolbox/gsw_sigma3_CT.m @@ -1,11 +1,17 @@ function sigma3_CT = gsw_sigma3_CT(SA,CT) -% gsw_sigma3_CT potential density anomaly with -% reference sea pressure of 3000 dbar. +% gsw_sigma3_CT potential density anomaly with reference +% sea pressure of 3000 dbar (48-term equation) %========================================================================== % % USAGE: -% sigma3_CT = gsw_sigma3_CT(SA,CT) +% sigma3_CT = gsw_sigma3_CT(SA,CT), or equivalently +% sigma3 = gsw_sigma3(SA,CT) +% +% Note that gsw_sigma3(SA,CT) is identical to gsw_sigma3_CT(SA,CT). +% The extra "_CT" emphasises that the input temperature is Conservative +% Temperature, but the extra "_CT" part of the function name is not +% needed. % % DESCRIPTION: % Calculates potential density anomaly with reference pressure of 3000 @@ -13,9 +19,15 @@ % This function has inputs of Absolute Salinity and Conservative % Temperature. % +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% % INPUT: % SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % % SA & CT need to have the same dimensions. % @@ -25,9 +37,9 @@ % that is, this potential density - 1000 kg/m^3. % % AUTHOR: -% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (24th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -36,6 +48,11 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See Eqn. (A.30.1) of this TEOS-10 Manual. % +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% % The software is available from http://www.TEOS-10.org % %========================================================================== @@ -56,8 +73,8 @@ end if ms == 1 - SA = SA'; - CT = CT'; + SA = SA.'; + CT = CT.'; transposed = 1; else transposed = 0; @@ -67,19 +84,10 @@ % Start of the calculation %-------------------------------------------------------------------------- -pr0 = zeros(size(SA)); -pr3000 = 3000*ones(size(SA)); -pt0 = gsw_pt_from_CT(SA,CT); -t3000 = gsw_pt_from_t(SA,pt0,pr0,pr3000); - -n0 = 0; -n1 = 1; - -sigma3_CT = ones(size(SA))./gsw_gibbs(n0,n0,n1,SA,t3000,pr3000) ... - - 1000; +sigma3_CT = gsw_sigma3(SA,CT); if transposed - sigma3_CT = sigma3_CT'; + sigma3_CT = sigma3_CT.'; end % The output, being potential density anomaly, has units of kg/m^3 and is diff --git a/Toolbox/gsw_sigma3_CT_exact.m b/Toolbox/gsw_sigma3_CT_exact.m new file mode 100644 index 0000000..5a65140 --- /dev/null +++ b/Toolbox/gsw_sigma3_CT_exact.m @@ -0,0 +1,91 @@ +function sigma3_CT_exact = gsw_sigma3_CT_exact(SA,CT) + +% gsw_sigma3_CT_exact potential density anomaly with +% reference sea pressure of 3000 dbar +%========================================================================== +% +% USAGE: +% sigma3_CT_exact = gsw_sigma3_CT_exact(SA,CT) +% +% DESCRIPTION: +% Calculates potential density anomaly with reference pressure of 3000 +% dbar, this being this particular potential density minus 1000 kg/m^3. +% This function has inputs of Absolute Salinity and Conservative +% Temperature. +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely gsw_sigma3_CT(SA,CT,p), +% which uses the computationally efficient 48-term expression for density +% in terms of SA, CT and p (McDougall et al., 2011). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% +% SA & CT need to have the same dimensions. +% +% OUTPUT: +% sigma3_CT_exact = potential density anomaly with [ kg/m^3 ] +% respect to a reference pressure of 3000 dbar, +% that is, this potential density - 1000 kg m^-3. +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (3rd April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (A.30.1) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_sigma3_CT_exact: Requires two inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); + +if (mt ~= ms | nt ~= ns) + error('gsw_sigma3_CT_exact: SA and CT must have same dimensions') +end + +if ms == 1 + SA = SA.'; + CT = CT.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +pr3000 = 3000*ones(size(SA)); +t = gsw_t_from_CT(SA,CT,pr3000); +sigma3_CT_exact = gsw_rho_t_exact(SA,t,pr3000) - 1000; + +if transposed + sigma3_CT_exact = sigma3_CT_exact.'; +end + +% The output, being potential density anomaly, has units of kg/m^3 and is +% potential density with 1000 kg/m^3 subtracted from it. + +end diff --git a/Toolbox/gsw_sigma4.m b/Toolbox/gsw_sigma4.m new file mode 100644 index 0000000..aa8b785 --- /dev/null +++ b/Toolbox/gsw_sigma4.m @@ -0,0 +1,104 @@ +function sigma4 = gsw_sigma4(SA,CT) + +% gsw_sigma4 potential density anomaly with reference +% sea pressure of 4000 dbar (48-term equation) +%========================================================================== +% +% USAGE: +% sigma4 = gsw_sigma4(SA,CT) +% +% DESCRIPTION: +% Calculates potential density anomaly with reference pressure of 4000 +% dbar, this being this particular potential density minus 1000 kg/m^3. +% This function has inputs of Absolute Salinity and Conservative +% Temperature. +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% +% SA & CT need to have the same dimensions. +% +% OUTPUT: +% sigma4 = potential density anomaly with [ kg/m^3 ] +% respect to a reference pressure of 4000 dbar, +% that is, this potential density - 1000 kg/m^3. +% +% AUTHOR: +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (24th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (A.30.1) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_sigma4: Requires two inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); + +if (mt ~= ms | nt ~= ns) + error('gsw_sigma4: SA and CT must have same dimensions') +end + +if ms == 1 + SA = SA.'; + CT = CT.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +pr4000 = 4000*ones(size(SA)); + +rho4 = gsw_rho(SA,CT,pr4000); + +%-------------------------------------------------------------------------- +% This function calculates rho using the computationally-efficient +% 48-term expression for density in terms of SA, CT and p. If one wanted +% to compute rho with the full TEOS-10 Gibbs function expression for +% density, the following lines of code will enable this. +% +% rho4 = gsw_rho_CT_exact(SA,CT,pr4000); +% +%---------------This is the end of the alternative code ------------------- + +sigma4 = rho4 - 1000; + +if transposed + sigma4 = sigma4.'; +end + +% The output, being potential density anomaly, has units of kg/m^3 and is +% potential density with 1000 kg/m^3 subtracted from it. + +end diff --git a/Toolbox/gsw_sigma4_CT.m b/Toolbox/gsw_sigma4_CT.m index 4bcd247..6ff377e 100644 --- a/Toolbox/gsw_sigma4_CT.m +++ b/Toolbox/gsw_sigma4_CT.m @@ -1,11 +1,17 @@ function sigma4_CT = gsw_sigma4_CT(SA,CT) -% gsw_sigma4_CT potential density anomaly with -% reference sea pressure of 4000 dbar. +% gsw_sigma4_CT potential density anomaly with reference +% sea pressure of 4000 dbar (48-term equation) %========================================================================== % % USAGE: -% sigma4_CT = gsw_sigma4_CT(SA,CT) +% sigma4_CT = gsw_sigma4_CT(SA,CT), or equivalently +% sigma4 = gsw_sigma4(SA,CT) +% +% Note that gsw_sigma4(SA,CT) is identical to gsw_sigma4_CT(SA,CT). +% The extra "_CT" emphasises that the input temperature is Conservative +% Temperature, but the extra "_CT" part of the function name is not +% needed. % % DESCRIPTION: % Calculates potential density anomaly with reference pressure of 4000 @@ -13,9 +19,15 @@ % This function has inputs of Absolute Salinity and Conservative % Temperature. % +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% % INPUT: % SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % % SA & CT need to have the same dimensions. % @@ -25,9 +37,9 @@ % that is, this potential density - 1000 kg/m^3. % % AUTHOR: -% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (24th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -36,6 +48,11 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See Eqn. (A.30.1) of this TEOS-10 Manual. % +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% % The software is available from http://www.TEOS-10.org % %========================================================================== @@ -56,8 +73,8 @@ end if ms == 1 - SA = SA'; - CT = CT'; + SA = SA.'; + CT = CT.'; transposed = 1; else transposed = 0; @@ -67,19 +84,10 @@ % Start of the calculation %-------------------------------------------------------------------------- -pr0 = zeros(size(SA)); -pr4000 = 4000*ones(size(SA)); -pt0 = gsw_pt_from_CT(SA,CT); -t4000 = gsw_pt_from_t(SA,pt0,pr0,pr4000); - -n0 = 0; -n1 = 1; - -sigma4_CT = ones(size(SA))./gsw_gibbs(n0,n0,n1,SA,t4000,pr4000) ... - - 1000; +sigma4_CT = gsw_sigma4(SA,CT); if transposed - sigma4_CT = sigma4_CT'; + sigma4_CT = sigma4_CT.'; end % The output, being potential density anomaly, has units of kg/m^3 and is diff --git a/Toolbox/gsw_sigma4_CT_exact.m b/Toolbox/gsw_sigma4_CT_exact.m new file mode 100644 index 0000000..0a19ef1 --- /dev/null +++ b/Toolbox/gsw_sigma4_CT_exact.m @@ -0,0 +1,91 @@ +function sigma4_CT_exact = gsw_sigma4_CT_exact(SA,CT) + +% gsw_sigma4_CT_exact potential density anomaly with +% reference sea pressure of 4000 dbar +%========================================================================== +% +% USAGE: +% sigma4_CT_exact = gsw_sigma4_CT_exact(SA,CT) +% +% DESCRIPTION: +% Calculates potential density anomaly with reference pressure of 4000 +% dbar, this being this particular potential density minus 1000 kg/m^3. +% This function has inputs of Absolute Salinity and Conservative +% Temperature. +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely gsw_sigma4_CT(SA,CT,p), +% which uses the computationally efficient 48-term expression for density +% in terms of SA, CT and p (McDougall et al., 2011). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% +% SA & CT need to have the same dimensions. +% +% OUTPUT: +% sigma4_CT_exact = potential density anomaly with [ kg/m^3 ] +% respect to a reference pressure of 4000 dbar, +% that is, this potential density - 1000 kg/m^3. +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (3rd April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (A.30.1) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2) + error('gsw_sigma4_CT_exact: Requires two inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); + +if (mt ~= ms | nt ~= ns) + error('gsw_sigma4_CT_exact: SA and CT must have same dimensions') +end + +if ms == 1 + SA = SA.'; + CT = CT.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +pr4000 = 4000*ones(size(SA)); +t = gsw_t_from_CT(SA,CT,pr4000); +sigma4_CT_exact = gsw_rho_t_exact(SA,t,pr4000) - 1000; + +if transposed + sigma4_CT_exact = sigma4_CT_exact.'; +end + +% The output, being potential density anomaly, has units of kg/m^3 and is +% potential density with 1000 kg/m^3 subtracted from it. + +end diff --git a/Toolbox/gsw_sound_speed.m b/Toolbox/gsw_sound_speed.m index 4d262ab..3a461b0 100644 --- a/Toolbox/gsw_sound_speed.m +++ b/Toolbox/gsw_sound_speed.m @@ -1,30 +1,40 @@ -function sound_speed = gsw_sound_speed(SA,t,p) +function sound_speed = gsw_sound_speed(SA,CT,p) -% gsw_sound_speed sound speed +% gsw_sound_speed sound speed (48-term equation) +% (approximate with a r.m.s. of 6.7 cm s^-1) %========================================================================== % % USAGE: -% sound_speed = gsw_sound_speed(SA,t,p) +% sound_speed = gsw_sound_speed(SA,CT,p) % % DESCRIPTION: -% Calculates the speed of sound in seawater. +% Calculates the speed of sound in seawater. This function has inputs of +% Absolute Salinity and Conservative Temperature. This function uses the +% computationally-efficient 48-term expression for density in terms of SA, +% CT and p (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % -% SA & t need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. % % OUTPUT: % sound_speed = speed of sound in seawater [ m/s ] % % AUTHOR: -% David Jackett, Paul Barker and Trevor McDougall. [ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (23rd Macrh, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -33,6 +43,11 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See Eqn. (2.17.1) of this TEOS-10 Manual. % +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% % The software is available from http://www.TEOS-10.org % %========================================================================== @@ -46,11 +61,11 @@ end %if [ms,ns] = size(SA); -[mt,nt] = size(t); +[mt,nt] = size(CT); [mp,np] = size(p); if (mt ~= ms | nt ~= ns) - error('gsw_sound_speed: SA and t must have same dimensions') + error('gsw_sound_speed: SA and CT must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -59,6 +74,9 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else @@ -66,9 +84,9 @@ end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -78,18 +96,117 @@ % Start of the calculation %-------------------------------------------------------------------------- -n0 = 0; -n1 = 1; -n2 = 2; +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +v01 = 9.998420897506056e+2; +v02 = 2.839940833161907; +v03 = -3.147759265588511e-2; +v04 = 1.181805545074306e-3; +v05 = -6.698001071123802; +v06 = -2.986498947203215e-2; +v07 = 2.327859407479162e-4; +v08 = -3.988822378968490e-2; +v09 = 5.095422573880500e-4; +v10 = -1.426984671633621e-5; +v11 = 1.645039373682922e-7; +v12 = -2.233269627352527e-2; +v13 = -3.436090079851880e-4; +v14 = 3.726050720345733e-6; +v15 = -1.806789763745328e-4; +v16 = 6.876837219536232e-7; +v17 = -3.087032500374211e-7; +v18 = -1.988366587925593e-8; +v19 = -1.061519070296458e-11; +v20 = 1.550932729220080e-10; + +v21 = 1.0; +v22 = 2.775927747785646e-3; +v23 = -2.349607444135925e-5; +v24 = 1.119513357486743e-6; +v25 = 6.743689325042773e-10; +v26 = -7.521448093615448e-3; +v27 = -2.764306979894411e-5; +v28 = 1.262937315098546e-7; +v29 = 9.527875081696435e-10; +v30 = -1.811147201949891e-11; +v31 = -3.303308871386421e-5; +v32 = 3.801564588876298e-7; +v33 = -7.672876869259043e-9; +v34 = -4.634182341116144e-11; +v35 = 2.681097235569143e-12; +v36 = 5.419326551148740e-6; +v37 = -2.742185394906099e-5; +v38 = -3.212746477974189e-7; +v39 = 3.191413910561627e-9; +v40 = -1.931012931541776e-12; +v41 = -1.105097577149576e-7; +v42 = 6.211426728363857e-10; +v43 = -1.119011592875110e-10; +v44 = -1.941660213148725e-11; +v45 = -1.864826425365600e-14; +v46 = 1.119522344879478e-14; +v47 = -1.200507748551599e-15; +v48 = 6.057902487546866e-17; + +c01 = -2.233269627352527e-2; +c02 = -3.436090079851880e-4; +c03 = 3.726050720345733e-6; +c04 = -1.806789763745328e-4; +c05 = 6.876837219536232e-7; +c06 = -6.174065000748422e-7; +c07 = -3.976733175851186e-8; +c08 = -2.123038140592916e-11; +c09 = 3.101865458440160e-10; + +c10 = -2.742185394906099e-5; +c11 = -3.212746477974189e-7; +c12 = 3.191413910561627e-9; +c13 = -1.931012931541776e-12; +c14 = -1.105097577149576e-7; +c15 = 6.211426728363857e-10; +c16 = -2.238023185750219e-10; +c17 = -3.883320426297450e-11; +c18 = -3.729652850731201e-14; +c19 = 2.239044689758956e-14; +c20 = -3.601523245654798e-15; +c21 = 1.817370746264060e-16; + +sqrtSA = sqrt(SA); + +v_hat_denominator = v01 + CT.*(v02 + CT.*(v03 + v04*CT)) ... + + SA.*(v05 + CT.*(v06 + v07*CT) ... + + sqrtSA.*(v08 + CT.*(v09 + CT.*(v10 + v11*CT)))) ... + + p.*(v12 + CT.*(v13 + v14*CT) + SA.*(v15 + v16*CT) ... + + p.*(v17 + CT.*(v18 + v19*CT) + v20*SA)); + +v_hat_numerator = v21 + CT.*(v22 + CT.*(v23 + CT.*(v24 + v25*CT))) ... + + SA.*(v26 + CT.*(v27 + CT.*(v28 + CT.*(v29 + v30*CT))) + v36*SA ... + + sqrtSA.*(v31 + CT.*(v32 + CT.*(v33 + CT.*(v34 + v35*CT))))) ... + + p.*(v37 + CT.*(v38 + CT.*(v39 + v40*CT)) ... + + SA.*(v41 + v42*CT) ... + + p.*(v43 + CT.*(v44 + v45*CT + v46*SA) ... + + p.*(v47 + v48*CT))); + +dvden_dp = c01 + CT.*(c02 + c03*CT) ... + + SA.*(c04 + c05*CT) ... + + p.*(c06 + CT.*(c07 + c08*CT) + c09*SA); -g_tt = gsw_gibbs(n0,n2,n0,SA,t,p); -g_tp = gsw_gibbs(n0,n1,n1,SA,t,p); +dvnum_dp = c10 + CT.*(c11 + CT.*(c12 + c13*CT)) ... + + SA.*(c14 + c15*CT) ... + + p.*(c16 + CT.*(c17 + c18*CT + c19*SA) ... + + p.*(c20 + c21*CT)); -sound_speed = gsw_gibbs(n0,n0,n1,SA,t,p) .* ... - sqrt(g_tt./(g_tp.*g_tp - g_tt.*gsw_gibbs(n0,n0,n2,SA,t,p))); +drho_dp = (dvden_dp.*v_hat_numerator - dvnum_dp.*v_hat_denominator)./ ... + (v_hat_numerator.*v_hat_numerator); + +sound_speed = 100*sqrt(1./drho_dp); if transposed - sound_speed = sound_speed'; + sound_speed = sound_speed.'; end end \ No newline at end of file diff --git a/Toolbox/gsw_sound_speed_CT.m b/Toolbox/gsw_sound_speed_CT.m new file mode 100644 index 0000000..5bfe8b0 --- /dev/null +++ b/Toolbox/gsw_sound_speed_CT.m @@ -0,0 +1,111 @@ +function sound_speed_CT = gsw_sound_speed_CT(SA,CT,p) + +% gsw_sound_speed_CT sound speed (48-term equation) +% (approximate with a r.m.s. of 6.7 cm s^-1) +%========================================================================== +% +% USAGE: +% sound_speed_CT = gsw_sound_speed_CT(SA,CT,p), or equivalently +% sound_speed = gsw_sound_speed(SA,CT,p) +% +% Note that gsw_sound_speed(SA,CT,p) is identical to +% gsw_sound_speed_CT(SA,CT,p). The extra "_CT" emphasises that the input +% temperature is Conservative Temperature, but the extra "_CT" part of the +% function name is not needed. +% +% DESCRIPTION: +% Calculates the speed of sound in seawater. This function has inputs of +% Absolute Salinity and Conservative Temperature. This function uses the +% computationally-efficient 48-term expression for density in terms of SA, +% CT and p (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% sound_speed_CT = speed of sound in seawater [ m/s ] +% +% AUTHOR: +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (23rd Macrh, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (2.17.1) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_sound_speed_CT: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_sound_speed_CT: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_sound_speed_CT: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +sound_speed_CT = gsw_sound_speed(SA,CT,p); + +if transposed + sound_speed_CT = sound_speed_CT.'; +end + +end \ No newline at end of file diff --git a/Toolbox/gsw_sound_speed_CT_exact.m b/Toolbox/gsw_sound_speed_CT_exact.m new file mode 100644 index 0000000..0239d45 --- /dev/null +++ b/Toolbox/gsw_sound_speed_CT_exact.m @@ -0,0 +1,92 @@ +function sound_speed_CT_exact = gsw_sound_speed_CT_exact(SA,CT,p) + +% gsw_sound_speed_CT_exact sound speed +%========================================================================== +% +% USAGE: +% sound_speed_CT = gsw_sound_speed_CT(SA,CT,p) +% +% DESCRIPTION: +% Calculates the speed of sound in seawater from Absolute Salinity and +% Conservative Temperature and pressure. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% sound_speed_CT_exact = speed of sound in seawater [ m/s ] +% +% AUTHOR: +% David Jackett, Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (5th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (2.17.1) of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_sound_speed_CT_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_sound_speed_CT_exact: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_sound_speed_CT_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +t = gsw_t_from_CT(SA,CT,p); +sound_speed_CT_exact = gsw_sound_speed_t_exact(SA,t,p); + +if transposed + sound_speed_CT_exact = sound_speed_CT_exact.'; +end + +end diff --git a/Toolbox/gsw_sound_speed_t_exact.m b/Toolbox/gsw_sound_speed_t_exact.m new file mode 100644 index 0000000..5ee77e1 --- /dev/null +++ b/Toolbox/gsw_sound_speed_t_exact.m @@ -0,0 +1,98 @@ +function sound_speed_t_exact = gsw_sound_speed_t_exact(SA,t,p) + +% gsw_sound_speed_t_exact sound speed +%========================================================================== +% +% USAGE: +% sound_speed_t_exact = gsw_sound_speed_t_exact(SA,t,p) +% +% DESCRIPTION: +% Calculates the speed of sound in seawater. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & t need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% +% OUTPUT: +% sound_speed_t_exact = speed of sound in seawater [ m/s ] +% +% AUTHOR: +% David Jackett, Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (2.17.1) of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_sound_speed_t_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_sound_speed_t_exact: SA and t must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_sound_speed_t_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +n0 = 0; +n1 = 1; +n2 = 2; + +g_tt = gsw_gibbs(n0,n2,n0,SA,t,p); +g_tp = gsw_gibbs(n0,n1,n1,SA,t,p); + +sound_speed_t_exact = gsw_gibbs(n0,n0,n1,SA,t,p) .* ... + sqrt(g_tt./(g_tp.*g_tp - g_tt.*gsw_gibbs(n0,n0,n2,SA,t,p))); + +if transposed + sound_speed_t_exact = sound_speed_t_exact.'; +end + +end \ No newline at end of file diff --git a/Toolbox/gsw_specvol.m b/Toolbox/gsw_specvol.m index c23a399..20324ca 100644 --- a/Toolbox/gsw_specvol.m +++ b/Toolbox/gsw_specvol.m @@ -1,39 +1,52 @@ -function specvol = gsw_specvol(SA,t,p) +function specvol = gsw_specvol(SA,CT,p) -% gsw_specvol specific volume +% gsw_specvol specific volume (48-term equation) %========================================================================== -% +% % USAGE: -% specvol = gsw_specvol(SA,t,p) +% specvol = gsw_specvol(SA,CT,p) % % DESCRIPTION: -% Calculates the specific volume of seawater -% +% Calculates specific volume from Absolute Salinity, Conservative +% Temperature and pressure, using the computationally-efficient 48-term +% expression for density (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % -% SA & t need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA and CT are MxN. % % OUTPUT: -% specvol = specific volume [ kg/m^3 ] +% specvol = specific volume [ m^3/kg ] % % AUTHOR: -% David Jackett & Paul Barker[ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (18th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of % seawater - 2010: Calculation and use of thermodynamic properties. % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See section 2.7 of this TEOS-10 Manual. +% See Eqn. (2.7.2) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % -% The software is available from http://www.TEOS-10.org +% The software is available from http://www.TEOS-10.org % %========================================================================== @@ -46,20 +59,12 @@ end %if [ms,ns] = size(SA); -[mt,nt] = size(t); +[mt,nt] = size(CT); [mp,np] = size(p); -if (mt == 1) & (nt == 1) % t scalar - fill to size of SA - t = t*ones(size(SA)); -elseif (ns == nt) & (mt == 1) % t is row vector, - t = t(ones(1,ms), :); % copy down each column. -elseif (ms == mt) & (nt == 1) % t is column vector, - t = t(:,ones(1,ns)); % copy across each row. -elseif (ms == mt) & (ns == nt) - % ok -else - error('gsw_specvol: Inputs array dimensions arguments do not agree') -end %if +if (mt ~= ms | nt ~= ns) + error('gsw_specvol: SA and CT must have same dimensions') +end if (mp == 1) & (np == 1) % p scalar - fill to size of SA p = p*ones(size(SA)); @@ -67,6 +72,9 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else @@ -74,9 +82,9 @@ end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -86,13 +94,98 @@ % Start of the calculation %-------------------------------------------------------------------------- -n0 = 0; -n1 = 1; +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +v01 = 9.998420897506056e+2; +v02 = 2.839940833161907; +v03 = -3.147759265588511e-2; +v04 = 1.181805545074306e-3; +v05 = -6.698001071123802; +v06 = -2.986498947203215e-2; +v07 = 2.327859407479162e-4; +v08 = -3.988822378968490e-2; +v09 = 5.095422573880500e-4; +v10 = -1.426984671633621e-5; +v11 = 1.645039373682922e-7; +v12 = -2.233269627352527e-2; +v13 = -3.436090079851880e-4; +v14 = 3.726050720345733e-6; +v15 = -1.806789763745328e-4; +v16 = 6.876837219536232e-7; +v17 = -3.087032500374211e-7; +v18 = -1.988366587925593e-8; +v19 = -1.061519070296458e-11; +v20 = 1.550932729220080e-10; +v21 = 1.0; +v22 = 2.775927747785646e-3; +v23 = -2.349607444135925e-5; +v24 = 1.119513357486743e-6; +v25 = 6.743689325042773e-10; +v26 = -7.521448093615448e-3; +v27 = -2.764306979894411e-5; +v28 = 1.262937315098546e-7; +v29 = 9.527875081696435e-10; +v30 = -1.811147201949891e-11; +v31 = -3.303308871386421e-5; +v32 = 3.801564588876298e-7; +v33 = -7.672876869259043e-9; +v34 = -4.634182341116144e-11; +v35 = 2.681097235569143e-12; +v36 = 5.419326551148740e-6; +v37 = -2.742185394906099e-5; +v38 = -3.212746477974189e-7; +v39 = 3.191413910561627e-9; +v40 = -1.931012931541776e-12; +v41 = -1.105097577149576e-7; +v42 = 6.211426728363857e-10; +v43 = -1.119011592875110e-10; +v44 = -1.941660213148725e-11; +v45 = -1.864826425365600e-14; +v46 = 1.119522344879478e-14; +v47 = -1.200507748551599e-15; +v48 = 6.057902487546866e-17; + +sqrtSA = sqrt(SA); + +v_hat_numerator = v21 + CT.*(v22 + CT.*(v23 + CT.*(v24 + v25*CT))) ... + + SA.*(v26 + CT.*(v27 + CT.*(v28 + CT.*(v29 + v30*CT))) + v36*SA ... + + sqrtSA.*(v31 + CT.*(v32 + CT.*(v33 + CT.*(v34 + v35*CT))))) ... + + p.*(v37 + CT.*(v38 + CT.*(v39 + v40*CT)) ... + + SA.*(v41 + v42*CT) ... + + p.*(v43 + CT.*(v44 + v45*CT + v46*SA) ... + + p.*(v47 + v48*CT))); + +v_hat_denominator = v01 + CT.*(v02 + CT.*(v03 + v04*CT)) ... + + SA.*(v05 + CT.*(v06 + v07*CT) ... + + sqrtSA.*(v08 + CT.*(v09 + CT.*(v10 + v11*CT)))) ... + + p.*(v12 + CT.*(v13 + v14*CT) + SA.*(v15 + v16*CT) ... + + p.*(v17 + CT.*(v18 + v19*CT) + v20*SA)); + +specvol = v_hat_numerator./v_hat_denominator; -specvol = gsw_gibbs(n0,n0,n1,SA,t,p); +%-------------------------------------------------------------------------- +% This function calculates specvol using the computationally-efficient +% 48-term expression for density in terms of SA, CT and p. If one wanted to +% compute specvol from SA, CT, and p with the full TEOS-10 Gibbs function, +% the following lines of code will enable this. +% +% pt = gsw_pt_from_CT(SA,CT); +% pr0 = zeros(size(SA)); +% t = gsw_pt_from_t(SA,pt,pr0,p); +% specvol = gsw_specvol_t_exact(SA,t,p); +% +% or call the following, it is identical to the lines above. +% +% specvol = gsw_specvol_CT_exact(SA,CT,p) +% +%-----------------This is the end of the alternative code------------------ if transposed - specvol = specvol'; + specvol = specvol.'; end end diff --git a/Toolbox/gsw_specvol_CT.m b/Toolbox/gsw_specvol_CT.m index 72504c0..80fd3de 100644 --- a/Toolbox/gsw_specvol_CT.m +++ b/Toolbox/gsw_specvol_CT.m @@ -1,40 +1,44 @@ function specvol_CT = gsw_specvol_CT(SA,CT,p) -% gsw_specvol_CT specific volume +% gsw_specvol_CT specific volume (48-term equation) %========================================================================== % % USAGE: -% specvol_CT = gsw_specvol_CT(SA,CT,p) +% specvol_CT = gsw_specvol_CT(SA,CT,p), or equivalently +% specvol = gsw_specvol(SA,CT,p) +% +% Note that gsw_specvol(SA,CT,p) is identical to gsw_specvol_CT(SA,CT,p). +% The extra "_CT" emphasises that the input temperature is Conservative +% Temperature, but the extra "_CT" part of the function name is not +% needed. % % DESCRIPTION: % Calculates specific volume from Absolute Salinity, Conservative -% Temperature and pressure. +% Temperature and pressure, using the computationally-efficient 48-term +% expression for density (McDougall et al., 2011). % -% Note that this function uses the full Gibbs function. There is an -% alternative to calling this function, namely gsw_specvol_CT25(SA,CT,p), -% which uses the computationally efficient 25-term expression for density -% in terms of SA, CT and p (McDougall et al., (2010)). For SA, CT and p -% values which fall inside the oceanographic "funnel" (McDougall et al., -% 2010), this computationally efficient (i. e. faster) 25-term version -% fits the underlying laboratory density data almost as well as does the -% density derived from the full TEOS-10 Gibbs function. +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: % SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & CT need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA and CT are MxN. % % OUTPUT: -% specvol_CT = specific volume [ kg m^-3 ] +% specvol_CT = specific volume [ m^3/kg ] % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (18th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -43,11 +47,10 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See Eqn. (2.7.2) of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -76,7 +79,7 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok @@ -85,9 +88,9 @@ end %if if ms == 1 - SA = SA'; - CT = CT'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -97,13 +100,10 @@ % Start of the calculation %-------------------------------------------------------------------------- -pt = gsw_pt_from_CT(SA,CT); -pr0 = zeros(size(SA)); -t = gsw_pt_from_t(SA,pt,pr0,p); -specvol_CT = gsw_specvol(SA,t,p); +specvol_CT = gsw_specvol(SA,CT,p); if transposed - specvol_CT = specvol_CT'; + specvol_CT = specvol_CT.'; end end diff --git a/Toolbox/gsw_specvol_CT25.m b/Toolbox/gsw_specvol_CT25.m deleted file mode 100644 index 49ff16d..0000000 --- a/Toolbox/gsw_specvol_CT25.m +++ /dev/null @@ -1,158 +0,0 @@ -function [specvol_CT25, in_funnel] = gsw_specvol_CT25(SA,CT,p) - -% gsw_specvol_CT25 specific volume (25-term equation) -%========================================================================== -% -% USAGE: -% [specvol_CT25, in_funnel] = gsw_specvol_CT25(SA,CT,p) -% -% DESCRIPTION: -% Calculates specific volume from Absolute Salinity, Conservative -% Temperature and pressure, using the computationally-efficient 25-term -% expression for density (McDougall et al., 2010). -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) -% -% SA & CT need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA and CT are MxN. -% -% OUTPUT: -% specvol_CT25 = specific volume [ kg m^-3 ] -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). -% -% AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] -% -% VERSION NUMBER: 2.0 (26th August, 2010) -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See Eqn. (2.7.2) of this TEOS-10 Manual. -% -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 3) - error('gsw_specvol_CT25: Requires three inputs') -end %if - -[ms,ns] = size(SA); -[mt,nt] = size(CT); -[mp,np] = size(p); - -if (mt ~= ms | nt ~= ns) - error('gsw_specvol_CT25: SA and CT must have same dimensions') -end - -if (mp == 1) & (np == 1) % p scalar - fill to size of SA - p = p*ones(size(SA)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_specvol_CT25: Inputs array dimensions arguments do not agree') -end %if - -if ms == 1 - SA = SA'; - CT = CT'; - p = p'; - transposed = 1; -else - transposed = 0; -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -% These few lines ensure that SA is non-negative. -[I_neg_SA] = find(SA < 0); -if ~isempty(I_neg_SA) - SA(I_neg_SA) = 0; -end - -in_funnel = gsw_infunnel(SA,CT,p); - -CT2 = CT.*CT; - -anum = 9.9984380290708214e+002 + ... - CT.*( 7.1188090678940910e+000 + ... - CT.*(-1.9459922513379687e-002 + ... - CT * 6.1748404455874641e-004)) + ... - SA.*( 2.8925731541277653e+000 + ... - CT * 2.1471495493268324e-003 + ... - SA * 1.9457531751183059e-003) + ... - p.*( 1.1930681818531748e-002 + ... - CT2 * 2.6969148011830758e-007 + ... - SA * 5.9355685925035653e-006 + ... - p.*(-2.5943389807429039e-008 + ... - CT2 * -7.2734111712822707e-012)); - -adenom = 1.00000000d+00 + ... - CT.*( 7.0547681896071576e-003 + ... - CT.*(-1.1753695605858647e-005 + ... - CT.*( 5.9219809488274903e-007 + ... - CT * 3.4887902228012519e-010))) + ... - SA.*( 2.0777716085618458e-003 + ... - CT.*(-2.2210857293722998e-008 + ... - CT2 * -3.6628141067895282e-010) + ... - sqrt(SA).*( 3.4688210757917340e-006 + ... - CT2 * 8.0190541528070655e-010)) + ... - p.*( 6.8314629554123324e-006 + ... - (p.*CT).*(CT2 *-8.5294794834485446e-017 + ... - p * -9.2275325145038070e-018)); - -specvol_CT25 = (adenom./anum); - -%-------------------------------------------------------------------------- -% This function calculates specvol_CT25 using the computationally-efficient -% 25-term expression for density in terms of SA, CT and p. If one wanted to -% compute specvol from SA, CT, and p with the full TEOS-10 Gibbs function, -% the following lines of code will enable this. -% -% pt = gsw_pt_from_CT(SA,CT); -% pr0 = zeros(size(SA)); -% t = gsw_pt_from_t(SA,pt,pr0,p); -% specvol = gsw_specvol(SA,t,p); -% -% or call the following, it is identical to the lines above. -% -% specvol = gsw_specvol_CT(SA,CT,p) -% -%-----------------This is the end of the alternative code------------------ - -if transposed - specvol_CT25 = specvol_CT25'; - in_funnel = in_funnel'; -end - -end diff --git a/Toolbox/gsw_specvol_CT_exact.m b/Toolbox/gsw_specvol_CT_exact.m new file mode 100644 index 0000000..397049e --- /dev/null +++ b/Toolbox/gsw_specvol_CT_exact.m @@ -0,0 +1,102 @@ +function specvol_CT_exact = gsw_specvol_CT_exact(SA,CT,p) + +% gsw_specvol_CT_exact specific volume +%========================================================================== +% +% USAGE: +% specvol_CT_exact = gsw_specvol_CT_exact(SA,CT,p) +% +% DESCRIPTION: +% Calculates specific volume from Absolute Salinity, Conservative +% Temperature and pressure. +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely gsw_specvol_CT(SA,CT,p), +% which uses the computationally efficient 48-term expression for density +% in terms of SA, CT and p (McDougall et al., 2011). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA and CT are MxN. +% +% OUTPUT: +% specvol_CT_exact = specific volume [ m^3/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (6th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (2.7.2) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_specvol_CT_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_specvol_CT_exact: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_specvol_CT_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +t = gsw_t_from_CT(SA,CT,p); +specvol_CT_exact = gsw_specvol_t_exact(SA,t,p); + +if transposed + specvol_CT_exact = specvol_CT_exact.'; +end + +end diff --git a/Toolbox/gsw_specvol_anom.m b/Toolbox/gsw_specvol_anom.m index eec64cf..7191988 100644 --- a/Toolbox/gsw_specvol_anom.m +++ b/Toolbox/gsw_specvol_anom.m @@ -1,33 +1,40 @@ -function specvol_anom = gsw_specvol_anom(SA,t,p) +function specvol_anom = gsw_specvol_anom(SA,CT,p) -% gsw_specvol_anom specific volume anomaly +% gsw_specvol_anom specific volume anomaly (48-term equation) %========================================================================== -% +% % USAGE: -% specvol_anom = gsw_specvol_anom(SA,t,p) +% specvol_anom = gsw_specvol_anom(SA,CT,p) % % DESCRIPTION: -% Calculates specific volume anomaly from Absolute Salinity, in-situ -% temperature and pressure, using the full TEOS-10 Gibbs function. The -% reference value of Absolute Salinity is SSO and the reference value -% of Conservative Temperature is equal to 0 degrees C. -% +% Calculates specific volume anomaly from Absolute Salinity, Conservative +% Temperature and pressure. It uses the computationally-efficient 48-term +% expression for density as a function of SA, CT and p (McDougall et al., +% 2011). The reference value of Absolute Salinity is SSO and the reference +% value of Conservative Temperature is equal to 0 degress C. +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% % INPUT: -% SA = Absolute Salinity [ g/kg ] -% t = in-situ temperature (ITS-90) [ deg C ] -% p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. % -% SA & t need to have the same dimensions, -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. -% % OUTPUT: -% specvol_anom = specific volume anomaly [ kg/m^3 ] +% specvol_anom = specific volume anomaly [ m^3/kg ] % % AUTHOR: -% Trevor McDougall & Paul Barker[ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (24th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -36,7 +43,12 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See Eqn. (3.7.3) of this TEOS-10 Manual. % -% The software is available from http://www.TEOS-10.org +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org % %========================================================================== @@ -45,15 +57,15 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_specvol_anom: Requires three inputs') + error('gsw_specvol_anom: Requires three inputs') end %if [ms,ns] = size(SA); -[mt,nt] = size(t); +[mt,nt] = size(CT); [mp,np] = size(p); -if (mt ~= ms | nt ~= ns ) - error('gsw_specvol_anom: SA and t must have same dimensions') +if (mt ~= ms | nt ~= ns) + error('gsw_specvol_anom: SA and CT must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -62,6 +74,9 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else @@ -69,9 +84,9 @@ end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -81,19 +96,98 @@ % Start of the calculation %-------------------------------------------------------------------------- -n0 = 0; -n1 = 1; +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + SA(I_neg_SA) = 0; +end + +v01 = 9.998420897506056e+2; +v02 = 2.839940833161907; +v03 = -3.147759265588511e-2; +v04 = 1.181805545074306e-3; +v05 = -6.698001071123802; +v06 = -2.986498947203215e-2; +v07 = 2.327859407479162e-4; +v08 = -3.988822378968490e-2; +v09 = 5.095422573880500e-4; +v10 = -1.426984671633621e-5; +v11 = 1.645039373682922e-7; +v12 = -2.233269627352527e-2; +v13 = -3.436090079851880e-4; +v14 = 3.726050720345733e-6; +v15 = -1.806789763745328e-4; +v16 = 6.876837219536232e-7; +v17 = -3.087032500374211e-7; +v18 = -1.988366587925593e-8; +v19 = -1.061519070296458e-11; +v20 = 1.550932729220080e-10; +v21 = 1.0; +v22 = 2.775927747785646e-3; +v23 = -2.349607444135925e-5; +v24 = 1.119513357486743e-6; +v25 = 6.743689325042773e-10; +v26 = -7.521448093615448e-3; +v27 = -2.764306979894411e-5; +v28 = 1.262937315098546e-7; +v29 = 9.527875081696435e-10; +v30 = -1.811147201949891e-11; +v31 = -3.303308871386421e-5; +v32 = 3.801564588876298e-7; +v33 = -7.672876869259043e-9; +v34 = -4.634182341116144e-11; +v35 = 2.681097235569143e-12; +v36 = 5.419326551148740e-6; +v37 = -2.742185394906099e-5; +v38 = -3.212746477974189e-7; +v39 = 3.191413910561627e-9; +v40 = -1.931012931541776e-12; +v41 = -1.105097577149576e-7; +v42 = 6.211426728363857e-10; +v43 = -1.119011592875110e-10; +v44 = -1.941660213148725e-11; +v45 = -1.864826425365600e-14; +v46 = 1.119522344879478e-14; +v47 = -1.200507748551599e-15; +v48 = 6.057902487546866e-17; + +sqrtSA = sqrt(SA); + +v_hat_numerator = v21 + CT.*(v22 + CT.*(v23 + CT.*(v24 + v25*CT))) ... + + SA.*(v26 + CT.*(v27 + CT.*(v28 + CT.*(v29 + v30*CT))) + v36*SA ... + + sqrtSA.*(v31 + CT.*(v32 + CT.*(v33 + CT.*(v34 + v35*CT))))) ... + + p.*(v37 + CT.*(v38 + CT.*(v39 + v40*CT)) ... + + SA.*(v41 + v42*CT) ... + + p.*(v43 + CT.*(v44 + v45*CT + v46*SA) ... + + p.*(v47 + v48*CT))); -SSO = 35.16504*ones(size(SA)); -CT0 = zeros(size(SA)); -pr0 = zeros(size(SA)); -pt_zero = gsw_pt_from_CT(SSO,CT0); -t_zero = gsw_pt_from_t(SSO,pt_zero,pr0,p); +v_hat_denominator = v01 + CT.*(v02 + CT.*(v03 + v04*CT)) ... + + SA.*(v05 + CT.*(v06 + v07*CT) ... + + sqrtSA.*(v08 + CT.*(v09 + CT.*(v10 + v11*CT)))) ... + + p.*(v12 + CT.*(v13 + v14*CT) + SA.*(v15 + v16*CT) ... + + p.*(v17 + CT.*(v18 + v19*CT) + v20*SA)); -specvol_anom = gsw_gibbs(n0,n0,n1,SA,t,p) - gsw_gibbs(n0,n0,n1,SSO,t_zero,p); +specvol_anom = v_hat_numerator./v_hat_denominator - gsw_specvol_SSO_0_p(p); + +%-------------------------------------------------------------------------- +% This function calculates specvol_anom using the computationally- +% efficient 48-term expression for density in terms of SA, CT and p. If +% one wanted to compute specvol_anom from SA, CT, and p with the full +% TEOS-10 Gibbs function, the following lines of code will enable this. +% +% pt = gsw_pt_from_CT(SA,CT); +% pr0 = zeros(size(SA)); +% t = gsw_pt_from_t(SA,pt,pr0,p); +% specvol_anom = gsw_specvol_anom_t_exact(SA,t,p); +% +% or call the following, it is identical to the lines above. +% +% specvol_anom = gsw_specvol_anom_CT_exact(SA,CT,p) +% +%-----------------This is the end of the alternative code------------------ if transposed - specvol_anom = specvol_anom'; + specvol_anom = specvol_anom.'; end end diff --git a/Toolbox/gsw_specvol_anom_CT.m b/Toolbox/gsw_specvol_anom_CT.m index 75b430b..715ca5e 100644 --- a/Toolbox/gsw_specvol_anom_CT.m +++ b/Toolbox/gsw_specvol_anom_CT.m @@ -1,43 +1,46 @@ function specvol_anom_CT = gsw_specvol_anom_CT(SA,CT,p) -% gsw_specvol_anom_CT specific volume anomaly +% gsw_specvol_anom_CT specific volume anomaly (48-term equation) %========================================================================== % % USAGE: -% specvol_anom_CT = gsw_specvol_anom_CT(SA,CT,p) +% specvol_anom_CT = gsw_specvol_anom_CT(SA,CT,p), or equivalently +% specvol_anom = gsw_specvol_anom(SA,CT,p) +% +% Note that gsw_specvol_anom(SA,CT,p) is identical to +% gsw_specvol_anom_CT(SA,CT,p). The extra "_CT" emphasises that the input +% temperature is Conservative Temperature, but the extra "_CT" part of the +% function name is not needed. % % DESCRIPTION: % Calculates specific volume anomaly from Absolute Salinity, Conservative -% Temperature and pressure. The reference value of Absolute Salinity is -% SSO and the reference value of Conservative Temperature is equal to -% 0 degress C. +% Temperature and pressure. It uses the computationally-efficient 48-term +% expression for density as a function of SA, CT and p (McDougall et al., +% 2011). The reference value of Absolute Salinity is SSO and the reference +% value of Conservative Temperature is equal to 0 degress C. % -% Note that this function uses the full Gibbs function. There is an -% alternative to calling this function, namely -% gsw_specvol_anom_CT25(SA,CT,p), which uses the computationally efficient -% 25-term expression for density in terms of SA, CT and p -% (McDougall et al., (2010)). For SA, CT and p values which fall inside -% the oceanographic "funnel" (McDougall et al., 2010), this -% computationally efficient (i. e. faster) 25-term version fits the -% underlying laboratory density data almost as well as does the density -% derived from the full TEOS-10 Gibbs function. +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". % % INPUT: % SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] +% CT = Conservative Temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & CT need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. % % OUTPUT: -% specvol_anom_CT = specific volume anomaly [ kg m^-3 ] +% specvol_anom_CT = specific volume anomaly [ m^3/kg ] % % AUTHOR: -% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (24th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -46,11 +49,10 @@ % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % See Eqn. (3.7.3) of this TEOS-10 Manual. % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % The software is available from http://www.TEOS-10.org % @@ -61,7 +63,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_specvol_anom_CT: Requires three inputs') + error('gsw_specvol_anom_CT: Requires three inputs') end %if [ms,ns] = size(SA); @@ -79,7 +81,7 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok @@ -88,9 +90,9 @@ end %if if ms == 1 - SA = SA'; - CT = CT'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -100,13 +102,10 @@ % Start of the calculation %-------------------------------------------------------------------------- -pt = gsw_pt_from_CT(SA,CT); -pr0 = zeros(size(SA)); -t = gsw_pt_from_t(SA,pt,pr0,p); -specvol_anom_CT = gsw_specvol_anom(SA,t,p); +specvol_anom_CT = gsw_specvol_anom(SA,CT,p); if transposed - specvol_anom_CT = specvol_anom_CT'; + specvol_anom_CT = specvol_anom_CT.'; end end diff --git a/Toolbox/gsw_specvol_anom_CT25.m b/Toolbox/gsw_specvol_anom_CT25.m deleted file mode 100644 index 15ba5ec..0000000 --- a/Toolbox/gsw_specvol_anom_CT25.m +++ /dev/null @@ -1,160 +0,0 @@ -function [specvol_anom_CT25, in_funnel] = gsw_specvol_anom_CT25(SA,CT,p) - -% gsw_specvol_anom_CT25 specific volume anomaly (25-term equation) -%========================================================================== -% -% USAGE: -% [specvol_anom_CT25, in_funnel] = gsw_specvol_anom_CT25(SA,CT,p) -% -% DESCRIPTION: -% Calculates specific volume anomaly from Absolute Salinity, Conservative -% Temperature and pressure. It uses the computationally-efficient 25-term -% expression for density as a function of SA, CT and p (McDougall et al., -% 2010). The reference value of Absolute Salinity is SSO and the reference -% value of Conservative Temperature is equal to 0 degress C. -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) -% -% SA & CT need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. -% -% OUTPUT: -% specvol_anom_CT25 = specific volume anomaly [ kg m^-3 ] -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). -% -% AUTHOR: -% Trevor McDougall, David Jackett and Paul Barker [ help_gsw@csiro.au ] -% -% VERSION NUMBER: 2.0 (26th August, 2010) -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See Eqn. (3.7.3) of this TEOS-10 Manual. -% -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 3) - error('gsw_specvol_anom_CT25: Requires three inputs') -end %if - -[ms,ns] = size(SA); -[mt,nt] = size(CT); -[mp,np] = size(p); - -if (mt ~= ms | nt ~= ns) - error('gsw_specvol_anom_CT25: SA and CT must have same dimensions') -end - -if (mp == 1) & (np == 1) % p scalar - fill to size of SA - p = p*ones(size(SA)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_specvol_anom_CT25: Inputs array dimensions arguments do not agree') -end %if - -if ms == 1 - SA = SA'; - CT = CT'; - p = p'; - transposed = 1; -else - transposed = 0; -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -% These few lines ensure that SA is non-negative. -[I_neg_SA] = find(SA < 0); -if ~isempty(I_neg_SA) - SA(I_neg_SA) = 0; -end - -in_funnel = gsw_infunnel(SA,CT,p); - -CT2 = CT.*CT; - -anum = 9.9984380290708214e+002 + ... - CT.*( 7.1188090678940910e+000 + ... - CT.*(-1.9459922513379687e-002 + ... - CT * 6.1748404455874641e-004)) + ... - SA.*( 2.8925731541277653e+000 + ... - CT * 2.1471495493268324e-003 + ... - SA * 1.9457531751183059e-003) + ... - p.*( 1.1930681818531748e-002 + ... - CT2 * 2.6969148011830758e-007 + ... - SA * 5.9355685925035653e-006 + ... - p.*(-2.5943389807429039e-008 + ... - CT2 * -7.2734111712822707e-012)); - -adenom = 1.00000000d+00 + ... - CT.*( 7.0547681896071576e-003 + ... - CT.*(-1.1753695605858647e-005 + ... - CT.*( 5.9219809488274903e-007 + ... - CT * 3.4887902228012519e-010))) + ... - SA.*( 2.0777716085618458e-003 + ... - CT.*(-2.2210857293722998e-008 + ... - CT2 * -3.6628141067895282e-010) + ... - sqrt(SA).*( 3.4688210757917340e-006 + ... - CT2 * 8.0190541528070655e-010)) + ... - p.*( 6.8314629554123324e-006 + ... - (p.*CT).*(CT2 * -8.5294794834485446e-017 + ... - p * -9.2275325145038070e-018)); - -specvol_anom_CT25 = (adenom./anum) - gsw_specvol_SSO_0_CT25(p); - -%-------------------------------------------------------------------------- -% This function calculates specvol_anom_CT25 using the computationally- -% efficient 25-term expression for density in terms of SA, CT and p. -% If one wanted to compute specvol_anom from SA, CT, and p with the full -% TEOS-10 Gibbs function, the following lines of code will enable this. -% -% pt = gsw_pt_from_CT(SA,CT); -% pr0 = zeros(size(SA)); -% t = gsw_pt_from_t(SA,pt,pr0,p); -% specvol_anom = gsw_specvol_anom(SA,t,p); -% -% or call the following, it is identical to the lines above. -% -% specvol_anom = gsw_specvol_anom_CT(SA,CT,p) -% -%-----------------This is the end of the alternative code------------------ - -if transposed - specvol_anom_CT25 = specvol_anom_CT25'; - in_funnel = in_funnel'; -end - -end diff --git a/Toolbox/gsw_specvol_anom_CT_exact.m b/Toolbox/gsw_specvol_anom_CT_exact.m new file mode 100644 index 0000000..b145692 --- /dev/null +++ b/Toolbox/gsw_specvol_anom_CT_exact.m @@ -0,0 +1,105 @@ +function specvol_anom_CT_exact = gsw_specvol_anom_CT_exact(SA,CT,p) + +% gsw_specvol_anom_CT_exact specific volume anomaly +%========================================================================== +% +% USAGE: +% specvol_anom_CT_exact = gsw_specvol_anom_CT_exact(SA,CT,p) +% +% DESCRIPTION: +% Calculates specific volume anomaly from Absolute Salinity, Conservative +% Temperature and pressure. The reference value of Absolute Salinity is +% SSO and the reference value of Conservative Temperature is equal to +% 0 degress C. +% +% Note that this function uses the full Gibbs function. There is an +% alternative to calling this function, namely +% gsw_specvol_anom_CT(SA,CT,p), which uses the computationally efficient +% 48-term expression for density in terms of SA, CT and p +% (McDougall et al., 2011). +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% specvol_anom_CT = specific volume anomaly [ m^3/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (6th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (3.7.3) of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_specvol_anom_CT_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_specvol_anom_CT_exact: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_specvol_anom_CT_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +t = gsw_t_from_CT(SA,CT,p); +specvol_anom_CT_exact = gsw_specvol_anom_t_exact(SA,t,p); + +if transposed + specvol_anom_CT_exact = specvol_anom_CT_exact.'; +end + +end diff --git a/Toolbox/gsw_beta_const_pt.m b/Toolbox/gsw_specvol_anom_t_exact.m similarity index 55% rename from Toolbox/gsw_beta_const_pt.m rename to Toolbox/gsw_specvol_anom_t_exact.m index 95890d6..890c16c 100644 --- a/Toolbox/gsw_beta_const_pt.m +++ b/Toolbox/gsw_specvol_anom_t_exact.m @@ -1,41 +1,40 @@ -function beta_const_pt = gsw_beta_const_pt(SA,t,p) +function specvol_anom_t_exact = gsw_specvol_anom_t_exact(SA,t,p) -% gsw_beta_const_pt saline contraction coefficient -% at constant potential temperature +% gsw_specvol_anom_t_exact specific volume anomaly %========================================================================== % % USAGE: -% beta_const_pt = gsw_beta_const_pt(SA,t,p) +% specvol_anom_t_exact = gsw_specvol_anom_t_exact(SA,t,p) % % DESCRIPTION: -% Calculates the saline (i.e. haline) contraction coefficient of seawater -% at constant potential temperature with a reference pressure of 0 dbar. -% +% Calculates specific volume anomaly from Absolute Salinity, in-situ +% temperature and pressure, using the full TEOS-10 Gibbs function. The +% reference value of Absolute Salinity is SSO and the reference value +% of Conservative Temperature is equal to 0 degrees C. +% % INPUT: % SA = Absolute Salinity [ g/kg ] % t = in-situ temperature (ITS-90) [ deg C ] % p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) +% ( i.e. absolute pressure - 10.1325 dbar ) % -% SA & t need to have the same dimensions. +% SA & t need to have the same dimensions, % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. -% +% % OUTPUT: -% beta_const_pt = saline contraction coefficient [ kg/g ] -% at constant potential temperature -% and with a reference pressure of 0 dbar. +% specvol_anom_t_exact = specific volume anomaly [ m^3/kg ] % % AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (23rd March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of % seawater - 2010: Calculation and use of thermodynamic properties. % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See Eqn. (2.19.2) of this TEOS-10 manual. +% See Eqn. (3.7.3) of this TEOS-10 Manual. % % The software is available from http://www.TEOS-10.org % @@ -46,15 +45,15 @@ %-------------------------------------------------------------------------- if ~(nargin == 3) - error('gsw_beta_const_pt: Requires three inputs') + error('gsw_specvol_anom_t_exact: Requires three inputs') end %if [ms,ns] = size(SA); [mt,nt] = size(t); [mp,np] = size(p); -if (mt ~= ms | nt ~= ns) - error('gsw_beta_const_t: SA and t must have same dimensions') +if (mt ~= ms | nt ~= ns ) + error('gsw_specvol_anom_t_exact: SA and t must have same dimensions') end if (mp == 1) & (np == 1) % p scalar - fill to size of SA @@ -64,18 +63,18 @@ elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. elseif (ns == mp) & (np == 1) % p is a transposed row vector, - p = p'; % transposed then + p = p.'; % transposed then p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_beta_const_pt: Inputs array dimensions arguments do not agree') + error('gsw_specvol_anom_t_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - t = t'; - p = p'; + SA = SA.'; + t = t.'; + p = p.'; transposed = 1; else transposed = 0; @@ -85,25 +84,19 @@ % Start of the calculation %-------------------------------------------------------------------------- -n0 = 0; -n1 = 1; -n2 = 2; - -pr0 = zeros(size(p)); - -pt0 = gsw_pt0_from_t(SA,t,p); - -gp = gsw_gibbs(n0,n0,n1,SA,t,p); - -factora = gsw_gibbs(n1,n1,n0,SA,t,p) - gsw_gibbs(n1,n1,n0,SA,pt0,pr0); +n0 = 0; +n1 = 1; -factor = factora./(gp.*gsw_gibbs(n0,n2,n0,SA,t,p)); +SSO = 35.16504*ones(size(SA)); +CT0 = zeros(size(SA)); +pr0 = zeros(size(SA)); +pt_zero = gsw_pt_from_CT(SSO,CT0); +t_zero = gsw_pt_from_t(SSO,pt_zero,pr0,p); -beta_const_pt = gsw_gibbs(n0,n1,n1,SA,t,p).*factor - ... - gsw_gibbs(n1,n0,n1,SA,t,p)./gp; +specvol_anom_t_exact = gsw_gibbs(n0,n0,n1,SA,t,p) - gsw_gibbs(n0,n0,n1,SSO,t_zero,p); if transposed - beta_const_pt = beta_const_pt'; + specvol_anom_t_exact = specvol_anom_t_exact.'; end end diff --git a/Toolbox/gsw_specvol_t_exact.m b/Toolbox/gsw_specvol_t_exact.m new file mode 100644 index 0000000..8c7cac1 --- /dev/null +++ b/Toolbox/gsw_specvol_t_exact.m @@ -0,0 +1,93 @@ +function specvol_t_exact = gsw_specvol_t_exact(SA,t,p) + +% gsw_specvol_t_exact specific volume +%========================================================================== +% +% USAGE: +% specvol_t_exact = gsw_specvol_t_exact(SA,t,p) +% +% DESCRIPTION: +% Calculates the specific volume of seawater. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% t = in-situ temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & t need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & t are MxN. +% +% OUTPUT: +% specvol_t_exact = specific volume [ m^3/kg ] +% +% AUTHOR: +% David Jackett and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (23rd March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 2.7 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_specvol_t_exact: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(t); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_specvol_t_exact: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_specvol_t_exact: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + t = t.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +n0 = 0; +n1 = 1; + +specvol_t_exact = gsw_gibbs(n0,n0,n1,SA,t,p); + +if transposed + specvol_t_exact = specvol_t_exact.'; +end + +end diff --git a/Toolbox/gsw_steric_height.m b/Toolbox/gsw_steric_height.m new file mode 100644 index 0000000..99be279 --- /dev/null +++ b/Toolbox/gsw_steric_height.m @@ -0,0 +1,178 @@ +function steric_height = gsw_steric_height(SA,CT,p,p_ref) + +% gsw_steric_height steric height anomaly +% (48-term equation) +%========================================================================== +% +% USAGE: +% steric_height = gsw_steric_height(SA,CT,p,p_ref) +% +% DESCRIPTION: +% Calculates steric height anomaly as the pressure integral of specific +% volume anomaly from the pressure p of the “bottle” to the reference +% pressure p_ref, divided by the constant value of the gravitational +% acceleration, 9.7963 m s^-2. That is, this function returns the dynamic +% height anomaly divided by 9.7963 m s^-2; this being the gravitational +% acceleration averaged over the surface of the global ocean (see page 46 +% of Griffies, 2004). Hence, steric_height is the steric height anomaly +% with respect to a given reference pressure p_ref. +% +% Dynamic height anomaly is the geostrophic streamfunction for the +% difference between the horizontal velocity at the pressure concerned, p, +% and the horizontal velocity at p_ref. Dynamic height anomaly is the +% exact geostrophic streamfunction in isobaric surfaces even though the +% gravitational acceleration varies with latitude and pressure. Steric +% height anomaly, being simply proportional to dynamic height anomaly, is +% also an exact geostrophic streamfunction in an isobaric surface (up to +% the constant of proportionality, 9.7963 m s^-2). +% +% Note however that steric_height is not exactly the height (in metres) +% of an isobaric surface above a geopotential surface. It is tempting to +% divide dynamic height anomaly by the local value of the gravitational +% acceleration, but doing so robs the resulting quantity of either being +% (i) an exact geostrophic streamfunction, or +% (ii) exactly the height of an isobaric surface above a geopotential +% surface. +% By using a constant value of the gravitational acceleration, we have +% retained the first of these two properties. So it should be noted that +% becasue of the variation of the gravitational acceleration with +% latitude, steric_height does not exactly represent the height of an +% isobaric surface above a geopotential surface under the assumption of +% geostropy. +% +% The reference values used for the specific volume anomaly are +% SSO = 35.16504 g/kg and CT = 0 deg C. This function calculates +% specific volume anomaly using the computationally efficient 48-term +% expression for specific volume of McDougall et al. (2011). Note that the +% 48-term equation has been fitted in a restricted range of parameter +% space, and is most accurate inside the "oceanographic funnel" described +% in McDougall et al. (2011) and IOC et al. (2010). For dynamical +% oceanography we may take the 48-term rational function expression for +% density as essentially reflecting the full accuracy of TEOS-10. The GSW +% internal library function "gsw_infunnel(SA,CT,p)" is avaialble to be +% used if one wants to test if some of one's data lies outside this +% "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% p_ref = reference pressure [ dbar ] +% ( i.e. reference absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions Mx1 or 1xN or MxN, where SA & CT are MxN. +% p_ref needs to be a single value, it can have dimensions 1x1 or Mx1 or +% 1xN or MxN. +% +% OUTPUT: +% steric_height = dynamic height anomaly divided by 9.7963 m s^-2 [ m ] +% Note. If p_ref exceeds the pressure of the deepest “bottle” on a +% vertical profile, the steric height anomaly for each “bottle” +% on the whole vertical profile is returned as NaN. +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (20th May, 2011) +% +% REFERENCES: +% Griffies, S. M., 2004: Fundamentals of Ocean Climate Models. Princeton, +% NJ: Princeton University Press, 518 pp + xxxiv. +% +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (3.7.3) and section 3.27 of this TEOS-10 Manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 4) + error('gsw_steric_height: Requires four inputs') +end %if + +unique_p_ref = unique(p_ref); +if ~isscalar(unique_p_ref) + error('gsw_steric_height: The reference pressure p_ref must be unique') +end +clear p_ref +p_ref = unique_p_ref; + +if p_ref < 0 + error('gsw_steric_height: The reference pressure p_ref must be positive') +end + +[InegSA] = find(SA < 0); +if ~isempty(InegSA) + error('gsw_steric_height: The Absolute Salinity must be positive!') +end + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (ms~=mt) | (ns~=nt) + error('gsw_steric_height: SA & CT need to have the same dimensions') +elseif (ms*ns == 1) + error('gsw_steric_height: There must be at least 2 values') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + error('gsw_steric_height: need more than one pressure') +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_steric_height: Inputs array dimensions arguments do not agree') +end %if + +[Inan] = find(isnan(SA.*CT.*p)); +SA(Inan) = NaN; +CT(Inan) = NaN; +p(Inan) = NaN; + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +if max(p(:)) < p_ref + error('gsw_steric_height: The reference pressure p_ref is deeper than all bottles') +end + +dynamic_height_anomaly = gsw_geo_strf_dyn_height(SA,CT,p,p_ref); +const_grav = 9.7963; % (Griffies, 2004); +steric_height = dynamic_height_anomaly./const_grav; + +if transposed + steric_height = steric_height.'; +end %if + +end diff --git a/Toolbox/gsw_t90_from_t48.m b/Toolbox/gsw_t90_from_t48.m index 0836bcf..db402c6 100644 --- a/Toolbox/gsw_t90_from_t48.m +++ b/Toolbox/gsw_t90_from_t48.m @@ -12,15 +12,16 @@ % data collected prior to 31/12/1967. % % INPUT: -% t48 = in-situ temperature (IPTS-48) [ deg C ] +% t48 = in-situ temperature (IPTS-48) [ deg C ] % % OUTPUT: -% t90 = in-situ temperature (ITS-90) [ deg C ] +% t90 = in-situ temperature (ITS-90) [ deg C ] % % AUTHOR: -% Paul Barker & Trevor McDougall [ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % International Temperature Scales of 1948, 1968 and 1990, an ICES diff --git a/Toolbox/gsw_t90_from_t68.m b/Toolbox/gsw_t90_from_t68.m index 8f5c0b8..e969664 100644 --- a/Toolbox/gsw_t90_from_t68.m +++ b/Toolbox/gsw_t90_from_t68.m @@ -12,15 +12,16 @@ % data collected between 1/1/1968 and 31/12/1989. % % INPUT: -% t68 = in-situ temperature (IPTS-68) [ deg C ] +% t68 = in-situ temperature (IPTS-68) [ deg C ] % % OUTPUT: -% t90 = in-situ temperature (ITS-90) [ deg C ] +% t90 = in-situ temperature (ITS-90) [ deg C ] % % AUTHOR: -% Paul Barker & Trevor McDougall [ help_gsw@csiro.au ] +% Paul Barker and Trevor McDougall [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (23rd July, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % International Temperature Scales of 1948, 1968 and 1990, an ICES @@ -41,13 +42,13 @@ %-------------------------------------------------------------------------- if ~(nargin == 1) - error('sw_t90_from_t68.m: Requires only one input argument') + error('gsw_t90_from_t68: Requires only one input argument') end %if %-------------------------------------------------------------------------- % Start of the calculation %-------------------------------------------------------------------------- -t90 = t68.*0.999760057586179; % t90 = t68./1.00024; +t90 = t68.*0.999760057586179; % t90 = t68./1.00024; end diff --git a/Toolbox/gsw_t_freezing.m b/Toolbox/gsw_t_freezing.m new file mode 100644 index 0000000..13365ca --- /dev/null +++ b/Toolbox/gsw_t_freezing.m @@ -0,0 +1,187 @@ +function t_freezing = gsw_t_freezing(SA,p,saturation_fraction) + +% gsw_t_freezing in-situ temperature at which seawater freezes +%========================================================================== +% +% USAGE: +% t_freezing = gsw_t_freezing(SA,p,saturation_fraction) +% +% DESCRIPTION: +% Calculates the in-situ temperature at which seawater freezes. +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% OPTIONAL: +% saturation_fraction = the saturation fraction of dissolved air in +% seawater +% (i.e., saturation_fraction must be between 0 and 1, and the default +% is 1, completely saturated) +% +% p & saturation_fraction (if provided) may have dimensions 1x1 or Mx1 or +% 1xN or MxN, where SA is MxN. +% +% OUTPUT: +% t_freezing = in-situ temperature at which seawater freezes. [ deg C ] +% (ITS-90) +% +% AUTHOR: +% Trevor McDougall, Paul Barker and Rainer Feistal [ help@teos-10.org ] +% +% VERSION NUMBER: 3.0 (3th November, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. +% See sections 3.33 and 3.34 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 2 | nargin == 3) + error('gsw_t_freezing: Requires either two or three inputs') +end %if + +if ~exist('saturation_fraction','var') + saturation_fraction = 1; +end + +if (saturation_fraction < 0 | saturation_fraction > 1) + error('gsw_t_freezing: saturation_fraction MUST be between zero and one.') +end + +[ms,ns] = size(SA); +[mp,np] = size(p); +[map,nap] = size(saturation_fraction); + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_t_freezing: Inputs array dimensions arguments do not agree') +end %if + +if (map == 1) & (nap == 1) % saturation_fraction scalar + saturation_fraction = saturation_fraction*ones(size(SA)); % fill to size of SA +elseif (ns == nap) & (map == 1) % saturation_fraction is row vector, + saturation_fraction = saturation_fraction(ones(1,ms), :); % copy down each column. +elseif (ms == map) & (nap == 1) % saturation_fraction is column vector, + saturation_fraction = saturation_fraction(:,ones(1,ns)); % copy across each row. +elseif (ns == map) & (nap == 1) % saturation_fraction is a transposed row vector, + saturation_fraction = saturation_fraction.'; % transposed then + saturation_fraction = saturation_fraction(ones(1,ms), :); % copy down each column. +elseif (ms == map) & (ns == nap) + % ok +else + error('gsw_t_freezing: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + p = p.'; + saturation_fraction = saturation_fraction.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% These few lines ensure that SA is non-negative. +[I_neg_SA] = find(SA < 0); +if ~isempty(I_neg_SA) + error(' gsw_CT_freezing: SA must be non-negative!') +end + +CT_freezing = gsw_CT_freezing(SA,p,saturation_fraction); +t_freezing = gsw_t_from_CT(SA,CT_freezing,p); + +%-------------------------------------------------------------------------- +% This function, gsw_t_freezing, calculates the in-situ freezing +% temperature, t_freezing, of seawater by first evaluating a polynomial of +% the Conservative Temperature at which seawater freezes, CT_freezing, +% using the GSW function gsw_CT_freezing. The in-situ freezing temperature +% is then calculated using the GSW function gsw_t_from_CT. However, if one +% wanted to compute the in-situ freezing temperature directly from a single +% polynomial expression without first calculating the Conservative +% Temperature at the freezing point, the following lines of code achieve +% this. The error of the following fit is similar to that of the present +% function, gsw_t_freezing, and ranges between -8e-4 K and 3e-4 K when +% compared with the in-situ freezing temperature evaluated by Newton- +% Raphson iteration of the equality of the chemical potentials of water in +% seawater and in ice. (Note that the in-situ freezing temperature can be +% found by this exact method using the function +% sea_ice_freezingtemperature_si in the SIA library). +% +% c0 = 0.002519; +% +% c1 = -5.946302841607319; +% c2 = 4.136051661346983; +% c3 = -1.115150523403847e1; +% c4 = 1.476878746184548e1; +% c5 = -1.088873263630961e1; +% c6 = 2.961018839640730; +% +% c7 = -7.433320943962606; +% c8 = -1.561578562479883; +% c9 = 4.073774363480365e-2; +% +% c10 = 1.158414435887717e-2; +% c11 = -4.122639292422863e-1; +% c12 = -1.123186915628260e-1; +% c13 = 5.715012685553502e-1; +% c14 = 2.021682115652684e-1; +% c15 = 4.140574258089767e-2; +% c16 = -6.034228641903586e-1; +% c17 = -1.205825928146808e-2; +% c18 = -2.812172968619369e-1; +% c19 = 1.877244474023750e-2; +% c20 = -1.204395563789007e-1; +% c21 = 2.349147739749606e-1; +% c22 = 2.748444541144219e-3; +% +% SA_r = SA.*1e-2; +% x = sqrt(SA_r); +% p_r = p.*1e-4; +% +% t_freezing = c0 ... +% + SA_r.*(c1 + x.*(c2 + x.*(c3 + x.*(c4 + x.*(c5 + c6.*x))))) ... +% + p_r.*(c7 + p_r.*(c8 + c9.*p_r)) ... +% + SA_r.*p_r.*(c10 + p_r.*(c12 + p_r.*(c15 + c21.*SA_r)) + SA_r.*(c13 + c17.*p_r + c19.*SA_r) ... +% + x.*(c11 + p_r.*(c14 + c18.*p_r) + SA_r.*(c16 + c20.*p_r + c22.*SA_r))); +% +% Adjust for the effects of dissolved air +% t_freezing = t_freezing - saturation_fraction.*(1e-3).*(2.4 - SA./70.33008); +% +%---------------This is the end of the alternative code-------------------- + +[Iout_of_range] = find(p > 10000 | SA > 120 | ... + p + SA.*71.428571428571402 > 13571.42857142857); +if ~isempty(Iout_of_range) + t_freezing(Iout_of_range) = NaN; +end + +if transposed + t_freezing = t_freezing.'; +end + +end \ No newline at end of file diff --git a/Toolbox/gsw_t_from_CT.m b/Toolbox/gsw_t_from_CT.m index 2970832..14a3f94 100644 --- a/Toolbox/gsw_t_from_CT.m +++ b/Toolbox/gsw_t_from_CT.m @@ -7,24 +7,26 @@ % t = gsw_t_from_CT(SA,CT,p) % % DESCRIPTION: -% Calculates in-situ temperature from Conservative Temperature of seawater +% Calculates in-situ temperature from the Conservative Temperature of +% seawater. % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % % SA & CT need to have the same dimensions. % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA and CT are MxN. % % OUTPUT: -% t = in-situ temperature (ITS-90) [ deg C ] +% t = in-situ temperature (ITS-90) [ deg C ] % % AUTHOR: -% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (29th March, 2011) +% This function is unchanged from version 2.0 (24th September, 2010). % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -59,6 +61,9 @@ p = p(ones(1,ms),:); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else @@ -66,9 +71,9 @@ end %if if ms == 1 - SA = SA'; - CT = CT'; - p = p'; + SA = SA.'; + CT = CT.'; + p = p.'; transposed = 1; else transposed = 0; @@ -83,7 +88,7 @@ t = gsw_pt_from_t(SA,pt0,pr0,p); if transposed - t = t'; + t = t.'; end end diff --git a/Toolbox/gsw_t_from_rho_exact.m b/Toolbox/gsw_t_from_rho_exact.m new file mode 100644 index 0000000..aaca704 --- /dev/null +++ b/Toolbox/gsw_t_from_rho_exact.m @@ -0,0 +1,233 @@ +function [t,t_multiple] = gsw_t_from_rho_exact(rho,SA,p) + +% gsw_t_from_rho_exact in-situ temperature from density +% ========================================================================= +% +% USAGE: +% [t,t_multiple] = gsw_t_from_rho_exact(rho,SA,p) +% +% DESCRIPTION: +% Calculates the in-situ temperature of a seawater sample, for given +% values of its density, Absolute Salinity and sea pressure (in dbar). +% +% INPUT: +% rho = density of a seawater sample (e.g. 1026 kg/m^3) [ kg/m^3 ] +% Note. This input has not had 1000 kg m^-3 subtracted from it. +% That is, it is 'density', not 'density anomaly'. +% SA = Absolute Salinity [ g/kg ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% rho & SA need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where rho & SA are MxN. +% +% OUTPUT: +% t = in-situ temperature (ITS-90) [ deg C ] +% t_multiple = in-situ temperature (ITS-90) [ deg C ] +% Note that at low salinities, in brackish water, there are two possible +% temperatures for a single density. This programme will output both +% valid solutions. To see this second solution the user must call the +% programme with two outputs (i.e. [t,t_multiple]), if there is only +% one possible solution and the programme has been called with two +% outputs the second variable will be set to NaN. +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (21th April, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin==3) + error('gsw_t_from_rho_exact: Requires three inputs') +end %if + +[md,nd] = size(rho); +[ms,ns] = size(SA); +[mp,np] = size(p); + +if (ms ~= md | ns ~= nd) + error('gsw_t_from_rho_exact: rho and SA must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of rho + p = p*ones(size(rho)); +elseif (nd == np) & (mp == 1) % p is row vector, + p = p(ones(1,md), :); % copy down each column. +elseif (md == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,nd)); % copy across each row. +elseif (nd == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,md), :); % copy down each column. +elseif (md == mp) & (nd == np) + % ok +else + error('gsw_t_from_rho_exact: Inputs array dimensions arguments do not agree') +end %if + +if md == 1 + rho = rho.'; + SA = SA.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +% alpha_limit is the positive value of the thermal expansion coefficient +% which is used at the freezing temperature to distinguish between +% I_salty and I_fresh. +alpha_limit = 1e-5; + +% rec_half_rho_TT is a constant representing the reciprocal of half the +% second derivative of density with respect to temperature near the +% temperature of maximum density. +rec_half_rho_TT = -110.0; + +t = nan(size(SA)); +t_multiple = nan(size(SA)); + +[I_SA_p] = find(SA<0 | SA>42 | p <-1.5 | p>12000); +if ~isempty(I_SA_p) + SA(I_SA_p) = NaN; +end + +rho_40 = gsw_rho_t_exact(SA,40*ones(size(SA)),p); +[I_rho_light] = find((rho - rho_40) < 0); +if ~isempty(I_rho_light) + SA(I_rho_light) = NaN; +end + +t_max_rho = gsw_t_maxdensity_exact(SA,p); +rho_max = gsw_rho_t_exact(SA,t_max_rho,p); +rho_extreme = rho_max; +t_freezing = gsw_t_freezing(SA,p); % this assumes that the seawater is always saturated with air +rho_freezing = gsw_rho_t_exact(SA,t_freezing,p); +[I_fr_gr_max] = find((t_freezing - t_max_rho) > 0); +rho_extreme(I_fr_gr_max) = rho_freezing(I_fr_gr_max); +[I_rho_dense] = find(rho > rho_extreme); +if ~isempty(I_rho_dense) + SA(I_rho_dense) = NaN; +end + +[I_bad] = find(isnan(SA.*p.*rho)); +if ~isempty (I_bad) + SA(I_bad) = NaN; +end + +alpha_freezing = gsw_alpha_wrt_t_exact(SA,t_freezing,p); +[I_salty] = find(alpha_freezing > alpha_limit); + +if ~isempty(I_salty) + t_diff = 40*ones(size(I_salty)) - t_freezing(I_salty); + + top = rho_40(I_salty) - rho_freezing(I_salty) ... + + rho_freezing(I_salty).*alpha_freezing(I_salty).*t_diff; + a = top./(t_diff.*t_diff); + b = - rho_freezing(I_salty).*alpha_freezing(I_salty); + c = rho_freezing(I_salty) - rho(I_salty); + sqrt_disc = sqrt(b.*b - 4*a.*c); + % the value of t(I_salty) here is the initial guess at t in the range of + % I_salty. + t(I_salty) = t_freezing(I_salty) + 0.5*(-b - sqrt_disc)./a; +end + +[I_fresh] = find(alpha_freezing <= alpha_limit); +if ~isempty(I_fresh) + t_diff = 40*ones(size(I_fresh)) - t_max_rho(I_fresh); + factor = (rho_max(I_fresh) - rho(I_fresh))./ ... + (rho_max(I_fresh) - rho_40(I_fresh)); + delta_t = t_diff.*sqrt(factor); + + [I_fresh_NR] = find(delta_t > 5); + if ~isempty(I_fresh_NR) + t(I_fresh(I_fresh_NR)) = t_max_rho(I_fresh(I_fresh_NR)) + delta_t(I_fresh_NR); + end + + [I_quad] = find(delta_t <= 5); + if ~isempty(I_quad) + t_a = nan(size(SA)); + % set the initial value of the quadratic solution roots. + t_a(I_fresh(I_quad)) = t_max_rho(I_fresh(I_quad)) + ... + sqrt(rec_half_rho_TT*(rho(I_fresh(I_quad)) - rho_max(I_fresh(I_quad)))); + for Number_of_iterations = 1:7 + t_old = t_a; + rho_old = gsw_rho_t_exact(SA,t_old,p); + factorqa = (rho_max - rho)./(rho_max - rho_old); + t_a = t_max_rho + (t_old - t_max_rho).*sqrt(factorqa); + end + [Ifrozen] = find(t_freezing - t_a < 0); + if ~isempty(Ifrozen) + t_a(Ifrozen) = NaN; + end + + t_b = nan(size(SA)); + % set the initial value of the quadratic solution routes. + t_b(I_fresh(I_quad)) = t_max_rho(I_fresh(I_quad)) - ... + sqrt(rec_half_rho_TT*(rho(I_fresh(I_quad)) - rho_max(I_fresh(I_quad)))); + for Number_of_iterations = 1:7 + t_old = t_b; + rho_old = gsw_rho_t_exact(SA,t_old,p); + factorqb = (rho_max - rho)./(rho_max - rho_old); + t_b = t_max_rho + (t_old - t_max_rho).*sqrt(factorqb); + end +% After seven iterations of this quadratic iterative procedure, +% the error in rho is no larger than 4.6x10^-13 kg/m^3. + [Ifrozen] = find(t_freezing - t_b < 0); + if ~isempty(Ifrozen) + t_b(Ifrozen) = NaN; + end + end +end + +% begin the modified Newton-Raphson iterative method, which will only +% operate on non-NaN t data. + +v_lab = ones(size(rho))./rho; +v_t = gsw_gibbs(0,1,1,SA,t,p); +for Number_of_iterations = 1:4 + t_old = t; + delta_v = gsw_gibbs(0,0,1,SA,t_old,p) - v_lab; + t = t_old - delta_v./v_t ; % this is half way through the modified N-R method + t_mean = 0.5*(t + t_old); + v_t = gsw_gibbs(0,1,1,SA,t_mean,p); + t = t_old - delta_v./v_t ; +end + +if exist('t_a','var') + [I_quad] = find(~isnan(t_a)); + if ~isempty(I_quad) + t(I_quad) = t_a(I_quad); + end +end +if exist('t_b','var') + [I_quad] = find(~isnan(t_b)); + if ~isempty(I_quad) + t_multiple(I_quad) = t_b(I_quad); + end +end +% After three iterations of this modified Newton-Raphson iteration, +% the error in rho is no larger than 4.6x10^-13 kg/m^3. + +if transposed + t = t.'; + t_multiple = t_multiple.'; +end + +end diff --git a/Toolbox/gsw_temps_maxdensity.m b/Toolbox/gsw_t_maxdensity_exact.m similarity index 54% rename from Toolbox/gsw_temps_maxdensity.m rename to Toolbox/gsw_t_maxdensity_exact.m index 6cf6869..f961932 100644 --- a/Toolbox/gsw_temps_maxdensity.m +++ b/Toolbox/gsw_t_maxdensity_exact.m @@ -1,40 +1,34 @@ -function [t_maxden, pt_maxden, CT_maxden] = gsw_temps_maxdensity(SA,p) +function t_maxdensity_exact = gsw_t_maxdensity_exact(SA,p) -% gsw_temps_maxdensity temperatures of maximum density of seawater +% gsw_t_maxdensity_exact in-situ temperature of maximum +% density of seawater % ========================================================================= % % USAGE: -% [t_maxden, pt_maxden, CT_maxden] = gsw_temps_maxdensity(SA,p) +% t_maxdensity_exact = gsw_t_maxdensity_exact(SA,p) % % DESCRIPTION: -% Calculates the temperatures of maximum density of seawater. This -% function returns the in-situ, potential, and Conservative temperatures -% at which the density of seawater is a maximum, at given Absolute -% Salinity, SA, and sea pressure, p (in dbar). +% Calculates the in-situ temperature of maximum density of seawater. +% This function returns the in-situ temperature at which the density +% of seawater is a maximum, at given Absolute Salinity, SA, and sea +% pressure, p (in dbar). % % INPUT: -% SA = Absolute Salinity [ g/kg ] -% p = sea pressure [ dbar ] -% (ie. absolute pressure - 10.1325 dbar) +% SA = Absolute Salinity [ g/kg ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) % % p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA is MxN. % % OUTPUT: -% t_maxden = In-situ temperature at which the density of seawater -% is a maximum for given Absolute Salinity and pressure, -% measured on the ITS-90 temperature scale. [ deg C ] -% pt_maxden = potential temperature at which the density of seawater -% is a maximum for given Absolute Salinity and pressure. -% This is the potential temperature referenced to a sea -% pressure of 0 dbar. [ deg C ] -% CT_maxden = Conservative Temperature at which the density of -% seawater is a maximum for given Absolute Salinity -% and pressure. [ deg C ] +% t_maxdensity_exact = in-situ temperature at which [ deg C ] +% the density of seawater is a maximum for +% given Absolute Salinity and pressure. % % AUTHOR: -% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (3rd April, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -52,11 +46,7 @@ %-------------------------------------------------------------------------- if ~(nargin == 2) - error('gsw_temps_maxdensity: Requires two inputs') -end %if - -if ~(nargout == 3) - error('gsw_temps_maxdensity: Requires three outputs') + error('gsw_t_maxdensity_exact: Requires two inputs') end %if [ms,ns] = size(SA); @@ -68,15 +58,18 @@ p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (np == 1) % p is column vector, p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. elseif (ms == mp) & (ns == np) % ok else - error('gsw_temps_maxdensity: Inputs array dimensions arguments do not agree') + error('gsw_t_maxdensity_exact: Inputs array dimensions arguments do not agree') end %if if ms == 1 - SA = SA'; - p = p'; + SA = SA.'; + p = p.'; transposed = 1; else transposed = 0; @@ -106,18 +99,12 @@ end % After three iterations of this modified Newton-Raphson iteration, the -% error in t_maxden is typically no larger than 1x10^-15 degress C. - -t_maxden = t; - -pt_maxden = gsw_pt0_from_t(SA,t_maxden,p); +% error in t_maxdensity_exact is typically no larger than 1x10^-15 degress C. -CT_maxden = gsw_CT_from_pt(SA,pt_maxden); +t_maxdensity_exact = t; if transposed - t_maxden = t_maxden'; - pt_maxden = pt_maxden'; - CT_maxden = CT_maxden'; + t_maxdensity_exact = t_maxdensity_exact.'; end end diff --git a/Toolbox/gsw_thermobaric.m b/Toolbox/gsw_thermobaric.m new file mode 100644 index 0000000..9f78e1c --- /dev/null +++ b/Toolbox/gsw_thermobaric.m @@ -0,0 +1,151 @@ +function thermobaric = gsw_thermobaric(SA,CT,p) + +% gsw_thermobaric thermobaric coefficient (48-term equation) +%========================================================================== +% +% USAGE: +% thermobaric = gsw_thermobaric(SA,CT,p) +% +% DESCRIPTION: +% Calculates the thermobaric coefficient of seawater with respect to +% Conservative Temperature. This routine calculates rho from the +% computationally-efficient 48-term expression for density in terms of +% SA, CT and p (McDougall et al., 2011). +% +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% +% INPUT: +% SA = Absolute Salinity [ g/kg ] +% CT = Conservative Temperature (ITS-90) [ deg C ] +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% +% SA & CT need to have the same dimensions. +% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. +% +% OUTPUT: +% thermobaric = thermobaric coefficient with [ 1/(K Pa) ] +% respect to Conservative Temperature. +% Note. The pressure derivative is taken with respect to +% pressure in Pa not dbar. +% +% AUTHOR: +% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (24th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqns. (3.8.2) and (P.2) of this TEOS-10 manual. +% +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_thermobaric: Requires three inputs') +end %if + +[ms,ns] = size(SA); +[mt,nt] = size(CT); +[mp,np] = size(p); + +if (mt ~= ms | nt ~= ns) + error('gsw_thermobaric: SA and CT must have same dimensions') +end + +if (mp == 1) & (np == 1) % p scalar - fill to size of SA + p = p*ones(size(SA)); +elseif (ns == np) & (mp == 1) % p is row vector, + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (np == 1) % p is column vector, + p = p(:,ones(1,ns)); % copy across each row. +elseif (ns == mp) & (np == 1) % p is a transposed row vector, + p = p.'; % transposed then + p = p(ones(1,ms), :); % copy down each column. +elseif (ms == mp) & (ns == np) + % ok +else + error('gsw_thermobaric: Inputs array dimensions arguments do not agree') +end %if + +if ms == 1 + SA = SA.'; + CT = CT.'; + p = p.'; + transposed = 1; +else + transposed = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +db2Pa = 1e4; +dp = 1e-1; % pressure increment is 1e-1 dbar (10 Pa) + +if p == 0 + p = p + dp; +end + +inds = find(p >= dp); +p_u = zeros(size(p)); +p_l = dp*ones(size(p)); + +if ~isempty(inds) + p_u(inds) = p(inds) - dp; + p_l(inds) = p(inds) + dp; +end + +[dummy,alpha,beta] = gsw_rho_alpha_beta(SA,CT,p); +[dummy,alpha_u,beta_u] = gsw_rho_alpha_beta(SA,CT,p_u); +[dummy,alpha_l,beta_l] = gsw_rho_alpha_beta(SA,CT,p_l); + +alpha_p = (alpha_u - alpha_l)./(p_u - p_l); +beta_p = (beta_u - beta_l)./(p_u - p_l); + +thermobaric = alpha_p - (alpha./beta).*beta_p; +thermobaric = thermobaric./db2Pa; % To have units of 1/(K Pa) + +%-------------------------------------------------------------------------- +% This function calculates thermobaric_CT using the computationally +% efficient 48-term expression for density in terms of SA, CT and p. If +% one wanted to compute thermobaric_CT with the full TEOS-10 Gibbs function +% expression for density, the following lines of code will do this. +% +% pr0 = zeros(size(p)); +% pt = gsw_pt_from_CT(SA,CT); +% t_l = gsw_pt_from_t(SA,pt,pr0,p_l); +% t_u = gsw_pt_from_t(SA,pt,pr0,p_u); +% t = 0.5*(t_l + t_u); +% alpha = gsw_alpha_wrt_CT_t_exact(SA,t,p); +% beta = gsw_beta_const_CT_t_exact(SA,t,p); +% alpha_p = (gsw_alpha_wrt_CT_t_exact(SA,t_u,p_u) - gsw_alpha_wrt_CT_t_exact(SA,t_l,p_l))./(p_u - p_l); +% beta_p = (gsw_beta_const_CT_t_exact(SA,t_u,p_u) - gsw_beta_const_CT_t_exact(SA,t_l,p_l))./(p_u - p_l); +% thermobaric = alpha_p - (alpha./beta).*beta_p; +% thermobaric = thermobaric./db2Pa; % To have units of 1/(K Pa) +% +%----------------This is the end of the alternative code------------------- + +if transposed + thermobaric = thermobaric.'; +end + +end diff --git a/Toolbox/gsw_thermobaric_CT25.m b/Toolbox/gsw_thermobaric_CT25.m deleted file mode 100644 index 915421b..0000000 --- a/Toolbox/gsw_thermobaric_CT25.m +++ /dev/null @@ -1,148 +0,0 @@ -function [thermobaric_CT25, in_funnel] = gsw_thermobaric_CT25(SA,CT,p) - -% gsw_thermobaric_CT25 thermobaric coefficient (25-term equation) -%========================================================================== -% -% USAGE: -% [thermobaric_CT25, in_funnel] = gsw_thermobaric_CT25(SA,CT,p) -% -% DESCRIPTION: -% Calculates the thermobaric coefficient of seawater with respect to -% Conservative Temperature. This routine calculates rho from the -% computationally-efficient 25-term expression for density in terms of -% SA, CT and p (McDougall et al., 2010). -% -% INPUT: -% SA = Absolute Salinity [ g/kg ] -% CT = Conservative Temperature [ deg C ] -% p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) -% -% SA & CT need to have the same dimensions. -% p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & CT are MxN. -% -% OUTPUT: -% thermobaric_CT25 = Thermobaric coefficient with [ 1/(K Pa) ] -% respect to Conservative Temperature. -% Note. The pressure derivative is taken with respect to -% pressure in Pa not dbar. -% -% in_funnel = 0, if SA, CT and p are outside the "funnel" -% = 1, if SA, CT and p are inside the "funnel" -% Note. The term "funnel" describes the range of SA, CT and p over which -% the error in the fit of the computationally-efficient 25-term -% expression for density was calculated (McDougall et al., 2010). -% -% AUTHOR: -% David Jackett, Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] -% -% VERSION NUMBER: 2.0 (24th August, 2010) -% -% REFERENCES: -% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of -% seawater - 2010: Calculation and use of thermodynamic properties. -% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, -% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org -% See Eqns. (3.8.2) and (P.2) of this TEOS-10 manual. -% -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, -% R. Feistel and R. W. Hallberg, 2010: A computationally efficient -% 25-term expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted to -% Ocean Science Discussions. -% -% The software is available from http://www.TEOS-10.org -% -%========================================================================== - -%-------------------------------------------------------------------------- -% Check variables and resize if necessary -%-------------------------------------------------------------------------- - -if ~(nargin == 3) - error('gsw_thermobaric_CT25: Requires three inputs') -end %if - -[ms,ns] = size(SA); -[mt,nt] = size(CT); -[mp,np] = size(p); - -if (mt ~= ms | nt ~= ns) - error('gsw_thermobaric_CT25: SA and CT must have same dimensions') -end - -if (mp == 1) & (np == 1) % p scalar - fill to size of SA - p = p*ones(size(SA)); -elseif (ns == np) & (mp == 1) % p is row vector, - p = p(ones(1,ms), :); % copy down each column. -elseif (ms == mp) & (np == 1) % p is column vector, - p = p(:,ones(1,ns)); % copy across each row. -elseif (ms == mp) & (ns == np) - % ok -else - error('gsw_thermobaric_CT25: Inputs array dimensions arguments do not agree') -end %if - -if ms == 1 - SA = SA'; - CT = CT'; - p = p'; - transposed = 1; -else - transposed = 0; -end - -%-------------------------------------------------------------------------- -% Start of the calculation -%-------------------------------------------------------------------------- - -in_funnel = gsw_infunnel(SA,CT,p); - -db2Pa = 1e4; -dp = 1e-1; % pressure increment is 1e-1 dbar (10 Pa) - -if p==0, p = p+dp; end -inds = find(p>=dp); -p_u = zeros(size(p)); -p_l = dp*ones(size(p)); -if ~isempty(inds) - p_u(inds) = p(inds)-dp; - p_l(inds) = p(inds)+dp; -end - -[dummy,alpha_CT,beta_CT,flag] = gsw_rho_alpha_beta_CT25(SA,CT,p); -[dummy,alpha_CT_u,beta_CT_u,flag] = gsw_rho_alpha_beta_CT25(SA,CT,p_u); -[dummy,alpha_CT_l,beta_CT_l,flag] = gsw_rho_alpha_beta_CT25(SA,CT,p_l); - -alpha_CT_p = (alpha_CT_u - alpha_CT_l)./(p_u-p_l); -beta_CT_p = (beta_CT_u - beta_CT_l)./(p_u-p_l); - -thermobaric_CT = alpha_CT_p - (alpha_CT./beta_CT).*beta_CT_p; -thermobaric_CT25 = thermobaric_CT./db2Pa; % To have units of 1/(K Pa) - -%-------------------------------------------------------------------------- -% This function calculates thermobaric_CT using the computationally-efficient -% 25-term expression for density in terms of SA, CT and p. If one wanted to -% compute thermobaric_CT with the full TEOS-10 Gibbs function expression -% for density, the following lines of code will do this. -% -% pr0 = zeros(size(p)); -% pt = gsw_pt_from_CT(SA,CT); -% t_l = gsw_pt_from_t(SA,pt,pr0,p_l); -% t_u = gsw_pt_from_t(SA,pt,pr0,p_u); -% t = 0.5*(t_l + t_u); -% alpha_CT = gsw_alpha_wrt_CT(SA,t,p); -% beta_CT = gsw_beta_const_CT(SA,t,p); -% alpha_CT_p = (gsw_alpha_wrt_CT(SA,t_u,p_u)-gsw_alpha_wrt_CT(SA,t_l,p_l))./(p_u-p_l); -% beta_CT_p = (gsw_beta_const_CT(SA,t_u,p_u)-gsw_beta_const_CT(SA,t_l,p_l))./(p_u-p_l); -% thermobaric_CT = alpha_CT_p - (alpha_CT./beta_CT).*beta_CT_p; -% thermobaric_CT = thermobaric_CT./db2Pa; % To have units of 1/(K Pa) -% -%----------------This is the end of the alternative code------------------- - -if transposed - thermobaric_CT25 = thermobaric_CT25'; - in_funnel = in_funnel'; -end - -end diff --git a/Toolbox/gsw_uPS.m b/Toolbox/gsw_uPS.m new file mode 100644 index 0000000..32de801 --- /dev/null +++ b/Toolbox/gsw_uPS.m @@ -0,0 +1,39 @@ +function uPS = gsw_uPS + +% gsw_uPS unit conversion factor for salinities +%========================================================================== +% +% USAGE: +% uPS = gsw_uPS +% +% DESCRIPTION: +% The unit conversion factor for salinities (35.16504/35) g/kg (Millero et +% al., 2008). Reference Salinity SR is uPS times Practical Salinity SP. +% +% OUTPUT: +% uPS = unit conversion factor for salinities [ g/kg ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org. +% See section 2.4 and Table D.4 of this TEOS-10 Manual. +% +% Millero, F. J., R. Feistel, D. G. Wright, and T. J. McDougall, 2008: +% The composition of Standard Seawater and the definition of the +% Reference-Composition Salinity Scale, Deep-Sea Res. I, 55, 50-72. +% See section 6, Eqn. (6.1) of this paper. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +uPS = 35.16504/35; + +end diff --git a/Toolbox/gsw_valence_factor.m b/Toolbox/gsw_valence_factor.m new file mode 100644 index 0000000..8dedf4e --- /dev/null +++ b/Toolbox/gsw_valence_factor.m @@ -0,0 +1,43 @@ +function valence_factor = gsw_valence_factor + +% gsw_valence_factor valence factor of Reference Salinity sea salt +%========================================================================== +% +% USAGE: +% valence_factor = gsw_valence_factor +% +% DESCRIPTION: +% This function returns the valence factor of sea salt of Reference +% Composition, 1.2452898. This valence factor is exact, and follows from +% the definition of the Reference-Composition Salinity Scale 2008 of +% Millero et al. (2008). The valence factor is the mole-weighted square +% of the charges, Z, of the ions comprising Reference Composition sea salt. +% +% OUTPUT: +% valence_factor = valence factor of sea salt of Reference Composition +% [ unitless ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Table D.4 of this TEOS-10 Manual. +% +% Millero, F. J., R. Feistel, D. G. Wright, and T. J. McDougall, 2008: +% The composition of Standard Seawater and the definition of the +% Reference-Composition Salinity Scale, Deep-Sea Res. I, 55, 50-72. +% See Eqn. (5.9) of this paper. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +valence_factor = 1.2452898; + +end diff --git a/Toolbox/gsw_ver.m b/Toolbox/gsw_ver.m new file mode 100644 index 0000000..1d2d9e7 --- /dev/null +++ b/Toolbox/gsw_ver.m @@ -0,0 +1,42 @@ +function gsw_ver + +% gsw_ver GSW Oceanographic toolbox version number +%========================================================================== +% +% USAGE: +% gsw_ver +% +% DESCRIPTION: +% This function displays the version number of the GSW Oceanographic +% toolbox. +% +% AUTHOR: +% Paul Barker and Trevor McDougall [ help@teos-10.org ] +% +% VERSION NUMBER: 3.0 (15th May, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See Eqn. (3.7.3) and section 3.27 of this TEOS-10 Manual. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +gsw_data = 'gsw_data_v3_0.mat'; +gsw_data_file = which(gsw_data); +load(gsw_data_file,'version_number','version_date'); + +disp('====================================================================') +disp(' ') +disp(' Gibbs SeaWater (GSW) Oceanographic Toolbox') +disp([' version ',version_number,' (',version_date,')']) +disp(' This toolbox uses the Absolute Salinity Anomaly Ratio ') +disp([' look-up table dataset ',gsw_data(1:(end-4))]) +disp(' ') +disp('====================================================================') + +end diff --git a/Toolbox/gsw_z_from_depth.m b/Toolbox/gsw_z_from_depth.m new file mode 100644 index 0000000..dd7fc71 --- /dev/null +++ b/Toolbox/gsw_z_from_depth.m @@ -0,0 +1,42 @@ +function z = gsw_z_from_depth(depth) + +% gsw_z_from_depth height, z, from depth +%========================================================================== +% +% USAGE: +% z = gsw_z_from_depth(depth) +% +% DESCRIPTION: +% Calculates height, z, from depth. Note that in general height is +% negative in the ocean. +% +% INPUT: +% depth = depth [ m ] +% +% OUTPUT: +% z = height [ m ] +% +% AUTHOR: +% Winston [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (26th March, 2011) +% +% This software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 1) + error('gsw_z_from_depth: Requires one input') +end %if + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +z = -depth; + +end diff --git a/Toolbox/gsw_z_from_p.m b/Toolbox/gsw_z_from_p.m index c446211..bd78823 100644 --- a/Toolbox/gsw_z_from_p.m +++ b/Toolbox/gsw_z_from_p.m @@ -1,35 +1,51 @@ -function z = gsw_z_from_p(p,lat) +function z = gsw_z_from_p(p,lat,geo_strf_dyn_height) % gsw_z_from_p height from pressure %========================================================================== % % USAGE: -% z = gsw_z_from_p(p,lat) +% z = gsw_z_from_p(p,lat,{geo_strf_dyn_height}) % % DESCRIPTION: % Calculates height from sea pressure using the computationally-efficient -% 25-term expression for density in terms of SA, CT and p. -% (McDougall et al., 2010) -% Note. Height z is NEGATIVE in the ocean. ie. Depth is -z. +% 48-term expression for density in terms of SA, CT and p (McDougall et +% al., 2011). Dynamic height anomaly, geo_strf_dyn_height, if provided, +% must be computed with its p_ref = 0 (the surface). +% +% Note. Height z is NEGATIVE in the ocean. i.e. Depth is -z. % Depth is not used in the GSW computer software library. % +% Note that the 48-term equation has been fitted in a restricted range of +% parameter space, and is most accurate inside the "oceanographic funnel" +% described in McDougall et al. (2011). The GSW library function +% "gsw_infunnel(SA,CT,p)" is avaialble to be used if one wants to test if +% some of one's data lies outside this "funnel". +% % INPUT: -% p = sea pressure [ dbar ] -% ( ie. absolute pressure - 10.1325 dbar ) -% lat = latitude in decimal degrees north [ -90 ... +90 ] -% lat may have dimensions 1x1 or Mx1 or 1xN or MxN, where p is MxN. +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% lat = latitude in decimal degrees north [ -90 ... +90 ] +% +% OPTIONAL: +% geo_strf_dyn_height = dynamic height anomaly [ m^2/s^2 ] +% Note that the refernce pressure, p_ref, of geo_strf_dyn_height must be +% zero (0) dbar. +% +% lat may have dimensions 1x1 or Mx1 or 1xN or MxN, where p is MxN. +% geo_strf_dyn_height, if provided, must have dimensions MxN which is +% the same as p. % % OUTPUT: -% z = height [ m ] +% z = height [ m ] % Note. At sea level z = 0, and since z (HEIGHT) is defined to be % positive upwards, it follows that while z is positive in the % atmosphere, it is NEGATIVE in the ocean. % % AUTHOR: -% Trevor McDougall, Claire Roberts-Thomson & Paul Barker. -% [ help_gsw@csiro.au ] +% Trevor McDougall, Claire Roberts-Thomson & Paul Barker. +% [ help_gsw@csiro.au ] % -% VERSION NUMBER: 2.0 (26th August, 2010) +% VERSION NUMBER: 3.0 (26th March, 2011) % % REFERENCES: % IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of @@ -37,11 +53,10 @@ % Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, % UNESCO (English), 196 pp. Available from http://www.TEOS-10.org % -% McDougall T. J., D. R. Jackett, P. M. Barker, C. Roberts-Thomson, R. -% Feistel and R. W. Hallberg, 2010: A computationally efficient 25-term -% expression for the density of seawater in terms of Conservative -% Temperature, and related properties of seawater. To be submitted -% to Ocean Science Discussions. +% McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2011: A +% computationally efficient 48-term expression for the density of +% seawater in terms of Conservative Temperature, and related properties +% of seawater. To be submitted to Ocean Science Discussions. % % Moritz (2000) Goedetic reference system 1980. J. Geodesy, 74, 128-133. % @@ -53,12 +68,21 @@ % Check variables and resize if necessary %-------------------------------------------------------------------------- -if ~(nargin == 2) - error('gsw_z_from_p: Requires two inputs, pressure and latitude') +if ~(nargin == 2 | nargin == 3) + error('gsw_z_from_p: Requires two or three inputs') end %if +if ~exist('geo_strf_dyn_height','var') + geo_strf_dyn_height = zeros(size(p)); +end + [mp,np] = size(p); [ml,nl] = size(lat); +[mdh,ndh] = size(geo_strf_dyn_height); + +if (mp ~= mdh) | (np ~= ndh) + error('gsw_z_from_p: pressure & dynamic height anomaly need to have the same dimensions') +end if (ml == 1) & (nl == 1) % lat scalar - fill to size of p lat = lat*ones(size(p)); @@ -66,6 +90,9 @@ lat = lat(ones(1,mp), :); % copy down each column. elseif (mp == ml) & (nl == 1) % lat is column vector, lat = lat(:,ones(1,np)); % copy across each row. +elseif (np == ml) & (nl == 1) % lat is a transposed row vector, + lat = lat.'; % transposed then + lat = lat(ones(1,mp), :); % copy down each column. elseif (mp == ml) & (np == nl) % ok else @@ -73,8 +100,9 @@ end %if if mp == 1 - p = p'; - lat = lat'; + p = p.'; + lat = lat.'; + geo_strf_dyn_height = geo_strf_dyn_height.'; transposed = 1; else transposed = 0; @@ -90,11 +118,11 @@ sin2 = X.*X; B = 9.780327*(1.0 + (5.2792e-3 + (2.32e-5*sin2)).*sin2); A = -0.5*gamma*B ; -C = gsw_enthalpy_SSO_0_CT25(p); +C = gsw_enthalpy_SSO_0_p(p) - geo_strf_dyn_height; z = -2*C./(B + sqrt(B.*B - 4.*A.*C)); if transposed - z = z'; + z = z.'; end end diff --git a/Toolbox/info.xml b/Toolbox/info.xml new file mode 100644 index 0000000..58cb82e --- /dev/null +++ b/Toolbox/info.xml @@ -0,0 +1,44 @@ + + + + + + + 3.0 + GSW Oceanographic + toolbox + /html/gsw_icon.png + /html + + + + + + + + + + + + web(which('gsw_front_page.html'),'-helpbrowser') + + /html/gsw_icon.png + + + + + + web(which('gsw_contents.html'),'-helpbrowser') + + $toolbox/matlab/icons/helpicon.gif + + + + + web http://www.TEOS-10.org -browser; + $docroot/techdoc/matlab_env/examples/webicon.gif + + + + \ No newline at end of file diff --git a/Toolbox/library/gsw_Fdelta.m b/Toolbox/library/gsw_Fdelta.m new file mode 100644 index 0000000..9debb94 --- /dev/null +++ b/Toolbox/library/gsw_Fdelta.m @@ -0,0 +1,150 @@ +function Fdelta = gsw_Fdelta(p,long,lat) + +% gsw_Fdelta Fdelta +%========================================================================== +% +% USAGE: +% Fdelta = gsw_Fdelta(p,long,lat) +% +% DESCRIPTION: +% Calculates Fdelta from the Absolute Salinity Anomaly Ratio (SAAR). It +% finds SAAR by calling the function "gsw_SAAR(p,long,lat)" and then +% simply calculates Fdelta from +% +% Fdelta = (1 + r1)SAAR/(1 - r1*SAAR) +% = (SA/Sstar) - 1 +% +% with r1 being the constant 0.35 based on the work of Pawlowicz et al. +% (2011). Note that since SAAR is everywhere less than 0.001 in the global +% ocean, Fdelta is only slighty different to 1.35*SAAR. +% +% INPUT: +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% long = longitude in decimal degrees [ 0 ... +360 ] +% or [ -180 ... +180 ] +% lat = latitude in decimal degrees north [ -90 ... +90 ] +% +% lat & long may have dimensions 1x1 or Mx1 or 1xN or MxN, +% where p is MxN. +% +% OUTPUT: +% Fdelta = ratio of SA to Sstar, minus 1 [ unitless ] +% +% AUTHOR: +% Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (26th May, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See section 2.5 and appendices A.4 and A.5 of this TEOS-10 Manual. +% +% McDougall, T.J., D.R. Jackett and F.J. Millero, 2010: An algorithm +% for estimating Absolute Salinity in the global ocean. Submitted to +% Ocean Science. A preliminary version is available at Ocean Sci. Discuss., +% 6, 215-242. +% http://www.ocean-sci-discuss.net/6/215/2009/osd-6-215-2009-print.pdf +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin==3) + error('gsw_Fdelta: Requires three inputs') +end %if + +[mp,np] = size(p); +[mla,nla] = size(lat); + +if (mla == 1) & (nla == 1) % lat is a scalar - fill to size of p + lat = lat*ones(size(p)); +elseif (np == nla) & (mla == 1) % lat is a row vector, + lat = lat(ones(1,mp), :); % copy down each column. +elseif (mp == mla) & (nla == 1) % lat is a column vector, + lat = lat(:,ones(1,np)); % copy across each row. +elseif (np == mla) & (nla == 1) % lat is a transposed row vector, + lat = lat.'; % transposed then + lat = lat(ones(1,ms), :); % copy down each column. +elseif (mp == mla) & (np == nla) + % ok +else + error('gsw_Fdelta: Inputs array dimensions arguments do not agree') +end %if + +[mlo,nlo] = size(long); +[Iwest] =find(long < 0); +if ~isempty(Iwest) + long(Iwest) = long(Iwest) + 360; +end + +if (mlo == 1) & (nlo == 1) % long is a scalar - fill to size of p + long = long*ones(size(p)); +elseif (np == nlo) & (mlo == 1) % long is a row vector, + long = long(ones(1,mp), :); % copy down each column. +elseif (mp == mlo) & (nlo == 1) % long is a column vector, + long = long(:,ones(1,np)); % copy across each row. +elseif (np == mlo) & (nlo == 1) % long is a transposed row vector, + long = long.'; % transposed then + long = long(ones(1,mp), :); % copy down each column. +elseif (ms == nlo) & (mlo == 1) % long is a transposed column vector, + long = long.'; % transposed then + long = long(:,ones(1,np)); % copy down each column. +elseif (mp == mlo) & (np == nlo) + % ok +else + error('gsw_Fdelta: Inputs array dimensions arguments do not agree') +end %if + +if mp == 1 + p = p.'; + lat = lat.'; + long = long.'; + transposed = 1; +else + transposed = 0; +end + +[Inan] = find(abs(p) == 99999 | abs(p) == 999999); +p(Inan) = NaN; +[Inan] = find(abs(long) == 9999 | abs(long) == 99999); +long(Inan) = NaN; +[Inan] = find(abs(lat) == 9999 | abs(lat) == 99999); +lat(Inan) = NaN; + +if ~isempty(find(p < -1.5 | p > 12000)) + error('gsw_Fdelta: pressure is out of range') +end +if ~isempty(find(long < 0 | long > 360)) + error('gsw_Fdelta: longitude is out of range') +end +if ~isempty(find(abs(lat) > 90)) + error('gsw_Fdelta: latitude is out of range') +end + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +r_1 = 0.35; + +SAAR = nan(size(p)); +[I] = find(~isnan(p.*long.*lat)); +if ~isempty(I) + SAAR(I) = gsw_SAAR(p(I),long(I),lat(I)); +end + +Fdelta = ((1 + r_1).*SAAR)./(1 - r_1*SAAR); + +if transposed + Fdelta = Fdelta.'; +end + +end diff --git a/Toolbox/library/gsw_Hill_ratio_at_SP2.m b/Toolbox/library/gsw_Hill_ratio_at_SP2.m new file mode 100644 index 0000000..134e471 --- /dev/null +++ b/Toolbox/library/gsw_Hill_ratio_at_SP2.m @@ -0,0 +1,123 @@ +function Hill_ratio = gsw_Hill_ratio_at_SP2(t) + +% gsw_Hill_ratio_at_SP2 Hill ratio at SP of 2 +%========================================================================== +% +% USAGE: +% Hill_ratio = gsw_Hill_ratio_at_SP2(t) +% +% DESCRIPTION: +% Calculates the Hill ratio, which is the adjustment needed to apply for +% Practical Salinities smaller than 2. This ratio is defined at a +% Practical Salinity = 2 and in-situ temperature, t using PSS-78. The Hill +% ratio is the ratio of 2 to the output of the Hill et al. (1986) formula +% for Practical Salinity at the conductivity ratio, Rt, at which Practical +% Salinity on the PSS-78 scale is exactly 2. +% +% INPUT: +% t = in-situ temperature (ITS-90) [ deg C ] +% +% OUTPUT: +% Hill_ratio = Hill ratio at SP of 2 [ unitless ] +% +% AUTHOR: +% Trevor McDougall and Paul Barker [ help_gsw@csiro.au ] +% +% VERSION NUMBER: 3.0 (26th March, 2011) +% +% REFERENCES: +% Hill, K.D., T.M. Dauphinee & D.J. Woods, 1986: The extension of the +% Practical Salinity Scale 1978 to low salinities. IEEE J. Oceanic Eng., +% 11, 109 - 112. +% +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% See appendix E of this TEOS-10 Manual. +% +% Unesco, 1983: Algorithms for computation of fundamental properties of +% seawater. Unesco Technical Papers in Marine Science, 44, 53 pp. +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables +%-------------------------------------------------------------------------- + +if ~(nargin == 1) + error('gsw_Hill_ratio_at_SP2: Needs only one input argument') +end %if + +SP2 = 2.*(ones(size(t))); + +%-------------------------------------------------------------------------- +% Start of the calculation +%-------------------------------------------------------------------------- + +a0 = 0.0080; +a1 = -0.1692; +a2 = 25.3851; +a3 = 14.0941; +a4 = -7.0261; +a5 = 2.7081; + +b0 = 0.0005; +b1 = -0.0056; +b2 = -0.0066; +b3 = -0.0375; +b4 = 0.0636; +b5 = -0.0144; + +g0 = 2.641463563366498e-1; +g1 = 2.007883247811176e-4; +g2 = -4.107694432853053e-6; +g3 = 8.401670882091225e-8; +g4 = -1.711392021989210e-9; +g5 = 3.374193893377380e-11; +g6 = -5.923731174730784e-13; +g7 = 8.057771569962299e-15; +g8 = -7.054313817447962e-17; +g9 = 2.859992717347235e-19; + +k = 0.0162; + +t68 = t.*1.00024; +ft68 = (t68 - 15)./(1 + k.*(t68 - 15)); + +%-------------------------------------------------------------------------- +% Find the initial estimates of Rtx (Rtx0) and of the derivative dSP_dRtx +% at SP = 2. +%-------------------------------------------------------------------------- +Rtx0 = g0 + t68.*(g1 + t68.*(g2 + t68.*(g3 + t68.*(g4 + t68.*(g5... + + t68.*(g6 + t68.*(g7 + t68.*(g8 + t68.*g9)))))))); + +dSP_dRtx = a1 + (2*a2 + (3*a3 + (4*a4 + 5*a5.*Rtx0).*Rtx0).*Rtx0).*Rtx0 + ... + ft68.*(b1 + (2*b2 + (3*b3 + (4*b4 + 5*b5.*Rtx0).*Rtx0).*Rtx0).*Rtx0); + +%-------------------------------------------------------------------------- +% Begin a single modified Newton-Raphson iteration to find Rt at SP = 2. +%-------------------------------------------------------------------------- +SP_est = a0 + (a1 + (a2 + (a3 + (a4 + a5.*Rtx0).*Rtx0).*Rtx0).*Rtx0).*Rtx0 ... + + ft68.*(b0 + (b1 + (b2+ (b3 + (b4 + b5.*Rtx0).*Rtx0).*Rtx0).*Rtx0).*Rtx0); + Rtx = Rtx0 - (SP_est - SP2)./dSP_dRtx; + Rtxm = 0.5*(Rtx + Rtx0); +dSP_dRtx = a1 + (2*a2 + (3*a3 + (4*a4 + 5*a5.*Rtxm).*Rtxm).*Rtxm).*Rtxm... + + ft68.*(b1 + (2*b2 + (3*b3 + (4*b4 + 5*b5.*Rtxm).*Rtxm).*Rtxm).*Rtxm); + Rtx = Rtx0 - (SP_est - SP2)./dSP_dRtx; + +% This is the end of one full iteration of the modified Newton-Raphson +% iterative equation solver. The error in Rtx at this point is equivalent +% to an error in SP of 9e-16 psu. + +x = 400*Rtx.*Rtx; +sqrty = 10*Rtx; +part1 = 1 + x.*(1.5 + x) ; +part2 = 1 + sqrty.*(1 + sqrty.*(1 + sqrty)); +SP_Hill_raw_at_SP2 = SP2 - a0./part1 - b0.*ft68./part2; + +Hill_ratio = 2./SP_Hill_raw_at_SP2; + +end diff --git a/Toolbox/library/gsw_SAAR.m b/Toolbox/library/gsw_SAAR.m new file mode 100644 index 0000000..e5d196a --- /dev/null +++ b/Toolbox/library/gsw_SAAR.m @@ -0,0 +1,402 @@ +function [SAAR, in_ocean] = gsw_SAAR(p,long,lat) + +% gsw_SAAR Absolute Salinity Anomaly Ratio (excluding the Baltic Sea) +%========================================================================== +% +% USAGE: +% [SAAR, in_ocean] = gsw_SAAR(p,long,lat) +% +% DESCRIPTION: +% Calculates the Absolute Salinity Anomaly Ratio, SAAR, in the open ocean +% by spatially interpolating the global reference data set of SAAR to the +% location of the seawater sample. +% +% This function uses version 3.0 of the SAAR look up table. +% +% The Absolute Salinity Anomaly Ratio in the Baltic Sea is evaluated +% separately, since it is a function of Practical Salinity, not of space. +% The present function returns a SAAR of zero for data in the Baltic Sea. +% The correct way of calculating Absolute Salinity in the Baltic Sea is by +% calling gsw_SA_from_SP. +% +% INPUT: +% p = sea pressure [ dbar ] +% ( i.e. absolute pressure - 10.1325 dbar ) +% long = Longitude in decimal degrees [ 0 ... +360 ] +% or [ -180 ... +180 ] +% lat = Latitude in decimal degrees north [ -90 ... +90 ] +% +% p, long & lat need to be vectors and have the same dimensions. +% +% OUTPUT: +% SAAR = Absolute Salinity Anomaly Ratio [ unitless ] +% in_ocean = 0, if long and lat are a long way from the ocean +% = 1, if long and lat are in the ocean +% Note. This flag is only set when the observation is well and truly on +% dry land; often the warning flag is not set until one is several +% hundred kilometres inland from the coast. +% +% AUTHOR: +% David Jackett [ help_gsw@csiro.au ] +% +% MODIFIED: +% Paul Barker and Trevor McDougall +% +% VERSION NUMBER: 3.0 (31st May, 2011) +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% +% McDougall, T.J., D.R. Jackett and F.J. Millero, 2010: An algorithm +% for estimating Absolute Salinity in the global ocean. Submitted to +% Ocean Science. A preliminary version is available at Ocean Sci. +% Discuss., 6, 215-242. +% http://www.ocean-sci-discuss.net/6/215/2009/osd-6-215-2009-print.pdf +% +% The software is available from http://www.TEOS-10.org +% +%========================================================================== + +%-------------------------------------------------------------------------- +% Check variables and resize if necessary +%-------------------------------------------------------------------------- + +if ~(nargin == 3) + error('gsw_SAAR: Requires three inputs') +end %if + +[mp,np] = size(p); +[mla,nla] = size(lat); +[mlo,nlo] = size(long); + +if (mp ~= mla) | (mp ~=mlo) | (np ~= nla) | (np ~= nlo) + error('gsw_SAAR: Inputs need be of the same size') +end %if + +if ~isempty(find(p < -1.5)) + error('gsw_SAAR: pressure needs to be positive') +end + +[Ipn] = find(p < 0 & p > -1.5); +if ~isempty(Ipn) + p(Ipn) = 0; +end + +%-------------------------------------------------------------------------- +% Start of the calculation (extracting from a look up table) +%-------------------------------------------------------------------------- + +gsw_data = 'gsw_data_v3_0.mat'; + +gsw_data_file = which(gsw_data); + +load (gsw_data_file,'SAAR_ref','lats_ref','longs_ref','p_ref', ... + 'ndepth_ref'); + +nx = length(longs_ref); +ny = length(lats_ref); +nz = length(p_ref); +n0 = length(p); + +dlongs_ref = longs_ref(2) - longs_ref(1); +dlats_ref = lats_ref(2) - lats_ref(1); + +indsx0 = floor(1 + (nx-1)*(long - longs_ref(1))./(longs_ref(nx) - longs_ref(1))); +indsx0 = indsx0(:); +inds = find(indsx0 == nx); +indsx0(inds) = nx - 1; + +indsy0 = floor(1 + (ny-1)*(lat - lats_ref(1))./(lats_ref(ny) - lats_ref(1))); +indsy0 = indsy0(:); +inds = find(indsy0 == ny); +indsy0(inds) = ny - 1; + +indsz0 = sum(ones(nz,1)*p(:)' >= p_ref(:)*ones(1,n0)); +indsz0 = indsz0(:); % adjust in the vertical + +indsn1 = sub2ind([ny,nx],indsy0,indsx0); % casts containing data +indsn2 = sub2ind([ny,nx],indsy0,indsx0+1); +indsn3 = sub2ind([ny,nx],indsy0+1,indsx0+1); +indsn4 = sub2ind([ny,nx],indsy0+1,indsx0); + +nmax = max([ndepth_ref(indsn1)';ndepth_ref(indsn2)';ndepth_ref(indsn3)';ndepth_ref(indsn4)']); + +inds1 = find(indsz0(:)' > nmax); % casts deeper than GK maximum + +p(inds1) = p_ref(nmax(inds1)); % have reset p here so have to reset indsz0 + +indsz0 = sum(ones(nz,1)*p(:)' >= p_ref(:)*ones(1,n0)); +indsz0 = indsz0(:); +inds = find(indsz0 == nz); +indsz0(inds) = nz - 1; + +inds0 = sub2ind([nz,ny,nx],indsz0,indsy0,indsx0); + +data_indices = [indsx0,indsy0,indsz0,inds0]; +data_inds = data_indices(:,3); + +r1 = (long(:) - longs_ref(indsx0))./(longs_ref(indsx0+1) - longs_ref(indsx0)); +s1 = (lat(:) - lats_ref(indsy0))./(lats_ref(indsy0+1) - lats_ref(indsy0)); +t1 = (p(:) - p_ref(indsz0))./(p_ref(indsz0+1) - p_ref(indsz0)); + +nksum = 0; +no_levels_missing = 0; + +sa_upper = nan(size(data_inds)); +sa_lower = nan(size(data_inds)); +SAAR = nan(size(data_inds)); +in_ocean = ones(size(SAAR)); + +for k = 1:nz-1 + + inds_k = find(indsz0 == k); + nk = length(inds_k); + + if nk>0 + nksum = nksum+nk; + indsx = indsx0(inds_k); + indsy = indsy0(inds_k); + indsz = k*ones(size(indsx)); + inds_di = find(data_inds == k); % level k interpolation + saar = nan(4,n0); + inds1 = sub2ind([nz,ny,nx], indsz, indsy, indsx); + saar(1,inds_k) = SAAR_ref(inds1); + inds2 = sub2ind([nz,ny,nx], indsz, indsy, indsx+1); + saar(2,inds_k) = SAAR_ref(inds2); % inds0 + ny*nz + inds3 = sub2ind([nz,ny,nx], indsz, indsy+1, indsx+1); + saar(3,inds_k) = SAAR_ref(inds3); % inds0 + ny*nz + nz + inds4 = sub2ind([nz ny,nx], indsz, indsy+1, indsx); + saar(4,inds_k) = SAAR_ref(inds4); % inds0 + nz + + inds = find(260<=long(:) & long(:)<=295.217 & ... + 0<=lat(:) & lat(:)<=19.55 & indsz0(:)==k); + if ~isempty(inds) + saar(:,inds) = gsw_saar_add_barrier(saar(:,inds),long(inds), ... + lat(inds),longs_ref(indsx0(inds)),lats_ref(indsy0(inds)),dlongs_ref,dlats_ref); + end + + inds = find(isnan(sum(saar))' & indsz0==k); + if ~isempty(inds) + saar(:,inds) = gsw_saar_add_mean(saar(:,inds)); + end + + sa_upper(inds_di) = (1-s1(inds_di)).*(saar(1,inds_k)' + ... + r1(inds_di).*(saar(2,inds_k)'-saar(1,inds_k)')) + ... + s1(inds_di).*(saar(4,inds_k)' + ... + r1(inds_di).*(saar(3,inds_k)'-saar(4,inds_k)')); % level k+1 interpolation + + saar = nan(4,n0); + inds1 = sub2ind([nz,ny,nx], indsz+1, indsy, indsx); + saar(1,inds_k) = SAAR_ref(inds1); + inds2 = sub2ind([nz,ny,nx], indsz+1, indsy, indsx+1); + saar(2,inds_k) = SAAR_ref(inds2); % inds1 + ny*nz + inds3 = sub2ind([nz,ny,nx], indsz+1, indsy+1, indsx+1); + saar(3,inds_k) = SAAR_ref(inds3); % inds1 + ny*nz + nz + inds4 = sub2ind([nz ny,nx], indsz+1, indsy+1, indsx); + saar(4,inds_k) = SAAR_ref(inds4); % inds1 + nz + + inds = find(260<=long(:) & long(:)<=295.217 & ... + 0<=lat(:) & lat(:)<=19.55 & indsz0(:)==k); + if ~isempty(inds) + saar(:,inds) = gsw_saar_add_barrier(saar(:,inds),long(inds), ... + lat(inds),longs_ref(indsx0(inds)),lats_ref(indsy0(inds)),dlongs_ref,dlats_ref); + end + + inds = find(isnan(sum(saar))' & indsz0==k); + + if ~isempty(inds) + saar(:,inds) = gsw_saar_add_mean(saar(:,inds)); + end + + sa_lower(inds_di) = (1-s1(inds_di)).*(saar(1,inds_k)' + ... + r1(inds_di).*(saar(2,inds_k)'-saar(1,inds_k)')) + ... + s1(inds_di).*(saar(4,inds_k)' + ... + r1(inds_di).*(saar(3,inds_k)'-saar(4,inds_k)')); + + inds_different = find(isfinite(sa_upper(inds_di)) & isnan(sa_lower(inds_di))); + + if ~isempty(inds_different) + sa_lower(inds_di(inds_different)) = sa_upper(inds_di(inds_different)); + end + + SAAR(inds_di) = sa_upper(inds_di) + t1(inds_di).*(sa_lower(inds_di) - sa_upper(inds_di)); + + else + no_levels_missing = no_levels_missing + 1; + end +end + +inds = find(~isfinite(SAAR)); +SAAR(inds) = 0; + +in_ocean(inds) = 0; + +end + +%########################################################################## + +function SAAR = gsw_saar_add_mean(saar) + +% gsw_saar_add_mean +%========================================================================== +% +% USAGE: +% SAAR = gsw_saar_add_mean(saar) +% +% DESCRIPTION: +% Replaces NaN's with nanmean of the 4 adjacent neighbours +% +% INPUT: +% saar = Absolute Salinity Anomaly Ratio of the 4 adjacent neighbours +% [ unitless ] +% +% OUTPUT: +% SAAR = nanmean of the 4 adjacent neighbours [ unitless ] +% +% AUTHOR: +% David Jackett +% +% MODIFIED: +% Paul Barker and Trevor McDougall +% +% VERSION NUMBER: 3.0 +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% +% McDougall, T. J., D. R. Jackett and F. J. Millero, 2010: An algorithm +% for estimating Absolute Salinity in the global ocean. Submitted to +% Ocean Science, a preliminary version is available at Ocean Sci. +% Discuss., 6, 215-242. +% http://www.ocean-sci-discuss.net/6/215/2009/osd-6-215-2009-print.pdf +% and the computer software is available from http://www.TEOS-10.org +% +%========================================================================== + +saar_mean = mean(saar); +inds_nan = find(isnan(saar_mean)); +no_nan = length(inds_nan); + +for kk = 1:no_nan + col = inds_nan(kk); + inds_kk = find(isnan(saar(:,col))); + [Inn] = find(~isnan(saar(:,col))); + if ~isempty(Inn) + saar(inds_kk,col) = mean(saar(Inn,col)); + end +end + +SAAR = saar; + +end + +%########################################################################## + +function SAAR = gsw_saar_add_barrier(saar,long,lat,longs_ref,lats_ref,dlongs_ref,dlats_ref) + +% gsw_saar_add_barrier +%========================================================================== +% +% USAGE: +% SAAR = gsw_saar_add_barrier(saar,long,lat,longs_ref,lats_ref,dlongs_ref,dlats_ref) +% +% DESCRIPTION: +% Adds a barrier through Central America (Panama) and then averages +% over the appropriate side of the barrier +% +% INPUT: +% saar = Absolute Salinity Anomaly Ratio [ unitless ] +% long = Longitudes of data in decimal degrees east [ 0 ... +360 ] +% lat = Latitudes of data in decimal degrees north [ -90 ... +90 ] +% longs_ref = Longitudes of regular grid in decimal degrees east [ 0 ... +360 ] +% lats_ref = Latitudes of regular grid in decimal degrees north [ -90 ... +90 ] +% dlongs_ref = Longitude difference of regular grid in decimal degrees [ deg longitude ] +% dlats_ref = Latitude difference of regular grid in decimal degrees [ deg latitude ] +% +% OUTPUT: +% SAAR = Absolute Salinity Anomaly Ratio [ unitless ] +% +% AUTHOR: +% David Jackett +% +% MODIFIED: +% Paul Barker and Trevor McDougall +% +% VERSION NUMBER: 3.0 +% +% REFERENCES: +% IOC, SCOR and IAPSO, 2010: The international thermodynamic equation of +% seawater - 2010: Calculation and use of thermodynamic properties. +% Intergovernmental Oceanographic Commission, Manuals and Guides No. 56, +% UNESCO (English), 196 pp. Available from http://www.TEOS-10.org +% +% McDougall, T. J., D. R. Jackett and F. J. Millero, 2010: An algorithm +% for estimating Absolute Salinity in the global ocean. Submitted to +% Ocean Science, a preliminary version is available at Ocean Sci. +% Discuss., 6, 215-242. +% http://www.ocean-sci-discuss.net/6/215/2009/osd-6-215-2009-print.pdf +% and the computer software is available from http://www.TEOS-10.org +% +%========================================================================== + +longs_pan = [260.0000 272.5900 276.5000 278.6500 280.7300 295.2170]; + +lats_pan = [ 19.5500 13.9700 9.6000 8.1000 9.3300 0]; + +lats_lines0 = interp1(longs_pan,lats_pan,long); + +lats_lines1 = interp1(longs_pan,lats_pan,longs_ref); +lats_lines2 = interp1(longs_pan,lats_pan,(longs_ref+dlongs_ref)); + +for k0 = 1:length(long) + if lats_lines0(k0) <= lat(k0) + above_line0 = 1; + else + above_line0 = 0; + end + if lats_lines1(k0) <= lats_ref(k0) + above_line(1) = 1; + else + above_line(1) = 0; + end + if lats_lines1(k0) <= (lats_ref(k0) + dlats_ref) + above_line(4) = 1; + else + above_line(4) = 0; + end + if lats_lines2(k0) <= lats_ref(k0) + above_line(2) = 1; + else + above_line(2) = 0; + end + if lats_lines2(k0) <= (lats_ref(k0) + dlats_ref) + above_line(3) = 1; + else + above_line(3) = 0; + end + inds = find(above_line ~= above_line0); % indices of different sides of CA line + saar(inds,k0) = nan; +end + +saar_mean = mean(saar); +inds_nan = find(isnan(saar_mean)); +no_nan = length(inds_nan); + +for kk = 1:no_nan + col = inds_nan(kk); + inds_kk = find(isnan(saar(:,col))); + [Inn] = find(~isnan(saar(:,col))); + if ~isempty(Inn) + saar(inds_kk,col) = mean(saar(Inn,col)); + end +end + +SAAR = saar; + +end diff --git a/Toolbox/library/gsw_SA_from_SP_Baltic.m b/Toolbox/library/gsw_SA_from_SP_Baltic.m index c42bc06..32e44f9 100644 --- a/Toolbox/library/gsw_SA_from_SP_Baltic.m +++ b/Toolbox/library/gsw_SA_from_SP_Baltic.m @@ -11,18 +11,18 @@ % Since SP is non-negative by definition, this function changes any % negative input values of SP to be zero. % Note. This programme will only produce Absolute Salinity values for the -% Baltic Sea. +% Baltic Sea. % % INPUT: -% SP = Practical Salinity (PSS-78) [ unitless ] -% long = Longitude in decimal degrees east [ 0 ... +360 ] -% lat = Latitude in decimal degrees north [ -90 ... +90 ] +% SP = Practical Salinity (PSS-78) [ unitless ] +% long = Longitude in decimal degrees east [ 0 ... +360 ] +% lat = Latitude in decimal degrees north [ -90 ... +90 ] % % OUTPUT: -% SA_baltic = Absolute Salinity in the Baltic Sea [ g/kg ] +% SA_baltic = Absolute Salinity in the Baltic Sea [ g kg^-1 ] % % AUTHOR: -% David Jackett, Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] +% David Jackett, Trevor McDougall & Paul Barker [ help_gsw@csiro.au ] % % VERSION NUMBER: 2.0 (23rd July, 2010) % @@ -70,13 +70,15 @@ inds_baltic = find(xb2 8000 |... SA < 0 |... - SA > 42.2 |... - CT < (-0.3595467 - 0.0553734*SA) |... - (p < 5500 & SA < 0.006028*(p - 500)) |... - (p < 5500 & CT > (33.0 - 0.003818181818182*p)) | ... - (p > 5500 & SA < 30.14) |... - (p > 5500 & CT > 12.0) ); + SA > 42 |... + (p < 500 & CT < gsw_CT_freezing(SA,p)) |... + (p > 500 & p < 6500 & SA < p*5e-3 - 2.5) |... + (p > 500 & p < 6500 & CT > (31.66666666666667 - p*3.333333333333334e-3)) | ... + (p > 6500 & SA < 30) |... + (p > 6500 & CT > 10.0) ); in_funnel(Ifunnel) = 0; diff --git a/Toolbox/library/gsw_interp_SA_CT.m b/Toolbox/library/gsw_interp_SA_CT.m index ce405c7..7a0be46 100644 --- a/Toolbox/library/gsw_interp_SA_CT.m +++ b/Toolbox/library/gsw_interp_SA_CT.m @@ -4,20 +4,26 @@ % This function interpolates the cast with respect to the interpolating % variable p. This function finds the values of SA, CT at p_i on this cast. % +% VERSION NUMBER: 3.0 (8th April, 2011) +% % This fuction was adapted from Matlab's interp1q. %========================================================================== p = p(:); [min_p,Imin_p] = min(p); -[Ishallow] = find(p <= min_p); % Set equal to the shallowest bottle. -SA_i(Ishallow) = SA(Imin_p); -CT_i(Ishallow) = CT(Imin_p); +[Ishallow] = find(p_i <= min_p); % Set equal to the shallowest bottle. +if ~isempty(Ishallow) + SA_i(Ishallow) = SA(Imin_p); + CT_i(Ishallow) = CT(Imin_p); +end [max_p,Imax_p] = max(p); [Ideep] = find(p_i >= max_p); % Set equal to the deepest bottle. -SA_i(Ideep) = SA(Imax_p); -CT_i(Ideep) = CT(Imax_p); +if ~isempty(Ideep) + SA_i(Ideep) = SA(Imax_p); + CT_i(Ideep) = CT(Imax_p); +end [I] = find(p_i >= min_p & p_i <= max_p); @@ -42,8 +48,13 @@ u = (xi(ind)-xrind)./(x(rind+1)-xrind); SArind = SA(rind,:); CTrind = CT(rind,:); - SA_ri(ind,:) = SArind + bsxfun(@times,SA(rind+1,:)-SArind,u); - CT_ri(ind,:) = CTrind + bsxfun(@times,CT(rind+1,:)-CTrind,u); + if exist('bsxfun','builtin') == 5 + SA_ri(ind,:) = SArind + bsxfun(@times,SA(rind+1,:)-SArind,u); + CT_ri(ind,:) = CTrind + bsxfun(@times,CT(rind+1,:)-CTrind,u); + else + SA_ri(ind,:) = SArind + (SA(rind+1,:)-SArind).*u; + CT_ri(ind,:) = CTrind + (CT(rind+1,:)-CTrind).*u; + end else % Special scalar xi case r = find(x <= xi,1,'last'); @@ -55,8 +66,13 @@ u = (xi-x(r))./(x(r+1)-x(r)); SAr = SA(r,:); CTr = CT(r,:); - SA_ri = SAr + bsxfun(@times,SA(r+1,:)-SAr,u); - CT_ri = CTr + bsxfun(@times,CT(r+1,:)-CTr,u); + if exist('bsxfun','builtin') == 5 + SA_ri = SAr + bsxfun(@times,SA(r+1,:)-SAr,u); + CT_ri = CTr + bsxfun(@times,CT(r+1,:)-CTr,u); + else + SA_ri = SAr + (SA(r+1,:)-SAr).*u; + CT_ri = CTr + (CT(r+1,:)-CTr).*u; + end end end @@ -68,4 +84,4 @@ SA_i(I) = SA_ri; CT_i(I) = CT_ri; -end \ No newline at end of file +end diff --git a/Toolbox/library/gsw_interp_McD_Klocker.m b/Toolbox/library/gsw_interp_ref_cast.m similarity index 58% rename from Toolbox/library/gsw_interp_McD_Klocker.m rename to Toolbox/library/gsw_interp_ref_cast.m index 57d77c6..d9eae37 100644 --- a/Toolbox/library/gsw_interp_McD_Klocker.m +++ b/Toolbox/library/gsw_interp_ref_cast.m @@ -1,17 +1,20 @@ -function [SA_iref_cast, CT_iref_cast, p_iref_cast] = gsw_interp_McD_Klocker(spycnl,A) -% gsw_interp_McD_Klocker linear interpolation of the reference cast +function [SA_iref_cast, CT_iref_cast, p_iref_cast] = gsw_interp_ref_cast(spycnl,A) + +% gsw_interp_ref_cast linear interpolation of the reference cast %========================================================================== % This function interpolates the reference cast with respect to the -% interpolating variable "spycnl". This reference cast is at the location +% interpolating variable "spycnl". This reference cast is at the location % 188E,4N from the reference data set which underlies the Jackett & % McDougall (1997) Neutral Density computer code. This function finds the % values of SA, CT and p on this reference cast which correspond to the % value of isopycnal which is passed to this function from the function -% "gsw_geo_str_McD_Klocker". The isopycnal could be either gamma_n or -% sigma_2. if A is set to any of the following 's2','S2','sigma2','sigma_2' +% "gsw_geo_strf_isopycnal_CT". The isopycnal could be either gamma_n or +% sigma_2. If A is set to any of the following 's2','S2','sigma2','sigma_2' % the interpolation will take place in sigma 2 space, any other input % will result in the programme working in gamma_n space. % +% VERSION NUMBER: 3.0 (14th April, 2011) +% % REFERENCE: % Jackett, D. R. and T. J. McDougall, 1997: A neutral density variable % for the world’s oceans. Journal of Physical Oceanography, 27, 237-263. @@ -33,28 +36,32 @@ A = 's2'; end -temp = which('gsw_data_v2_0.mat'); -dir = temp(1:((length(temp) - 17))); +gsw_data = 'gsw_data_v3_0.mat'; +gsw_data_file = which(gsw_data); if strcmpi(A,'s2') - load ([dir,'gsw_data_v2_0'],'SA_ref_cast','CT_ref_cast','p_ref_cast','sigma_2_ref_cast'); + load (gsw_data_file,'SA_ref_cast','CT_ref_cast','p_ref_cast','sigma_2_ref_cast'); spycnl_ref_cast = sigma_2_ref_cast; else - load ([dir,'gsw_data_v2_0'],'SA_ref_cast','CT_ref_cast','p_ref_cast','gamma_n_ref_cast'); + load (gsw_data_file,'SA_ref_cast','CT_ref_cast','p_ref_cast','gamma_n_ref_cast'); spycnl_ref_cast = gamma_n_ref_cast; end -[min_spycnl_ref_cast,Imin_spycnl_ref_cast] = min(spycnl_ref_cast); +[min_spycnl_ref_cast, Imin_spycnl_ref_cast] = min(spycnl_ref_cast); [Ishallow] = find(spycnl <= min_spycnl_ref_cast); % Set equal to the shallowest bottle. -SA_iref_cast(Ishallow) = SA_ref_cast(Imin_spycnl_ref_cast); -CT_iref_cast(Ishallow) = CT_ref_cast(Imin_spycnl_ref_cast); -p_iref_cast(Ishallow) = p_ref_cast(Imin_spycnl_ref_cast); +if ~isempty(Ishallow) + SA_iref_cast(Ishallow) = SA_ref_cast(Imin_spycnl_ref_cast); + CT_iref_cast(Ishallow) = CT_ref_cast(Imin_spycnl_ref_cast); + p_iref_cast(Ishallow) = p_ref_cast(Imin_spycnl_ref_cast); +end -[max_spycnl_ref_cast,Imax_spycnl_ref_cast] = max(spycnl_ref_cast); +[max_spycnl_ref_cast, Imax_spycnl_ref_cast] = max(spycnl_ref_cast); [Ideep] = find(spycnl >= max_spycnl_ref_cast); % Set equal to the deepest bottle. -SA_iref_cast(Ideep) = SA_ref_cast(Imax_spycnl_ref_cast); -CT_iref_cast(Ideep) = CT_ref_cast(Imax_spycnl_ref_cast); -p_iref_cast(Ideep) = p_ref_cast(Imax_spycnl_ref_cast); +if ~isempty(Ideep) + SA_iref_cast(Ideep) = SA_ref_cast(Imax_spycnl_ref_cast); + CT_iref_cast(Ideep) = CT_ref_cast(Imax_spycnl_ref_cast); + p_iref_cast(Ideep) = p_ref_cast(Imax_spycnl_ref_cast); +end [I] = find(spycnl >= 21.805 & spycnl <= 28.3614); @@ -81,9 +88,15 @@ SArind = SA_ref_cast(rind,:); CTrind = CT_ref_cast(rind,:); prind = p_ref_cast(rind,:); - SA_ref_casti(ind,:) = SArind + bsxfun(@times,SA_ref_cast(rind+1,:)-SArind,u); - CT_ref_casti(ind,:) = CTrind + bsxfun(@times,CT_ref_cast(rind+1,:)-CTrind,u); - p_ref_casti(ind,:) = prind + bsxfun(@times,p_ref_cast(rind+1,:)-prind,u); + if exist('bsxfun','builtin') == 5 + SA_ref_casti(ind,:) = SArind + bsxfun(@times,SA_ref_cast(rind+1,:)-SArind,u); + CT_ref_casti(ind,:) = CTrind + bsxfun(@times,CT_ref_cast(rind+1,:)-CTrind,u); + p_ref_casti(ind,:) = prind + bsxfun(@times,p_ref_cast(rind+1,:)-prind,u); + else + SA_ref_casti(ind,:) = SArind + (SA_ref_cast(rind+1,:)-SArind).*u; + CT_ref_casti(ind,:) = CTrind + (CT_ref_cast(rind+1,:)-CTrind).*u; + p_ref_casti(ind,:) = prind + (p_ref_cast(rind+1,:)-prind).*u; + end else % Special scalar xi case r = find(x <= xi,1,'last'); @@ -92,15 +105,20 @@ SA_ref_casti = NaN(1,size(SA,2),superiorfloat(x,SA,xi)); CT_ref_casti = NaN(1,size(CT,2),superiorfloat(x,CT,xi)); p_ref_casti = NaN(1,size(p,2),superiorfloat(x,p,xi)); - else u = (xi-x(r))./(x(r+1)-x(r)); SAr_ref_cast = SA_ref_cast(r,:); CTr_ref_cast = CT_ref_cast(r,:); pr_ref_cast = p_ref_cast(r,:); - SA_ref_casti = SAr_ref_cast + bsxfun(@times,SA_ref_cast(r+1,:)-SAr_ref_cast,u); - CT_ref_casti = CTr_ref_cast + bsxfun(@times,CT_ref_cast(r+1,:)-CTr_ref_cast,u); - p_ref_casti = pr_ref_cast + bsxfun(@times,p_ref_cast(r+1,:)-pr_ref_cast,u); + if exist('bsxfun','builtin') == 5 + SA_ref_casti = SAr_ref_cast + bsxfun(@times,SA_ref_cast(r+1,:)-SAr_ref_cast,u); + CT_ref_casti = CTr_ref_cast + bsxfun(@times,CT_ref_cast(r+1,:)-CTr_ref_cast,u); + p_ref_casti = pr_ref_cast + bsxfun(@times,p_ref_cast(r+1,:)-pr_ref_cast,u); + else + SA_ref_casti = SAr_ref_cast + (SA_ref_cast(r+1,:)-SAr_ref_cast).*u; + CT_ref_casti = CTr_ref_cast + (CT_ref_cast(r+1,:)-CTr_ref_cast).*u; + p_ref_casti = pr_ref_cast + (p_ref_cast(r+1,:)-pr_ref_cast).*u; + end end end @@ -114,4 +132,4 @@ CT_iref_cast(I) = CT_ref_casti; p_iref_cast(I) = p_ref_casti; -end \ No newline at end of file +end diff --git a/Toolbox/library/gsw_specvol_SSO_0_CT25.m b/Toolbox/library/gsw_specvol_SSO_0_CT25.m deleted file mode 100644 index 0440931..0000000 --- a/Toolbox/library/gsw_specvol_SSO_0_CT25.m +++ /dev/null @@ -1,26 +0,0 @@ -function specvol_SSO_0_CT25 = gsw_specvol_SSO_0_CT25(p) - -%gsw_specvol_SSO_0_CT25 specific volume at (SSO,CT = 0,p) -% (25-term equation) -%========================================================================== -% This function calcualtes specifc volume at the Standard Ocean -% Salinty, SSO, and at a Conservative Temperature of zero degrees C, -% as a function of pressure, p, in dbar, using a streamlined version -% of the 25-term CT version of specific volume, that is, a streamlined -% version of the code "gsw_rho_alpha_beta_CT25(SA,CT,p)". -%========================================================================== - -SSO = 35.16504*ones(size(p)); - -specvol_SSO_0_CT25 = (1.00000000e+00 + ... - SSO.*( 2.0777716085618458e-003 + ... - sqrt(SSO).* 3.4688210757917340e-006) + ... - p.* 6.8314629554123324e-006)./ ... - (9.9984380290708214e+002 + ... - SSO.*( 2.8925731541277653e+000 + ... - SSO.* 1.9457531751183059e-003) + ... - p.*( 1.1930681818531748e-002 + ... - SSO.* 5.9355685925035653e-006 + ... - p.* -2.5943389807429039e-008)); - -end diff --git a/Toolbox/library/gsw_specvol_SSO_0_p.m b/Toolbox/library/gsw_specvol_SSO_0_p.m new file mode 100644 index 0000000..0dea5de --- /dev/null +++ b/Toolbox/library/gsw_specvol_SSO_0_p.m @@ -0,0 +1,41 @@ +function specvol_SSO_0_p = gsw_specvol_SSO_0_p(p) + +%gsw_specvol_SSO_0_p specific volume at (SSO,CT=0,p) +% (48-term equation) +%========================================================================== +% This function calculates specifc volume at the Standard Ocean Salinity, +% SSO, and at a Conservative Temperature of zero degrees C, as a function +% of pressure, p, in dbar, using a streamlined version of the 48-term CT +% version of specific volume, that is, a streamlined version of the code +% "gsw_specvol(SA,CT,p)". +% +% VERSION NUMBER: 3.0 (29th March, 2011) +% +%========================================================================== + +v01 = 9.998420897506056e+2; +v05 = -6.698001071123802; +v08 = -3.988822378968490e-2; +v12 = -2.233269627352527e-2; +v15 = -1.806789763745328e-4; +v17 = -3.087032500374211e-7; +v20 = 1.550932729220080e-10; +v21 = 1.0; +v26 = -7.521448093615448e-3; +v31 = -3.303308871386421e-5; +v36 = 5.419326551148740e-6; +v37 = -2.742185394906099e-5; +v41 = -1.105097577149576e-7; +v43 = -1.119011592875110e-10; +v47 = -1.200507748551599e-15; + +SSO = 35.16504*ones(size(p)); + +sqrtSSO = 5.930011804372737*ones(size(p)); % sqrt(SSO) = 5.930011804372737; + +specvol_SSO_0_p = (v21 + SSO.*(v26 + v36*SSO + v31*sqrtSSO) ... + + p.*(v37 + v41*SSO + p.*(v43 + v47*p )))./ ... + (v01 + SSO.*(v05 + v08*sqrtSSO) ... + + p.*(v12 + v15*SSO + p.*(v17 + v20*SSO))); + +end