[gsw] 01/02: Imported Upstream version 3.0.3
Alastair McKinstry
mckinstry at moszumanska.debian.org
Thu Jul 9 13:21:26 UTC 2015
This is an automated email from the git hooks/post-receive script.
mckinstry pushed a commit to branch debian/master
in repository gsw.
commit e6caa7cbd60bc59ff093c7b27b7eedf503df8f54
Author: Alastair McKinstry <mckinstry at debian.org>
Date: Thu Jul 9 14:13:07 2015 +0100
Imported Upstream version 3.0.3
---
CHANGES.txt | 6 +
LICENSE.txt | 19 +
MANIFEST.in | 11 +
PKG-INFO | 154 +++
README.txt | 106 ++
docs/Makefile | 89 ++
docs/conf.py | 195 ++++
docs/index.rst | 45 +
gsw.egg-info/PKG-INFO | 154 +++
gsw.egg-info/SOURCES.txt | 47 +
gsw.egg-info/dependency_links.txt | 1 +
gsw.egg-info/requires.txt | 2 +
gsw.egg-info/top_level.txt | 4 +
gsw/__init__.py | 12 +
gsw/gibbs/__init__.py | 19 +
gsw/gibbs/constants.py | 144 +++
gsw/gibbs/conversions.py | 1724 ++++++++++++++++++++++++++++
gsw/gibbs/density_enthalpy_48.py | 1459 ++++++++++++++++++++++++
gsw/gibbs/density_enthalpy_48_ct.py | 106 ++
gsw/gibbs/density_enthalpy_ct_exact.py | 716 ++++++++++++
gsw/gibbs/derivatives.py | 677 +++++++++++
gsw/gibbs/earth.py | 219 ++++
gsw/gibbs/freezing.py | 569 ++++++++++
gsw/gibbs/geostrophic.py | 16 +
gsw/gibbs/geostrophic_48.py | 41 +
gsw/gibbs/isobaric.py | 72 ++
gsw/gibbs/library.py | 1646 +++++++++++++++++++++++++++
gsw/gibbs/neutral_nonlinear_48.py | 35 +
gsw/gibbs/practical_salinity.py | 754 +++++++++++++
gsw/gibbs/steric.py | 131 +++
gsw/gibbs/thermodynamics_from_t.py | 1750 +++++++++++++++++++++++++++++
gsw/gibbs/water_column_48.py | 344 ++++++
gsw/test/__init__.py | 1 +
gsw/test/check_functions.py | 194 ++++
gsw/test/signatures.py | 178 +++
gsw/test/test_check_values.py | 66 ++
gsw/test/test_octave.py | 208 ++++
gsw/test/test_profiles.py | 339 ++++++
gsw/test/test_tuples.py | 99 ++
gsw/utilities/__init__.py | 3 +
gsw/utilities/data/gsw_cf.npz | Bin 0 -> 266964 bytes
gsw/utilities/data/gsw_cv_v3_0.npz | Bin 0 -> 285644 bytes
gsw/utilities/data/gsw_data_v3_0.npz | Bin 0 -> 4492826 bytes
gsw/utilities/data/gsw_demo_data_v3_0.npz | Bin 0 -> 4456 bytes
gsw/utilities/list_npz.py | 26 +
gsw/utilities/mat2npz.py | 50 +
gsw/utilities/utilities.py | 333 ++++++
setup.cfg | 5 +
setup.py | 69 ++
49 files changed, 12838 insertions(+)
diff --git a/CHANGES.txt b/CHANGES.txt
new file mode 100644
index 0000000..81f6484
--- /dev/null
+++ b/CHANGES.txt
@@ -0,0 +1,6 @@
+version 3.0.3
+=============
+
+version 3.0
+===========
+* New repository with TEOS10 code (version 3 only).
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..eb056c7
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,19 @@
+Copyright Notice and Statement for the gsw project:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..8de1cd7
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,11 @@
+include README.txt
+include LICENSE.txt
+include CHANGES.txt
+include docs/conf.py
+include docs/index.rst
+include docs/Makefile
+include gsw/*.py
+include gsw/gibbs/*.py
+include gsw/test/*.py
+include gsw/utilities/*.py
+include gsw/utilities/data/*.npz
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..f2e2952
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,154 @@
+Metadata-Version: 1.1
+Name: gsw
+Version: 3.0.3
+Summary: Gibbs SeaWater Oceanographic Package of TEOS-10
+Home-page: http://pypi.python.org/pypi/seawater/
+Author: Filipe Fernandes
+Author-email: ocefpaf at gmail.com
+License: Copyright Notice and Statement for the gsw project:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+Download-URL: https://pypi.python.org/pypi/gsw/
+Description: This python module is incomplete and should be used with caution.
+ =================================================================
+
+ python gsw
+ ==========
+
+ | |Build|
+ | |Build|
+ | |Downloads|
+
+ Python implementation of the Thermodynamic Equation Of Seawater - 2010 (TEOS-10)[http://www.teos-10.org/\ ]
+ -----------------------------------------------------------------------------------------------------------
+
+ gsw vs. csiro
+ -------------
+
+ This table shows some function names in the gibbs library and the
+ corresponding function names in the csiro library.
+
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | **Variable** | **SeaWater (EOS 80)** | **Gibbs SeaWater (GSW TEOS 10)** |
+ +===========================================================+====================================================+==============================================================+
+ | Absolute Salinity | NA | gsw.SA\_from\_SP(SP,p,long,lat) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | Conservative Temperature | NA | gsw.CT\_from\_t(SA,t,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | density (i.e. in situ density) | sw.dens(SP,t,p) | gsw.rho\_CT(SA,CT,p), or gsw.rho(SA,t,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | potential density | sw.pden(SP,t,p,pr) | gsw.rho\_CT(SA,CT,pr) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | potential temperature | sw.ptmp(SP,t,p,pr) | gsw.pt\_from\_t(SA,t,p,pr) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | $\\sigma\_0$, using $\\theta\_o$ = sw.ptmp(SP,t,p,0) | sw.dens(SP, $\\theta\_o$, 0) -1000 kg m$^{-3}$ | gsw.sigma0\_CT(SA,CT) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | $\\sigma\_2$, using $\\theta\_2$ = sw.ptmp(SP,t,p,2000) | sw.dens(SP,$\\theta\_2$, 2000) -1000 kg m$^{-3}$ | gsw.sigma2\_CT(SA,CT) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | $\\sigma\_4$, using $\\theta\_4$ = sw.ptmp(SP,t,p,2000) | sw.dens(SP,$\\theta\_4$, 4000) -1000 kg m$^{-3}$ | gsw.sigma2\_CT(SA,CT) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | specific volume anomaly | sw.svan(SP,t,p) | gsw.specvol\_anom\_CT(SA,CT,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | dynamic height anomaly | -sw.gpan(SP,t,p) | gsw.geo\_strf\_dyn\_height(SA,CT,p,delta\_p,interp\_style) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | geostrophic velocity | sw.gvel(ga,lat,long) | gsw.geostrophic\_velocity(geo\_str,long,lat,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | N$^2$ | sw.bfrq(SP,t,p,lat) | gsw.Nsquared(SA,CT,p,lat) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | pressure from height (SW uses depth, not height) | sw.pres(-z,lat) | gsw.p\_from\_z(z,lat) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | height from pressure (SW outputs depth, not height) | z = -sw.dpth(p,lat) | gsw.z\_from\_p(p,lat) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | in situ temperature from pt | sw.temp(SP,pt,p,pr) | gsw.pt\_from\_t(SA,pt,pr,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | sound speed | sw.svel(SP,t,p) | gsw.sound\_speed(SA,t,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | isobaric heat capacity | sw.cp(SP,t,p) | gsw.cp(SA,t,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | adiabatic lapse rate\* | sw.adtg(SP,t,p) | gsw.adiabatic\_lapse\_rate(SA,t,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | SP from cndr, (PSS 78) | sw.salt(cndr,t,p) | gsw.SP\_from\_cndr(cndr,t,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | cndr from SP, (PSS 78) | sw.cndr(SP,t,p) | gsw.cndr\_from\_SP(SP,t,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | distance | sw.dist(lat,long,units) | gsw.distance(long,lat,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | gravitational acceleration | sw.g(lat,z) | gsw.grav(lat,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | Coriolis parameter | sw.f(lat) | gsw.f(lat) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+
+ | Note that the SW and GSW functions output the adiabatic lapse rate in
+ different units, being K (dbar)$^{-1}$ and K Pa$^{-1}$
+ | respectively.
+
+ Authors
+ -------
+
+ - Bjørn Ådlandsvik
+ - Eric Firing
+ - Filipe Fernandes
+
+ Thanks
+ ------
+
+ - Bjørn Ådlandsvik - Testing unit and several bug fixes.
+ - Eric Firing - Support for masked arrays, re-write of *delta*\ SA.
+ - Trevor J. McDougall (and all of SCOR/IAPSO WG127) for making
+ available the Matlab version of this software.
+
+ Acknowledgments
+ ---------------
+
+ - SCOR/IAPSO WG127.
+
+ Caveats
+ -------
+
+ - This python module is incomplete and should be used with caution.
+ - The database used in ``_delta_SA`` comes from the MatlabTM gsw
+ version.
+
+ .. |Build| image:: https://badge.fury.io/py/gsw.png
+ :target: http://badge.fury.io/py/gsw
+ .. |Build| image:: https://api.travis-ci.org/ocefpaf/python-gsw.png?branch=master
+ :target: https://travis-ci.org/ocefpaf/python-gsw
+ .. |Downloads| image:: https://pypip.in/d/gsw/badge.png
+ :target: https://crate.io/packages/gsw/
+
+ version 3.0.3
+ =============
+
+ version 3.0
+ ===========
+ * New repository with TEOS10 code (version 3 only).
+
+Keywords: oceanography,seawater,TEOS-10,gibbs
+Platform: any
+Classifier: Development Status :: 4 - Beta
+Classifier: Environment :: Console
+Classifier: Intended Audience :: Science/Research
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Education
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Topic :: Education
+Classifier: Topic :: Scientific/Engineering
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..b986cfc
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,106 @@
+This python module is incomplete and should be used with caution.
+=================================================================
+
+python gsw
+==========
+
+| |Build|
+| |Build|
+| |Downloads|
+
+Python implementation of the Thermodynamic Equation Of Seawater - 2010 (TEOS-10)[http://www.teos-10.org/\ ]
+-----------------------------------------------------------------------------------------------------------
+
+gsw vs. csiro
+-------------
+
+This table shows some function names in the gibbs library and the
+corresponding function names in the csiro library.
+
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| **Variable** | **SeaWater (EOS 80)** | **Gibbs SeaWater (GSW TEOS 10)** |
++===========================================================+====================================================+==============================================================+
+| Absolute Salinity | NA | gsw.SA\_from\_SP(SP,p,long,lat) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| Conservative Temperature | NA | gsw.CT\_from\_t(SA,t,p) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| density (i.e. in situ density) | sw.dens(SP,t,p) | gsw.rho\_CT(SA,CT,p), or gsw.rho(SA,t,p) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| potential density | sw.pden(SP,t,p,pr) | gsw.rho\_CT(SA,CT,pr) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| potential temperature | sw.ptmp(SP,t,p,pr) | gsw.pt\_from\_t(SA,t,p,pr) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| $\\sigma\_0$, using $\\theta\_o$ = sw.ptmp(SP,t,p,0) | sw.dens(SP, $\\theta\_o$, 0) -1000 kg m$^{-3}$ | gsw.sigma0\_CT(SA,CT) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| $\\sigma\_2$, using $\\theta\_2$ = sw.ptmp(SP,t,p,2000) | sw.dens(SP,$\\theta\_2$, 2000) -1000 kg m$^{-3}$ | gsw.sigma2\_CT(SA,CT) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| $\\sigma\_4$, using $\\theta\_4$ = sw.ptmp(SP,t,p,2000) | sw.dens(SP,$\\theta\_4$, 4000) -1000 kg m$^{-3}$ | gsw.sigma2\_CT(SA,CT) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| specific volume anomaly | sw.svan(SP,t,p) | gsw.specvol\_anom\_CT(SA,CT,p) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| dynamic height anomaly | -sw.gpan(SP,t,p) | gsw.geo\_strf\_dyn\_height(SA,CT,p,delta\_p,interp\_style) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| geostrophic velocity | sw.gvel(ga,lat,long) | gsw.geostrophic\_velocity(geo\_str,long,lat,p) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| N$^2$ | sw.bfrq(SP,t,p,lat) | gsw.Nsquared(SA,CT,p,lat) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| pressure from height (SW uses depth, not height) | sw.pres(-z,lat) | gsw.p\_from\_z(z,lat) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| height from pressure (SW outputs depth, not height) | z = -sw.dpth(p,lat) | gsw.z\_from\_p(p,lat) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| in situ temperature from pt | sw.temp(SP,pt,p,pr) | gsw.pt\_from\_t(SA,pt,pr,p) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| sound speed | sw.svel(SP,t,p) | gsw.sound\_speed(SA,t,p) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| isobaric heat capacity | sw.cp(SP,t,p) | gsw.cp(SA,t,p) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| adiabatic lapse rate\* | sw.adtg(SP,t,p) | gsw.adiabatic\_lapse\_rate(SA,t,p) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| SP from cndr, (PSS 78) | sw.salt(cndr,t,p) | gsw.SP\_from\_cndr(cndr,t,p) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| cndr from SP, (PSS 78) | sw.cndr(SP,t,p) | gsw.cndr\_from\_SP(SP,t,p) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| distance | sw.dist(lat,long,units) | gsw.distance(long,lat,p) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| gravitational acceleration | sw.g(lat,z) | gsw.grav(lat,p) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+| Coriolis parameter | sw.f(lat) | gsw.f(lat) |
++-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+
+| Note that the SW and GSW functions output the adiabatic lapse rate in
+different units, being K (dbar)$^{-1}$ and K Pa$^{-1}$
+| respectively.
+
+Authors
+-------
+
+- Bjørn Ådlandsvik
+- Eric Firing
+- Filipe Fernandes
+
+Thanks
+------
+
+- Bjørn Ådlandsvik - Testing unit and several bug fixes.
+- Eric Firing - Support for masked arrays, re-write of *delta*\ SA.
+- Trevor J. McDougall (and all of SCOR/IAPSO WG127) for making
+ available the Matlab version of this software.
+
+Acknowledgments
+---------------
+
+- SCOR/IAPSO WG127.
+
+Caveats
+-------
+
+- This python module is incomplete and should be used with caution.
+- The database used in ``_delta_SA`` comes from the MatlabTM gsw
+ version.
+
+.. |Build| image:: https://badge.fury.io/py/gsw.png
+ :target: http://badge.fury.io/py/gsw
+.. |Build| image:: https://api.travis-ci.org/ocefpaf/python-gsw.png?branch=master
+ :target: https://travis-ci.org/ocefpaf/python-gsw
+.. |Downloads| image:: https://pypip.in/d/gsw/badge.png
+ :target: https://crate.io/packages/gsw/
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..fd6fd6e
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,89 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/seawater.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/seawater.qhc"
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+ "run these through (pdf)latex."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..97ad07b
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,195 @@
+# -*- coding: utf-8 -*-
+#
+# seawater documentation build configuration file, created by
+# sphinx-quickstart on Tue Aug 10 16:47:25 2010.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.append(os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.pngmath', 'numpydoc',
+ 'numpydoc.plot_directive']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'seawater'
+copyright = u'2010, Filipe Fernandes'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '3.0'
+# The full version, including alpha/beta/rc tags.
+release = '3.0.1'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be searched
+# for source files.
+exclude_trees = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. Major themes that come with
+# Sphinx are currently 'default' and 'sphinxdoc'.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_use_modindex = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'gswdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'gsw.tex', u'GSW Documentation',
+ u'Filipe Fernandes', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..805ad3d
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,45 @@
+.. seawater documentation master file, created by
+ sphinx-quickstart on Tue Aug 10 16:47:25 2010.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to gsw's documentation!
+====================================
+
+python gsw
+==========
+
+Introduction:
+-------------
+Python implementation of the Thermodynamic Equation Of Seawater - 2010
+(TEOS-10)
+
+For more information go to:
+ http://www.teos-10.org/
+
+Modules:
+--------
+
+.. toctree::
+ :maxdepth: 4
+
+
+gibbs Seawater Documentation
+============================
+
+This page contains the gsw Module documentation.
+
+The :mod:`gibbs` module
+-----------------------
+
+.. automodule:: seawater.gibbs
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
diff --git a/gsw.egg-info/PKG-INFO b/gsw.egg-info/PKG-INFO
new file mode 100644
index 0000000..f2e2952
--- /dev/null
+++ b/gsw.egg-info/PKG-INFO
@@ -0,0 +1,154 @@
+Metadata-Version: 1.1
+Name: gsw
+Version: 3.0.3
+Summary: Gibbs SeaWater Oceanographic Package of TEOS-10
+Home-page: http://pypi.python.org/pypi/seawater/
+Author: Filipe Fernandes
+Author-email: ocefpaf at gmail.com
+License: Copyright Notice and Statement for the gsw project:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+Download-URL: https://pypi.python.org/pypi/gsw/
+Description: This python module is incomplete and should be used with caution.
+ =================================================================
+
+ python gsw
+ ==========
+
+ | |Build|
+ | |Build|
+ | |Downloads|
+
+ Python implementation of the Thermodynamic Equation Of Seawater - 2010 (TEOS-10)[http://www.teos-10.org/\ ]
+ -----------------------------------------------------------------------------------------------------------
+
+ gsw vs. csiro
+ -------------
+
+ This table shows some function names in the gibbs library and the
+ corresponding function names in the csiro library.
+
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | **Variable** | **SeaWater (EOS 80)** | **Gibbs SeaWater (GSW TEOS 10)** |
+ +===========================================================+====================================================+==============================================================+
+ | Absolute Salinity | NA | gsw.SA\_from\_SP(SP,p,long,lat) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | Conservative Temperature | NA | gsw.CT\_from\_t(SA,t,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | density (i.e. in situ density) | sw.dens(SP,t,p) | gsw.rho\_CT(SA,CT,p), or gsw.rho(SA,t,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | potential density | sw.pden(SP,t,p,pr) | gsw.rho\_CT(SA,CT,pr) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | potential temperature | sw.ptmp(SP,t,p,pr) | gsw.pt\_from\_t(SA,t,p,pr) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | $\\sigma\_0$, using $\\theta\_o$ = sw.ptmp(SP,t,p,0) | sw.dens(SP, $\\theta\_o$, 0) -1000 kg m$^{-3}$ | gsw.sigma0\_CT(SA,CT) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | $\\sigma\_2$, using $\\theta\_2$ = sw.ptmp(SP,t,p,2000) | sw.dens(SP,$\\theta\_2$, 2000) -1000 kg m$^{-3}$ | gsw.sigma2\_CT(SA,CT) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | $\\sigma\_4$, using $\\theta\_4$ = sw.ptmp(SP,t,p,2000) | sw.dens(SP,$\\theta\_4$, 4000) -1000 kg m$^{-3}$ | gsw.sigma2\_CT(SA,CT) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | specific volume anomaly | sw.svan(SP,t,p) | gsw.specvol\_anom\_CT(SA,CT,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | dynamic height anomaly | -sw.gpan(SP,t,p) | gsw.geo\_strf\_dyn\_height(SA,CT,p,delta\_p,interp\_style) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | geostrophic velocity | sw.gvel(ga,lat,long) | gsw.geostrophic\_velocity(geo\_str,long,lat,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | N$^2$ | sw.bfrq(SP,t,p,lat) | gsw.Nsquared(SA,CT,p,lat) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | pressure from height (SW uses depth, not height) | sw.pres(-z,lat) | gsw.p\_from\_z(z,lat) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | height from pressure (SW outputs depth, not height) | z = -sw.dpth(p,lat) | gsw.z\_from\_p(p,lat) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | in situ temperature from pt | sw.temp(SP,pt,p,pr) | gsw.pt\_from\_t(SA,pt,pr,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | sound speed | sw.svel(SP,t,p) | gsw.sound\_speed(SA,t,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | isobaric heat capacity | sw.cp(SP,t,p) | gsw.cp(SA,t,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | adiabatic lapse rate\* | sw.adtg(SP,t,p) | gsw.adiabatic\_lapse\_rate(SA,t,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | SP from cndr, (PSS 78) | sw.salt(cndr,t,p) | gsw.SP\_from\_cndr(cndr,t,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | cndr from SP, (PSS 78) | sw.cndr(SP,t,p) | gsw.cndr\_from\_SP(SP,t,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | distance | sw.dist(lat,long,units) | gsw.distance(long,lat,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | gravitational acceleration | sw.g(lat,z) | gsw.grav(lat,p) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+ | Coriolis parameter | sw.f(lat) | gsw.f(lat) |
+ +-----------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------+
+
+ | Note that the SW and GSW functions output the adiabatic lapse rate in
+ different units, being K (dbar)$^{-1}$ and K Pa$^{-1}$
+ | respectively.
+
+ Authors
+ -------
+
+ - Bjørn Ådlandsvik
+ - Eric Firing
+ - Filipe Fernandes
+
+ Thanks
+ ------
+
+ - Bjørn Ådlandsvik - Testing unit and several bug fixes.
+ - Eric Firing - Support for masked arrays, re-write of *delta*\ SA.
+ - Trevor J. McDougall (and all of SCOR/IAPSO WG127) for making
+ available the Matlab version of this software.
+
+ Acknowledgments
+ ---------------
+
+ - SCOR/IAPSO WG127.
+
+ Caveats
+ -------
+
+ - This python module is incomplete and should be used with caution.
+ - The database used in ``_delta_SA`` comes from the MatlabTM gsw
+ version.
+
+ .. |Build| image:: https://badge.fury.io/py/gsw.png
+ :target: http://badge.fury.io/py/gsw
+ .. |Build| image:: https://api.travis-ci.org/ocefpaf/python-gsw.png?branch=master
+ :target: https://travis-ci.org/ocefpaf/python-gsw
+ .. |Downloads| image:: https://pypip.in/d/gsw/badge.png
+ :target: https://crate.io/packages/gsw/
+
+ version 3.0.3
+ =============
+
+ version 3.0
+ ===========
+ * New repository with TEOS10 code (version 3 only).
+
+Keywords: oceanography,seawater,TEOS-10,gibbs
+Platform: any
+Classifier: Development Status :: 4 - Beta
+Classifier: Environment :: Console
+Classifier: Intended Audience :: Science/Research
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Education
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Topic :: Education
+Classifier: Topic :: Scientific/Engineering
diff --git a/gsw.egg-info/SOURCES.txt b/gsw.egg-info/SOURCES.txt
new file mode 100644
index 0000000..c5f117c
--- /dev/null
+++ b/gsw.egg-info/SOURCES.txt
@@ -0,0 +1,47 @@
+CHANGES.txt
+LICENSE.txt
+MANIFEST.in
+README.txt
+setup.py
+docs/Makefile
+docs/conf.py
+docs/index.rst
+gsw/__init__.py
+gsw.egg-info/PKG-INFO
+gsw.egg-info/SOURCES.txt
+gsw.egg-info/dependency_links.txt
+gsw.egg-info/requires.txt
+gsw.egg-info/top_level.txt
+gsw/gibbs/__init__.py
+gsw/gibbs/constants.py
+gsw/gibbs/conversions.py
+gsw/gibbs/density_enthalpy_48.py
+gsw/gibbs/density_enthalpy_48_ct.py
+gsw/gibbs/density_enthalpy_ct_exact.py
+gsw/gibbs/derivatives.py
+gsw/gibbs/earth.py
+gsw/gibbs/freezing.py
+gsw/gibbs/geostrophic.py
+gsw/gibbs/geostrophic_48.py
+gsw/gibbs/isobaric.py
+gsw/gibbs/library.py
+gsw/gibbs/neutral_nonlinear_48.py
+gsw/gibbs/practical_salinity.py
+gsw/gibbs/steric.py
+gsw/gibbs/thermodynamics_from_t.py
+gsw/gibbs/water_column_48.py
+gsw/test/__init__.py
+gsw/test/check_functions.py
+gsw/test/signatures.py
+gsw/test/test_check_values.py
+gsw/test/test_octave.py
+gsw/test/test_profiles.py
+gsw/test/test_tuples.py
+gsw/utilities/__init__.py
+gsw/utilities/list_npz.py
+gsw/utilities/mat2npz.py
+gsw/utilities/utilities.py
+gsw/utilities/data/gsw_cf.npz
+gsw/utilities/data/gsw_cv_v3_0.npz
+gsw/utilities/data/gsw_data_v3_0.npz
+gsw/utilities/data/gsw_demo_data_v3_0.npz
\ No newline at end of file
diff --git a/gsw.egg-info/dependency_links.txt b/gsw.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/gsw.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/gsw.egg-info/requires.txt b/gsw.egg-info/requires.txt
new file mode 100644
index 0000000..9b65aaf
--- /dev/null
+++ b/gsw.egg-info/requires.txt
@@ -0,0 +1,2 @@
+numpy
+nose
\ No newline at end of file
diff --git a/gsw.egg-info/top_level.txt b/gsw.egg-info/top_level.txt
new file mode 100644
index 0000000..d9a3fb5
--- /dev/null
+++ b/gsw.egg-info/top_level.txt
@@ -0,0 +1,4 @@
+gsw/utilities
+gsw/gibbs
+gsw/test
+gsw
diff --git a/gsw/__init__.py b/gsw/__init__.py
new file mode 100644
index 0000000..c8ea799
--- /dev/null
+++ b/gsw/__init__.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+
+from .gibbs import *
+from .utilities import (Bunch, match_args_return, read_data, strip_mask,
+ loadmatbunch)
+
+data = read_data("gsw_data_v3_0.npz")
+
+__version__ = "3.0.3"
+__all__ = ['gibbs', 'utilities']
+__data_date__ = str(data['version_date'])
+__data_version__ = str(data['version_number'])
diff --git a/gsw/gibbs/__init__.py b/gsw/gibbs/__init__.py
new file mode 100644
index 0000000..f236509
--- /dev/null
+++ b/gsw/gibbs/__init__.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+
+from .earth import *
+from .steric import *
+from .library import *
+from .freezing import *
+from .isobaric import *
+from .constants import *
+from .derivatives import *
+from .conversions import *
+from .geostrophic import *
+from .geostrophic_48 import *
+from .water_column_48 import *
+from .practical_salinity import *
+from .density_enthalpy_48 import *
+from .neutral_nonlinear_48 import *
+from .thermodynamics_from_t import *
+from .density_enthalpy_48_ct import *
+from .density_enthalpy_ct_exact import *
diff --git a/gsw/gibbs/constants.py b/gsw/gibbs/constants.py
new file mode 100644
index 0000000..4939be7
--- /dev/null
+++ b/gsw/gibbs/constants.py
@@ -0,0 +1,144 @@
+# -*- coding: utf-8 -*-
+
+"""Constants"""
+
+from __future__ import division
+
+C3515 = 42.9140
+r"""Conductivity of 42.914 [mmho cm :sup:`-1` == mS cm :sup:`-1`] at Salinity
+35 psu, Temperature 15 :math:`^\\circ` C [ITPS 68] and Pressure 0 db.
+
+References
+----------
+.. [1] 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.
+
+.. [2] Unesco, 1983: Algorithms for computation of fundamental properties of
+seawater. Unesco Technical Papers in Marine Science, 44, 53 pp."""
+
+earth_radius = 6371000.
+r"""Mean radius of earth A.E. Gill."""
+
+OMEGA = 7.292115e-5
+r""":math:`\\Omega = \\frac{2\\pi}{\\textrm{sidereal day}}` =
+ 7.292e-5.radians sec :sup:`-1`
+
+1 sidereal day = 23.9344696 hours
+
+Changed to a more precise value at Groten 2004
+
+References
+----------
+.. [1] A.E. Gill 1982. p.54 eqn 3.7.15 "Atmosphere-Ocean Dynamics" Academic
+Press: New York. ISBN: 0-12-283522-0. page: 597
+.. [2] 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."""
+
+gdef = 9.8
+r"""Acceleration of gravity [m s :sup:`2`] used by sw.swvel and bfrq without
+lat info."""
+
+T0 = Kelvin = 273.15
+r"""The Celsius 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."""
+
+db2Pascal = 1e4
+r"""Decibar to pascal."""
+
+gamma = 2.26e-7
+r"""Gamma (A.E. Gill)."""
+
+M_S = 0.0314038218
+r"""Mole-weighted average atomic weight of the elements of
+Reference-Composition sea salt, in units of kg mol :sup:`-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."""
+
+cp0 = 3991.86795711963
+r"""The "specific heat" for use with Conservative Temperature. cp0 is the ratio
+of potential enthalpy to Conservative Temperature.
+See Eqn. (3.3.3) and Table D.5 from IOC et al. (2010)."""
+
+SSO = 35.16504
+r"""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 fundamental part of the
+TEOS-10 definition of seawater.
+
+References:
+-----------
+.. [1] 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. See appendices A.3, A.5 and Table D.4.
+
+.. [2] 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."""
+
+sfac = 0.0248826675584615
+r"""sfac = 1 / (40. * (SSO / 35.))"""
+
+R = 8.314472
+r"""The molar gas constant = 8.314472 m :sup:`2` kg s:sup:`-21 K :sup:`-1`
+mol :sup:`-1`."""
+
+r1 = 0.35
+""" TODO """
+
+uPS = SSO / 35.0
+r"""The unit conversion factor for salinities (35.16504/35) g/kg (Millero et
+al., 2008). Reference Salinity SR is uPS times Practical Salinity SP.
+
+Ratio, unit conversion factor for salinities [g kg :sup:`-1`]
+
+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 6, Eqn.(6.1)."""
+
+
+P0 = 101325
+r"""Absolute Pressure of one standard atmosphere in Pa, 101325 Pa."""
+
+SonCl = 1.80655
+r"""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.
+
+References:
+-----------
+.. [1] 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)."""
+
+valence_factor = 1.2452898
+r"""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.
+
+References:
+-----------
+.. [1] 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. See Table D.4 of this TEOS-10 Manual.
+
+.. [2] 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)."""
diff --git a/gsw/gibbs/conversions.py b/gsw/gibbs/conversions.py
new file mode 100644
index 0000000..9b66eee
--- /dev/null
+++ b/gsw/gibbs/conversions.py
@@ -0,0 +1,1724 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+
+from ..utilities import match_args_return, strip_mask
+from .constants import SSO, cp0, r1, Kelvin, sfac, uPS
+from .constants import db2Pascal, gamma, P0, M_S, valence_factor
+from .library import (entropy_part, entropy_part_zerop, gibbs, gibbs_pt0_pt0,
+ enthalpy_SSO_0_p, specvol_SSO_0_p)
+
+from .library import SA_from_SP_Baltic, SP_from_SA_Baltic, SAAR
+
+# This first set is moved over from absolute_salinity_sstar_ct,
+# which is being absorbed into this module.
+__all__ = ['CT_from_t',
+ 'SA_from_SP',
+ 'Sstar_from_SP',
+ 'Abs_Pressure_from_p',
+ 'CT_from_entropy',
+ 'CT_from_pt',
+ 'SA_Sstar_from_SP',
+ 'SA_from_Sstar',
+ 'SP_from_SA',
+ 'SP_from_SR',
+ 'SP_from_Sstar', # TODO
+ 'SR_from_SP',
+ 'Sstar_from_SA',
+ 'deltaSA_from_SP', # TODO
+ 'depth_from_z',
+ 'entropy_from_CT',
+ 'entropy_from_pt',
+ 'entropy_from_t',
+ 'ionic_strength_from_SA',
+ 'molality_from_SA',
+ 'p_from_Abs_Pressure',
+ 'p_from_z',
+ 'pot_enthalpy_from_pt',
+ 'pt0_from_t',
+ 'pt_from_CT',
+ 'pt_from_entropy',
+ 'pt_from_t',
+ 't90_from_t48',
+ 't90_from_t68',
+ 't_from_CT',
+ 't_from_entropy',
+ 'z_from_depth',
+ 'z_from_p'] # TODO: Test with geo_strf_dyn_height != None
+
+DEG2RAD = np.pi / 180.0
+n0, n1, n2 = 0, 1, 2 # constants used as arguments to gibbs()
+
+
+def check_input(SP, p, lon, lat):
+ r"""Check for out of range values."""
+ # Helper for the "from_SP" functions.
+ lon, lat, p, SP = np.broadcast_arrays(lon, lat, p, SP)
+
+ cond1 = ((p < 100) & (SP > 120))
+ cond2 = ((p >= 100) & (SP > 42))
+ if cond1.any() or cond2.any(): # don't modify input array
+ mask = np.ma.filled(cond1, False) | np.ma.filled(cond2, False)
+ SP = np.ma.array(SP, mask=mask)
+
+ lon = lon % 360
+
+ # FIXME: If we do keep the checks below, they need to
+ # be reformulated with ValueError('pressure out of range') etc.
+ # The original also checks for 9999s--a fossil from old-time
+ # Fortran days.
+
+ # I don't think we need these here; if any such checking is
+ # needed, it should not just be for the "from_SP" functions.
+ if False:
+ if ((p < -1.5) | (p > 12000)).any():
+ raise(Exception, 'Sstar_from_SP: pressure is out of range')
+ if ((lon < 0) | (lon > 360)).any():
+ raise(Exception, 'Sstar_from_SP: longitude is out of range')
+ if (np.abs(lat) > 90).any():
+ raise(Exception, 'Sstar_from_SP: latitude is out of range')
+
+ SP = np.maximum(SP, 0) # Works on masked array also.
+
+ return SP, p, lon, lat
+
+
+ at match_args_return
+def Abs_Pressure_from_p(p):
+ r"""Calculates Absolute Pressure from sea pressure. Note that Absolute
+ Pressure is in Pa NOT dbar.
+
+ Parameters
+ ---------
+ p : array_like
+ sea pressure [dbar]
+
+ Returns
+ -------
+ Absolute_Pressure : array_like
+ Absolute Pressure [Pa]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.2.1).
+
+ Modifications:
+ 2011-03-29. Trevor McDougall & Paul Barker
+ """
+
+ return p * db2Pascal + P0
+
+
+ at match_args_return
+def CT_from_entropy(SA, entropy):
+ r"""Calculates Conservative Temperature with entropy as an input variable.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ entropy : array_like
+ specific entropy [J kg :sup:`-1` K :sup:`-1`]
+
+ Returns
+ -------
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> entropy = [400.3892, 395.4378, 319.8668, 146.7910, 98.6471, 62.7919]
+ >>> gsw.CT_from_entropy(SA, entropy)
+ array([ 28.80990279, 28.43919923, 22.78619927, 10.22619767,
+ 6.82719674, 4.32360295])
+
+ References
+ ----------
+ .. [1] 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. See appendix A.10.
+
+ Modifications:
+ 2011-03-03. Trevor McDougall and Paul Barker.
+ """
+
+ SA = np.maximum(SA, 0)
+ pt = pt_from_entropy(SA, entropy)
+ return CT_from_pt(SA, pt)
+
+
+ at match_args_return
+def CT_from_pt(SA, pt):
+ r"""Calculates Conservative Temperature of seawater from potential
+ temperature (whose reference sea pressure is zero dbar).
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ pt : array_like
+ potential temperature referenced to a sea pressure of zero dbar
+ [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> pt = [28.7832, 28.4209, 22.7850, 10.2305, 6.8292, 4.3245]
+ >>> gsw.CT_from_pt(SA, pt)
+ array([ 28.80992302, 28.43914426, 22.78624661, 10.22616561,
+ 6.82718342, 4.32356518])
+
+ References
+ ----------
+ .. [1] 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. See section 3.3.
+
+ Modifications:
+ 2011-03-29. David Jackett, Trevor McDougall and Paul Barker.
+ """
+
+ SA, pt, mask = strip_mask(SA, pt)
+
+ pot_enthalpy = pot_enthalpy_from_pt(SA, pt)
+
+ CT = pot_enthalpy / cp0
+
+ return np.ma.array(CT, mask=mask, copy=False)
+
+
+ at match_args_return
+def SA_Sstar_from_SP(SP, p, lon, lat):
+ """
+ TODO: docstring
+ """
+ # Note: with match_args_return, the variables inside
+ # this function are masked arrays, so the outputs of
+ # other functions called here are also masked arrays.
+
+ SP, p, lon, lat = check_input(SP, p, lon, lat)
+
+ saar, in_ocean = SAAR(p, lon, lat)
+ SA = uPS * SP * (1 + saar)
+ Sstar = uPS * SP * (1 - r1 * saar)
+
+ SA_baltic = SA_from_SP_Baltic(SP, lon, lat)
+ bmask = SA_baltic.mask
+ if bmask is not np.ma.nomask and not bmask.all():
+ inbaltic = ~bmask
+ SA[inbaltic] = SA_baltic[inbaltic]
+ Sstar[inbaltic] = SA_baltic[inbaltic]
+
+ return SA, Sstar
+
+
+ at match_args_return
+def SA_from_Sstar(Sstar, p, lon, lat):
+ """
+ TODO: docstring
+ """
+ # maybe add some input checking...
+
+ saar, in_ocean = SAAR(p, lon, lat)
+ SA = Sstar * (1 + saar) / (1.0 - r1 * saar)
+
+ # % In the Baltic Sea, SA = Sstar, and note that gsw_delta_SA returns zero
+ # % for dSA in the Baltic.
+
+ return SA, in_ocean
+
+
+ at match_args_return
+def SP_from_SA(SA, p, lon, lat):
+ """
+ TODO: docstring
+ """
+ # maybe add input checking...
+
+ saar, in_ocean = SAAR(p, lon, lat)
+ SP = (35 / 35.16504) * SA / (1.0 + saar)
+
+ SP_baltic = SP_from_SA_Baltic(SA, lon, lat)
+ bmask = SP_baltic.mask
+ if bmask is not np.ma.nomask and not bmask.all():
+ inbaltic = ~bmask
+ SP[inbaltic] = SP_baltic[inbaltic]
+
+ return SP, in_ocean
+
+
+ at match_args_return
+def SP_from_SR(SR):
+ r"""Calculates Practical Salinity from Reference Salinity.
+
+ Parameters
+ ---------
+ SR : array_like
+ Reference Salinity [g kg :sup:`-1`]
+
+ Returns
+ -------
+ SP : array_like
+ Practical Salinity (PSS-78) [unitless]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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.
+
+ Modifications:
+ 2011-03-27. Trevor McDougall & Paul Barker
+ """
+
+ return 1. / uPS * SR
+
+
+def SP_from_Sstar():
+ pass
+
+
+ at match_args_return
+def SR_from_SP(SP):
+ r"""Calculates Reference Salinity from Practical Salinity.
+
+ Parameters
+ ---------
+ SP : array_like
+ Practical Salinity (PSS-78) [unitless]
+
+ Returns
+ -------
+ SR : array_like
+ Reference Salinity [g kg :sup:`-1`]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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.
+
+ Modifications:
+ 2011-03-27. Trevor McDougall & Paul Barker
+ """
+
+ return uPS * SP
+
+
+ at match_args_return
+def Sstar_from_SA(SA, p, lon, lat):
+ """
+ TODO: docstring
+ """
+ saar, in_ocean = SAAR(p, lon, lat)
+ Sstar = SA * (1 - r1 * saar) / (1 + saar)
+ # dSA is zero in Baltic
+ return Sstar, in_ocean
+
+
+ at match_args_return
+def CT_from_t(SA, t, p):
+ r"""Calculates Conservative Temperature of seawater from in situ
+ temperature.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+
+ Returns
+ -------
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See section 3.3.
+
+ Modifications:
+ 2011-03-27. David Jackett, Trevor McDougall and Paul Barker
+ """
+ # Find values that are out of range, set them to NaN.
+ invalid = np.logical_and(p < 100, np.logical_or(t > 80, t < -12))
+ t[invalid] = np.ma.masked
+
+ invalid = np.logical_and(p >= 100, np.logical_or(t > 40, t < -12))
+ t[invalid] = np.ma.masked
+
+ pt0 = pt0_from_t(SA, t, p)
+ CT = CT_from_pt(SA, pt0)
+
+ return CT
+
+
+ at match_args_return
+def SA_from_SP(SP, p, lon, lat):
+ r"""Calculates Absolute Salinity from Practical Salinity.
+
+ Parameters
+ ----------
+ SP : array_like
+ salinity (PSS-78) [unitless]
+ p : array_like
+ pressure [dbar]
+ lon : array_like
+ decimal degrees east [0..+360] or [-180..+180]
+ lat : array_like
+ decimal degrees (+ve N, -ve S) [-90..+90]
+
+ Returns
+ -------
+ SA : masked array
+ Absolute salinity [g kg :sup:`-1`]
+
+ See Also
+ --------
+ FIXME
+ _delta_SA, _SA_from_SP_Baltic
+
+ Notes
+ -----
+ The mask 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
+ kilometers inland from the coast.
+
+ Since SP is non-negative by definition, this function changes any negative
+ input values of SP to be zero.
+
+ Examples
+ --------
+ >>> import seawater.gibbs as gsw
+ >>> SP = [34.5487, 34.7275, 34.8605, 34.6810, 34.5680, 34.5600]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> lon, lat = 188, 4
+ >>> gsw.SA_from_SP(SP, p, lon, lat)
+ array([ 34.71177971, 34.89152372, 35.02554774, 34.84723008,
+ 34.7366296 , 34.73236186])
+
+ References
+ ----------
+ .. [1] 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. See section 2.5 and appendices A.4 and A.5.
+
+ .. [2] 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
+
+ Modifications:
+ 2011-05-31. David Jackett, Trevor McDougall & Paul Barker.
+ """
+
+ SP, p, lon, lat = check_input(SP, p, lon, lat)
+
+ SA = (SSO / 35) * SP * (1 + SAAR(p, lon, lat)[0])
+ SA_baltic = SA_from_SP_Baltic(SP, lon, lat)
+
+ # The following function (SAAR) finds SAAR in the non-Baltic parts of
+ # the world ocean. (Actually, this SAAR look-up table returns values
+ # of zero in the Baltic Sea since SAAR in the Baltic is a function of SP,
+ # not space.
+ if SA_baltic is not None:
+ SA[~SA_baltic.mask] = SA_baltic[~SA_baltic.mask]
+
+ return SA
+
+
+ at match_args_return
+def Sstar_from_SP(SP, p, lon, lat):
+ r"""Calculates Preformed Salinity from Absolute Salinity.
+
+ Parameters
+ ----------
+ SP : array_like
+ salinity (PSS-78) [unitless]
+ p : array_like
+ pressure [dbar]
+ lon : array_like
+ decimal degrees east [0..+360] or [-180..+180]
+ lat : array_like
+ decimal degrees (+ve N, -ve S) [-90..+90]
+
+ Returns
+ -------
+ Sstar : masked array
+ Preformed Salinity [g kg :sup:`-1`]
+
+ See Also
+ --------
+ FIXME
+ _delta_SA, _SA_from_SP_Baltic
+
+ Notes
+ -----
+ The mask 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
+ kilometers inland from the coast.
+
+ Since SP is non-negative by definition, this function changes any negative
+ input values of SP to be zero.
+
+ Examples
+ --------
+ >>> import seawater.gibbs as gsw
+ >>> SP = [34.5487, 34.7275, 34.8605, 34.6810, 34.5680, 34.5600]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> lon, lat = 188, 4
+ >>> gsw.Sstar_from_SP(SP, p, lon, lat)
+ array([ 34.7115532 , 34.89116101, 35.02464926, 34.84359277,
+ 34.7290336 , 34.71967638])
+
+ References
+ ----------
+ .. [1] 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. See section 2.5 and appendices A.4 and A.5.
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-03-27. David Jackett, Trevor McDougall and Paul Barker.
+ """
+
+ SP, p, lon, lat = check_input(SP, p, lon, lat)
+
+ Sstar = (SSO / 35.0) * SP * (1.0 - r1 * SAAR(p, lon, lat)[0])
+
+ # In the Baltic Sea, Sstar==SA.
+ Sstar_baltic = SA_from_SP_Baltic(SP, lon, lat)
+
+ # TODO: Create Baltic and non-Baltic test cases.
+ if Sstar_baltic is not None:
+ Sstar[~Sstar_baltic.mask] = Sstar_baltic[~Sstar_baltic.mask]
+
+ return Sstar
+
+
+ at match_args_return
+def deltaSA_from_SP(SP, p, lon, 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 at teos-10.org ]
+
+ VERSION NUMBER: 3.03 (29th April, 2013)
+
+ 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, F.J. Millero, R. Pawlowicz and
+ P.M. Barker, 2012: A global algorithm for estimating Absolute Salinity.
+ Ocean Science, 8, 1117-1128.
+ http://www.ocean-sci.net/8/1117/2012/os-8-1117-2012.pdf
+
+ """
+ return SA_from_SP(SP, p, lon, lat) - SR_from_SP(SP)
+
+
+def depth_from_z(z):
+ r"""Calculates depth from height, z. Note that in general height is
+ negative in the ocean.
+
+ Parameters
+ ---------
+ z : array_like
+ height [m]
+
+ Returns
+ -------
+ depth : array_like
+ depth [m]
+
+ Modifications:
+ 2011-03-26. Winston.
+ """
+
+ return -z
+
+
+ at match_args_return
+def entropy_from_CT(SA, CT):
+ r"""Calculates specific entropy of seawater.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ entropy : array_like
+ specific entropy [J kg :sup:`-1` K :sup:`-1`]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> CT = [28.8099, 28.4392, 22.7862, 10.2262, 6.8272, 4.3236]
+ >>> gsw.entropy_from_CT(SA, CT)
+ array([ 400.38916315, 395.43781023, 319.86680989, 146.79103279,
+ 98.64714648, 62.79185763])
+
+ References
+ ----------
+ .. [1] 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. See appendix A.10.
+
+ Modifications:
+ 2011-04-04. Trevor McDougall & Paul Barker
+ """
+
+ SA = np.maximum(SA, 0)
+ pt0 = pt_from_CT(SA, CT)
+ return -gibbs(n0, n1, n0, SA, pt0, 0)
+
+
+ at match_args_return
+def entropy_from_pt(SA, pt):
+ r"""Calculates specific entropy of seawater.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ pt : array_like
+ potential temperature [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ entropy : array_like
+ specific entropy [J kg :sup:`-1` K :sup:`-1`]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> pt = [28.7832, 28.4210, 22.7850, 10.2305, 6.8292, 4.3245]
+ >>> gsw.entropy_from_pt(SA, pt)
+ array([ 400.38946744, 395.43839949, 319.86743859, 146.79054828,
+ 98.64691006, 62.79135672])
+
+ References
+ ----------
+ .. [1] 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. See appendix A.10.
+
+ Modifications:
+ 2011-04-03. Trevor McDougall & Paul Barker
+ """
+
+ SA = np.maximum(SA, 0)
+ return -gibbs(n0, n1, n0, SA, pt, 0)
+
+
+ at match_args_return
+def entropy_from_t(SA, t, p):
+ """
+ gsw_entropy_from_t specific entropy of seawater
+ ==========================================================================
+
+ USAGE:
+ entropy = gsw_entropy_from_t(SA,t,p)
+
+ DESCRIPTION:
+ Calculates specific entropy 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:
+ entropy = specific entropy [ J/(kg*K) ]
+
+ AUTHOR:
+ David Jackett, Trevor McDougall and Paul Barker [ help at teos-10.org ]
+
+ VERSION NUMBER: 3.03 (29th April, 2013)
+
+ 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
+
+ """
+
+ return -gibbs(n0, n1, n0, SA, t, p)
+
+
+ at match_args_return
+def ionic_strength_from_SA(SA):
+ r"""Calculates the ionic strength of seawater from Absolute Salinity.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+
+ Returns
+ -------
+ ionic_strength : array_like
+ ionic strength of seawater [mol kg :sup:`-1`]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> gsw.ionic_strength_from_SA(SA)
+ array([ 0.71298118, 0.71680567, 0.71966059, 0.71586272, 0.71350891,
+ 0.71341953])
+
+ References
+ ----------
+ .. [1] 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. See Table L.1.
+
+ .. [2] 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 Eqns. 5.9 and 5.12.
+
+ Modifications:
+ 2011-03-29. Trevor McDougall and Paul Barker
+ """
+
+ # Molality of seawater in mol kg :sup:`-1`
+ molality = molality_from_SA(SA)
+
+ return 0.5 * valence_factor * molality
+
+
+ at match_args_return
+def molality_from_SA(SA):
+ r"""Calculates the molality of seawater from Absolute Salinity.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+
+ Returns
+ -------
+ molality : array_like
+ seawater molality [mol kg :sup:`-1`]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> gsw.molality(SA)
+ array([ 1.14508476, 1.15122708, 1.15581223, 1.14971265, 1.14593231,
+ 1.14578877])
+
+ References
+ ----------
+ .. [1] 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.
+
+ Modifications:
+ 2011-03-29. Trevor McDougall & Paul Barker
+ """
+
+ # Molality of seawater in mol kg :sup:`-1`.
+ SA = np.maximum(SA, 0)
+ molality = SA / (M_S * (1000 - SA))
+
+ return molality
+
+
+ at match_args_return
+def p_from_Abs_Pressure(Absolute_Pressure):
+ r"""Calculates sea pressure from Absolute Pressure. Note that Absolute
+ Pressure is in Pa NOT dbar.
+
+ Parameters
+ ---------
+ Absolute_Pressure : array_like
+ Absolute Pressure [Pa]
+
+ Returns
+ -------
+ p : array_like
+ sea pressure [dbar]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.2.1).
+
+ Modifications:
+ 2011-03-29. Trevor McDougall & Paul Barker
+ """
+
+ return (Absolute_Pressure - P0) * 1. / db2Pascal
+
+
+ at match_args_return
+def p_from_z(z, lat, geo_strf_dyn_height=0):
+ r"""Calculates sea pressure from height using computationally-efficient
+ 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 pr=0 (the surface.)
+
+ Parameters
+ ----------
+ z : array_like
+ height [m]
+ lat : array_like
+ latitude in decimal degrees north [-90..+90]
+ geo_strf_dyn_height : float, optional
+ dynamic height anomaly [ m :sup:`2` s :sup:`-2` ]
+ The reference pressure (p_ref) of geo_strf_dyn_height
+ must be zero (0) dbar.
+
+ Returns
+ -------
+ p : array_like
+ pressure [dbar]
+
+ See Also
+ --------
+ #FIXME: specvol_SSO_0_CT25, enthalpy_SSO_0_CT25, changed!
+
+ Examples
+ --------
+ >>> import gsw
+ >>> z = [-10., -50., -125., -250., -600., -1000.]
+ >>> lat = 4.
+ >>> gsw.p_from_z(z, lat)
+ array([ 10.05521794, 50.2711751, 125.6548857, 251.23284504,
+ 602.44050752, 1003.07609807])
+ >>> z = [9.94460074, 49.71817465, 124.2728275, 248.47044828, 595.82618014,
+ ... 992.0931748]
+ >>> gsw.p_from_z(z, lat)
+ array([ 10., 50., 125., 250., 600., 1000.])
+
+ Notes
+ -----
+ Height (z) is NEGATIVE in the ocean. Depth is -z. Depth is not used in the
+ gibbs library.
+
+ References
+ ----------
+ .. [1] 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.
+
+ .. [2] 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.
+
+ .. [3] Moritz (2000) Goedetic reference system 1980. J. Geodesy, 74,
+ 128-133.
+
+ .. [4] Saunders, P. M., 1981: Practical conversion of pressure to depth.
+ Journal of Physical Oceanography, 11, 573-574.
+
+ Modifications:
+ 2010-08-26. Trevor McDougall, Claire Roberts-Thomson and Paul Barker.
+ 2011-03-26. Trevor McDougall, Claire Roberts-Thomson and Paul Barker
+ """
+
+ X = np.sin(lat * DEG2RAD)
+ sin2 = X ** 2
+ gs = 9.780327 * (1.0 + (5.2792e-3 + (2.32e-5 * sin2)) * sin2)
+
+ # get the first estimate of p from Saunders (1981)
+ c1 = 5.25e-3 * sin2 + 5.92e-3
+ p = -2 * z / ((1 - c1) + np.sqrt((1 - c1) * (1 - c1) + 8.84e-6 * z))
+
+ df_dp = db2Pascal * specvol_SSO_0_p(p) # Initial value for f derivative.
+
+ f = (enthalpy_SSO_0_p(p) + gs *
+ (z - 0.5 * gamma * (z ** 2)) - geo_strf_dyn_height)
+
+ p_old = p
+ p = p_old - f / df_dp
+ p_mid = 0.5 * (p + p_old)
+ df_dp = db2Pascal * 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.
+
+ return p
+
+
+ at match_args_return
+def pot_enthalpy_from_pt(SA, pt):
+ r"""Calculates the potential enthalpy of seawater from potential
+ temperature (whose reference sea pressure is zero dbar).
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ pt : array_like
+ potential temperature referenced to a sea pressure of zero dbar
+ [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ pot_enthalpy : array_like
+ potential enthalpy [J kg :sup:`-1`]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> pt = [28.7832, 28.4209, 22.7850, 10.2305, 6.8292, 4.3245]
+ >>> gsw.pot_enthalpy_from_pt(SA, pt)
+ array([ 115005.40853458, 113525.30870246, 90959.68769935,
+ 40821.50280454, 27253.21472227, 17259.10131183])
+
+ References
+ ----------
+ .. [1] 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. See section 3.2.
+
+ Modifications:
+ 2011-03-29. David Jackett, Trevor McDougall and Paul Barker
+ """
+
+ SA, pt, mask = strip_mask(SA, pt)
+
+ SA = np.maximum(SA, 0)
+
+ x2 = sfac * SA
+ x = np.sqrt(x2)
+ y = pt * 0.025 # Normalize for F03 and F08
+
+ pot_enthalpy = (61.01362420681071 + y * (168776.46138048015 +
+ y * (-2735.2785605119625 + y * (2574.2164453821433 +
+ y * (-1536.6644434977543 + y * (545.7340497931629 +
+ (-50.91091728474331 - 18.30489878927802 * y) * y))))) +
+ x2 * (268.5520265845071 + y * (-12019.028203559312 +
+ y * (3734.858026725145 + y * (-2046.7671145057618 +
+ y * (465.28655623826234 + (-0.6370820302376359 -
+ 10.650848542359153 * y) * y)))) +
+ x * (937.2099110620707 + y * (588.1802812170108 +
+ y * (248.39476522971285 + (-3.871557904936333 -
+ 2.6268019854268356 * y) * y)) +
+ x * (-1687.914374187449 + x * (246.9598888781377 +
+ x * (123.59576582457964 - 48.5891069025409 * x)) +
+ y * (936.3206544460336 +
+ y * (-942.7827304544439 + y * (369.4389437509002 +
+ (-33.83664947895248 - 9.987880382780322 * y) * y)))))))
+
+ """The above polynomial for pot_enthalpy is the full expression for
+ potential enthalpy in terms of SA and pt, obtained from the Gibbs function
+ as below. It has simply collected like powers of x and y so that it is
+ computationally faster than calling the Gibbs function twice as is done in
+ the commented code below. When this code below is run, the results are
+ identical to calculating pot_enthalpy as above, to machine precision.
+
+ g000 = gibbs(n0, n0, n0, SA, pt, 0)
+ g010 = gibbs(n0, n1, n0, SA, pt, 0)
+ pot_enthalpy = g000 - (Kelvin + pt) * g010
+
+ This is the end of the alternative code
+ %timeit gsw.CT_from_pt(SA, pt)
+ 1000 loops, best of 3: 1.34 ms per loop <- calling gibbs
+ 1000 loops, best of 3: 254 us per loop <- standard
+ """
+
+ return np.ma.array(pot_enthalpy, mask=mask, copy=False)
+
+
+ at match_args_return
+def pt0_from_t(SA, t, p):
+ r"""Calculates potential temperature with reference pressure, pr = 0 dbar.
+ The present routine is computationally faster than the more general
+ function "pt_from_t(SA, t, p, pr)" which can be used for any reference
+ pressure value.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+
+ Returns
+ -------
+ pt0 : array_like
+ potential temperature relative to 0 dbar [:math:`^\circ` C (ITS-90)]
+
+ See Also
+ --------
+ entropy_part, gibbs_pt0_pt0, entropy_part_zerop
+
+ Notes
+ -----
+ pt_from_t has the same result (only slower)
+
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.pt0_from_t(SA, t, p)
+ array([ 28.78319682, 28.42098334, 22.7849304 , 10.23052366,
+ 6.82923022, 4.32451057])
+
+ References
+ ----------
+ .. [1] 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. See section 3.1.
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-03-29. Trevor McDougall, David Jackett, Claire Roberts-Thomson and
+ Paul Barker.
+ """
+
+ SA = np.maximum(SA, 0)
+
+ s1 = SA * (35. / SSO)
+
+ 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 / ((Kelvin + pt0) * (1 - 0.05 * (1 - SA / SSO)))
+
+ true_entropy_part = entropy_part(SA, t, p)
+
+ for Number_of_iterations in range(0, 2, 1):
+ pt0_old = pt0
+ dentropy = entropy_part_zerop(SA, pt0_old) - true_entropy_part
+ # Half way the mod. method (McDougall and Wotherspoon, 2012).
+ pt0 = pt0_old - dentropy / dentropy_dt
+ pt0m = 0.5 * (pt0 + pt0_old)
+ dentropy_dt = -gibbs_pt0_pt0(SA, pt0m)
+ pt0 = pt0_old - dentropy / dentropy_dt
+
+ """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."""
+
+ return pt0
+
+
+ at match_args_return
+def pt_from_CT(SA, CT):
+ r"""Calculates potential temperature (with a reference sea pressure of zero
+ dbar) from Conservative Temperature.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ pt : array_like
+ potential temperature referenced to a sea pressure of zero dbar
+ [:math:`^\circ` C (ITS-90)]
+
+ See Also
+ --------
+ specvol_anom
+
+ Notes
+ -----
+ This function uses 1.5 iterations through a modified Newton-Raphson (N-R)
+ iterative solution procedure, starting from a rational-function-based
+ initial condition for both pt and dCT_dpt.
+
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> CT = [28.8099, 28.4392, 22.7862, 10.2262, 6.8272, 4.3236]
+ >>> gsw.pt_from_CT(SA, CT)
+ array([ 28.78317705, 28.4209556 , 22.78495347, 10.23053439,
+ 6.82921659, 4.32453484])
+
+ References
+ ----------
+ .. [1] 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. See sections 3.1 and 3.3.
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-03-29. Trevor McDougall, David Jackett, Claire Roberts-Thomson and
+ Paul Barker.
+ """
+
+ SA, CT, mask = strip_mask(SA, CT)
+ SA = np.maximum(SA, 0)
+
+ s1 = SA * 35. / SSO
+
+ a0 = -1.446013646344788e-2
+ a1 = -3.305308995852924e-3
+ a2 = 1.062415929128982e-4
+ a3 = 9.477566673794488e-1
+ a4 = 2.166591947736613e-3
+ a5 = 3.828842955039902e-3
+
+ b0 = 1.000000000000000e+0
+ b1 = 6.506097115635800e-4
+ b2 = 3.830289486850898e-3
+ b3 = 1.247811760368034e-6
+
+ a5CT = a5 * CT
+ b3CT = b3 * CT
+ CT_factor = (a3 + a4 * s1 + a5CT)
+ pt_num = a0 + s1 * (a1 + a2 * s1) + CT * CT_factor
+ pt_den = b0 + b1 * s1 + CT * (b2 + b3CT)
+ pt = pt_num / pt_den
+
+ dCT_dpt = pt_den / (CT_factor + a5CT - (b2 + b3CT + b3CT) * pt)
+
+ # 1.5 iterations through the modified Newton-Rapshon iterative method
+ CT_diff = CT_from_pt(SA, pt) - CT
+ pt_old = pt
+ pt = pt_old - CT_diff / dCT_dpt # 1/2-way through the 1st modified N-R.
+ ptm = 0.5 * (pt + pt_old)
+
+ # This routine calls gibbs_pt0_pt0(SA, pt0) to get the second derivative of
+ # the Gibbs function with respect to temperature at zero sea pressure.
+
+ dCT_dpt = -(ptm + Kelvin) * gibbs_pt0_pt0(SA, ptm) / cp0
+ pt = pt_old - CT_diff / dCT_dpt # End of 1st full modified N-R iteration.
+ CT_diff = CT_from_pt(SA, pt) - CT
+ pt_old = pt
+ pt = pt_old - CT_diff / dCT_dpt # 1.5 iterations of the modified N-R.
+ # Abs max error of result is 1.42e-14 deg C.
+ return np.ma.array(pt, mask=mask, copy=False)
+
+
+ at match_args_return
+def pt_from_entropy(SA, entropy):
+ r"""Calculates potential temperature with reference pressure p_ref = 0 dbar
+ and with entropy as an input variable.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ entropy : array_like
+ specific entropy [J kg :sup:`-1` K :sup:`-1`]
+
+ Returns
+ -------
+ pt : array_like
+ potential temperature [:math:`^\circ` C (ITS-90)]
+ with reference sea pressure (p_ref) = 0 dbar.
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ >>> import seawater.gibbs as gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> entropy = [400.3892, 395.4378, 319.8668, 146.7910, 98.6471, 62.7919]
+ >>> gsw.pt_from_entropy(SA, entropy)
+ array([ 28.78317983, 28.42095483, 22.78495274, 10.23053207,
+ 6.82921333, 4.32453778])
+
+ References
+ ----------
+ .. [1] 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. See appendix A.10.
+
+ Modifications:
+ 2011-04-03. Trevor McDougall and Paul Barker.
+ """
+
+ SA = np.maximum(SA, 0)
+
+ part1 = 1 - SA / SSO
+ part2 = 1 - 0.05 * part1
+ ent_SA = (cp0 / Kelvin) * part1 * (1 - 1.01 * part1)
+ c = (entropy - ent_SA) * part2 / cp0
+ pt = Kelvin * (np.exp(c) - 1)
+ dentropy_dt = cp0 / ((Kelvin + pt) * part2) # Initial dentropy_dt.
+
+ for Number_of_iterations in range(0, 3):
+ pt_old = pt
+ dentropy = entropy_from_pt(SA, pt_old) - entropy
+ # This is half way through the modified method
+ # (McDougall and Wotherspoon, 2012)
+ pt = pt_old - dentropy / dentropy_dt
+ ptm = 0.5 * (pt + pt_old)
+ dentropy_dt = -gibbs_pt0_pt0(SA, ptm)
+ pt = pt_old - dentropy / dentropy_dt
+
+ """maximum error of 2.2x10^-6 degrees C for one iteration. maximum error is
+ 1.4x10^-14 degrees C for two iterations (two iterations is the default,
+ "for Number_of_iterations = 1:2")."""
+
+ return pt
+
+
+ at match_args_return
+def pt_from_t(SA, t, p, p_ref=0):
+ r"""Calculates potential temperature with the general reference pressure,
+ pr, from in situ temperature.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ p_ref : int, float, optional
+ reference pressure, default = 0
+
+ Returns
+ -------
+ pt : array_like
+ potential temperature [:math:`^\circ` C (ITS-90)]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ This function calls `entropy_part` which evaluates entropy except for the
+ parts which are a function of Absolute Salinity alone. A faster routine
+ exists pt0_from_t(SA,t,p) if p_ref is indeed zero dbar.
+
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.pt_from_t(SA, t, p)
+ array([ 28.78319682, 28.42098334, 22.7849304 , 10.23052366,
+ 6.82923022, 4.32451057])
+ >>> gsw.pt_from_t(SA, t, p, pr = 1000)
+ array([ 29.02665528, 28.662375 , 22.99149634, 10.35341725,
+ 6.92732954, 4.4036 ])
+
+ References
+ ----------
+ .. [1] 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. See section 3.1.
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-03-29. Trevor McDougall, David Jackett, Claire Roberts-Thomson and
+ Paul Barker.
+ """
+
+ p_ref = np.asanyarray(p_ref)
+
+ SA = np.maximum(SA, 0)
+
+ s1 = SA * 35. / SSO
+
+ 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 / ((Kelvin + pt) *
+ (1 - 0.05 * (1 - SA / SSO)))
+
+ true_entropy_part = entropy_part(SA, t, p)
+
+ for Number_of_iterations in range(0, 2, 1):
+ pt_old = pt
+ dentropy = entropy_part(SA, pt_old, p_ref) - true_entropy_part
+ pt = pt_old - dentropy / dentropy_dt # half way through the method
+ ptm = 0.5 * (pt + pt_old)
+ dentropy_dt = -gibbs(n0, n2, n0, SA, ptm, p_ref)
+ pt = pt_old - dentropy / dentropy_dt
+
+ """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."""
+
+ return pt
+
+
+ at match_args_return
+def t90_from_t48(t48):
+ r"""Converts IPTS-48 temperature to International Temperature Scale 1990
+ (ITS-90) temperature. This conversion should be applied to all in-situ
+ data collected prior to 31/12/1967.
+
+ Parameters
+ ---------
+ t48 : array_like
+ in-situ temperature [:math:`^\circ` C (ITPS-48)]
+
+ Returns
+ -------
+ t90 : array_like
+ in-situ temperature [:math:`^\circ` C (ITS-90)]
+
+ References
+ ----------
+ .. [1] International Temperature Scales of 1948, 1968 and 1990, an ICES
+ note, available from http://www.ices.dk/ocean/procedures/its.htm
+
+ Modifications:
+ 2011-03-29. Paul Barker and Trevor McDougall.
+ """
+
+ return (t48 - (4.4e-6) * t48 * (100 - t48)) / 1.00024
+
+
+ at match_args_return
+def t90_from_t68(t68):
+ r"""Converts IPTS-68 temperature to International Temperature Scale 1990
+ (ITS-90) temperature. This conversion should be applied to all in-situ
+ data collected between 1/1/1968 and 31/12/1989.
+
+ Parameters
+ ---------
+ t68 : array_like
+ in-situ temperature [:math:`^\circ` C (ITPS-68)]
+
+ Returns
+ -------
+ t90 : array_like
+ in-situ temperature [:math:`^\circ` C (ITS-90)]
+
+ References
+ ----------
+ .. [1] International Temperature Scales of 1948, 1968 and 1990, an ICES
+ note, available from http://www.ices.dk/ocean/procedures/its.htm
+
+ Modifications:
+ 2011-03-29. Paul Barker and Trevor McDougall.
+ """
+
+ # t90 = t68 / 1.00024
+ return t68 * 0.999760057586179
+
+
+ at match_args_return
+def t_from_CT(SA, CT, p):
+ r"""Calculates *in-situ* temperature from Conservative Temperature of
+ seawater.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+
+ Returns
+ -------
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> CT = [28.8099, 28.4392, 22.7862, 10.2262, 6.8272, 4.3236]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.t_from_CT(SA, CT, p)
+ array([ 28.78558023, 28.43287225, 22.81032309, 10.26001075,
+ 6.8862863 , 4.40362445])
+
+ References
+ ----------
+ .. [1] 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. See sections 3.1 and 3.3.
+
+ Modifications:
+ 2011-03-29. Trevor McDougall and Paul Barker
+ """
+
+ pt0 = pt_from_CT(SA, CT)
+ return pt_from_t(SA, pt0, 0, p)
+
+
+ at match_args_return
+def t_from_entropy(SA, entropy, p):
+ """
+ gsw_t_from_entropy in-situ temperature
+ as a function of entropy
+ =========================================================================
+
+ USAGE:
+ t = gsw_t_from_entropy(SA,entropy,p)
+
+ DESCRIPTION:
+ Calculates in-situ temperature with entropy as an input variable.
+
+ INPUT:
+ SA = Absolute Salinity [ g/kg ]
+ entropy = specific entropy [ J/(kg*K) ]
+ p = sea pressure [ dbar ]
+ ( i.e. absolute pressure - 10.1325 dbar )
+
+ SA & entropy need to have the same dimensions.
+ p may have dimensions 1x1 or Mx1 or 1xN or MxN, where SA & entropy are
+ MxN.
+
+ OUTPUT:
+ t = in-situ temperature (ITS-90) [ deg C ]
+
+ AUTHOR:
+ Trevor McDougall and Paul Barker [ help at teos-10.org ]
+
+ VERSION NUMBER: 3.03 (29th April, 2013)
+
+ 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.10 of this TEOS-10 Manual.
+
+ """
+ pt = pt_from_entropy(SA, entropy)
+ #% Note that pt is potential temperature with a reference pressure of zero.
+ p0 = 0
+ return pt_from_t(SA, pt, p0, p)
+
+
+def z_from_depth(depth):
+ r"""Calculates height, z, from depth. Note that in general height is
+ negative in the ocean.
+
+ Parameters
+ ---------
+ depth : array_like
+ depth [m]
+
+ Returns
+ -------
+ z : array_like
+ height [m]
+
+ Modifications:
+ 2011-03-26. Winston.
+ """
+
+ return -depth
+
+
+ at match_args_return
+def z_from_p(p, lat, geo_strf_dyn_height=0):
+ r"""Calculates height from sea pressure using the computationally-efficient
+ 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 pr=0 (the surface).
+
+ Parameters
+ ----------
+ p : array_like
+ pressure [dbar]
+ lat : array_like
+ latitude in decimal degrees north [-90..+90]
+ geo_strf_dyn_height : float, optional
+ dynamic height anomaly [ m :sup:`2` s :sup:`-2` ]
+
+ Returns
+ -------
+ z : array_like
+ height [m]
+
+ See Also
+ --------
+ # FIXME: enthalpy_SSO_0_CT25, changed!
+
+
+ Examples
+ --------
+ >>> import gsw
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> lat = 4
+ >>> gsw.z_from_p(p, lat)
+ array([ -9.94460074, -49.71817465, -124.2728275 , -248.47044828,
+ -595.82618014, -992.0931748 ])
+
+ Notes
+ -----
+ 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.
+
+ References
+ ----------
+ .. [1] 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.
+
+ .. [2] 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.
+
+ .. [3] Moritz (2000) Goedetic reference system 1980. J. Geodesy, 74,
+ 128-133.
+
+ Modifications:
+ 2011-03-26. Trevor McDougall, Claire Roberts-Thomson and Paul Barker.
+ """
+
+ X = np.sin(lat * DEG2RAD)
+ sin2 = X ** 2
+ B = 9.780327 * (1.0 + (5.2792e-3 + (2.32e-5 * sin2)) * sin2)
+ A = -0.5 * gamma * B
+ C = enthalpy_SSO_0_p(p) - geo_strf_dyn_height
+
+ return -2 * C / (B + np.sqrt(B ** 2 - 4 * A * C))
+
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/density_enthalpy_48.py b/gsw/gibbs/density_enthalpy_48.py
new file mode 100644
index 0000000..cacffa5
--- /dev/null
+++ b/gsw/gibbs/density_enthalpy_48.py
@@ -0,0 +1,1459 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+
+from .library import specvol_SSO_0_p
+from .constants import P0, db2Pascal, cp0
+from ..utilities import match_args_return
+
+__all__ = ['alpha',
+ 'alpha_on_beta',
+ 'alpha_on_beta_CT',
+ 'beta',
+ 'dynamic_enthalpy',
+ 'enthalpy',
+ 'enthalpy_diff',
+ 'internal_energy',
+ 'rho',
+ 'rho_alpha_beta',
+ 'SA_from_rho',
+ 'sigma0',
+ 'sigma1',
+ 'sigma2',
+ 'sigma3',
+ 'sigma4',
+ 'sound_speed',
+ 'specvol',
+ 'specvol_anom']
+
+
+# NOTE: these are from gsw_rho_alpha_beta.m
+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
+
+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
+
+# Helper functions that are used by more than one user function.
+# FIXME: arrange all these things so that inputs to these
+# functions are done with ordinary ndarrays with nans, not
+# masked arrays. We might need a different decorator for this.
+
+
+def v_hat_denominator(SA, CT, p, sqrtSA):
+ return (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)))
+
+
+def v_hat_numerator(SA, CT, p, sqrtSA):
+ return (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))))
+
+
+# Next 4 are from alpha on beta:
+def dvhatden_dCT(SA, CT, p, sqrtSA):
+ return (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)))
+
+
+def dvhatnum_dCT(SA, CT, p, sqrtSA):
+ return (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)))
+
+
+def dvhatden_dSA(SA, CT, p, sqrtSA):
+ return (b01 + CT * (b02 + b03 * CT) + sqrtSA *
+ (b04 + CT * (b05 + CT * (b06 + b07 * CT))) +
+ p * (b08 + b09 * CT + b10 * p))
+
+
+def dvhatnum_dSA(SA, CT, p, sqrtSA):
+ return(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)))
+
+
+ at match_args_return
+def alpha_on_beta(SA, CT, p):
+ """
+ gsw_alpha_on_beta alpha/beta (48-term equation)
+ ==========================================================================
+
+ USAGE:
+ alpha_on_beta = gsw_alpha_on_beta(SA,CT,p)
+
+ DESCRIPTION:
+ Calculates alpha divided by beta, where alpha is the thermal expansion
+ coefficient and beta is the 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 (IOC et al., 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 IOC et al. (2010). 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_on_beta = thermal expansion coefficient with respect to
+ Conservative Temperature divided by the saline
+ contraction coefficient at constant Conservative
+ Temperature [ kg g^-1 K^-1 ]
+
+ AUTHOR:
+ Paul Barker and Trevor McDougall [ help at teos-10.org ]
+
+ VERSION NUMBER: 3.03 (10th May, 2013)
+
+ 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
+
+ """
+ SA = np.maximum(SA, 0)
+ sqrtSA = np.sqrt(SA)
+ args = SA, CT, p, sqrtSA
+
+ num = (dvhatnum_dCT(*args) * v_hat_denominator(*args) -
+ dvhatden_dCT(*args) * v_hat_numerator(*args))
+ denom = (dvhatden_dSA(*args) * v_hat_numerator(*args) -
+ dvhatnum_dSA(*args) * v_hat_denominator(*args))
+ return num / denom
+
+alpha_on_beta_CT = alpha_on_beta
+
+
+ at match_args_return
+def alpha(SA, CT, p):
+ r"""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)
+
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+
+ Returns
+ -------
+ alpha : array_like
+ thermal expansion coefficient [K :math:`-1`]
+ with respect to Conservative Temperature
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ 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
+ "infunnel(SA, CT, p)" is available to be used if one wants to test if
+ some of one's data lies outside this "funnel".
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.18.3).
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-03-23. Paul Barker and Trevor McDougall.
+ """
+ SA = np.maximum(SA, 0)
+ sqrtSA = np.sqrt(SA)
+ args = SA, CT, p, sqrtSA
+
+ spec_vol = v_hat_numerator(*args) / v_hat_denominator(*args)
+
+ return ((dvhatnum_dCT(*args) - dvhatden_dCT(*args) * spec_vol) /
+ v_hat_numerator(*args))
+
+
+ at match_args_return
+def beta(SA, CT, p):
+ r"""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).
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+
+ Returns
+ -------
+ beta : array_like
+ saline contraction coefficient [kg g :math:`-1`]
+ at constant Conservative Temperature.
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ 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
+ "infunnel(SA, CT, p)" is available to be used if one wants to test if some
+ of one's data lies outside this "funnel".
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.19.3).
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-03-23. Paul Barker and Trevor McDougall.
+ """
+
+ SA = np.maximum(SA, 0)
+ sqrtSA = np.sqrt(SA)
+ args = SA, CT, p, sqrtSA
+
+ spec_vol = v_hat_numerator(*args) / v_hat_denominator(*args)
+
+ return ((dvhatden_dSA(*args) * spec_vol - dvhatnum_dSA(*args)) /
+ v_hat_numerator(*args))
+
+
+ at match_args_return
+def dynamic_enthalpy(SA, CT, p):
+ r"""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).
+
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+
+ Returns
+ -------
+ dynamic_enthalpy : array_like
+ dynamic enthalpy [J/kg]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ 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 "infunnel(SA, CT, p)" is
+ available to be used if one wants to test if some of one's data lies
+ outside this "funnel".
+
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See section 3.2
+
+ .. [2] 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.
+
+ .. [3] Young, W.R., 2010: Dynamic enthalpy, Conservative Temperature, and
+ the seawater Boussinesq approximation. Journal of Physical Oceanography,
+ 40, 394-400.
+
+ Modifications:
+ 2011-04-05. Trevor McDougall and Paul Barker.
+ """
+
+ SA = np.maximum(SA, 0)
+
+ sqrtSA = np.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 = np.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))
+
+ """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 = dynamic_enthalpy_CT_exact(SA, CT, p)
+ """
+
+ return db2Pascal * (p * (a2 - 2 * a3 * b1 / b2 + 0.5 * a3 * p) / b2 +
+ (M / (2 * b2)) *
+ np.log(1 + p * (2 * b1 + b2 * p) / b0) + part *
+ np.log(1 + (b2 * p * (B - A)) / (A * (B + b2 * p))))
+
+
+ at match_args_return
+def enthalpy(SA, CT, p):
+ r"""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)
+
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+
+ Returns
+ -------
+ enthalpy : array_like
+ specific enthalpy [J/kg]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ 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 "infunnel(SA, CT, p)" is
+ available to be used if one wants to test if some of one's data lies
+ outside this "funnel".
+
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Eqn. (A.30.6).
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-04-05. Trevor McDougall, David Jackett, Claire Roberts-Thomson and
+ Paul Barker.
+ """
+
+ SA = np.maximum(SA, 0)
+
+ sqrtSA = np.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 = np.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))
+
+ """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 = pt_from_CT(SA, CT)
+ t = pt_from_t(SA, pt, 0, p)
+ enthalpy = enthalpy_t_exact(SA, t, p)
+
+ or call the following, it is identical to the lines above.
+
+ enthalpy = enthalpy_CT_exact(SA, CT, p)
+ """
+
+ return (cp0 * CT + db2Pascal *
+ (p * (a2 - 2 * a3 * b1 / b2 + 0.5 * a3 * p) / b2 + (M / (2 * b2)) *
+ np.log(1 + p * (2 * b1 + b2 * p) / b0) + part *
+ np.log(1 + (b2 * p * (B - A)) / (A * (B + b2 * p)))))
+
+
+ at match_args_return
+def enthalpy_diff(SA, CT, p_shallow, p_deep):
+ r"""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).
+
+
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p_shallow : array_like
+ lower sea pressure [dbar]
+ p_deep : array_like
+ upper sea pressure [dbar]
+
+ Returns
+ -------
+ enthalpy_diff : array_like
+ difference of specific enthalpy [J/kg]
+ (deep minus shallow)
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ 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 "infunnel(SA, CT, p)" is
+ available to be used if one wants to test if some of one's data lies
+ outside this "funnel".
+
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Eqns. (3.32.2) and (A.30.6).
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-03-21. Trevor McDougall & Paul Barker.
+ """
+
+ SA = np.maximum(SA, 0)
+
+ sqrtSA = np.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 = np.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))
+
+ """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 = pt_from_CT(SA, CT)
+ t_shallow = pt_from_t(SA, pt, 0, p_shallow)
+ t_deep = pt_from_t(SA, pt, 0, p_deep)
+ enthalpy_diff = (enthalpy_t_exact(SA, t_deep, p_deep) -
+ enthalpy_t_exact(SA, t_shallow, p_shallow))
+
+ or call the following, it is identical to the lines above.
+
+ enthalpy_diff = enthalpy_diff_CT_exact(SA, CT, p_shallow, p_deep)
+ """
+
+ return db2Pascal * (delta_p * (a2 - 2 * a3 * b1 / b2 + 0.5 * a3 * p_sum) /
+ b2 + (M / (2 * b2)) *
+ np.log(1 + delta_p * (2 * b1 + b2 * p_sum) / part1) +
+ part3 * np.log(1 + delta_p * b2 * (B - A) / part2))
+
+
+ at match_args_return
+def internal_energy(SA, CT, p):
+ r"""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).
+
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+
+ Returns
+ -------
+ internal_energy : array_like
+ specific internal energy [J/kg]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ 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
+ "infunnel(SA, CT, p)" is available to be used if one wants to test if
+ some of one's data lies outside this "funnel".
+
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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.
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-04-04. Trevor McDougall and Paul Barker.
+ """
+
+ SA = np.maximum(SA, 0)
+
+ """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 = internal_energy_CT_exact(SA, CT, p)
+ """
+
+ return (enthalpy(SA, CT, p) - (P0 + db2Pascal * p) * specvol(SA, CT, p))
+
+
+ at match_args_return
+def rho(SA, CT, p):
+ r"""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).
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+
+ Returns
+ -------
+ rho : array_like
+ in-situ density [kg/m**3]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ The potential density with respect to reference pressure, pr, is obtained
+ by calling this function with the pressure argument being pr (i.e.
+ "rho(SA,CT,pr)").
+
+ 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 "infunnel(SA,CT,p)" is
+ available to be used if one wants to test if some of one's data lies
+ outside this "funnel".
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See appendix A.20 and appendix K.
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-04-18. Paul Barker and Trevor McDougall.
+ """
+
+ SA = np.maximum(SA, 0)
+ sqrtSA = np.sqrt(SA)
+ args = SA, CT, p, sqrtSA
+
+ """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 = pt_from_CT(SA, CT)
+ t = pt_from_t(SA, pt0, 0, p)
+ rho = rho_t_exact(SA, t, p)
+
+ or call the following, it is identical to the lines above.
+
+ rho = rho_CT_exact(SA, CT, p)
+
+ or call the following, it is identical to the lines above.
+
+ rho,_ ,_ = rho_alpha_beta_CT_exact(SA, CT, p)
+ """
+
+ return v_hat_denominator(*args) / v_hat_numerator(*args)
+
+
+def rho_alpha_beta(SA, CT, p):
+ r"""Calculates in-situ density, the appropriate 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).
+
+ The 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, _, _] = rho_alpha_beta(SA, CT, p_ref).
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+
+ Returns
+ -------
+ rho : array_like
+ in-situ density [kg/m**3]
+ alpha : array_like
+ thermal expansion coefficient [K :math:`-1`]
+ with respect to Conservative Temperature
+ beta : array_like
+ saline contraction coefficient [kg g :math:`-1`]
+ at constant Conservative Temperature.
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ 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 "infunnel(SA, CT, p)" is
+ available to be used if one wants to test if some of one's data lies
+ outside this "funnel".
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See appendix A.20 and appendix K.
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-04-03. Paul Barker and Trevor McDougall.
+ """
+
+ return rho(SA, CT, p), alpha(SA, CT, p), beta(SA, CT, p)
+
+
+ at match_args_return
+def SA_from_rho(rho, CT, p):
+ r"""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).
+
+ Parameters
+ ----------
+ rho : array_like
+ density of a seawater sample [kg/m**3]
+ This input has not had 1000 kg/m^3 subtracted from it
+ (e.g. 1026 kg m**-3), that is, it is density, NOT density anomaly.
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+
+ Returns
+ -------
+ SA : array_like
+ Absolute Salinity [g/kg]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ This is expressed on the Reference-Composition Salinity Scale of
+ Millero et al. (2008).
+
+ 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 "infunnel(SA, CT, p)" is
+ available to be used if one wants to test if some of one's data lies
+ outside this "funnel".
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See section 2.5
+
+ .. [2] 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.
+
+ .. [3] 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.
+
+ Modifications:
+ 2011-04-04. Trevor McDougall and Paul Barker.
+ """
+
+ v_lab = 1. / rho
+ v_0 = specvol(np.zeros_like(rho), CT, p)
+ v_50 = specvol(50 * np.ones_like(rho), CT, p)
+
+ SA = 50 * (v_lab - v_0) / (v_50 - v_0) # Initial estimate of SA.
+
+ SA[np.logical_or(SA < 0, SA > 50)] = np.ma.masked
+
+ v_SA = (v_50 - v_0) / 50. # Initial v_SA estimate (SA derivative of v).
+
+ # Begin the modified Newton-Raphson iterative procedure.
+ for Number_of_iterations in range(0, 3):
+ SA_old = SA
+ delta_v = specvol(SA_old, CT, p) - v_lab
+ # Half way the mod. N-R method (McDougall and Wotherspoon, 2012)
+ SA = SA_old - delta_v / v_SA # Half way through the mod. N-R method.
+ SA_mean = 0.5 * (SA + SA_old)
+ rho, alpha, beta = rho_alpha_beta(SA_mean, CT, p)
+ v_SA = -beta / rho
+ SA = SA_old - delta_v / v_SA
+ SA[np.logical_or(SA < 0, SA > 50)] = np.ma.masked
+
+ # 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.
+ return SA
+
+
+def sigma0(SA, CT):
+ r"""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).
+
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ sigma0 : array_like
+ potential density anomaly with [kg/m**3]
+ respect to a reference pressure of 0 dbar
+
+ See Also
+ --------
+ gsw.rho
+ """
+
+ """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.
+
+ sigma0 = rho_CT_exact(SA, CT, 0) - 1000
+ """
+
+ return rho(SA, CT, 0.) - 1000
+
+
+def sigma1(SA, CT):
+ r"""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.
+
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ sigma1 : array_like
+ potential density anomaly with [kg/m**3]
+ respect to a reference pressure of 1000 dbar
+
+ See Also
+ --------
+ gsw.rho
+ """
+
+ """This function calculates sigma1 using the computationally-efficient
+ 48-term expression for density in terms of SA, CT and p. If one wanted
+ to compute sigma1 with the full TEOS-10 Gibbs function expression for
+ density, the following lines of code will enable this.
+
+ rho1 = rho_CT_exact(SA, CT, 1000)
+ """
+
+ return rho(SA, CT, 1000.) - 1000
+
+
+def sigma2(SA, CT):
+ r"""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.
+
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ sigma2 : array_like
+ potential density anomaly with [kg/m**3]
+ respect to a reference pressure of 2000 dbar
+
+ See Also
+ --------
+ gsw.rho
+ """
+
+ """This function calculates sigma2 using the computationally-efficient
+ 48-term expression for density in terms of SA, CT and p. If one wanted
+ to compute sigma2 with the full TEOS-10 Gibbs function expression for
+ density, the following lines of code will enable this.
+
+ rho2 = rho_CT_exact(SA, CT, 2000.)
+ """
+
+ return rho(SA, CT, 2000.) - 1000
+
+
+def sigma3(SA, CT):
+ r"""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.
+
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ sigma1 : array_like
+ potential density anomaly with [kg/m**3]
+ respect to a reference pressure of 3000 dbar
+
+ See Also
+ --------
+ gsw.rho
+ """
+
+ """This function calculates sigma3 using the computationally-efficient
+ 48-term expression for density in terms of SA, CT and p. If one wanted
+ to compute sigma3 with the full TEOS-10 Gibbs function expression for
+ density, the following lines of code will enable this.
+
+ rho3 = rho_CT_exact(SA, CT, 3000.)
+ """
+
+ return rho(SA, CT, 3000.) - 1000
+
+
+def sigma4(SA, CT):
+ r"""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.
+
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ sigma1 : array_like
+ potential density anomaly with [kg/m**3]
+ respect to a reference pressure of 4000 dbar
+
+ See Also
+ --------
+ gsw.rho
+ """
+
+ """This function calculates sigma3 using the computationally-efficient
+ 48-term expression for density in terms of SA, CT and p. If one wanted
+ to compute sigma3 with the full TEOS-10 Gibbs function expression for
+ density, the following lines of code will enable this.
+
+ rho4 = rho_CT_exact(SA, CT, 4000.)
+ """
+
+ return rho(SA, CT, 4000.) - 1000
+
+
+ at match_args_return
+def sound_speed(SA, CT, p):
+ r"""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).
+
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+
+ Returns
+ -------
+ sound_speed : array_like
+ speed of sound in seawater [m/s]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ Approximate with a r.m.s. of 6.7 cm s^-1.
+
+ 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
+ "infunnel(SA, CT, p)" is available to be used if one wants to test if
+ some of one's data lies outside this "funnel".
+
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.17.1).
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-03-23. Paul Barker and Trevor McDougall.
+ """
+
+ SA = np.maximum(SA, 0)
+ sqrtSA = np.sqrt(SA)
+ args = SA, CT, p, sqrtSA
+
+ dvden_dp = (c01 + CT * (c02 + c03 * CT) + SA * (c04 + c05 * CT) + p *
+ (c06 + CT * (c07 + c08 * CT) + c09 * SA))
+
+ 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)))
+
+ drho_dp = ((dvden_dp * v_hat_numerator(*args) - dvnum_dp *
+ v_hat_denominator(*args)) / (v_hat_numerator(*args) *
+ v_hat_numerator(*args)))
+
+ return 100 * np.sqrt(1. / drho_dp)
+
+
+ at match_args_return
+def specvol(SA, CT, p):
+ r"""Calculates specific volume from Absolute Salinity, Conservative
+ Temperature and pressure, using the computationally-efficient 48-term
+ expression for density (McDougall et al., 2011).
+
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+
+ Returns
+ -------
+ specvol : array_like
+ specific volume [m**3/kg]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ 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 "infunnel(SA,CT,p)" is
+ available to be used if one wants to test if some of one's data lies
+ outside this "funnel".
+
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.7.2).
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-03-18. Paul Barker and Trevor McDougall.
+ """
+
+ SA = np.maximum(SA, 0)
+
+ """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 = pt_from_CT(SA, CT)
+ t = pt_from_t(SA, pt, 0, p)
+ specvol = specvol_t_exact(SA, t, p)
+
+ or call the following, it is identical to the lines above.
+
+ specvol = specvol_CT_exact(SA, CT, p)
+ """
+
+ SA = np.maximum(SA, 0)
+ sqrtSA = np.sqrt(SA)
+ args = SA, CT, p, sqrtSA
+
+ return v_hat_numerator(*args) / v_hat_denominator(*args)
+
+
+ at match_args_return
+def specvol_anom(SA, CT, p):
+ r"""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 degrees C.
+
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+
+ Returns
+ -------
+ specvol_anom : array_like
+ specific volume anomaly [m**3/kg]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ 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 "infunnel(SA,CT,p)" is
+ available to be used if one wants to test if some of one's data lies
+ outside this "funnel".
+
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Eqn. (3.7.3).
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-03-24. Paul Barker and Trevor McDougall.
+ """
+
+ SA = np.maximum(SA, 0)
+ sqrtSA = np.sqrt(SA)
+ args = SA, CT, p, sqrtSA
+
+ """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 = pt_from_CT(SA, CT)
+ t = pt_from_t(SA, pt, 0, p)
+ specvol_anom = specvol_anom_t_exact(SA, t, p)
+
+ or call the following, it is identical to the lines above.
+
+ specvol_anom = specvol_anom_CT_exact(SA, CT, p)
+ """
+
+ return (v_hat_numerator(*args) / v_hat_denominator(*args) -
+ specvol_SSO_0_p(p))
+
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/density_enthalpy_48_ct.py b/gsw/gibbs/density_enthalpy_48_ct.py
new file mode 100644
index 0000000..5e44463
--- /dev/null
+++ b/gsw/gibbs/density_enthalpy_48_ct.py
@@ -0,0 +1,106 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+
+__all__ = ['alpha_CT', # TODO
+ 'beta_CT', # TODO
+ 'CT_from_rho', # TODO
+ 'CT_maxdensity', # TODO
+ 'dynamic_enthalpy_CT', # TODO
+ 'enthalpy_CT', # TODO
+ 'enthalpy_diff_CT', # TODO
+ 'internal_energy_CT', # TODO
+ 'rho_CT', # TODO
+ 'rho_alpha_beta_CT', # TODO
+ 'SA_from_rho_CT', # TODO
+ 'sigma0_CT', # TODO
+ 'sigma1_CT', # TODO
+ 'sigma2_CT', # TODO
+ 'sigma3_CT', # TODO
+ 'sigma4_CT', # TODO
+ 'sound_speed_CT', # TODO
+ 'specvol_CT', # TODO
+ 'specvol_anom_CT'] # TODO
+
+
+def alpha_CT():
+ pass
+
+
+def beta_CT():
+ pass
+
+
+def CT_from_rho():
+ pass
+
+
+def CT_maxdensity():
+ pass
+
+
+def dynamic_enthalpy_CT():
+ pass
+
+
+def enthalpy_CT():
+ pass
+
+
+def enthalpy_diff_CT():
+ pass
+
+
+def internal_energy_CT():
+ pass
+
+
+def rho_CT():
+ pass
+
+
+def rho_alpha_beta_CT():
+ pass
+
+
+def SA_from_rho_CT():
+ pass
+
+
+def sigma0_CT():
+ pass
+
+
+def sigma1_CT():
+ pass
+
+
+def sigma2_CT():
+ pass
+
+
+def sigma3_CT():
+ pass
+
+
+def sigma4_CT():
+ pass
+
+
+def sound_speed_CT():
+ pass
+
+
+def specvol_CT():
+ pass
+
+
+def specvol_anom_CT():
+ pass
+
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/density_enthalpy_ct_exact.py b/gsw/gibbs/density_enthalpy_ct_exact.py
new file mode 100644
index 0000000..d7351ee
--- /dev/null
+++ b/gsw/gibbs/density_enthalpy_ct_exact.py
@@ -0,0 +1,716 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+
+from .constants import cp0
+from ..utilities import match_args_return
+from .conversions import t_from_CT, CT_from_t, pt_from_CT
+from .thermodynamics_from_t import (t_from_rho_exact, rho_t_exact,
+ alpha_wrt_CT_t_exact, t_maxdensity_exact,
+ enthalpy_t_exact, beta_const_CT_t_exact,
+ specvol_t_exact, internal_energy_t_exact,
+ sigma0_pt0_exact, specvol_anom_t_exact,
+ sound_speed_t_exact)
+
+__all__ = ['alpha_CT_exact',
+ 'beta_CT_exact',
+ 'CT_from_rho_exact',
+ 'CT_maxdensity_exact',
+ 'dynamic_enthalpy_CT_exact',
+ 'enthalpy_CT_exact',
+ 'enthalpy_diff_CT_exact',
+ 'internal_energy_CT_exact',
+ 'rho_CT_exact',
+ 'rho_alpha_beta_CT_exact',
+ 'SA_from_rho_CT_exact',
+ 'sigma0_CT_exact',
+ 'sigma1_CT_exact',
+ 'sigma2_CT_exact',
+ 'sigma3_CT_exact',
+ 'sigma4_CT_exact',
+ 'sound_speed_CT_exact',
+ 'specvol_CT_exact',
+ 'specvol_anom_CT_exact']
+
+
+def alpha_CT_exact(SA, CT, p):
+ r"""Calculates the thermal expansion coefficient of seawater with respect
+ to Conservative Temperature from Absolute Salinity and Conservative
+ Temperature.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ alpha_CT_exact : array_like
+ thermal expansion coefficient [K :sup:`-1`]
+ with respect to Conservative Temperature
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ This function uses the full Gibbs function. There is an alternative to
+ calling this function, namely 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)).
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.18.3).
+ .. [2] 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.
+ Modifications:
+ 2011-03-23. David Jackett, Trevor McDougall and Paul Barker.
+ """
+ t = t_from_CT(SA, CT, p)
+ return alpha_wrt_CT_t_exact(SA, t, p)
+
+
+def beta_CT_exact(SA, CT, p):
+ r"""Calculates the saline (i.e. haline) contraction coefficient of seawater
+ at constant Conservative Temperature.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ beta_CT_exact : array_like
+ thermal expansion coefficient [K :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ This function uses the full Gibbs function. There is an alternative to
+ calling this function, namely 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)).
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.19.3).
+ .. [2] 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.
+ Modifications:
+ 2011-03-23. Trevor McDougall and Paul Barker.
+ """
+ t = t_from_CT(SA, CT, p)
+ return beta_const_CT_t_exact(SA, t, p)
+
+
+def CT_from_rho_exact(rho, SA, p):
+ r"""Calculates the in-situ temperature of a seawater sample, for given
+ values of its density, Absolute Salinity and sea pressure (in dbar).
+ Parameters
+ ----------
+ rho : array_like
+ density of a seawater sample [kg/m**3]
+ This input has not had 1000 kg/m^3 subtracted from it
+ (e.g. 1026 kg m**-3), that is, it is density, NOT density anomaly.
+ SA : array_like
+ Absolute Salinity [g/kg]
+ p : array_like
+ sea pressure [dbar]
+ Returns
+ -------
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ CT_multiple : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ At low salinities, in brackish water, there are two possible temperatures
+ for a single density. This program will output both valid solutions
+ (t, t_multiple), if there is only one possible solution the second variable
+ will be set to NaN.
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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. See section 2.5.
+ Modifications:
+ 2011-04-21. Trevor McDougall and Paul Barker.
+ """
+ t, t_multiple = t_from_rho_exact(rho, SA, p)
+ return CT_from_t(SA, t, p), CT_from_t(SA, t_multiple, p)
+
+
+def CT_maxdensity_exact(SA, p):
+ r"""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).
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ p : array_like
+ sea pressure [dbar]
+ Returns
+ -------
+ CT_maxdensity_exact : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ at which the density of seawater is a maximum for given SA and p.
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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. See section 3.42.
+ Modifications:
+ 2011-04-03. Trevor McDougall and Paul Barker.
+ """
+ t_max_exact = t_maxdensity_exact(SA, p)
+ return CT_from_t(SA, t_max_exact, p)
+
+
+def dynamic_enthalpy_CT_exact(SA, CT, p):
+ r"""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).
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+ Returns
+ -------
+ dynamic_enthalpy_CT_exact : array_like
+ dynamic enthalpy [J/kg]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ This function uses the full Gibbs function. There is an alternative to
+ calling this function, namely 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).
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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. See apendix A.30.
+ .. [2] 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.
+ .. [3] Young, W.R., 2010: Dynamic enthalpy, Conservative Temperature, and
+ the seawater Boussinesq approximation. Journal of Physical Oceanography,
+ 40, 394-400.
+ Modifications:
+ 2011-04-05. Trevor McDougall and Paul Barker.
+ """
+ t = t_from_CT(SA, CT, p)
+ return enthalpy_t_exact(SA, t, p) - cp0 * CT
+
+
+ at match_args_return
+def enthalpy_CT_exact(SA, CT, p):
+ r"""Calculates specific enthalpy of seawater from Absolute Salinity and
+ Conservative Temperature and pressure.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+ Returns
+ -------
+ enthalpy_CT_exact : array_like
+ specific enthalpy [J/kg]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ This function uses the full Gibbs function. There is an alternative to
+ calling this function, namely 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).
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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. See appendix A.11.
+ .. [2] 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.
+ Modifications:
+ 2011-04-06. Trevor McDougall and Paul Barker.
+ """
+ t = t_from_CT(SA, CT, p)
+ return enthalpy_t_exact(SA, t, p)
+
+
+def enthalpy_diff_CT_exact(SA, CT, p_shallow, p_deep):
+ r"""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).
+ parameters
+ ----------
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p_shallow : array_like
+ lower sea pressure [dbar]
+ p_deep : array_like
+ upper sea pressure [dbar]
+ returns
+ -------
+ enthalpy_diff_CT_exact : array_like
+ difference of specific enthalpy [J/kg]
+ (deep minus shallow)
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ This function uses the full Gibbs function. There is an alternative to
+ calling this function, namely 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).
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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. See Eqns (3.32.2).
+ .. [2] 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.
+ Modifications:
+ 2011-04-06. Trevor McDougall and Paul Barker.
+ """
+ t_shallow = t_from_CT(SA, CT, p_shallow)
+ t_deep = t_from_CT(SA, CT, p_deep)
+ return (enthalpy_t_exact(SA, t_deep, p_deep) -
+ enthalpy_t_exact(SA, t_shallow, p_shallow))
+
+
+def internal_energy_CT_exact(SA, CT, p):
+ r"""Calculates the specific internal energy of seawater from Absolute
+ Salinity, Conservative Temperature and pressure.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+ Returns
+ -------
+ internal_energy_CT_exact: array_like
+ specific internal energy (u) [J/kg]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.11.1).
+ Modifications:
+ 2011-04-05. Trevor McDougall.
+ """
+ t = t_from_CT(SA, CT, p)
+ return internal_energy_t_exact(SA, t, p)
+
+
+def rho_CT_exact(SA, CT, p):
+ r"""Calculates in-situ density from Absolute Salinity and Conservative
+ Temperature.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+ Returns
+ -------
+ rho_CT_exact : array_like
+ in-situ density [kg/m**3]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ The potential density with respect to reference pressure, p_ref, is
+ obtained by calling this function with the pressure argument being p_ref
+ (i.e. "rho_CT_exact(SA, CT, p_ref)"). This function uses the full Gibbs
+ function. There is an alternative to calling this function, namely
+ 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).
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.8.2).
+ .. [2] 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.
+ Modifications:
+ 2011-04-03. Trevor McDougall and Paul Barker.
+ """
+ t = t_from_CT(SA, CT, p)
+ return rho_t_exact(SA, t, p)
+
+
+def rho_alpha_beta_CT_exact(SA, CT, p):
+ r"""Calculates in-situ density, the appropriate thermal expansion
+ coefficient and the appropriate saline contraction coefficient of seawater
+ from Absolute Salinity and Conservative Temperature.
+ See the individual functions rho_CT_exact, alpha_CT_exact, and
+ beta_CT_exact. Retained for compatibility with the Matlab GSW toolbox.
+ """
+ t = t_from_CT(SA, CT, p)
+ rho_CT_exact = rho_t_exact(SA, t, p)
+ alpha_CT_exact = alpha_wrt_CT_t_exact(SA, t, p)
+ beta_CT_exact = beta_const_CT_t_exact(SA, t, p)
+ return rho_CT_exact, alpha_CT_exact, beta_CT_exact
+
+
+def SA_from_rho_CT_exact(rho, CT, p):
+ r"""Calculates the Absolute Salinity of a seawater sample, for given values
+ of its density, Conservative Temperature and sea pressure (in dbar).
+ Parameters
+ ----------
+ rho : array_like
+ density of a seawater sample [kg/m**3]
+ This input has not had 1000 kg/m^3 subtracted from it
+ (e.g. 1026 kg m**-3), that is, it is density, NOT density anomaly.
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+ Returns
+ -------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ This function uses the full Gibbs function. There is an alternative to
+ calling this function, namely 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).
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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. See section 2.5.
+ .. [2] 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.
+ Modifications:
+ 2011-04-05. Trevor McDougall and Paul Barker.
+ """
+ v_lab = 1. / rho
+ v_0 = specvol_CT_exact(np.zeros_like(rho), CT, p)
+ v_120 = specvol_CT_exact(120 * np.ones_like(rho), CT, p)
+ SA = 120 * (v_lab - v_0) / (v_120 - v_0) # Initial estimate of SA.
+ SA[np.logical_or(SA < 0, SA > 120)] = np.ma.masked
+ v_SA = (v_120 - v_0) / 120 # Initial v_SA estimate (SA derivative of v).
+ # Begin the modified Newton-Raphson iterative procedure.
+ for Number_of_iterations in range(0, 3):
+ SA_old = SA
+ delta_v = specvol_CT_exact(SA_old, CT, p) - v_lab
+ # Half way the mod. N-R method (McDougall and Wotherspoon, 2012).
+ SA = SA_old - delta_v / v_SA
+ SA_mean = 0.5 * (SA + SA_old)
+ rho, alpha, beta = rho_alpha_beta_CT_exact(SA_mean, CT, p)
+ v_SA = -beta / rho
+ SA = SA_old - delta_v / v_SA
+ SA[np.logical_or(SA < 0, SA > 120)] = np.ma.masked
+ """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."""
+ return SA
+
+
+def sigma0_CT_exact(SA, CT):
+ r"""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.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ Returns
+ -------
+ sigma0_CT_exact: array_like
+ Potential density anomaly with [kg/m**3]
+ respect to a reference pressure of 0 dbar
+ that is, this potential density - 1000 kg/m**3.
+ Notes
+ -----
+ 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).
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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. See Eqn. (A.30.1).
+ .. [2] 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.
+ Modifications:
+ 2011-04-03. Trevor McDougall and Paul Barker.
+ """
+ pt0 = pt_from_CT(SA, CT)
+ return sigma0_pt0_exact(SA, pt0)
+
+
+def sigma1_CT_exact(SA, CT):
+ r"""Calculates potential density anomaly with reference pressure of
+ 1000 dbar."""
+ t = t_from_CT(SA, CT, 1000.)
+ return rho_t_exact(SA, t, 1000.) - 1000
+
+
+def sigma2_CT_exact(SA, CT):
+ r"""Calculates potential density anomaly with reference pressure of
+ 2000 dbar."""
+ t = t_from_CT(SA, CT, 2000.)
+ return rho_t_exact(SA, t, 2000.) - 1000
+
+
+def sigma3_CT_exact(SA, CT):
+ r"""Calculates potential density anomaly with reference pressure of
+ 3000 dbar."""
+ t = t_from_CT(SA, CT, 3000.)
+ return rho_t_exact(SA, t, 3000.) - 1000
+
+
+def sigma4_CT_exact(SA, CT):
+ r"""Calculates potential density anomaly with reference pressure of
+ 4000 dbar."""
+ t = t_from_CT(SA, CT, 4000.)
+ return rho_t_exact(SA, t, 4000.) - 1000
+
+
+def sound_speed_CT_exact(SA, CT, p):
+ r"""Calculates the speed of sound in seawater from Absolute Salinity and
+ Conservative Temperature and pressure.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ sound_speed_CT_exact : array_like
+ Speed of sound in seawater [m s :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.17.1).
+ Modifications:
+ 2011-04-05. David Jackett, Paul Barker and Trevor McDougall.
+ """
+ t = t_from_CT(SA, CT, p)
+ return sound_speed_t_exact(SA, t, p)
+
+
+def specvol_CT_exact(SA, CT, p):
+ r"""Calculates specific volume from Absolute Salinity, Conservative
+ Temperature and pressure.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+ Returns
+ -------
+ specvol_CT_exact : array_like
+ specific volume [m**3/kg]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ This function uses the full Gibbs function. There is an alternative to
+ calling this function, namely 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).
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.7.2).
+ .. [2] 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.
+ Modifications:
+ 2011-04-06. Trevor McDougall and Paul Barker.
+ """
+ t = t_from_CT(SA, CT, p)
+ return specvol_t_exact(SA, t, p)
+
+
+def specvol_anom_CT_exact(SA, CT, p):
+ r"""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 deg C.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+ Returns
+ -------
+ specvol_anom_CT_exact : array_like
+ specific volume anomaly [m**3/kg]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ This function uses the full Gibbs function. There is an alternative to
+ calling this function, namely 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).
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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. See Eqn. (3.7.3).
+ .. [2] 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.
+ Modifications:
+ 2011-04-06. Trevor McDougall and Paul Barker.
+ """
+ t = t_from_CT(SA, CT, p)
+ return specvol_anom_t_exact(SA, t, p)
+
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/derivatives.py b/gsw/gibbs/derivatives.py
new file mode 100644
index 0000000..11db147
--- /dev/null
+++ b/gsw/gibbs/derivatives.py
@@ -0,0 +1,677 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+
+from .library import gibbs
+from .constants import Kelvin, cp0, sfac
+from ..utilities import match_args_return
+from .conversions import pt_from_CT, pt_from_t
+
+__all__ = ['CT_first_derivatives',
+ 'CT_second_derivatives',
+ 'enthalpy_first_derivatives',
+ 'enthalpy_second_derivatives',
+ 'entropy_first_derivatives',
+ 'entropy_second_derivatives',
+ 'pt_first_derivatives',
+ 'pt_second_derivatives']
+
+n0, n1, n2 = 0, 1, 2
+
+
+ at match_args_return
+def CT_first_derivatives(SA, pt):
+ r"""Calculates the following two derivatives of Conservative Temperature
+ (1) CT_SA, the derivative with respect to Absolute Salinity at constant
+ potential temperature (with pr = 0 dbar), and
+ (2) CT_pt, the derivative with respect to potential temperature (the
+ regular potential temperature which is referenced to 0 dbar) at
+ constant Absolute Salinity.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ pt : array_like
+ potential temperature referenced to a sea pressure of zero dbar
+ [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ CT_SA : array_like
+ The derivative of CT with respect to SA at constant potential
+ temperature reference sea pressure of 0 dbar.
+ [K (g kg :sup:`-1`) :sup:`-1`]
+
+ CT_pt : array_like
+ The derivative of CT with respect to pt at constant SA.
+ [ unitless ]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> pt = [28.7832, 28.4209, 22.7850, 10.2305, 6.8292, 4.3245]
+ >>> gsw.CT_first_derivatives(SA, pt)
+ array([[-0.04198109, -0.04155814, -0.03473921, -0.0187111 , -0.01407594,
+ -0.01057172],
+ [ 1.00281494, 1.00255482, 1.00164514, 1.00000377, 0.99971636,
+ 0.99947433]])
+
+ References
+ ----------
+ .. [1] 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. See Eqns. (A.12.3) and (A.12.9a,b).
+
+ .. [2] 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.
+
+ Modifications:
+ 2010-08-05. Trevor McDougall and Paul Barker.
+ """
+
+ # FIXME: Matlab version 3.0 has a copy-and-paste of the gibbs function here
+ # instead of a call. Why?
+
+ abs_pt = Kelvin + pt
+
+ CT_pt = -(abs_pt * gibbs(n0, n2, n0, SA, pt, 0)) / cp0
+
+ x2 = sfac * SA
+ x = np.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_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
+
+ CT_SA = (g_SA_mod - abs_pt * g_SA_T_mod) / cp0
+
+ return CT_SA, CT_pt
+
+
+ at match_args_return
+def CT_second_derivatives(SA, pt):
+ r"""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 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) and
+ Absolute Salinity, and
+ (3) CT_pt_pt, the second derivative with respect to potential temperature
+ (the regular potential temperature which is referenced to 0 dbar) at
+ constant Absolute Salinity.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ pt : array_like
+ potential temperature [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ CT_SA_SA : array_like
+ The second 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). [K/((g/kg)^2)]
+ CT_SA_pt : array_like
+ The derivative of Conservative Temperature with respect to
+ potential temperature (the regular one with p_ref = 0 dbar) and
+ Absolute Salinity. [1/(g/kg)]
+ CT_pt_pt : array_like
+ The second derivative of Conservative Temperature with respect
+ to potential temperature (the regular one with p_ref = 0 dbar)
+ at constant SA. [1/K]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See appendix A.12.
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-03-29. Trevor McDougall.
+ """
+
+ dSA = 1e-3
+ SA_l = SA - dSA
+ SA_l = np.maximum(SA_l, 0)
+ SA_u = SA + dSA
+
+ CT_SA_l, _ = CT_first_derivatives(SA_l, pt)
+ CT_SA_u, _ = CT_first_derivatives(SA_u, pt)
+
+ CT_SA_SA = np.zeros_like(SA) * np.NaN
+ CT_SA_SA[SA_u != SA_l] = ((CT_SA_u[SA_u != SA_l] - CT_SA_l[SA_u != SA_l]) /
+ (SA_u[SA_u != SA_l] - SA_l[SA_u != SA_l]))
+
+ # Increment of potential temperature is 0.01 degrees C.
+ dpt = 1e-2
+ pt_l = pt - dpt
+ pt_u = pt + dpt
+
+ CT_SA_l, CT_pt_l = CT_first_derivatives(SA, pt_l)
+ CT_SA_u, CT_pt_u = CT_first_derivatives(SA, pt_u)
+
+ CT_SA_pt = (CT_SA_u - CT_SA_l) / (pt_u - pt_l)
+ CT_pt_pt = (CT_pt_u - CT_pt_l) / (pt_u - pt_l)
+
+ return CT_SA_SA, CT_SA_pt, CT_pt_pt
+
+
+ at match_args_return
+def enthalpy_first_derivatives(SA, CT, p):
+ r"""Calculates the following three derivatives of specific enthalpy (h)
+ (1) h_SA, the derivative with respect to Absolute Salinity at
+ constant CT and p, and
+ (2) h_CT, derivative with respect to CT at constant SA and p.
+ (3) h_P, derivative with respect to pressure (in Pa) at constant SA and CT.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+
+ Returns
+ -------
+ h_SA : array_like
+ 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 : array_like
+ The first derivative of specific enthalpy with respect to CT at
+ constant SA and p. [J/(kg K)]
+ h_P : array_like
+ 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.)
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+
+ References
+ ----------
+ .. [1] 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. See Eqns. (A.11.18), (A.11.15) and (A.11.12.)
+
+ Modifications:
+ 2010-09-24. Trevor McDougall.
+ """
+
+ # FIXME: The gsw 3.0 has the gibbs derivatives "copy-and-pasted" here
+ # instead of the calls to the library! Why?
+
+ pt0 = pt_from_CT(SA, CT)
+ t = pt_from_t(SA, pt0, 0, p)
+ temp_ratio = (Kelvin + t) / (Kelvin + pt0)
+
+ def enthalpy_derivative_SA(SA, CT, p):
+ return (gibbs(n1, n0, n0, SA, t, p) -
+ temp_ratio * gibbs(n1, n0, n0, SA, pt0, 0))
+
+ def enthalpy_derivative_CT(SA, CT, p):
+ return cp0 * temp_ratio
+
+ def enthalpy_derivative_p(SA, CT, p):
+ return gibbs(n0, n0, n1, SA, t, p)
+
+ return (enthalpy_derivative_SA(SA, CT, p),
+ enthalpy_derivative_CT(SA, CT, p),
+ enthalpy_derivative_p(SA, CT, p),)
+
+
+ at match_args_return
+def enthalpy_second_derivatives(SA, CT, p):
+ r"""Calculates the following three second-order derivatives of specific
+ enthalpy (h),
+ (1) h_SA_SA, second-order derivative with respect to Absolute Salinity
+ at constant CT & p.
+ (2) h_SA_CT, second-order derivative with respect to SA & CT at
+ constant p.
+ (3) h_CT_CT, second-order derivative with respect to CT at constant SA
+ and p.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+
+ Returns
+ -------
+ h_SA_SA : array_like
+ The second derivative of specific enthalpy with respect to
+ Absolute Salinity at constant CT & p. [J/(kg (g/kg)^2)]
+ h_SA_CT : array_like
+ The second derivative of specific enthalpy with respect to SA and
+ CT at constant p. [J/(kg K(g/kg))]
+ h_CT_CT : array_like
+ The second derivative of specific enthalpy with respect to CT at
+ constant SA and p. [J/(kg K^2)]
+
+ References
+ ----------
+ .. [1] 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. See Eqns. (A.11.18), (A.11.15) and (A.11.12.)
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-03-29. Trevor McDougall.
+ """
+
+ # NOTE: The Matlab version 3.0 mentions that this function is unchanged,
+ # but that's not true!
+
+ pt0 = pt_from_CT(SA, CT)
+ abs_pt0 = Kelvin + pt0
+ t = pt_from_t(SA, pt0, 0, p)
+ temp_ratio = (Kelvin + t) / abs_pt0
+
+ rec_gTT_pt0 = 1 / gibbs(n0, n2, n0, SA, pt0, 0)
+ rec_gTT_t = 1 / gibbs(n0, n2, n0, SA, t, p)
+ gST_pt0 = gibbs(n1, n1, n0, SA, pt0, 0)
+ gST_t = gibbs(n1, n1, n0, SA, t, p)
+ gS_pt0 = gibbs(n1, n0, n0, SA, pt0, 0)
+
+ part = ((temp_ratio * gST_pt0 * rec_gTT_pt0 - gST_t * rec_gTT_t) /
+ (abs_pt0))
+
+ factor = gS_pt0 / cp0
+
+ # h_CT_CT is naturally well-behaved as SA approaches zero.
+ def enthalpy_derivative_CT_CT(SA, CT, p):
+ return (cp0 ** 2 * ((temp_ratio * rec_gTT_pt0 - rec_gTT_t) /
+ (abs_pt0 * abs_pt0)))
+
+ # h_SA_SA has a singularity at SA = 0, and blows up as SA approaches zero.
+ def enthalpy_derivative_SA_SA(SA, CT, p):
+ SA[SA < 1e-100] = 1e-100 # NOTE: Here is the changes from 2.0 to 3.0.
+ h_CT_CT = enthalpy_derivative_CT_CT(SA, CT, p)
+ return (gibbs(n2, n0, n0, SA, t, p) -
+ temp_ratio * gibbs(n2, n0, n0, SA, pt0, 0) +
+ temp_ratio * gST_pt0 ** 2 * rec_gTT_pt0 -
+ gST_t ** 2 * rec_gTT_t - 2.0 * gS_pt0 * part +
+ factor ** 2 * 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."""
+
+ def enthalpy_derivative_SA_CT(SA, CT, p):
+ h_CT_CT = enthalpy_derivative_CT_CT(SA, CT, p)
+ return cp0 * part - factor * h_CT_CT
+
+ return (enthalpy_derivative_SA_SA(SA, CT, p),
+ enthalpy_derivative_SA_CT(SA, CT, p),
+ enthalpy_derivative_CT_CT(SA, CT, p))
+
+
+ at match_args_return
+def entropy_first_derivatives(SA, CT):
+ r"""Calculates the following two partial derivatives of specific entropy
+ (eta)
+ (1) eta_SA, the derivative with respect to Absolute Salinity at constant
+ Conservative Temperature, and
+ (2) eta_CT, the derivative with respect to Conservative Temperature at
+ constant Absolute Salinity.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ eta_SA : array_like
+ The derivative of specific entropy with respect to SA at constant
+ CT [J g :sup:`-1` K :sup:`-1`]
+ eta_CT : array_like
+ The derivative of specific entropy with respect to CT at constant
+ SA [ J (kg K :sup:`-2`) :sup:`-1` ]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> CT = [28.8099, 28.4392, 22.7862, 10.2262, 6.8272, 4.3236]
+ >>> gsw.entropy_first_derivatives(SA, CT)
+ array([[ -0.2632868 , -0.26397728, -0.2553675 , -0.23806659,
+ -0.23443826, -0.23282068],
+ [ 13.22103121, 13.23691119, 13.48900463, 14.08659902,
+ 14.25772958, 14.38642995]])
+
+ References
+ ----------
+ .. [1] 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. See Eqns. (A.12.8) and (P.14a,c).
+
+ Modifications:
+ 2011-03-29. Trevor McDougall.
+ """
+ pt = pt_from_CT(SA, CT)
+
+ eta_SA = -(gibbs(n1, n0, n0, SA, pt, 0)) / (Kelvin + pt)
+ eta_CT = cp0 / (Kelvin + pt)
+ return eta_SA, eta_CT
+
+
+ at match_args_return
+def entropy_second_derivatives(SA, CT):
+ r"""Calculates the following three second-order partial derivatives of
+ specific entropy (eta)
+ (1) eta_SA_SA, the second derivative with respect to Absolute Salinity at
+ constant Conservative Temperature, and
+ (2) eta_SA_CT, the derivative with respect to Absolute Salinity and
+ Conservative Temperature.
+ (3) eta_CT_CT, the second derivative with respect to Conservative
+ Temperature at constant Absolute Salinity.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ eta_SA_SA : array_like
+ The second derivative of specific entropy with respect to SA at
+ constant CT [J (kg K (g kg :sup:`-1` ) :sup:`2`) :sup:`-1`]
+ eta_SA_CT : array_like
+ The second derivative of specific entropy with respect to
+ SA and CT [J (kg (g kg :sup:`-1` ) K :sup:`2`) :sup:`-1` ]
+ eta_CT_CT : array_like
+ The second derivative of specific entropy with respect to CT at
+ constant SA [J (kg K :sup:`3`) :sup:`-1` ]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> CT = [28.8099, 28.4392, 22.7862, 10.2262, 6.8272, 4.3236]
+ >>> gsw.entropy_second_derivatives(SA, CT)
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Eqns. (P.14b) and (P.15a,b).
+
+ Modifications:
+ 2011-03-29. Trevor McDougall and Paul Barker.
+ """
+
+ pt = pt_from_CT(SA, CT)
+ abs_pt = Kelvin + pt
+
+ CT_SA = ((gibbs(n1, n0, n0, SA, pt, 0) -
+ (abs_pt * gibbs(n1, n1, n0, SA, pt, 0))) / cp0)
+
+ CT_pt = -(abs_pt * gibbs(n0, n2, n0, SA, pt, 0)) / cp0
+
+ eta_CT_CT = - cp0 / (CT_pt * abs_pt ** 2)
+
+ eta_SA_CT = - CT_SA * eta_CT_CT
+
+ eta_SA_SA = -gibbs(n2, n0, n0, SA, pt, 0) / abs_pt - CT_SA * eta_SA_CT
+
+ return eta_SA_SA, eta_SA_CT, eta_CT_CT
+
+
+ at match_args_return
+def pt_first_derivatives(SA, CT):
+ r"""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
+ constant Absolute Salinity.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ pt_SA : array_like
+ The derivative of potential temperature with respect to Absolute
+ Salinity at constant Conservative Temperature. [K/(g/kg)]
+ pt_CT : array_like
+ The derivative of potential temperature with respect to
+ Conservative Temperature at constant Absolute Salinity. [unitless]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Eqns. (A.12.6), (A.12.3), (P.6) and (P.8).
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-03-29. Trevor McDougall and Paul Barker.
+ """
+
+ pt = pt_from_CT(SA, CT)
+ abs_pt = Kelvin + pt
+
+ CT_SA = ((gibbs(n1, n0, n0, SA, pt, 0) - abs_pt *
+ gibbs(n1, n1, n0, SA, pt, 0)) / cp0)
+
+ CT_pt = - (abs_pt * gibbs(n0, n2, n0, SA, pt, 0)) / cp0
+
+ pt_SA = - CT_SA / CT_pt
+
+ pt_CT = 1.0 / CT_pt
+
+ return pt_SA, pt_CT
+
+
+ at match_args_return
+def pt_second_derivatives(SA, CT):
+ r"""Calculates the following three second-order derivatives of potential
+ temperature (the regular potential temperature which has a reference
+ sea pressure of 0 dbar),
+ (1) pt_SA_SA, the second derivative with respect to Absolute Salinity at
+ constant Conservative Temperature,
+ (2) pt_SA_CT, the derivative with respect to Conservative Temperature and
+ Absolute Salinity, and
+ (3) pt_CT_CT, the second derivative with respect to Conservative
+ Temperature at constant Absolute Salinity.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ pt_SA_SA : array_like
+ The second derivative of potential temperature (the regular
+ potential temperature which has reference sea pressure of 0
+ dbar) with respect to Absolute Salinity at constant Conservative
+ Temperature. [K/((g/kg)^2)]
+ pt_SA_CT : array_like
+ The derivative of potential temperature with respect to Absolute
+ Salinity and Conservative Temperature. [1/(g/kg)]
+ pt_CT_CT : array_like
+ The second derivative of potential temperature (the regular one
+ with p_ref = 0 dbar) with respect to Conservative Temperature at
+ constant SA. [1/K]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Eqns. (A.12.9) and (A.12.10).
+
+ .. [2] 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.
+
+ Modifications:
+ 2011-03-29. Trevor McDougall and Paul Barker.
+ """
+ # Increment of Absolute Salinity is 0.001 g/kg.
+ dSA = 1e-3
+ SA_l = SA - dSA
+ SA_l = np.maximum(SA_l, 0)
+ SA_u = SA + dSA
+ pt_SA_l, pt_CT_l = pt_first_derivatives(SA_l, CT)
+ pt_SA_u, pt_CT_u = pt_first_derivatives(SA_u, CT)
+ pt_SA_SA = (pt_SA_u - pt_SA_l) / (SA_u - SA_l)
+ # Can calculate this either way.
+ # pt_SA_CT = (pt_CT_u - pt_CT_l) / (SA_u - SA_l)
+
+ dCT = 1e-2
+ CT_l = CT - dCT
+ CT_u = CT + dCT
+ pt_SA_l, pt_CT_l = pt_first_derivatives(SA, CT_l)
+ pt_SA_u, pt_CT_u = pt_first_derivatives(SA, CT_u)
+
+ pt_SA_CT = (pt_SA_u - pt_SA_l) / (CT_u - CT_l)
+ pt_CT_CT = (pt_CT_u - pt_CT_l) / (CT_u - CT_l)
+
+ return pt_SA_SA, pt_SA_CT, pt_CT_CT
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/earth.py b/gsw/gibbs/earth.py
new file mode 100644
index 0000000..585a363
--- /dev/null
+++ b/gsw/gibbs/earth.py
@@ -0,0 +1,219 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+
+from .conversions import z_from_p
+from ..utilities import match_args_return
+from .constants import gamma, earth_radius, OMEGA
+
+
+__all__ = ['distance',
+ 'f',
+ 'grav']
+
+DEG2RAD = np.pi / 180
+
+
+ at match_args_return
+def distance(lon, lat, p=0):
+ r"""Calculates the distance in met res between successive points in the
+ vectors lon 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 spherical 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.
+
+ Haversine formula:
+ R = earth's radius (mean radius = 6,371 km)
+
+ .. math::
+ a = \sin^2(\delta \text{lat}/2) +
+ \cos(\text{lat}_1) \cos(\text{lat}_2) \sin^2(\delta \text{lon}/2)
+
+ c = 2 \times \text{atan2}(\sqrt{a}, \sqrt{(1-a)})
+
+ d = R \times c
+
+ Parameters
+ ----------
+ lon : array_like
+ decimal degrees east [0..+360] or [-180 ... +180]
+ lat : array_like
+ latitude in decimal degrees north [-90..+90]
+ p : number or array_like. Default p = 0
+ pressure [dbar]
+
+ Returns
+ -------
+ dist: array_like
+ distance between points on a spherical Earth at pressure (p) [m]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ z is height and is negative in the oceanographic.
+
+ Distances are probably good to better than 1\% of the "true" distance on
+ the ellipsoidal earth.
+
+ Examples
+ --------
+ >>> import gsw
+ >>> lon = [159, 220]
+ >>> lat = [-35, 35]
+ >>> gsw.distance(lon, lat)
+ array([[ 10030974.652916]])
+ >>> p = [200, 1000]
+ >>> gsw.distance(lon, lat, p)
+ array([[ 10030661.63878009]])
+ >>> p = [[200], [1000]]
+ >>> gsw.distance(lon, lat, p)
+ array([[ 10030661.63878009],
+ [ 10029412.58776001]])
+
+ References
+ ----------
+ .. [1] http://www.eos.ubc.ca/~rich/map.html
+
+ Modifications:
+ 2000-11-06. Rich Pawlowicz
+ 2011-04-04. Paul Barker and Trevor McDougall
+ """
+ # FIXME? The argument handling seems much too complicated.
+ # Maybe we can come up with some simple specifications of
+ # what argument combinations are permitted, and handle everything
+ # with broadcasting. - EF
+
+ # FIXME: Eric what do you think? This assume p(stations, depth)
+ lon, lat, = np.atleast_2d(lon), np.atleast_2d(lat)
+
+ if (lon.size == 1) & (lat.size == 1):
+ raise ValueError('more than one point is needed to compute distance')
+ elif lon.ndim != lat.ndim:
+ raise ValueError('lon, lat must have the same dimension')
+
+ lon, lat, p = np.broadcast_arrays(lon, lat, p)
+
+ dlon = np.diff(lon * DEG2RAD)
+ dlat = np.diff(lat * DEG2RAD)
+
+ a = ((np.sin(dlat / 2)) ** 2 + np.cos(lat[:, :-1] * DEG2RAD) *
+ np.cos(lat[:, 1:] * DEG2RAD) * (np.sin(dlon / 2)) ** 2)
+
+ angles = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a))
+
+ p_mid = 0.5 * (p[:, 0:-1] + p[:, 0:-1])
+ lat_mid = 0.5 * (lat[:, :-1] + lat[:, 1:])
+
+ z = z_from_p(p_mid, lat_mid)
+
+ distance = (earth_radius + z) * angles
+
+ return distance
+
+
+def f(lat):
+ r"""Calculates the Coriolis parameter (f) defined by:
+ f = 2*omega*sin(lat)
+ where,
+ omega = 7.292115e-5 (Groten, 2004) [radians s :sup:`-1`]
+
+ Parameters
+ ----------
+ lat : array_like
+ latitude [degrees north]
+
+ Returns
+ -------
+ f : array_like
+ Coriolis paramter [s :sup:`-1`]
+
+ References
+ ----------
+ .. [1] 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.
+
+ .. [2] 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.
+
+ Modifications:
+ 1993-04-20. Phil Morgan
+ 2010-07-28. Paul Barker
+ """
+
+ lat = np.asanyarray(lat)
+ return 2 * OMEGA * np.sin(lat * DEG2RAD)
+
+
+ at match_args_return
+def grav(lat, p=0):
+ r"""Calculates acceleration due to gravity as a function of latitude and as
+ a function of pressure in the ocean.
+
+ Parameters
+ ----------
+ lat : array_like
+ latitude in decimal degrees north [-90...+90]
+ p : number or array_like. Default p = 0
+ pressure [dbar]
+
+ Returns
+ -------
+ g : array_like
+ gravity [m s :sup:`2`]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ In the ocean z is negative.
+
+ Examples
+ --------
+ >>> import gsw
+ >>> lat = [-90, -60, -30, 0]
+ >>> p = 0
+ >>> gsw.grav(lat, p)
+ array([ 9.83218621, 9.81917886, 9.79324926, 9.780327 ])
+ >>> gsw.grav(45)
+ 9.8061998770458008
+
+ References
+ ----------
+ .. [1] 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.
+
+ .. [2] Moritz (2000) Goedetic reference system 1980. J. Geodesy, 74,
+ 128-133.
+
+ .. [3] Saunders, P.M., and N.P. Fofonoff (1976) Conversion of pressure to
+ depth in the ocean. Deep-Sea Res.,pp. 109 - 111.
+
+ Modifications:
+ 2011-03-29. Trevor McDougall & Paul Barker
+ """
+
+ X = np.sin(lat * DEG2RAD)
+ sin2 = X ** 2
+ gs = 9.780327 * (1.0 + (5.2792e-3 + (2.32e-5 * sin2)) * sin2)
+ z = z_from_p(p, lat)
+ # z is the height corresponding to p.
+ grav = gs * (1 - gamma * z)
+
+ return grav
+
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/freezing.py b/gsw/gibbs/freezing.py
new file mode 100644
index 0000000..c2f3cc3
--- /dev/null
+++ b/gsw/gibbs/freezing.py
@@ -0,0 +1,569 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+
+from .constants import SSO
+from .conversions import t_from_CT, CT_from_t
+from ..utilities import match_args_return
+
+__all__ = ['brineSA_CT',
+ 'brineSA_t',
+ 'CT_freezing',
+ 't_freezing']
+
+# Constants:
+c = (0.017947064327968736, -6.076099099929818, 4.883198653547851,
+ -11.88081601230542, 13.34658511480257, -8.722761043208607,
+ 2.082038908808201, -7.389420998107497, -2.110913185058476,
+ 0.2295491578006229, -0.9891538123307282, -0.08987150128406496,
+ 0.3831132432071728, 1.054318231187074, 1.065556599652796,
+ -0.7997496801694032, 0.3850133554097069, -2.078616693017569,
+ 0.8756340772729538, -2.079022768390933, 1.596435439942262,
+ 0.1338002171109174, 1.242891021876471)
+
+T = (0.002519, -5.946302841607319, 4.136051661346983,
+ -1.115150523403847e1, 1.476878746184548e1, -1.088873263630961e1,
+ 2.961018839640730, -7.433320943962606, -1.561578562479883,
+ 4.073774363480365e-2, 1.158414435887717e-2, -4.122639292422863e-1,
+ -1.123186915628260e-1, 5.715012685553502e-1, 2.021682115652684e-1,
+ 4.140574258089767e-2, -6.034228641903586e-1, -1.205825928146808e-2,
+ -2.812172968619369e-1, 1.877244474023750e-2, -1.204395563789007e-1,
+ 2.349147739749606e-1, 2.748444541144219e-3)
+
+# Adjust for the effects of dissolved air. Note that
+# a = 0.502500117621 / 35.16504
+a, b = 0.014289763856964, 0.057000649899720
+
+P = (2.570124672768757e-1, -1.917742353032266e+1, -1.413382858617969e-2,
+ -5.427484830917552e-1, -4.126621135193472e-4, -4.176407833276121e-7,
+ 4.688217641883641e-5, -3.039808885885726e-8, -4.990118091261456e-11,
+ -9.733920711119464e-9, -7.723324202726337e-12, 7.121854166249257e-16,
+ 1.256474634100811e-12, 2.105103897918125e-15, 8.663811778227171e-19)
+
+
+ at match_args_return
+def brineSA_CT(CT, p, saturation_fraction=1):
+ r"""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.
+
+ Parameters
+ ----------
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+ saturation_fraction : fraction between 0, 1. The saturation fraction of
+ dissolved air in seawater. Default is 0 or
+ completely saturated.
+
+ Returns
+ -------
+ brine_SA_CT : array_like
+ Absolute Salinity of seawater when it freezes [ g/kg ]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See sections 3.33.
+
+ Modifications:
+ 2011-28-03. Trevor McDougall and Paul Barker.
+
+ """
+
+ CT, p, saturation_fraction = np.broadcast_arrays(CT, p,
+ saturation_fraction)
+
+ if np.logical_or(saturation_fraction < 0, saturation_fraction > 1).any():
+ raise ValueError('Saturation_fraction MUST be between zero and one.')
+
+ p_r = p * 1e-4
+ # Form the first estimate of brine_SA_CT from a polynomial in CT and p_r.
+ SA = -(CT + 9 * p_r) / 0.06 # A rough estimate to get the saturated CT.
+
+ SA = np.maximum(SA, 0)
+
+ CTsat = CT - (1 - saturation_fraction) * 1e-3 * (2.4 - a * SA) * (1 + b *
+ (1 - SA / SSO))
+
+ SA = (P[0] + p * (P[2] + P[4] * CTsat + p * (P[5] + CTsat * (P[7] + P[9] *
+ CTsat) + p * (P[8] + CTsat * (P[10] + P[12] * CTsat) + p * (P[11] +
+ P[13] * CTsat + P[14] * p)))) + CTsat * (P[1] + CTsat *
+ (P[3] + P[6] * p)))
+
+ CT_freezing_zero_SA = (c[0] + p_r * (c[7] + p_r * (c[8] + c[9] * 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 = (CT > CT_freezing_zero_SA) # tw stands for "too warm"
+ SA[Itw] = np.ma.masked
+
+ # 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 = (np.abs(SA) < SA_cut_off)
+ Icoa = np.logical_and(SA < 0, SA >= -SA_cut_off)
+
+ SA[Icoa] = 0
+
+ # Find SA < -SA_cut_off, set them to NaN.
+ SA[SA < -SA_cut_off] = np.ma.masked
+
+ # Form the first estimate of dCT_dSA, the derivative of CT with respect
+ # to SA at fixed p.
+ SA_r = 0.01 * SA
+ x = np.sqrt(SA_r)
+
+ dCT_dSA_part = (2 * c[1] + x * (3 * c[2] + x * (4 * c[3] + x * (5 * c[4] +
+ x * (6 * c[5] + 7 * c[6] * x)))) + p_r * (2 * c[10] + p_r *
+ (2 * c[12] + p_r * (2 * c[15] + 4 * c[21] * x * x)) + x *
+ x * (4 * c[13] + 4 * c[17] * p_r + 6 * c[19] * x * x) + x *
+ (3 * c[11] + 3 * p_r * (c[14] + c[18] * p_r) + x * x * (5 *
+ c[16] + 5 * c[20] * p_r + 7 * c[22] * x * x))))
+
+ dCT_dSA = 0.5 * 0.01 * dCT_dSA_part - saturation_fraction * 1e-3 * (-a *
+ (1 + b * (1 - SA / SSO)) - b * (2.4 - a * SA) / SSO)
+
+ # Now replace the estimate of SA with the one based on
+ # (CT_freezing_zero_SA - CT) when (np.abs(SA) < SA_cut_off).
+ SA[Ico] = (CT[Ico] - CT_freezing_zero_SA[Ico]) / dCT_dSA[Ico]
+
+ # Begin the modified Newton-Raphson method to solve the root of
+ # CT_freezing = CT for SA.
+ Number_of_Iterations = 2
+ for I_iter in range(0, Number_of_Iterations):
+ # CT_freezing temperature function evaluation (the forward function
+ # evaluation), the same as CT_freezing(SA, p, saturation_fraction).
+
+ SA_r = 0.01 * SA
+ x = np.sqrt(SA_r)
+ SA_old = SA
+ CT_freeze = (c[0] + SA_r * (c[1] + x * (c[2] + x * (c[3] + x * (c[4] +
+ x * (c[5] + c[6] * x))))) + p_r * (c[7] + p_r * (c[8] +
+ c[9] * p_r)) + SA_r * p_r * (c[10] + p_r * (c[12] + p_r *
+ (c[15] + c[21] * SA_r)) + SA_r * (c[13] + c[17] * p_r +
+ c[19] * SA_r) + x * (c[11] + p_r * (c[14] + c[18] * p_r) +
+ SA_r * (c[16] + c[20] * p_r + c[22] * SA_r))) -
+ saturation_fraction * 1e-3 * (2.4 - a * SA) * (1 + b *
+ (1 - SA / SSO)))
+
+ SA = SA_old - (CT_freeze - CT) / dCT_dSA
+
+ # Half-way point of the modified Newton-Raphson solution method.
+ SA_r = 0.5 * 0.01 * (SA + SA_old) # The mean value of SA and SA_old.
+ x = np.sqrt(SA_r)
+
+ dCT_dSA_part = 2 * c[1] + x * (3 * c[2] + x * (4 * c[3] + x * (5 *
+ c[4] + x * (6 * c[5] + 7 * c[6] * x)))) + p_r * (2 *
+ c[10] + p_r * (2 * c[12] + p_r * (2 * c[15] + 4 *
+ c[21] * x * x)) + x * x * (4 * c[13] + 4 * c[17] *
+ p_r + 6 * c[19] * x * x) + x * (3 * c[11] + 3 * p_r *
+ (c[14] + c[18] * p_r) + x * x * (5 * c[16] + 5 * c[20] *
+ p_r + 7 * c[22] * x * x)))
+
+ dCT_dSA = (0.5 * 0.01 * dCT_dSA_part - saturation_fraction * 1e-3 *
+ (-a * (1 + b * (1 - SA / SSO)) - b * (2.4 - a * SA) / SSO))
+
+ SA = SA_old - (CT_freeze - CT) / dCT_dSA
+
+ """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 = np.sqrt(SA_r)
+ CT_freeze = c[0] + SA_r * (c[1] + x * (c[2] + x * (c[3] + x * (c[4] + x *
+ (c[5] + c[6] * x))))) + p_r * (c[7] + p_r * (c[8] + c[9] *
+ p_r)) + SA_r * p_r * (c[10] + p_r * (c[12] + p_r * (c[15] +
+ c[21] * SA_r)) + SA_r * (c[13] + c[17] * p_r + c[19] * SA_r) +
+ x * (c[11] + p_r * (c[14] + c[18] * p_r) + SA_r * (c[16] +
+ c[20] * p_r + c[22] * SA_r))) - saturation_fraction * 1e-3 *
+ (2.4 - a * SA) * (1 + b * (1 - SA / SSO))
+
+ CT_error = np.abs(CT_freeze - CT)
+
+ tmp = np.logical_or(p > 10000, SA > 120
+ out = np.logical_and(tmp, p + SA * 71.428571428571402 > 13571.42857142857)
+ CT_error[out] = np.ma.masked
+ """
+
+ brine_SA_CT = SA
+
+ tmp = np.logical_or(p > 10000, SA > 120)
+ out = np.logical_and(tmp, p + SA * 71.428571428571402 > 13571.42857142857)
+
+ brine_SA_CT[out] = np.ma.masked
+
+ # If the CT input is too warm, then there is no (positive) value of SA
+ # that represents frozen seawater.
+ brine_SA_CT[Itw] = -99 # NOTE: Mask these?
+
+ return brine_SA_CT
+
+
+ at match_args_return
+def brineSA_t(t, p, saturation_fraction=1):
+ r"""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.
+
+ Parameters
+ ----------
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+ saturation_fraction : fraction between 0, 1. The saturation fraction of
+ dissolved air in seawater. Default is 0 or
+ completely saturated.
+
+ Returns
+ -------
+ brine_SA_t : array_like
+ Absolute Salinity of seawater when it freezes [ g/kg ]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See sections 3.33.
+
+ Modifications:
+ 2011-28-03. Trevor McDougall and Paul Barker.
+
+ """
+
+ t, p, saturation_fraction = np.broadcast_arrays(t, p, saturation_fraction)
+
+ if np.logical_or(saturation_fraction < 0, saturation_fraction > 1).any():
+ raise ValueError('Saturation_fraction MUST be between zero and one.')
+
+ p_r = p * 1e-4
+
+ # Form the first estimate of brine_SA_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.
+
+ SA = np.maximum(SA, 0)
+
+ CT = CT_from_t(SA, t, p)
+ CTsat = CT - (1 - saturation_fraction) * 1e-3 * (2.4 - a * SA) * (1 + b *
+ (1 - SA / SSO))
+
+ SA = P[0] + p * (P[2] + P[4] * CTsat + p * (P[5] + CTsat * (P[7] +
+ P[9] * CTsat) + p * (P[8] + CTsat * (P[10] + P[12] * CTsat) + p *
+ (P[11] + P[13] * CTsat + P[14] * p)))) + CTsat * (P[1] + CTsat *
+ (P[3] + P[6] * p))
+
+ t_freezing_zero_SA = t_freezing(np.zeros_like(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 = (t > t_freezing_zero_SA) # Itw stands for "I_too_warm"
+ SA[Itw] = np.ma.masked
+
+ # 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 = (np.abs(SA) < SA_cut_off)
+ Icoa = np.logical_and(SA < 0, SA >= -SA_cut_off)
+ SA[Icoa] = 0
+
+ # Find SA < -SA_cut_off, set them to masked.
+ SA[SA < -SA_cut_off] = np.ma.masked
+
+ # Form the first estimate of dt_dSA, the derivative of t with respect
+ # to SA at fixed p, using the coefficients, t0 ... t22 from t_freezing.
+ SA_r = 0.01 * SA
+ x = np.sqrt(SA_r)
+ dt_dSA_part = 2 * T[1] + x * (3 * T[2] + x * (4 * T[3] + x * (5 * T[4] +
+ x * (6 * T[5] + 7 * T[6] * x)))) + p_r * (2 * T[10] + p_r * (2 * T[12] +
+ p_r * (2 * T[15] + 4 * T[21] * x * x)) + x * x * (4 * T[13] + 4 * T[17] *
+ p_r + 6 * T[19] * x * x) + x * (3 * T[11] + 3 * p_r * (T[14] + T[18] *
+ p_r) + x * x * (5 * T[16] + 5 * T[20] * p_r + 7 * T[22] * 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).
+ SA[Ico] = (t[Ico] - t_freezing_zero_SA[Ico]) / dt_dSA[Ico]
+
+ # Begin the modified Newton-Raphson method to find the root of
+ # t_freeze = t for SA.
+ Number_of_Iterations = 5
+ for I_iter in range(0, Number_of_Iterations):
+ SA_old = SA
+ t_freeze = t_freezing(SA_old, p, saturation_fraction)
+ SA = SA_old - (t_freeze - t) / dt_dSA
+ # Half-way point of the modified Newton-Raphson solution method.
+ SA_r = 0.5 * 0.01 * (SA + SA_old) # Mean value of SA and SA_old.
+ x = np.sqrt(SA_r)
+ dt_dSA_part = (2 * T[1] + x * (3 * T[2] + x * (4 * T[3] + x * (5 *
+ T[4] + x * (6 * T[5] + 7 * T[6] * x)))) + p_r *
+ (2 * T[10] + p_r * (2 * T[12] + p_r * (2 * T[15] + 4 *
+ T[21] * x * x)) + x * x * (4 * T[13] + 4 * T[17] * p_r +
+ 6 * T[19] * x * x) + x * (3 * T[11] + 3 * p_r * (T[14] +
+ T[18] * p_r) + x * x * (5 * T[16] + 5 * T[20] * p_r +
+ 7 * T[22] * x * x))))
+
+ dt_dSA = (0.5 * 0.01 * dt_dSA_part + saturation_fraction * 1e-3 /
+ 70.33008)
+
+ SA = SA_old - (t_freeze - t) / dt_dSA
+
+ """The following lines of code, if implemented, calculate the error of this
+ function in terms of in-situ temperature. With Number_of_Iterations = 4,
+ the max error in t is 3x10^-13 C. With Number_of_Iterations = 5, the max
+ error in t is 2x10^-14 C, which is the machine precision of the computer.
+ Number_of_Iterations = 5 is what we recommend.
+
+ SA[SA < 0] = np.ma.masked
+
+ t_freeze = t_freezing(SA, p, saturation_fraction)
+ t_error = np.abs(t_freeze - t)
+ tmp = np.logical_or(p > 10000, SA > 120)
+ out = np.logical_and(tmp, p + SA * 71.428571428571402 > 13571.42857142857)
+ t_error[out] = np.ma.masked
+ """
+
+ brine_SA_t = SA
+ tmp = np.logical_or(p > 10000, SA > 120)
+ out = np.logical_and(tmp, p + SA * 71.428571428571402 > 13571.42857142857)
+ brine_SA_t[out] = np.ma.masked
+
+ brine_SA_t[Itw] = -99 # If the t input is too warm, then there is no
+ # (positive) value of SA that represents frozen
+ # seawater.
+
+ return brine_SA_t
+
+
+ at match_args_return
+def CT_freezing(SA, p, saturation_fraction=1):
+ r"""Calculates the Conservative Temperature at which seawater freezes.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ p : array_like
+ sea pressure [dbar]
+ saturation_fraction : fraction between 0, 1. The saturation fraction of
+ dissolved air in seawater. Default is 0 or
+ completely saturated.
+
+ Returns
+ -------
+ CT_freezing : array_like
+ Conservative Temperature at freezing of
+ seawater [:math:`^\circ` C (ITS-90)]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See sections 3.33 and 3.34.
+
+ Modifications:
+ 2011-11-04. Trevor McDougall, Paul Barker and Rainer Feistal.
+
+ """
+
+ SA, p, saturation_fraction = np.broadcast_arrays(SA, p,
+ saturation_fraction)
+ if (SA < 0).any():
+ raise ValueError('SA must be non-negative!')
+
+ if np.logical_or(saturation_fraction < 0, saturation_fraction > 1).any():
+ raise ValueError('Saturation_fraction MUST be between zero and one.')
+
+ SA_r = SA * 1e-2
+ x = np.sqrt(SA_r)
+ p_r = p * 1e-4
+
+ CT_freeze = (c[0] + SA_r * (c[1] + x * (c[2] + x * (c[3] + x * (c[4] +
+ x * (c[5] + c[6] * x))))) + p_r * (c[7] + p_r * (c[8] +
+ c[9] * p_r)) + SA_r * p_r * (c[10] + p_r * (c[12] + p_r *
+ (c[15] + c[21] * SA_r)) + SA_r * (c[13] + c[17] * p_r +
+ c[19] * SA_r) + x * (c[11] + p_r * (c[14] + c[18] * p_r) +
+ SA_r * (c[16] + c[20] * p_r + c[22] * 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, b = 0.014289763856964, 0.057000649899720
+ # Note that a = 0.502500117621 / 35.16504
+
+ CT_freeze = (CT_freeze - saturation_fraction * (1e-3) *
+ (2.4 - a * SA) * (1 + b * (1 - SA / 35.16504)))
+
+ tmp = np.logical_or(p > 10000, SA > 120)
+ out = np.logical_or(tmp, p + SA * 71.428571428571402 > 13571.42857142857)
+
+ CT_freeze[out] = np.ma.masked
+
+ return CT_freeze
+
+
+ at match_args_return
+def t_freezing(SA, p, saturation_fraction=1):
+ r"""Calculates the in-situ temperature at which seawater freezes.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ p : array_like
+ sea pressure [dbar]
+ saturation_fraction : fraction between 0, 1. The saturation fraction of
+ dissolved air in seawater. Default is 0 or
+ completely saturated.
+
+ Returns
+ -------
+ t_freezing : array_like
+ in-situ temperature at which seawater freezes
+ [:math:`^\circ` C (ITS-90)]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See sections 3.33 and 3.34.
+
+ Modifications:
+ 2011-11-03. Trevor McDougall, Paul Barker and Rainer Feistal.
+
+ """
+
+ """This function, 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 CT_freezing. The in-situ freezing temperature is then
+ calculated using the GSW function 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, 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).
+
+ SA_r = SA * 1e-2
+ x = np.sqrt(SA_r)
+ p_r = p * 1e-4
+
+ t_freeze = T[0] + SA_r * (T[1] + x * (T[2] + x * (T[3] + x * (T[4] + x *
+ (T[5] + T[6] * x))))) + p_r * (T[7] + p_r * (T[8] + T[9] *
+ p_r)) + SA_r * p_r * (T[10] + p_r * (T[12] + p_r * (T[15] +
+ T[21] * SA_r)) + SA_r * (T[13] + T[17] * p_r + T[19] * SA_r) +
+ x * (T[11] + p_r * (T[14] + T[18] * p_r) + SA_r * (T[16] +
+ T[20] * p_r + T[22] * SA_r)))
+
+ Adjust for the effects of dissolved air
+ t_freezing -= saturation_fraction * (1e-3) * (2.4 - SA / 70.33008)
+
+ """
+
+ SA, p, saturation_fraction = np.broadcast_arrays(SA, p,
+ saturation_fraction)
+ if (SA < 0).any():
+ raise ValueError('SA must be non-negative!')
+
+ if np.logical_or(saturation_fraction < 0, saturation_fraction > 1).any():
+ raise ValueError('Saturation_fraction MUST be between zero and one.')
+
+ CT_freeze = CT_freezing(SA, p, saturation_fraction)
+
+ t_freeze = t_from_CT(SA, CT_freeze, p)
+
+ tmp = np.logical_or(p > 10000, SA > 120)
+ out = np.logical_or(tmp, p + SA * 71.428571428571402 > 13571.42857142857)
+
+ t_freeze[out] = np.ma.masked
+
+ return t_freeze
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/geostrophic.py b/gsw/gibbs/geostrophic.py
new file mode 100644
index 0000000..ee3b751
--- /dev/null
+++ b/gsw/gibbs/geostrophic.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+
+__all__ = ['geostrophic_velocity'] # TODO
+
+
+def geostrophic_velocity():
+ pass
+
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/geostrophic_48.py b/gsw/gibbs/geostrophic_48.py
new file mode 100644
index 0000000..62d643f
--- /dev/null
+++ b/gsw/gibbs/geostrophic_48.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+
+__all__ = ['geo_strf_Cunningham', # TODO
+ 'geo_strf_dyn_height', # TODO
+ 'geo_strf_dyn_height_pc', # TODO
+ 'geo_strf_isopycnal', # TODO
+ 'geof_str_isopycnal_pc', # TODO
+ 'geo_strf_Montgomery'] # TODO
+
+
+def geo_strf_Cunningham():
+ pass
+
+
+def geo_strf_dyn_height():
+ pass
+
+
+def geo_strf_dyn_height_pc():
+ pass
+
+
+def geo_strf_isopycnal():
+ pass
+
+
+def geof_str_isopycnal_pc():
+ pass
+
+
+def geo_strf_Montgomery():
+ pass
+
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/isobaric.py b/gsw/gibbs/isobaric.py
new file mode 100644
index 0000000..b11e243
--- /dev/null
+++ b/gsw/gibbs/isobaric.py
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+from .conversions import CT_from_pt
+from ..utilities import match_args_return
+
+
+__all__ = ['latentheat_evap_CT',
+ 'latentheat_melting',
+ 'latentheat_evap_t']
+
+
+ at match_args_return
+def latentheat_evap_CT(SA, CT):
+ pass
+
+
+ at match_args_return
+def latentheat_melting(SA, p):
+ pass
+
+
+ at match_args_return
+def latentheat_evap_t(SA, t):
+ r"""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.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ latentheat_evap_t : array_like
+ latent heat of evaporation [J kg :sup:`-1`]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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.
+ See section 3.39.
+
+ Modifications:
+ 2011-03-29. Paul Barker, Trevor McDougall & Rainer Feistel
+ """
+
+ CT = CT_from_pt(SA, t)
+ return latentheat_evap_CT(SA, CT)
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/library.py b/gsw/gibbs/library.py
new file mode 100644
index 0000000..5acdc1b
--- /dev/null
+++ b/gsw/gibbs/library.py
@@ -0,0 +1,1646 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+
+from .constants import sfac, SSO, db2Pascal
+from ..utilities import match_args_return, strip_mask, read_data
+
+__all__ = ['deltaSA_atlas',
+ 'enthalpy_SSO_0_p',
+ 'entropy_part',
+ 'entropy_part_zerop',
+ 'Fdelta', # Seems to be new in V3.
+ 'gibbs',
+ 'gibbs_pt0_pt0',
+ 'Hill_ratio_at_SP2',
+ 'infunnel',
+ 'interp_ref_cast',
+ 'interp_SA_CT',
+ 'SAAR', # New in V3.
+ 'SA_from_SP_Baltic',
+ 'specvol_SSO_0_p',
+ 'SP_from_SA_Baltic']
+
+
+class SA_table(object):
+ """
+ TODO: Write docstring.
+ """
+ # Central America barrier
+ x_ca = np.array([260.0, 272.59, 276.5, 278.65, 280.73, 295.217])
+ y_ca = np.array([19.55, 13.97, 9.6, 8.1, 9.33, 0.0])
+
+ def __init__(self, fname="gsw_data_v3_0.npz", max_p_fudge=10000,
+ min_frac=0):
+ self.fname = fname
+ self.max_p_fudge = max_p_fudge
+ self.min_frac = min_frac
+ data = read_data(fname)
+ self.lon = data.longs_ref.astype(np.float)
+ self.lat = data.lats_ref.astype(np.float)
+ self.p = data.p_ref # Depth levels
+ self.dlon = self.lon[1] - self.lon[0]
+ self.dlat = self.lat[1] - self.lat[0]
+ self.i_ca, self.j_ca = self.xy_to_ij(self.x_ca, self.y_ca)
+ # Make the order x, y, z:
+ # Start with deltaSA_ref (was delta_SA_ref in V2):
+ temp = data.deltaSA_ref.transpose((2, 1, 0)).copy()
+ self.dsa_ref = np.ma.masked_invalid(temp)
+ self.dsa_ref.data[self.dsa_ref.mask] = 0
+ # Now SAAR_ref, which did not exist in V2:
+ temp = data.SAAR_ref.transpose((2, 1, 0)).copy()
+ self.SAAR_ref = np.ma.masked_invalid(temp)
+ self.SAAR_ref.data[self.SAAR_ref.mask] = 0
+
+ def xy_to_ij(self, x, y):
+ """
+ Convert from lat/lon to grid index coordinates,
+ without truncation or rounding.
+ """
+ i = (x - self.lon[0]) / self.dlon
+ j = (y - self.lat[0]) / self.dlat
+ return i, j
+
+ def _central_america(self, di, dj, ii, jj, gm):
+ """
+ Use a line running through Central America to zero
+ the goodmask for grid points in the Pacific forming
+ the grid box around input locations in the Atlantic,
+ and vice-versa.
+ """
+ ix, jy = ii[0] + di, jj[0] + dj # Reconstruction: minor inefficiency.
+ inear = ((ix >= self.i_ca[0]) & (ix <= self.i_ca[-1])
+ & (jy >= self.j_ca[-1]) & (jy <= self.j_ca[0]))
+ if not inear.any():
+ return gm
+ inear_ind = inear.nonzero()[0]
+ ix = ix[inear]
+ jy = jy[inear]
+ ii = ii[:, inear]
+ jj = jj[:, inear]
+ jy_ca = np.interp(ix, self.i_ca, self.j_ca)
+ above = jy - jy_ca # > 0 if input point is above dividing line
+ # Intersections of left and right grid lines with dividing line
+ jleft_ca = np.interp(ii[0], self.i_ca, self.j_ca)
+ jright_ca = np.interp(ii[1], self.i_ca, self.j_ca)
+ jgrid_ca = [jleft_ca, jright_ca, jright_ca, jleft_ca]
+ # Zero the goodmask for grid points on opposite side of divider
+ for i in range(4):
+ opposite = (above * (jj[i] - jgrid_ca[i])) < 0
+ gm[i, inear_ind[opposite]] = 0
+ return gm
+
+ def xy_interp(self, di, dj, ii, jj, k):
+ """
+ 2-D interpolation, bilinear if all 4 surrounding
+ grid points are present, but treating missing points
+ as having the average value of the remaining grid
+ points. This matches the matlab V2 behavior.
+ """
+ # Array of weights, CCW around the grid box
+ w = np.vstack(((1 - di) * (1 - dj), # lower left
+ di * (1 - dj), # lower right
+ di * dj, # upper right
+ (1 - di) * dj)) # upper left
+ gm = ~self.dsa.mask[ii, jj, k] # gm is "goodmask"
+ gm = self._central_america(di, dj, ii, jj, gm)
+ # Save a measure of real interpolation quality.
+ frac = (w * gm).sum(axis=0)
+ # Now loosen the interpolation, allowing a value to
+ # be calculated on a grid point that is masked.
+ # This matches the matlab gsw version 2 behavior.
+ jm_partial = gm.any(axis=0) & (~(gm.all(axis=0)))
+ # The weights of the unmasked points will be increased
+ # by the sum of the weights of the masked points divided
+ # by the number of unmasked points in the grid square.
+ # This is equivalent to setting the masked data values
+ # to the average of the unmasked values, and then
+ # unmasking, which is the matlab v2 implementation.
+ if jm_partial.any():
+ w_bad = w * (~gm)
+ w[:, jm_partial] += (w_bad[:, jm_partial].sum(axis=0) /
+ gm[:, jm_partial].sum(axis=0))
+ w *= gm
+ wsum = w.sum(axis=0)
+ valid = wsum > 0 # Only need to prevent division by zero here.
+ w[:, valid] /= wsum[valid]
+ w[:, ~valid] = 0
+ vv = self.dsa.data[ii, jj, k]
+ vv *= w
+ dsa = vv.sum(axis=0)
+ return dsa, frac
+
+ def _delta_SA(self, p, lon, lat):
+ """
+ Table lookup engine--to be called only from SAAR or SA_ref.
+ """
+ p = np.ma.masked_less(p, 0)
+ mask_in = np.ma.mask_or(np.ma.getmask(p), np.ma.getmask(lon))
+ mask_in = np.ma.mask_or(mask_in, np.ma.getmask(lat))
+ p, lon, lat = [np.ma.filled(a, 0).astype(float) for a in (p, lon, lat)]
+ p, lon, lat = np.broadcast_arrays(p, lon, lat)
+ if p.ndim > 1:
+ shape_in = p.shape
+ p, lon, lat = map(np.ravel, (p, lon, lat))
+ reshaped = True
+ else:
+ reshaped = False
+ p_orig = p.copy() # Save for comparison to clipped p.
+ ix0, iy0 = self.xy_to_ij(lon, lat)
+ i0raw = np.floor(ix0).astype(int)
+ i0 = np.clip(i0raw, 0, len(self.lon) - 2)
+ di = ix0 - i0
+ j0raw = np.floor(iy0).astype(int)
+ j0 = np.clip(j0raw, 0, len(self.lat) - 2)
+ dj = iy0 - j0
+ # Start at lower left and go CCW; match order in _xy_interp.
+ ii = np.vstack((i0, i0 + 1, i0 + 1, i0))
+ jj = np.vstack((j0, j0, j0 + 1, j0 + 1))
+ k1 = np.searchsorted(self.p, p, side='right')
+ # Clip p and k1 at max p of grid cell.
+ kmax = (self.ndepth[ii, jj].max(axis=0) - 1)
+ mask_out = kmax.mask
+ kmax = kmax.filled(1)
+ clip_p = (p >= self.p[kmax])
+ p[clip_p] = self.p[kmax[clip_p]]
+ k1[clip_p] = kmax[clip_p]
+ k0 = k1 - 1
+ dsa0, frac0 = self.xy_interp(di, dj, ii, jj, k0)
+ dsa1, frac1 = self.xy_interp(di, dj, ii, jj, k1)
+ dp = np.diff(self.p)
+ pfrac = (p - self.p[k0]) / dp[k0]
+ delta_SA = dsa0 * (1 - pfrac) + dsa1 * pfrac
+ # Save intermediate results in case we are curious about
+ # them; the frac values are most likely to be useful.
+ # We won't bother to reshape them, though, and we may
+ # delete them later.
+ self.dsa0 = dsa0
+ self.frac0 = frac0
+ self.dsa1 = dsa1
+ self.frac1 = frac1
+ self.pfrac = pfrac
+ self.p_fudge = p_orig - p
+ # Editing options, in case we don't want to use
+ # values calculated from the wrong pressure, or from
+ # an incomplete SA table grid square.
+ mask_out |= self.p_fudge > self.max_p_fudge
+ mask_out |= self.frac1 < self.min_frac
+ delta_SA = np.ma.array(delta_SA, mask=mask_out, copy=False)
+ if reshaped:
+ delta_SA.shape = shape_in
+ self.p_fudge.shape = shape_in
+ if mask_in is not np.ma.nomask:
+ delta_SA = np.ma.array(delta_SA, mask=mask_in, copy=False)
+ return delta_SA
+
+ def SAAR(self, p, lon, lat):
+ """
+ Table lookup of salinity anomaly ratio, given pressure, lon, and lat.
+ """
+ self.dsa = self.SAAR_ref
+ # In V2,
+ # ndepth from the file disagrees with the unmasked count from
+ # SAAR_ref in a few places; this should be fixed in the
+ # file, but for now we will simply calculate ndepth directly from
+ # SAAR_ref.
+ # TODO: check to see whether this discrepancy is also found in V3.
+ # TODO: check: do we even need to calculate ndepth? It doesn't
+ # appear to be used for anything.
+ #self.ndepth = np.ma.masked_invalid(data.ndepth_ref.T).astype(np.int8)
+ ndepth = self.dsa.count(axis=-1)
+ self.ndepth = np.ma.masked_equal(ndepth, 0)
+ return self._delta_SA(p, lon, lat)
+
+ def delta_SA_ref(self, p, lon, lat):
+ """
+ Table lookup of salinity anomaly reference value, given pressure,
+ lon, and lat.
+ """
+ self.dsa = self.dsa_ref
+ # See comment in previous method.
+ ndepth = self.dsa.count(axis=-1)
+ self.ndepth = np.ma.masked_equal(ndepth, 0)
+ return self._delta_SA(p, lon, lat)
+
+
+def Fdelta(p, lon, lat):
+ r"""Fdelta from the Absolute Salinity Anomaly Ratio (SAAR)::
+ 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 slightly different to 1.35*SAAR.
+ Parameters
+ ----------
+ p : array_like
+ pressure [dbar]
+ lon : array_like
+ decimal degrees east (will be treated modulo 360)
+ lat : array_like
+ decimal degrees (+ve N, -ve S) [-90..+90]
+ Returns
+ -------
+ Fdelta : masked array; masked where no nearby ocean is found in data
+ Ratio of SA to Sstar, minus 1 [unitless]
+ Notes
+ -----
+ The mask 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
+ kilometers inland from the coast.
+ References
+ ----------
+ .. [1] 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.
+ .. [2] McDougall, T.J., D.R. Jackett, F.J. Millero, R. Pawlowicz and
+ P.M. Barker, 2012: A global algorithm for estimating Absolute Salinity.
+ Ocean Science, 8, 1123-1134.
+ http://www.ocean-sci.net/8/1123/2012/os-8-1123-2012.pdf
+ .. [3] Pawlawicz, R., D.G. Wright and F.J. Millero, 2011; The effects of
+ biogeochemical processes on oceanic conductivity/salinty/density
+ relationships and the characterization of real seawater. Ocean Science,
+ 7, 363-387. http://www.ocean-sci.net/7/363/2011/os-7-363-2011.pdf
+ """
+ r = 0.35
+ saar, _ = SAAR(p, lon, lat)
+ Fdelta = ((1 + r) * saar) / (1 - r * saar)
+ return Fdelta
+
+
+ at match_args_return
+def Hill_ratio_at_SP2(t):
+ r"""TODO: Write docstring
+ Hill ratio at SP = 2
+ """
+ # USAGE:
+ # Hill_ratio = 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
+ #
+ # VERSION NUMBER: 3.0 (26th March, 2011)
+ SP2 = 2 * np.ones_like(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
+ return 2. / SP_Hill_raw_at_SP2
+
+
+ at match_args_return
+def SAAR(p, lon, lat):
+ r"""Absolute Salinity Anomaly Ratio (excluding the Baltic Sea).
+ 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.
+
+ Parameters
+ ----------
+ p : array_like
+ pressure [dbar]
+ lon : array_like
+ decimal degrees east (will be treated modulo 360)
+ lat : array_like
+ decimal degrees (+ve N, -ve S) [-90..+90]
+
+ Returns
+ -------
+ SAAR : array
+ Absolute Salinity Anomaly Ratio [unitless]
+ in_ocean : boolean array
+
+ Notes
+ -----
+ 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 SA_from_SP.
+ The in_ocean 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
+ kilometers inland from the coast.
+ References
+ ----------
+ .. [1] 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.
+ .. [2] 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 algorithm is taken from the matlab implementation of the references,
+ but the numpy implementation here differs substantially from the
+ matlab implementation.
+ """
+ saar = SA_table().SAAR(p, lon, lat)
+ return saar, ~saar.mask
+
+
+def SA_from_SP_Baltic(SP, lon, lat):
+ r"""Computes absolute salinity from practical in the Baltic Sea.
+ Parameters
+ ----------
+ SP : array_like or masked array
+ Practical salinity (PSS-78)
+ lon, lat : array_like or masked arrays
+ geographical position
+ Returns
+ -------
+ SA : masked array, at least 1D
+ Absolute salinity [g/kg]
+ masked where inputs are masked or position outside the Baltic
+ """
+ # Handle masked array input
+ input_mask = False
+ if np.ma.is_masked(SP):
+ input_mask = input_mask | SP.mask
+ if np.ma.is_masked(lon):
+ input_mask = input_mask | lon.mask
+ if np.ma.is_masked(lat):
+ input_mask = input_mask | lat.mask
+ SP, lon, lat = map(np.atleast_1d, (SP, lon, lat))
+ SP, lon, lat = np.broadcast_arrays(SP, lon, lat)
+ inds_baltic = in_Baltic(lon, lat)
+ #SA_baltic = np.ma.masked_all(SP.shape, dtype=np.float)
+ all_nans = np.nan + np.zeros_like(SP)
+ SA_baltic = np.ma.MaskedArray(all_nans, mask=~inds_baltic)
+ if np.any(inds_baltic):
+ SA_baltic[inds_baltic] = (((SSO - 0.087) / 35) *
+ SP[inds_baltic] + 0.087)
+ SA_baltic.mask = SA_baltic.mask | input_mask | np.isnan(SP)
+ return SA_baltic
+
+
+def SP_from_SA_Baltic(SA, lon, lat):
+ r"""Calculates Practical Salinity (SP) for the Baltic Sea, from a value
+ computed analytically from Absolute Salinity.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ lon : array_like
+ decimal degrees east [0..+360]
+ lat : array_like
+ decimal degrees (+ve N, -ve S) [-90..+90]
+ Returns
+ -------
+ SP_baltic : array_like
+ salinity [psu (PSS-78)], unitless
+ See Also
+ --------
+ SP_from_SA, SP_from_Sstar
+ Notes
+ -----
+ This program will only produce Practical Salinity values for the Baltic
+ Sea.
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] Feistel, R., S. Weinreben, H. Wolf, S. Seitz, P. Spitzer, B. Adel,
+ G. Nausch, B. Schneider and D. G. Wright, 2010c: Density and Absolute
+ Salinity of the Baltic Sea 2006-2009. Ocean Science, 6, 3-24.
+ http://www.ocean-sci.net/6/3/2010/os-6-3-2010.pdf
+ .. [2] 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.
+ .. [3] 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
+ Modifications:
+ 2010-07-23. David Jackett, Trevor McDougall & Paul Barker
+ """
+ SA, lon, lat = map(np.ma.masked_invalid, (SA, lon, lat))
+ lon, lat, SA = np.broadcast_arrays(lon, lat, SA)
+ inds_baltic = in_Baltic(lon, lat)
+ if not inds_baltic.sum():
+ return None
+ SP_baltic = np.ma.masked_all(SA.shape, dtype=np.float)
+ SP_baltic[inds_baltic] = ((35 / (SSO - 0.087)) *
+ (SA[inds_baltic] - 0.087))
+ return SP_baltic
+# FIXME: Check if this is still used and remove it.
+
+
+def SP_from_SA_Baltic_old(SA, lon, lat):
+ r"""Calculates Practical Salinity (SP) for the Baltic Sea, from a value
+ computed analytically from Absolute Salinity.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ lon : array_like
+ decimal degrees east [0..+360]
+ lat : array_like
+ decimal degrees (+ve N, -ve S) [-90..+90]
+ Returns
+ -------
+ SP_baltic : array_like
+ salinity [psu (PSS-78)], unitless
+ See Also
+ --------
+ SP_from_SA, SP_from_Sstar
+ Notes
+ -----
+ This program will only produce Practical Salinity values for the Baltic
+ Sea.
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] Feistel, R., S. Weinreben, H. Wolf, S. Seitz, P. Spitzer, B. Adel,
+ G. Nausch, B. Schneider and D. G. Wright, 2010c: Density and Absolute
+ Salinity of the Baltic Sea 2006-2009. Ocean Science, 6, 3-24.
+ http://www.ocean-sci.net/6/3/2010/os-6-3-2010.pdf
+ .. [2] 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.
+ .. [3] 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
+ Modifications:
+ 2010-07-23. David Jackett, Trevor McDougall & Paul Barker
+ """
+ SA, lon, lat = map(np.ma.masked_invalid, (SA, lon, lat))
+ lon, lat, SA = np.broadcast_arrays(lon, lat, SA)
+ xb1, xb2, xb3 = 12.6, 7., 26.
+ xb1a, xb3a = 45., 26.
+ yb1, yb2, yb3 = 50., 59., 69.
+ inds_baltic = (xb2 < lon) & (lon < xb1a) & (yb1 < lat) & (lat < yb3)
+ if not inds_baltic.sum():
+ return None
+ SP_baltic = np.ma.masked_all(SA.shape, dtype=np.float)
+ xx_left = np.interp(lat[inds_baltic], [yb1, yb2, yb3], [xb1, xb2, xb3])
+ xx_right = np.interp(lat[inds_baltic], [yb1, yb3], [xb1a, xb3a])
+ inds_baltic1 = ((xx_left <= lon[inds_baltic]) &
+ (lon[inds_baltic] <= xx_right))
+ if not inds_baltic1.sum():
+ return None
+ SP_baltic[inds_baltic[inds_baltic1]] = ((35 / (SSO - 0.087)) *
+ (SA[inds_baltic[inds_baltic1]] -
+ 0.087))
+ return SP_baltic
+
+
+ at match_args_return
+def deltaSA_atlas(p, lon, lat):
+ r"""Absolute Salinity anomaly atlas value (excluding the Baltic Sea).
+ Calculates the Absolute Salinity anomaly atlas value, SA - SR,
+ in the open ocean by spatially interpolating the global reference
+ data set of deltaSA_atlas to the location of the seawater sample.
+ This function uses version 3.0 of the deltaSA_ref look up table.
+ Parameters
+ ----------
+ p : array_like
+ sea pressure (absolute pressure - 10.1325 dbar) [dbar]
+ lon : array_like
+ decimal degrees east (will be treated modulo 360)
+ lat : array_like
+ decimal degrees (+ve N, -ve S) [-90..+90]
+ Returns
+ -------
+ deltaSA_atlas : masked array; masked where no nearby ocean is found in data
+ Absolute Salinity anomaly atlas value [g/kg]
+ Notes
+ -----
+ The Absolute Salinity anomaly atlas value in the Baltic Sea is
+ evaluated separately, since it is a function of Practical Salinity,
+ not of space. The present function returns a deltaSA_atlas of zero
+ for data in the Baltic Sea. The correct way of calculating Absolute
+ Salinity in the Baltic Sea is by calling SA_from_SP.
+ The mask 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
+ kilometers inland from the coast.
+ References
+ ----------
+ .. [1] 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.
+ .. [2] 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 algorithm is taken from the Matlab implementation of the references,
+ but the numpy implementation here differs substantially from the
+ Matlab implementation.
+ """
+ return SA_table().delta_SA_ref(p, lon, lat)
+
+
+def enthalpy_SSO_0_CT25(p):
+ r"""Calculates enthalpy at the Standard Ocean Salinity (SSO) and at a
+ Conservative Temperature of zero degrees C (CT=0), as a function of
+ pressure (p [dbar]) or enthalpy_CT25(35.16504,0,p).
+ Parameters
+ ----------
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ enthalpy_CT25 : array_like
+ enthalpy_CT25 at (SSO, CT = 0, p), 25-term equation.
+ [J kg :sup:`-1`]
+ Notes
+ -----
+ Uses a streamlined version of the 25-term CT version of the Gibbs function,
+ that is, a streamlined version of the code "enthalpy_CT25(SA,CT,p)"
+ Modifications:
+ """
+ p = np.asanyarray(p)
+ mask = np.ma.getmask(p)
+ p = np.ma.filled(p, 0)
+ a0 = 1 + SSO * (2.0777716085618458e-3 + np.sqrt(SSO) *
+ 3.4688210757917340e-6)
+ a1 = 6.8314629554123324e-6
+ b0 = 9.9984380290708214e2 + SSO * (2.8925731541277653e0 + SSO *
+ 1.9457531751183059e-3)
+ b1 = 0.5 * (1.1930681818531748e-2 + SSO * 5.9355685925035653e-6)
+ b2 = -2.5943389807429039e-8
+ A = b1 - np.sqrt(b1 ** 2 - b0 * b2)
+ B = b1 + np.sqrt(b1 ** 2 - b0 * b2)
+ part = (a0 * b2 - a1 * b1) / (b2 * (B - A))
+ enthalpy_SSO_0_CT25 = (db2Pascal * ((a1 / (2 * b2)) *
+ np.log(1 + p * (2 * b1 + b2 * p) / b0) + part *
+ np.log(1 + (b2 * p * (B - A)) /
+ (A * (B + b2 * p)))))
+ return np.ma.array(enthalpy_SSO_0_CT25, mask=mask, copy=False)
+
+
+# FIXME: Check if this is still used and remove it.
+def enthalpy_SSO_0_p(p):
+ r"""This function calculates enthalpy 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 48-term CT
+ version of the Gibbs function, that is, a streamlined version of the
+ code "enthalpy(SA,CT,p).
+ Examples
+ --------
+ >>> import gsw
+ >>> p = np.array([10, 50, 125, 250, 600, 1000])
+ >>> gsw.library.enthalpy_SSO_0_p(p)
+ array([ 97.26388276, 486.27439004, 1215.47518168, 2430.24919716,
+ 5827.90973888, 9704.32296903])
+ Modifications:
+ VERSION NUMBER: 3.03 (29th April, 2013)
+ References
+ ----------
+ .. [1] McDougall T.J., P.M. Barker, R. Feistel and D.R. Jackett, 2013: 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 J. Atm. Ocean. Technol., xx, yyy-zzz.
+ """
+ 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
+ a0 = v21 + SSO * (v26 + v36 * SSO + v31 * np.sqrt(SSO))
+ a1 = v37 + v41 * SSO
+ a2 = v43
+ a3 = v47
+ b0 = v01 + SSO * (v05 + v08 * np.sqrt(SSO))
+ b1 = 0.5 * (v12 + v15 * SSO)
+ b2 = v17 + v20 * SSO
+ b1sq = b1 ** 2
+ sqrt_disc = np.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))
+ return (db2Pascal * (p * (a2 - 2 * a3 * b1 / b2 + 0.5 * a3 * p) / b2 +
+ (M / (2 * b2)) * np.log(1 + p * (2 * b1 + b2 * p) / b0) + part *
+ np.log(1 + (b2 * p * (B - A)) / (A * (B + b2 * p)))))
+
+
+def entropy_part(SA, t, p):
+ r"""Calculates entropy, except that it does not evaluate any terms that are
+ functions of Absolute Salinity alone.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ entropy_part : array_like
+ entropy minus the terms that due to SA alone
+ [J kg :sup:`-1` K :sup:`-1`]
+ Notes
+ -----
+ By not calculating these terms, which are a function only of Absolute
+ Salinity, several unnecessary computations are avoided (including saving
+ the computation of a natural logarithm). These terms are a necessary part
+ of entropy, but are not needed when calculating potential temperature from
+ in situ temperature.
+ Modifications:
+ """
+ SA, t, p, mask = strip_mask(SA, t, p)
+ x2 = sfac * SA
+ x = np.sqrt(x2)
+ y = t * 0.025
+ z = p * 1e-4
+ g03 = (z * (-270.983805184062 + z * (776.153611613101 + z *
+ (-196.51255088122 + (28.9796526294175 - 2.13290083518327 * z) *
+ z))) + y * (-24715.571866078 + z * (2910.0729080936 + z *
+ (-1513.116771538718 + z * (546.959324647056 + z *
+ (-111.1208127634436 + 8.68841343834394 * z)))) + y *
+ (2210.2236124548363 + z * (-2017.52334943521 + z *
+ (1498.081172457456 + z * (-718.6359919632359 +
+ (146.4037555781616 - 4.9892131862671505 * z) * z))) + y *
+ (-592.743745734632 + z * (1591.873781627888 + z *
+ (-1207.261522487504 + (608.785486935364 - 105.4993508931208 * z) *
+ z)) + y * (290.12956292128547 + z * (-973.091553087975 + z *
+ (602.603274510125 + z * (-276.361526170076 + 32.40953340386105 *
+ z))) + y * (-113.90630790850321 + y * (21.35571525415769 -
+ 67.41756835751434 * z) + z * (381.06836198507096 + z *
+ (-133.7383902842754 + 49.023632509086724 * z))))))))
+
+ g08 = (x2 * (z * (729.116529735046 + z * (-343.956902961561 + z *
+ (124.687671116248 + z * (-31.656964386073 + 7.04658803315449 *
+ z)))) + x * (x * (y * (-137.1145018408982 + y *
+ (148.10030845687618 + y * (-68.5590309679152 + 12.4848504784754 *
+ y))) - 22.6683558512829 * z) + z * (-175.292041186547 +
+ (83.1923927801819 - 29.483064349429 * z) * z) + y *
+ (-86.1329351956084 + z * (766.116132004952 + z *
+ (-108.3834525034224 + 51.2796974779828 * z)) + y *
+ (-30.0682112585625 - 1380.9597954037708 * z + y *
+ (3.50240264723578 + 938.26075044542 * z)))) + y *
+ (1760.062705994408 + y * (-675.802947790203 + y *
+ (365.7041791005036 + y * (-108.30162043765552 + 12.78101825083098 *
+ y) + z * (-1190.914967948748 + (298.904564555024 -
+ 145.9491676006352 * z) * z)) + z * (2082.7344423998043 + z *
+ (-614.668925894709 + (340.685093521782 - 33.3848202979239 * z) *
+ z))) + z * (-1721.528607567954 + z * (674.819060538734 + z *
+ (-356.629112415276 + (88.4080716616 - 15.84003094423364 * z) *
+ z))))))
+
+ entropy_part = -(g03 + g08) * 0.025
+ return np.ma.array(entropy_part, mask=mask, copy=False)
+
+
+def entropy_part_zerop(SA, pt0):
+ r"""Calculates entropy at a sea surface (p = 0 dbar), except that it does
+ not evaluate any terms that are functions of Absolute Salinity alone.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ pt0 : array_like
+ potential temperature relative to 0 dbar [:math:`^\circ` C (ITS-90)]
+ Returns
+ -------
+ entropy_part_zerop : array_like
+ [J kg :sup:`-1` K :sup:`-1`]
+ Notes
+ -----
+ By not calculating these terms, which are a function only of Absolute
+ Salinity, several unnecessary computations are avoided (including saving
+ the computation of a natural logarithm). These terms are a necessary part
+ of entropy, but are not needed when calculating potential temperature from
+ in situ temperature.
+ Modifications:
+ """
+ SA, pt0, mask = strip_mask(SA, pt0)
+ x2 = sfac * SA
+ x = np.sqrt(x2)
+ y = pt0 * 0.025
+ g03 = y * (-24715.571866078 + y * (2210.2236124548363 +
+ y * (-592.743745734632 + y * (290.12956292128547 +
+ y * (-113.90630790850321 + y * 21.35571525415769)))))
+ g08 = x2 * (x * (x * (y * (-137.1145018408982 + y *
+ (148.10030845687618 +
+ y * (-68.5590309679152 + 12.4848504784754 * y)))) +
+ y * (-86.1329351956084 + y * (-30.0682112585625 + y *
+ 3.50240264723578))) +
+ y * (1760.062705994408 + y * (-675.802947790203 +
+ y * (365.7041791005036 + y * (-108.30162043765552 +
+ 12.78101825083098 * y)))))
+ entropy_part_zerop = -(g03 + g08) * 0.025
+ return np.ma.array(entropy_part_zerop, mask=mask, copy=False)
+
+
+# FIXME: Check if this is still used and remove it.
+def gibbs(ns, nt, npr, SA, t, p):
+ r"""Calculates specific Gibbs energy and its derivatives up to order 2 for
+ seawater.
+ The Gibbs function approach allows the calculation of internal energy,
+ entropy, enthalpy, potential enthalpy and the chemical potentials of
+ seawater as well as the freezing temperature, and the latent heats of
+ freezing and of evaporation. These quantities were not available from
+ EOS-80 but are essential for the accurate accounting of heat in the ocean
+ and for the consistent and accurate treatment of air-sea and ice-sea heat
+ fluxes.
+ Parameters
+ ----------
+ ns : int
+ order of SA derivative [0, 1 or 2 ]
+ nt : int
+ order of t derivative [0, 1 or 2 ]
+ npr : int
+ order of p derivative [0, 1 or 2 ]
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ gibbs : array_like
+ Specific Gibbs energy or its derivatives.
+ Gibbs energy (ns=nt=npr=0) has units of:
+ [J kg :sup:`-1`]
+ Absolute Salinity derivatives are output in units of:
+ [(J kg :sup:`-1`) (g kg :sup:`-1`) :sup:`-ns`]
+ Temperature derivatives are output in units of:
+ [(J kg :sup:`-1`) K :sup:`-nt`]
+ Pressure derivatives are output in units of:
+ [(J kg :sup:`-1`) Pa :sup:`-npr`]
+ The mixed derivatives are output in units of:
+ [(J kg :sup:`-1`) (g kg :sup:`-1`) :sup:`-ns` K :sup:`-nt`
+ Pa :sup:`-npr`]
+ Notes
+ -----
+ The Gibbs function for seawater is that of TEOS-10 (IOC et al., 2010),
+ being the sum of IAPWS-08 for the saline part and IAPWS-09 for the pure
+ water part. These IAPWS releases are the officially blessed IAPWS
+ descriptions of Feistel (2008) and the pure water part of Feistel (2003).
+ Absolute Salinity, SA, in all of the GSW routines is expressed on the
+ Reference-Composition Salinity Scale of 2008 (RCSS-08) of Millero et al.
+ (2008).
+ The derivatives are taken with respect to pressure in Pa, not withstanding
+ that the pressure input into this routine is in dbar.
+ References
+ ----------
+ .. [1] Feistel, R., 2003: A new extended Gibbs thermodynamic potential of
+ seawater Progr. Oceanogr., 58, 43-114.
+ .. [2] Feistel, R., 2008: A Gibbs function for seawater thermodynamics
+ for -6 to 80 :math:`^\circ` C and salinity up to 120 g kg :sup:`-1`,
+ Deep-Sea Res. I, 55, 1639-1671.
+ .. [3] IAPWS, 2008: Release on the IAPWS Formulation 2008 for the
+ Thermodynamic Properties of Seawater. The International Association for the
+ Properties of Water and Steam. Berlin, Germany, September 2008, available
+ from http://www.iapws.org. This Release is referred to as IAPWS-08.
+ .. [4] IAPWS, 2009: Supplementary Release on a Computationally Efficient
+ Thermodynamic Formulation for Liquid Water for Oceanographic Use. The
+ International Association for the Properties of Water and Steam. Doorwerth,
+ The Netherlands, September 2009, available from http://www.iapws.org.
+ This Release is referred to as IAPWS-09.
+ .. [5] 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. See section 2.6 and appendices A.6, G and H.
+ .. [6] 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.
+ Modifications:
+ 2010-09-24. David Jackett, Paul Barker and Trevor McDougall
+ """
+ SA, t, p = np.asanyarray(SA), np.asanyarray(t), np.asanyarray(p)
+ SA = np.atleast_1d(SA)
+ nonzero_SA = np.any(SA > 0)
+ _SA = SA
+ _t = t
+ _p = p
+ SA = np.ma.filled(SA, 0)
+ t = np.ma.filled(t, 20)
+ p = np.ma.filled(p, 10)
+ SA, t, p = np.broadcast_arrays(SA, t, p)
+ gibbs = np.zeros(SA.shape, dtype=np.float) # Use if all_masked is True
+ all_masked = False
+ # Ensure a full mask, so we can set elements if necessary.
+ mask = np.ma.mask_or(np.ma.getmaskarray(_SA), np.ma.getmask(_t))
+ mask = np.ma.mask_or(mask, np.ma.getmask(_p))
+ mask = np.ma.mask_or(mask, SA < 0)
+ ipos = (SA > 0)
+ # inpos = ~ipos # FIXME: Assigned but never used.
+ if np.all(ipos):
+ ipos = slice(None) # More efficient for usual case.
+ x2 = sfac * SA
+ x = np.sqrt(x2)
+ y = t * 0.025
+ z = p * 1e-4 # The input pressure (p) is sea pressure in units of dbar.
+ if (ns == 0) & (nt == 0) & (npr == 0):
+ g03 = (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)))))))))
+ if nonzero_SA:
+ g08 = x2 * (1416.27648484197 + z * (-3310.49154044839 +
+ z * (384.794152978599 + z * (-96.5324320107458 +
+ (15.8408172766824 - 2.62480156590992 * z) * z))) +
+ 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 + z * (729.116529735046 +
+ z * (-343.956902961561 + z * (124.687671116248 + z *
+ (-31.656964386073 + 7.04658803315449 * z)))) +
+ y * (880.031352997204 + y * (-225.267649263401 +
+ y * (91.4260447751259 + y * (-21.6603240875311 +
+ 2.13016970847183 * y) +
+ z * (-297.728741987187 + (74.726141138756 -
+ 36.4872919001588 * z) * z)) +
+ z * (694.244814133268 + z * (-204.889641964903 +
+ (113.561697840594 - 11.1282734326413 * z) * z))) +
+ z * (-860.764303783977 + z * (337.409530269367 +
+ z * (-178.314556207638 + (44.2040358308 -
+ 7.92001547211682 * z) * z))))))
+ g08[ipos] += x2[ipos] * (5812.81456626732 + 851.226734946706 *
+ y[ipos]) * np.log(x[ipos])
+ else:
+ g08 = 0
+ gibbs = g03 + g08
+ elif (ns == 1) & (nt == 0) & (npr == 0):
+ if nonzero_SA:
+ g08 = (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))))))
+ g08[ipos] = g08[ipos] + (11625.62913253464 + 1702.453469893412 *
+ y[ipos]) * np.log(x[ipos])
+ gibbs = 0.5 * sfac * g08
+ else:
+ all_masked = True
+ elif (ns == 0) & (nt == 1) & (npr == 0):
+ g03 = (5.90578347909402 + z * (-270.983805184062 +
+ z * (776.153611613101 + z * (-196.51255088122 +
+ (28.9796526294175 - 2.13290083518327 * z) * z))) +
+ y * (-24715.571866078 + z * (2910.0729080936 +
+ z * (-1513.116771538718 + z * (546.959324647056 + z *
+ (-111.1208127634436 + 8.68841343834394 * z)))) +
+ y * (2210.2236124548363 + z * (-2017.52334943521 +
+ z * (1498.081172457456 + z * (-718.6359919632359 +
+ (146.4037555781616 - 4.9892131862671505 * z) * z))) +
+ y * (-592.743745734632 + z * (1591.873781627888 +
+ z * (-1207.261522487504 + (608.785486935364 -
+ 105.4993508931208 * z) * z)) +
+ y * (290.12956292128547 + z * (-973.091553087975 +
+ z * (602.603274510125 + z * (-276.361526170076 +
+ 32.40953340386105 * z))) +
+ y * (-113.90630790850321 + y * (21.35571525415769 -
+ 67.41756835751434 * z) +
+ z * (381.06836198507096 + z * (-133.7383902842754 +
+ 49.023632509086724 * z))))))))
+ if nonzero_SA:
+ g08 = x2 * (168.072408311545 + z * (729.116529735046 +
+ z * (-343.956902961561 + z * (124.687671116248 + z *
+ (-31.656964386073 + 7.04658803315449 * z)))) +
+ x * (-493.407510141682 + x * (543.835333000098 + x *
+ (-196.028306689776 + 36.7571622995805 * x) +
+ y * (-137.1145018408982 + y * (148.10030845687618 + y *
+ (-68.5590309679152 + 12.4848504784754 * y))) -
+ 22.6683558512829 * z) + z * (-175.292041186547 +
+ (83.1923927801819 - 29.483064349429 * z) * z) +
+ y * (-86.1329351956084 + z * (766.116132004952 + z *
+ (-108.3834525034224 + 51.2796974779828 * z)) +
+ y * (-30.0682112585625 - 1380.9597954037708 * z + y *
+ (3.50240264723578 + 938.26075044542 * z)))) +
+ y * (1760.062705994408 + y * (-675.802947790203 +
+ y * (365.7041791005036 + y * (-108.30162043765552 +
+ 12.78101825083098 * y) +
+ z * (-1190.914967948748 + (298.904564555024 -
+ 145.9491676006352 * z) * z)) +
+ z * (2082.7344423998043 + z * (-614.668925894709 +
+ (340.685093521782 - 33.3848202979239 * z) * z))) +
+ z * (-1721.528607567954 + z * (674.819060538734 +
+ z * (-356.629112415276 + (88.4080716616 -
+ 15.84003094423364 * z) * z)))))
+ g08[ipos] += 851.226734946706 * x2[ipos] * np.log(x[ipos])
+ gibbs = (g03 + g08) * 0.025
+ else:
+ gibbs = g03
+ elif (ns == 0) & (nt == 0) & (npr == 1):
+ g03 = (100015.695367145 + z * (-5089.1530840726 +
+ z * (853.5533353388611 + z * (-133.2587017014444 +
+ (21.0131554401542 - 3.278571068826234 * z) * z))) +
+ y * (-270.983805184062 + z * (1552.307223226202 +
+ z * (-589.53765264366 + (115.91861051767 -
+ 10.664504175916349 * z) * z)) +
+ y * (1455.0364540468 + z * (-1513.116771538718 +
+ z * (820.438986970584 + z * (-222.2416255268872 +
+ 21.72103359585985 * z))) +
+ y * (-672.50778314507 + z * (998.720781638304 +
+ z * (-718.6359919632359 + (195.2050074375488 -
+ 8.31535531044525 * z) * z)) +
+ y * (397.968445406972 + z * (-603.630761243752 +
+ (456.589115201523 - 105.4993508931208 * z) * z) +
+ y * (-194.618310617595 + y * (63.5113936641785 -
+ 9.63108119393062 * y +
+ z * (-44.5794634280918 + 24.511816254543362 * z)) +
+ z * (241.04130980405 + z * (-165.8169157020456 +
+ 25.92762672308884 * z))))))))
+ if nonzero_SA:
+ g08 = x2 * (-3310.49154044839 + z * (769.588305957198 +
+ z * (-289.5972960322374 + (63.3632691067296 -
+ 13.1240078295496 * z) * z)) +
+ x * (199.459603073901 + x * (-54.7919133532887 +
+ 36.0284195611086 * x - 22.6683558512829 * y +
+ (-8.16387957824522 - 90.52653359134831 * z) * z) +
+ z * (-104.588181856267 + (204.1334828179377 -
+ 13.65007729765128 * z) * z) +
+ y * (-175.292041186547 + (166.3847855603638 -
+ 88.449193048287 * z) * z +
+ y * (383.058066002476 + y * (-460.319931801257 +
+ 234.565187611355 * y) +
+ z * (-108.3834525034224 + 76.9195462169742 * z)))) +
+ y * (729.116529735046 + z * (-687.913805923122 +
+ z * (374.063013348744 + z * (-126.627857544292 +
+ 35.23294016577245 * z))) +
+ y * (-860.764303783977 + y * (694.244814133268 +
+ y * (-297.728741987187 + (149.452282277512 -
+ 109.46187570047641 * z) * z) +
+ z * (-409.779283929806 + (340.685093521782 -
+ 44.5130937305652 * z) * z)) +
+ z * (674.819060538734 + z * (-534.943668622914 +
+ (176.8161433232 - 39.600077360584095 * z) * z)))))
+ else:
+ g08 = 0
+ # Pressure derivative of the Gibbs function
+ # in units of (J kg :sup:`-1`) (Pa :sup:`-1`) = m :sup:`3` kg :sup:`-1`
+ gibbs = (g03 + g08) * 1e-8
+ elif (ns == 1) & (nt == 1) & (npr == 0):
+ if nonzero_SA:
+ g08 = (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)))))
+ g08[ipos] = g08[ipos] + 1702.453469893412 * np.log(x[ipos])
+ gibbs = 0.5 * sfac * 0.025 * g08
+ # FIXME: commented by FF, g110 without nan did not pass
+ #mask[inpos] = True
+ else:
+ all_masked = True
+ elif (ns == 1) & (nt == 0) & (npr == 1):
+ g08 = (-6620.98308089678 + z * (1539.176611914396 +
+ z * (-579.1945920644748 + (126.7265382134592 -
+ 26.2480156590992 * z) * z)) +
+ x * (598.378809221703 + x * (-219.1676534131548 +
+ 180.142097805543 * x - 90.6734234051316 * y +
+ (-32.65551831298088 - 362.10613436539325 * z) * z) +
+ z * (-313.764545568801 + (612.4004484538132 -
+ 40.95023189295384 * z) * z) +
+ y * (-525.876123559641 + (499.15435668109143 -
+ 265.347579144861 * z) * z +
+ y * (1149.174198007428 + y * (-1380.9597954037708 +
+ 703.695562834065 * y) +
+ z * (-325.1503575102672 + 230.7586386509226 * z)))) +
+ y * (1458.233059470092 + z * (-1375.827611846244 +
+ z * (748.126026697488 + z * (-253.255715088584 +
+ 70.4658803315449 * z))) +
+ y * (-1721.528607567954 + y * (1388.489628266536 +
+ y * (-595.457483974374 + (298.904564555024 -
+ 218.92375140095282 * z) * z) +
+ z * (-819.558567859612 + (681.370187043564 -
+ 89.0261874611304 * z) * z)) +
+ z * (1349.638121077468 + z * (-1069.887337245828 +
+ (353.6322866464 - 79.20015472116819 * z) * z)))))
+ # Derivative of the Gibbs function is in units of
+ # (m :sup:`3` kg :sup:`-1`) / (g kg :sup:`-1`) = m :sup:`3` g :sup:`-1`
+ # that is, it is the derivative of specific volume with respect to
+ # Absolute Salinity measured in g kg :sup:`-1`
+ gibbs = g08 * sfac * 0.5e-8
+ elif (ns == 0) & (nt == 1) & (npr == 1):
+ g03 = (-270.983805184062 + z * (1552.307223226202 + z *
+ (-589.53765264366 +
+ (115.91861051767 - 10.664504175916349 * z) * z)) +
+ y * (2910.0729080936 + z * (-3026.233543077436 +
+ z * (1640.877973941168 + z * (-444.4832510537744 +
+ 43.4420671917197 * z))) +
+ y * (-2017.52334943521 + z * (2996.162344914912 +
+ z * (-2155.907975889708 + (585.6150223126464 -
+ 24.946065931335752 * z) * z)) +
+ y * (1591.873781627888 + z * (-2414.523044975008 +
+ (1826.356460806092 - 421.9974035724832 * z) * z) +
+ y * (-973.091553087975 + z * (1205.20654902025 + z *
+ (-829.084578510228 + 129.6381336154442 * z)) +
+ y * (381.06836198507096 - 67.41756835751434 * y + z *
+ (-267.4767805685508 + 147.07089752726017 * z)))))))
+ if nonzero_SA:
+ g08 = x2 * (729.116529735046 + z * (-687.913805923122 +
+ z * (374.063013348744 + z * (-126.627857544292 +
+ 35.23294016577245 * z))) +
+ x * (-175.292041186547 - 22.6683558512829 * x +
+ (166.3847855603638 - 88.449193048287 * z) * z +
+ y * (766.116132004952 + y * (-1380.9597954037708 +
+ 938.26075044542 * y) +
+ z * (-216.7669050068448 + 153.8390924339484 * z))) +
+ y * (-1721.528607567954 + y * (2082.7344423998043 +
+ y * (-1190.914967948748 + (597.809129110048 -
+ 437.84750280190565 * z) * z) +
+ z * (-1229.337851789418 + (1022.055280565346 -
+ 133.5392811916956 * z) * z)) +
+ z * (1349.638121077468 + z * (-1069.887337245828 +
+ (353.6322866464 - 79.20015472116819 * z) * z))))
+ else:
+ g08 = 0
+ # Derivative of the Gibbs function is in units of (m :sup:`3` (K kg))
+ # that is, the pressure of the derivative in Pa.
+ gibbs = (g03 + g08) * 2.5e-10
+ elif (ns == 2) & (nt == 0) & (npr == 0):
+ g08 = 2.0 * (8103.20462414788 +
+ y * (2175.341332000392 + y * (-274.2290036817964 +
+ y * (197.4670779425016 + y * (-68.5590309679152 +
+ 9.98788038278032 * y))) - 90.6734234051316 * z) +
+ 1.5 * x * (-5458.34205214835 - 980.14153344888 * y +
+ (4.0 / 3.0) * x * (2247.60742726704 - 340.1237483177863 * 1.25 *
+ x + 220.542973797483 * y) +
+ 180.142097805543 * z) +
+ z * (-219.1676534131548 + (-16.32775915649044 -
+ 120.7020447884644 * z) * z))
+ if nonzero_SA:
+ tmp = ((-7296.43987145382 + 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))))) / x +
+ (11625.62913253464 + 1702.453469893412 * y) / x2)
+ g08[ipos] += tmp[ipos]
+ gibbs = 0.25 * sfac ** 2 * g08
+ elif (ns == 0) & (nt == 2) & (npr == 0):
+ g03 = (-24715.571866078 + z * (2910.0729080936 + z *
+ (-1513.116771538718 + z * (546.959324647056 + z *
+ (-111.1208127634436 + 8.68841343834394 * z)))) +
+ y * (4420.4472249096725 + z * (-4035.04669887042 +
+ z * (2996.162344914912 + z * (-1437.2719839264719 +
+ (292.8075111563232 - 9.978426372534301 * z) * z))) +
+ y * (-1778.231237203896 + z * (4775.621344883664 +
+ z * (-3621.784567462512 + (1826.356460806092 -
+ 316.49805267936244 * z) * z)) +
+ y * (1160.5182516851419 + z * (-3892.3662123519 +
+ z * (2410.4130980405 + z * (-1105.446104680304 +
+ 129.6381336154442 * z))) +
+ y * (-569.531539542516 + y * (128.13429152494615 -
+ 404.50541014508605 * z) +
+ z * (1905.341809925355 + z * (-668.691951421377 +
+ 245.11816254543362 * z)))))))
+ if nonzero_SA:
+ g08 = x2 * (1760.062705994408 + x * (-86.1329351956084 +
+ x * (-137.1145018408982 + y * (296.20061691375236 +
+ y * (-205.67709290374563 + 49.9394019139016 * y))) +
+ z * (766.116132004952 + z * (-108.3834525034224 +
+ 51.2796974779828 * z)) +
+ y * (-60.136422517125 - 2761.9195908075417 * z +
+ y * (10.50720794170734 + 2814.78225133626 * z))) +
+ y * (-1351.605895580406 + y * (1097.1125373015109 +
+ y * (-433.20648175062206 + 63.905091254154904 * y) +
+ z * (-3572.7449038462437 + (896.713693665072 -
+ 437.84750280190565 * z) * z)) +
+ z * (4165.4688847996085 + z * (-1229.337851789418 +
+ (681.370187043564 - 66.7696405958478 * z) * z))) +
+ z * (-1721.528607567954 + z * (674.819060538734 +
+ z * (-356.629112415276 + (88.4080716616 -
+ 15.84003094423364 * z) * z))))
+ else:
+ g08 = 0
+ gibbs = (g03 + g08) * 0.000625
+ elif (ns == 0) & (nt == 0) & (npr == 2):
+ g03 = (-5089.1530840726 + z * (1707.1066706777221 +
+ z * (-399.7761051043332 + (84.0526217606168 -
+ 16.39285534413117 * z) * z)) +
+ y * (1552.307223226202 + z * (-1179.07530528732 +
+ (347.75583155301 - 42.658016703665396 * z) * z) +
+ y * (-1513.116771538718 + z * (1640.877973941168 +
+ z * (-666.7248765806615 + 86.8841343834394 * z)) +
+ y * (998.720781638304 + z * (-1437.2719839264719 +
+ (585.6150223126464 - 33.261421241781 * z) * z) +
+ y * (-603.630761243752 + (913.178230403046 -
+ 316.49805267936244 * z) * z +
+ y * (241.04130980405 + y * (-44.5794634280918 +
+ 49.023632509086724 * z) +
+ z * (-331.6338314040912 + 77.78288016926652 * z)))))))
+ if nonzero_SA:
+ g08 = x2 * (769.588305957198 + z * (-579.1945920644748 +
+ (190.08980732018878 - 52.4960313181984 * z) * z) +
+ x * (-104.588181856267 + x * (-8.16387957824522 -
+ 181.05306718269662 * z) +
+ (408.2669656358754 - 40.95023189295384 * z) * z +
+ y * (166.3847855603638 - 176.898386096574 * z + y *
+ (-108.3834525034224 + 153.8390924339484 * z))) +
+ y * (-687.913805923122 + z * (748.126026697488 +
+ z * (-379.883572632876 + 140.9317606630898 * z)) +
+ y * (674.819060538734 + z * (-1069.887337245828 +
+ (530.4484299696 - 158.40030944233638 * z) * z) +
+ y * (-409.779283929806 + y * (149.452282277512 -
+ 218.92375140095282 * z) +
+ (681.370187043564 - 133.5392811916956 * z) * z))))
+ else:
+ g08 = 0
+ # Second derivative of the Gibbs function with respect to pressure,
+ # measured in Pa; units of (J kg :sup:`-1`) (Pa :sup:`-2`).
+ gibbs = (g03 + g08) * 1e-16
+ else:
+ raise ValueError('Illegal derivative of the Gibbs function')
+ gibbs = np.ma.array(gibbs, mask=mask, copy=False)
+ # BÅ: Code below is not needed? EF: it is needed.
+ if all_masked:
+ gibbs[:] = np.ma.masked
+ # Do not allow zero salinity with salinity derivatives
+ if ns > 0:
+ gibbs = np.ma.masked_where(SA == 0, gibbs)
+ return gibbs
+
+
+def gibbs_pt0_pt0(SA, pt0):
+ r"""Calculates the second derivative of the specific Gibbs function with
+ respect to temperature at zero sea pressure or _gibbs(0,2,0,SA,t,0).
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ pt0 : array_like
+ potential temperature relative to 0 dbar [:math:`^\circ` C (ITS-90)]
+ Returns
+ -------
+ gibbs_pt0_pt0 : array_like
+ TODO: write the eq. for the second derivative of the
+ specific Gibbs function. FIXME: [units]
+ Notes
+ -----
+ This library function is called by both "pt_from_CT(SA,CT)"
+ and "pt0_from_t(SA,t,p)".
+ Modifications:
+ """
+ SA, pt0, mask = strip_mask(SA, pt0)
+ x2 = sfac * SA
+ x = np.sqrt(x2)
+ y = pt0 * 0.025
+ g03 = (-24715.571866078 +
+ y * (4420.4472249096725 +
+ y * (-1778.231237203896 +
+ y * (1160.5182516851419 +
+ y * (-569.531539542516 + y * 128.13429152494615)))))
+
+ g08 = (x2 * (1760.062705994408 + x * (-86.1329351956084 +
+ x * (-137.1145018408982 + y * (296.20061691375236 +
+ y * (-205.67709290374563 + 49.9394019139016 * y))) +
+ y * (-60.136422517125 + y * 10.50720794170734)) +
+ y * (-1351.605895580406 + y * (1097.1125373015109 +
+ y * (-433.20648175062206 + 63.905091254154904 * y)))))
+ gibbs_pt0_pt0 = (g03 + g08) * 0.000625
+ return np.ma.array(gibbs_pt0_pt0, mask=mask, copy=False)
+
+
+def in_Baltic(lon, lat):
+ """Check if positions are in the Baltic Sea
+ Parameters
+ ----------
+ lon, lat : array_like or masked arrays
+ Returns
+ -------
+ in_Baltic : boolean array (at least 1D)
+ True for points in the Baltic Sea
+ False for points outside, masked or NaN
+ """
+ lon, lat = np.atleast_1d(lon, lat)
+ # Polygon bounding the Baltic, (xb, yb)
+ # Effective boundary is the intersection of this polygon
+ # with rectangle defined by xmin, xmax, ymin, ymax
+ #
+ # start with southwestern point and go round cyclonically
+ xb = np.array([12.6, 45.0, 26.0, 7.0, 12.6])
+ yb = np.array([50.0, 50.0, 69.0, 59.0, 50.0])
+ # Enclosing rectangle
+ #xmin, xmax = xb.min(), xb.max()
+ #ymin, ymax = yb.min(), yb.max()
+ xmin, xmax = 7.0, 32.0
+ ymin, ymax = 52.0, 67.0
+ # First check if outside the rectangle
+ in_rectangle = ((xmin < lon) & (lon < xmax) &
+ (ymin < lat) & (lat < ymax))
+ # Masked values are also considered outside the rectangle
+ if np.ma.is_masked(in_rectangle):
+ in_rectangle = in_rectangle.data & ~in_rectangle.mask
+ # Closer check for points in the rectangle
+ if np.any(in_rectangle):
+ lon, lat = np.broadcast_arrays(lon, lat)
+ in_baltic = np.zeros(lon.shape, dtype='bool')
+ lon1 = lon[in_rectangle]
+ lat1 = lat[in_rectangle]
+ # There are general ways of testing for point in polygon
+ # This works for this special configuration of points
+ xx_right = np.interp(lat1, yb[1:3], xb[1:3])
+ xx_left = np.interp(lat1, yb[-1:1:-1], xb[-1:1:-1])
+ in_baltic[in_rectangle] = (xx_left <= lon1) & (lon1 <= xx_right)
+ return in_baltic
+ else: # Nothing inside the rectangle, return the False array.
+ return in_rectangle
+
+
+def infunnel(SA, CT, p):
+ r"""Oceanographic funnel check for the 25-term equation
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [°C]
+ p : array_like
+ sea pressure [dbar]
+ (ie. absolute pressure - 10.1325 dbar)
+ Returns
+ -------
+ in_funnel : boolean ndarray or scalar
+ True, if SA, CT and p are inside the "funnel"
+ False, if SA, CT and p are outside the "funnel",
+ or one of the values are NaN or masked
+ 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 in terms of SA, CT and p was calculated
+ (McDougall et al., 2010).
+ author:
+ Trevor McDougall and Paul Barker
+ 2011-02-27: Bjørn Ådlandsvik, python version
+ """
+ # Check variables and resize if necessary
+ scalar = np.isscalar(SA) and np.isscalar(CT) and np.isscalar(p)
+ SA, CT, p = np.broadcast_arrays(SA, CT, p)
+ input_nan = np.isnan(SA) | np.isnan(CT) | np.isnan(p)
+ infunnel = ((p <= 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)))
+ infunnel = infunnel & np.logical_not(input_nan)
+ if scalar:
+ infunnel = bool(infunnel)
+ return infunnel
+
+
+def interp_SA_CT(SA, CT, p, p_i):
+ r"""TODO: Write docstring.
+ function [SA_i, CT_i] = interp_SA_CT(SA,CT,p,p_i)
+ interp_SA_CT linear interpolation to p_i on a cast
+ ==========================================================================
+ 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.
+ """
+ return interp_S_T(SA, CT, p, p_i)
+
+
+def interp_S_T(S, T, z, znew, P=None):
+ r"""Linear interpolation of ndarrays *S* and *T* from *z* to *znew*.
+ Optionally interpolate a third ndarray, *P*.
+ *z* must be strictly increasing or strictly decreasing. It must
+ be a 1-D array, and its length must match the last dimension
+ of *S* and *T*.
+ *znew* may be a scalar or a sequence.
+ It is assumed, but not checked, that *S*, *T*, and *z* are
+ all plain ndarrays, not masked arrays or other sequences.
+ Out-of-range values of *znew*, and *nan* in *S* and *T*,
+ yield corresponding *nan* in the output.
+ The basic algorithm is from scipy.interpolate.
+ """
+ isscalar = False
+ if not np.iterable(znew):
+ isscalar = True
+ znew = [znew]
+ znew = np.asarray(znew)
+ inverted = False
+ if z[1] - z[0] < 0:
+ inverted = True
+ z = z[::-1]
+ S = S[..., ::-1]
+ T = T[..., ::-1]
+ if P is not None:
+ P = P[..., ::-1]
+ if (np.diff(z) <= 0).any():
+ raise ValueError("z must be strictly increasing or decreasing")
+ hi = np.searchsorted(z, znew)
+ hi = hi.clip(1, len(z) - 1).astype(int)
+ lo = hi - 1
+ z_lo = z[lo]
+ z_hi = z[hi]
+ S_lo = S[lo]
+ S_hi = S[hi]
+ T_lo = T[lo]
+ T_hi = T[hi]
+ zratio = (znew - z_lo) / (z_hi - z_lo)
+ Si = S_lo + (S_hi - S_lo) * zratio
+ Ti = T_lo + (T_hi - T_lo) * zratio
+ if P is not None:
+ Pi = P[lo] + (P[hi] - P[lo]) * zratio
+ if inverted:
+ Si = Si[..., ::-1]
+ Ti = Ti[..., ::-1]
+ if P is not None:
+ Pi = Pi[..., ::-1]
+ outside = (znew < z.min()) | (znew > z.max())
+ if np.any(outside):
+ Si[..., outside] = np.nan
+ Ti[..., outside] = np.nan
+ if P is not None:
+ Pi[..., outside] = np.nan
+ if isscalar:
+ Si = Si[0]
+ Ti = Ti[0]
+ if P is not None:
+ Pi = Pi[0]
+ if P is None:
+ return Si, Ti
+ return Si, Ti, Pi
+
+
+def interp_ref_cast(spycnl, A="gn"):
+ r"""Translation of:
+ [SA_iref_cast, CT_iref_cast, p_iref_cast] = interp_ref_cast(spycnl, A)
+ 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
+ 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
+ "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<92>s oceans. Journal of Physical Oceanography, 27, 237-263.
+ FIXME? Do we need argument checking here to handle masked arrays,
+ etc.? I suspect not, since I don't think this is intended to be
+ user-callable, but is instead used internally by user-callable
+ functions.
+ Note: The v3.03 matlab code is incorrectly using approximate numbers
+ for the gamma_n case, even when the sigma_2 case is in effect.
+ That bug is fixed here.
+ """
+ if A.lower() in ["s2", "sigma2", "sigma_2"]:
+ A = "s2"
+ gsw_data = read_data("gsw_data_v3_0.npz")
+ SA_ref = gsw_data.SA_ref_cast
+ CT_ref = gsw_data.CT_ref_cast
+ p_ref = gsw_data.p_ref_cast
+ if A == "s2":
+ zvar_ref = gsw_data.sigma_2_ref_cast
+ else:
+ zvar_ref = gsw_data.gamma_n_ref_cast
+ zvar_new = spycnl
+ Si, Ci, Pi = interp_S_T(SA_ref, CT_ref, zvar_ref, zvar_new, P=p_ref)
+ shallower = spycnl <= zvar_ref[0]
+ deeper = spycnl >= zvar_ref[-1]
+ if shallower.any():
+ Si[shallower] = SA_ref[0]
+ Ci[shallower] = CT_ref[0]
+ Pi[shallower] = p_ref[0]
+ if deeper.any():
+ Si[deeper] = SA_ref[-1]
+ Ci[deeper] = CT_ref[-1]
+ Pi[deeper] = p_ref[-1]
+ return Si, Ci, Pi
+
+
+def specvol_SSO_0_CT25(p):
+ r"""Calculates specific volume at the Standard Ocean Salinity (SSO) and
+ Conservative Temperature of zero degrees C (CT=0), as a function of
+ pressure (p [dbar]) or spec_vol_CT25(35.16504,0,p).
+ Parameters
+ ----------
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ specvol_SSO_0_CT25 : array_like
+ Specific volume at (SSO, CT=0, p), 25-term equation.
+ [m :sup:`3` kg :sup:`-1`]
+ Notes
+ -----
+ It uses a streamlined version of the 25-term CT version of specific volume
+ that is, a streamlined version of the code "rho_alpha_beta_CT25(SA,CT,p)"
+ Modifications
+ """
+ p = np.asanyarray(p)
+ # No need to strip mask and replace it here; the calculation is simple.
+ specvol_SSO_0_CT25 = ((1. + SSO * (2.0777716085618458e-003 + np.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)))
+ return specvol_SSO_0_CT25
+
+
+# Salinity lib functions
+def specvol_SSO_0_p(p):
+ r"""This function calculates specific 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 "specvol(SA, CT, p)".
+ Modifications:
+ """
+ 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
+ return ((v21 + SSO * (v26 + v36 * SSO + v31 * np.sqrt(SSO)) + p *
+ (v37 + v41 * SSO + p * (v43 + v47 * p))) / (v01 + SSO *
+ (v05 + v08 * np.sqrt(SSO)) + p * (v12 + v15 * SSO + p *
+ (v17 + v20 * SSO))))
+
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/neutral_nonlinear_48.py b/gsw/gibbs/neutral_nonlinear_48.py
new file mode 100644
index 0000000..a27a4f8
--- /dev/null
+++ b/gsw/gibbs/neutral_nonlinear_48.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+
+__all__ = ['cabbeling', # TODO
+ 'isopycnal_slope_ratio', # TODO
+ 'isopycnal_vs_ntp_CT_ratio', # TODO
+ 'ntp_pt_vs_CT_ratio', # TODO
+ 'thermobaric'] # TODO
+
+
+def cabbeling():
+ pass
+
+
+def isopycnal_slope_ratio():
+ pass
+
+
+def isopycnal_vs_ntp_CT_ratio():
+ pass
+
+
+def ntp_pt_vs_CT_ratio():
+ pass
+
+
+def thermobaric():
+ pass
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/practical_salinity.py b/gsw/gibbs/practical_salinity.py
new file mode 100644
index 0000000..0fec4a7
--- /dev/null
+++ b/gsw/gibbs/practical_salinity.py
@@ -0,0 +1,754 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+
+from .library import Hill_ratio_at_SP2
+from ..utilities import match_args_return
+
+__all__ = ['C_from_SP',
+ 'R_from_SP',
+ 'SK_from_SP',
+ 'SP_from_C',
+ 'SP_from_R',
+ 'SP_from_SK',
+ 'SP_salinometer']
+
+# Constants.
+a = (0.0080, -0.1692, 25.3851, 14.0941, -7.0261, 2.7081)
+b = (0.0005, -0.0056, -0.0066, -0.0375, 0.0636, -0.0144)
+c = (0.6766097, 2.00564e-2, 1.104259e-4, -6.9698e-7, 1.0031e-9)
+d = (3.426e-2, 4.464e-4, 4.215e-1, -3.107e-3)
+e = (2.070e-5, -6.370e-10, 3.989e-15)
+P = (4.577801212923119e-3, 1.924049429136640e-1, 2.183871685127932e-5,
+ -7.292156330457999e-3, 1.568129536470258e-4, -1.478995271680869e-6,
+ 9.086442524716395e-4, -1.949560839540487e-5, -3.223058111118377e-6,
+ 1.175871639741131e-7, -7.522895856600089e-5, -2.254458513439107e-6,
+ 6.179992190192848e-7, 1.005054226996868e-8, -1.923745566122602e-9,
+ 2.259550611212616e-6, 1.631749165091437e-7, -5.931857989915256e-9,
+ -4.693392029005252e-9, 2.571854839274148e-10, 4.198786822861038e-12)
+q = (5.540896868127855e-5, 2.015419291097848e-1, -1.445310045430192e-5,
+ -1.567047628411722e-2, 2.464756294660119e-4, -2.575458304732166e-7,
+ 5.071449842454419e-3, -9.081985795339206e-5, -3.635420818812898e-6,
+ 2.249490528450555e-8, -1.143810377431888e-3, 2.066112484281530e-5,
+ 7.482907137737503e-7, 4.019321577844724e-8, -5.755568141370501e-10,
+ 1.120748754429459e-4, -2.420274029674485e-6, -4.774829347564670e-8,
+ -4.279037686797859e-9, -2.045829202713288e-10, 5.025109163112005e-12)
+r = (3.432285006604888e-3, 1.672940491817403e-1, 2.640304401023995e-5,
+ 1.082267090441036e-1, -6.296778883666940e-5, -4.542775152303671e-7,
+ -1.859711038699727e-1, 7.659006320303959e-4, -4.794661268817618e-7,
+ 8.093368602891911e-9, 1.001140606840692e-1, -1.038712945546608e-3,
+ -6.227915160991074e-6, 2.798564479737090e-8, -1.343623657549961e-10,
+ 1.024345179842964e-2, 4.981135430579384e-4, 4.466087528793912e-6,
+ 1.960872795577774e-8, -2.723159418888634e-10, 1.122200786423241e-12)
+u = (5.180529787390576e-3, 1.052097167201052e-3, 3.666193708310848e-5,
+ 7.112223828976632, -3.631366777096209e-4, -7.336295318742821e-7,
+ -1.576886793288888e+2, -1.840239113483083e-3, 8.624279120240952e-6,
+ 1.233529799729501e-8, 1.826482800939545e+3, 1.633903983457674e-1,
+ -9.201096427222349e-5, -9.187900959754842e-8, -1.442010369809705e-10,
+ -8.542357182595853e+3, -1.408635241899082, 1.660164829963661e-4,
+ 6.797409608973845e-7, 3.345074990451475e-10, 8.285687652694768e-13)
+k = 0.0162
+
+a, b, c, d, e, P, q, r, u, k = map(np.asarray, (a, b, c, d, e, P, q, r, u, k))
+
+
+def C_from_SP(SP, t, p):
+ r"""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.
+
+ Parameters
+ ----------
+ SP : array
+ Practical Salinity [psu (PSS-78), unitless]
+ t : array
+ in-situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array
+ sea pressure [dbar]
+ (i.e. absolute pressure - 10.1325 dbar)
+
+ Returns
+ -------
+ C : array
+ conductivity [mS cm :sup:`-1`]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ 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).
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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.
+
+ .. [2] 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. See appendix E.
+
+ .. [3] Unesco, 1983: Algorithms for computation of fundamental properties
+ of seawater. Unesco Technical Papers in Marine Science, 44, 53 pp.
+ """
+
+ C = 42.9140 * R_from_SP(SP, t, p)
+
+ return C
+
+
+ at match_args_return
+def R_from_SP(SP, t, p):
+ r"""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) formula 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.
+
+ Parameters
+ ----------
+ SP : array
+ Practical Salinity [psu (PSS-78), unitless]
+ t : array_like
+ in-situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array
+ sea pressure [dbar]
+ (i.e. absolute pressure - 10.1325 dbar)
+
+ Returns
+ -------
+ R : array_like
+ conductivity ratio [unitless]
+
+ Examples
+ --------
+ TODO
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ 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).
+
+ References
+ ----------
+ .. [1] 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.
+
+ .. [2] 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.
+
+ .. [3] 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. Appendix E.
+
+ .. [4] Unesco, 1983: Algorithms for computation of fundamental properties
+ of seawater. Unesco Technical Papers in Marine Science, 44, 53 pp.
+
+ Modifications:
+ 2011-04-06. Paul Barker, Trevor McDougall and Rich Pawlowicz.
+ """
+
+ # These few lines ensure that SP is non-negative.
+ if (SP < 0).any():
+ raise ValueError('R_from_SP: SP must be non-negative!')
+
+ SP, t, p = np.broadcast_arrays(SP, t, p)
+
+ # Setting up the constants
+ t68 = t * 1.00024
+ ft68 = (t68 - 15) / (1 + k * (t68 - 15))
+
+ x = np.sqrt(SP)
+ Rtx = np.zeros_like(SP) * np.NaN
+
+ # Finding the starting value of Rtx, the square root of Rt, using four
+ # different polynomials of SP and t68.
+ # TODO: Test case that cover all those "ifs"
+ I = SP >= 9
+ if I.any():
+ Rtx[I] = (P[0] + x[I] * (P[1] + P[4] * t68[I] + x[I] * (P[3] + P[7] *
+ t68[I] + x[I] * (P[6] + P[11] * t68[I] + x[I] * (P[10] +
+ P[16] * t68[I] + x[I] * P[15])))) + t68[I] * (P[2] +
+ t68[I] * (P[5] + x[I] * x[I] * (P[12] + x[I] * P[17]) +
+ P[8] * x[I] + t68[I] * (P[9] + x[I] * (P[13] + x[I] *
+ P[18]) + t68[I] * (P[14] + P[19] * x[I] + P[20] * t68[I])))))
+
+ I = np.logical_and(SP >= 0.25, SP < 9)
+ if I.any():
+ Rtx[I] = (q[0] + x[I] * (q[1] + q[4] * t68[I] + x[I] * (q[3] + q[7] *
+ t68[I] + x[I] * (q[6] + q[11] * t68[I] + x[I] * (q[10] +
+ q[16] * t68[I] + x[I] * q[15])))) + t68[I] * (q[2] +
+ t68[I] * (q[5] + x[I] * x[I] * (q[12] + x[I] * q[17]) +
+ q[8] * x[I] + t68[I] * (q[9] + x[I] * (q[13] + x[I] *
+ q[18]) + t68[I] * (q[14] + q[19] * x[I] + q[20] * t68[I])))))
+
+ I = np.logical_and(SP >= 0.003, SP < 0.25)
+ if I.any():
+ Rtx[I] = (r[0] + x[I] * (r[1] + r[4] * t68[I] + x[I] * (r[3] + r[7] *
+ t68[I] + x[I] * (r[6] + r[11] * t68[I] + x[I] * (r[10] +
+ r[16] * t68[I] + x[I] * r[15])))) + t68[I] * (r[2] +
+ t68[I] * (r[5] + x[I] * x[I] * (r[12] + x[I] * r[17]) +
+ r[8] * x[I] + t68[I] * (r[9] + x[I] * (r[13] + x[I] *
+ r[18]) + t68[I] * (r[14] + r[19] * x[I] + r[20] * t68[I])))))
+
+ I = SP < 0.003
+ if I.any():
+ Rtx[I] = (u[0] + x[I] * (u[1] + u[4] * t68[I] + x[I] * (u[3] + u[7] *
+ t68[I] + x[I] * (u[6] + u[11] * t68[I] + x[I] * (u[10] +
+ u[16] * t68[I] + x[I] * u[15])))) + t68[I] * (u[2] +
+ t68[I] * (u[5] + x[I] * x[I] * (u[12] + x[I] * u[17]) +
+ u[8] * x[I] + t68[I] * (u[9] + x[I] * (u[13] + x[I] *
+ u[18]) + t68[I] * (u[14] + u[19] * x[I] + u[20] * t68[I])))))
+
+ # Finding the starting value of dSP_dRtx, the derivative of SP with
+ # respect to Rtx.
+ dSP_dRtx = (a[1] + (2 * a[2] + (3 * a[3] + (4 * a[4] + 5 * a[5] * Rtx) *
+ Rtx) * Rtx) * Rtx + ft68 * (b[1] + (2 * b[2] + (3 * b[3] +
+ (4 * b[4] + 5 * b[5] * Rtx) * Rtx) * Rtx) * Rtx))
+
+ # TODO: Test case that cover all those "ifs"
+ I2 = SP < 2
+ if I2.any():
+ x = 400 * (Rtx[I2] ** 2)
+ sqrty = 10 * Rtx[I2]
+ part1 = 1 + x * (1.5 + x)
+ part2 = 1 + sqrty * (1 + sqrty * (1 + sqrty))
+ Hill_ratio = Hill_ratio_at_SP2(t[I2])
+ dSP_dRtx[I2] = (dSP_dRtx[I2] + a[0] * 800 * Rtx[I2] * (1.5 + 2 * x) /
+ (part1 ** 2) + b[0] * ft68[I2] * (10 + sqrty * (20 +
+ 30 * sqrty)) / (part2 ** 2))
+
+ dSP_dRtx[I2] = Hill_ratio * dSP_dRtx[I2]
+
+ """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
+ achieves 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 = (a[0] + (a[1] + (a[2] + (a[3] + (a[4] + a[5] * Rtx) * Rtx) *
+ Rtx) * Rtx) * Rtx + ft68 * (b[0] + (b[1] + (b[2] + (b[3] +
+ (b[4] + b[5] * Rtx) * Rtx) * Rtx) * Rtx) * Rtx))
+
+ # TODO: Test case that cover all those "ifs"
+ I2 = SP_est < 2
+ if I2.any():
+ x = 400 * (Rtx[I2] ** 2)
+ sqrty = 10 * Rtx[I2]
+ part1 = 1 + x * (1.5 + x)
+ part2 = 1 + sqrty * (1 + sqrty * (1 + sqrty))
+ SP_Hill_raw = SP_est[I2] - a[0] / part1 - b[0] * ft68[I2] / part2
+ Hill_ratio = Hill_ratio_at_SP2(t[I2])
+ SP_est[I2] = Hill_ratio * SP_Hill_raw
+
+ Rtx_old = Rtx
+ Rtx = Rtx_old - (SP_est - SP) / dSP_dRtx
+
+ # This mean value of Rtx, Rtxm, is the value of Rtx at which the
+ # derivative dSP_dRtx is evaluated.
+ Rtxm = 0.5 * (Rtx + Rtx_old)
+
+ dSP_dRtx = (a[1] +
+ (2 * a[2] + (3 * a[3] + (4 * a[4] + 5 * a[5] * Rtxm) * Rtxm) *
+ Rtxm) * Rtxm + ft68 *
+ (b[1] + (2 * b[2] + (3 * b[3] + (4 * b[4] + 5 * b[5] * Rtxm) *
+ Rtxm) * Rtxm) * Rtxm))
+
+ # TODO: Test case that cover all those "ifs"
+ I2 = SP_est < 2
+ if I2.any():
+ x = 400 * (Rtxm[I2] ** 2)
+ sqrty = 10 * Rtxm[I2]
+ part1 = 1 + x * (1.5 + x)
+ part2 = 1 + sqrty * (1 + sqrty * (1 + sqrty))
+ dSP_dRtx[I2] = (dSP_dRtx[I2] + a[0] * 800 * Rtxm[I2] * (1.5 + 2 *
+ x) / (part1 ** 2) + b[0] * ft68[I2] * (10 + sqrty *
+ (20 + 30 * sqrty)) / (part2 ** 2))
+ Hill_ratio = Hill_ratio_at_SP2(t[I2])
+ dSP_dRtx[I2] = Hill_ratio * dSP_dRtx[I2]
+
+ # End of the one full iteration of the modified Newton-Raphson technique.
+ Rtx = Rtx_old - (SP_est - SP) / dSP_dRtx # Updated Rtx
+
+ # 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 = (a[0] + (a[1] + (a[2] + (a[3] + (a[4] + a[5] * Rtx) * Rtx) *
+ Rtx) * Rtx) * Rtx + ft68 *
+ (b[0] + (b[1] + (b[2] + (b[3] + (b[4] + b[5] * Rtx) * Rtx) *
+ Rtx) * Rtx) * Rtx))
+
+ # TODO: Test case that cover all those "ifs"
+ I2 = SP_est < 2
+ if I2.any():
+ x = 400 * (Rtx[I2] ** 2)
+ sqrty = 10 * Rtx[I2]
+ part1 = 1 + x * (1.5 + x)
+ part2 = 1 + sqrty * (1 + sqrty * (1 + sqrty))
+ SP_Hill_raw = SP_est[I2] - a[0] / part1 - b[0] * ft68[I2] / part2
+ Hill_ratio = Hill_ratio_at_SP2(t[I2])
+ SP_est[I2] = Hill_ratio * SP_Hill_raw
+
+ Rtx = Rtx - (SP_est - SP) / dSP_dRtx
+
+ """ TODO: add this as a kw.
+ Return the error, SP_error, in Rtx (in terms of psu).
+
+ SP_est = (a[0] + (a[1] + (a[2] + (a[3] + (a[4] + a[5] * Rtx) * Rtx) *
+ Rtx) * Rtx) * Rtx + ft68 * (b[0] + (b[1] + (b[2] + (b[3] +
+ (b[4] + b[5] * Rtx) * Rtx) * Rtx) * Rtx) * Rtx))
+ I2 = SP_est < 2
+ if I2.any():
+ x = 400 * (Rtx[I2] ** 2)
+ sqrty = 10 * Rtx[I2]
+ part1 = 1 + x * (1.5 + x)
+ part2 = 1 + sqrty * (1 + sqrty * (1 + sqrty))
+ SP_Hill_raw = SP_est[I2] - a[0] / part1 - b[0] * ft68[I2] / part2
+ Hill_ratio = Hill_ratio_at_SP2(t[I2])
+ SP_est[I2] = Hill_ratio * SP_Hill_raw
+
+ SP_error = np.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 ** 2
+ A = d[2] + d[3] * t68
+ B = 1 + d[0] * t68 + d[1] * t68 ** 2
+ C = p * (e[0] + e[1] * p + e[2] * p ** 2)
+ # rt_lc (i.e. rt_lower_case) corresponds to rt as defined in the
+ # UNESCO 44 (1983) routines.
+ rt_lc = c[0] + (c[1] + (c[2] + (c[3] + c[4] * t68) * t68) * t68) * t68
+
+ D = B - A * rt_lc * Rt
+ E = rt_lc * Rt * A * (B + C)
+ Ra = np.sqrt(D ** 2 + 4 * E) - D
+
+ return 0.5 * Ra / A
+
+
+ at match_args_return
+def SK_from_SP(SP):
+ r"""Calculates Knudsen Salinity from Practical Salinity.
+
+ Parameters
+ ----------
+ SP : array
+ Practical Salinity [psu (PSS-78), unitless]
+
+ Returns
+ -------
+ SK : array_like
+ Knudsen Salinity [parts per thousand, ppt]
+
+ Examples
+ --------
+ TODO
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Appendix A.3.
+
+ Modifications:
+ 2011-11-16. Trevor McDougall and Paul Barker.
+ """
+ SP = np.maximum(SP, 0) # Ensure that SP is non-negative.
+
+ return 0.03 + SP * (1.805 / 1.80655)
+
+
+ at match_args_return
+def SP_from_C(C, t, p):
+ r"""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).
+
+ Parameters
+ ----------
+ C : array
+ conductivity [mS cm :sup:`-1`]
+ t : array
+ in-situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array
+ sea pressure [dbar]
+ (i.e. absolute pressure - 10.1325 dbar)
+
+ Returns
+ -------
+ SP : array
+ Practical Salinity [psu (PSS-78), unitless]
+
+ Examples
+ --------
+ TODO
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ References
+ ----------
+ .. [1] 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.
+
+ .. [2] 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.
+
+ .. [3] 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. Appendix E.
+
+ .. [4] Unesco, 1983: Algorithms for computation of fundamental properties
+ of seawater. Unesco Technical Papers in Marine Science, 44, 53 pp.
+
+ Modifications:
+ 2011-04-01. Paul Barker, Trevor McDougall and Rich Pawlowicz.
+ """
+
+ C, t, p = np.broadcast_arrays(C, t, p)
+
+ 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 = c[0] + (c[1] + (c[2] + (c[3] + c[4] * t68) * t68) * t68) * t68
+ Rp = (1 + (p * (e[0] + e[1] * p + e[2] * p ** 2)) /
+ (1 + d[0] * t68 + d[1] * t68 ** 2 + (d[2] + d[3] * t68) * R))
+ Rt = R / (Rp * rt_lc)
+
+ Rt[Rt < 0] = np.ma.masked
+ Rtx = np.sqrt(Rt)
+
+ SP = (a[0] + (a[1] + (a[2] + (a[3] + (a[4] + a[5] * Rtx) * Rtx) * Rtx) *
+ Rtx) * Rtx + ft68 *
+ (b[0] + (b[1] + (b[2] + (b[3] + (b[4] + b[5] * 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, = np.nonzero(np.ravel(SP) < 2)
+ if len(I2) > 0:
+ Hill_ratio = 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] - a[0] / part1 - b[0] * ft68[I2] / part2
+ SP[I2] = Hill_ratio * SP_Hill_raw
+
+ SP = np.maximum(SP, 0) # Ensure that SP is non-negative.
+
+ return SP
+
+
+ at match_args_return
+def SP_from_R(R, t, p):
+ r"""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.
+
+ Parameters
+ ----------
+ R : array_like
+ conductivity ratio [unitless]
+ t : array_like
+ in-situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array
+ sea pressure [dbar]
+ (i.e. absolute pressure - 10.1325 dbar)
+
+ Returns
+ -------
+ SP : array
+ Practical Salinity [psu (PSS-78), unitless]
+
+ Examples
+ --------
+ TODO
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ References
+ ----------
+ .. [1] 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.
+
+ .. [2] 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.
+
+ .. [3] 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. Appendix E.
+
+ .. [4] Unesco, 1983: Algorithms for computation of fundamental properties
+ of seawater. Unesco Technical Papers in Marine Science, 44, 53 pp.
+
+ Modifications:
+ 2011-04-01. Paul Barker, Trevor McDougall and Rich Pawlowicz.
+ """
+
+ R, t, p = np.broadcast_arrays(R, t, p)
+
+ 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 = c[0] + (c[1] + (c[2] + (c[3] + c[4] * t68) * t68) * t68) * t68
+ Rp = (1 + (p * (e[0] + e[1] * p + e[2] * p ** 2)) /
+ (1 + d[0] * t68 + d[1] * t68 ** 2 + (d[2] + d[3] * t68) * R))
+ Rt = R / (Rp * rt_lc)
+
+ Rt[Rt < 0] = np.ma.masked
+ Rtx = np.sqrt(Rt)
+
+ SP = (a[0] + (a[1] + (a[2] + (a[3] + (a[4] + a[5] * Rtx) * Rtx) * Rtx) *
+ Rtx) * Rtx + ft68 *
+ (b[0] + (b[1] + (b[2] + (b[3] + (b[4] + b[5] * 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 = SP < 2
+ if I2.any():
+ Hill_ratio = 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] - a[0] / part1 - b[0] * ft68[I2] / part2
+ SP[I2] = Hill_ratio * SP_Hill_raw
+
+ SP = np.maximum(SP, 0) # Ensure that SP is non-negative.
+
+ return SP
+
+
+ at match_args_return
+def SP_from_SK(SK):
+ r"""Calculates Practical Salinity from Knudsen Salinity.
+
+ Parameters
+ ----------
+ SK : array_like
+ Knudsen Salinity [parts per thousand, ppt]
+
+ Returns
+ -------
+ SP : array
+ Practical Salinity [psu (PSS-78), unitless]
+
+ Examples
+ --------
+ TODO
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Appendix A.3.
+
+ Modifications:
+ 2011-11-16. Trevor McDougall and Paul Barker.
+ """
+
+ SP = (SK - 0.03) * (1.80655 / 1.805)
+ return np.maximum(SP, 0) # Ensure that SP is non-negative.
+
+
+ at match_args_return
+def SP_salinometer(Rt, t):
+ r"""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.
+
+ Parameters
+ ----------
+ Rt : array
+ C(SP,t_68,0)/C(SP=35,t_68,0) [unitless]
+ conductivity ratio
+ :math:`R = \frac{C(S, t_68, 0)}{C(35, 15(IPTS-68),0)} [unitless]
+
+ t : array
+ Temperature of the bath of the salinometer [:math:`^\circ` C (ITS-90)]
+
+ Returns
+ -------
+ SP : array
+ Practical Salinity [psu (PSS-78), unitless]
+
+ See Also
+ --------
+ TODO: sw.sals
+
+ Notes
+ -----
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ -----------
+ ..[1] 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.
+
+ ..[2] 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.
+
+ .. [3] 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. See appendix E of this TEOS-10 Manual, and in
+ particular, Eqns. (E.2.1) and (E.2.6).
+
+ Modifications:
+ 2011-04-30. Paul Barker, Trevor McDougall and Rich Pawlowicz. Version 3.0
+ """
+
+ Rt, t = np.broadcast_arrays(Rt, t)
+
+ t68 = t * 1.00024
+ ft68 = (t68 - 15) / (1 + k * (t68 - 15))
+
+ Rt[Rt < 0] = np.ma.masked
+ Rtx = np.sqrt(Rt)
+
+ SP = (a[0] + (a[1] + (a[2] + (a[3] + (a[4] + a[5] * Rtx) * Rtx) * Rtx) *
+ Rtx) * Rtx + ft68 *
+ (b[0] + (b[1] + (b[2] + (b[3] + (b[4] + b[5] * 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 = SP < 2
+ if I2.any():
+ Hill_ratio = 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] - a[0] / part1 - b[0] * ft68[I2] / part2
+ SP[I2] = Hill_ratio * SP_Hill_raw
+ # Ensure that SP is non-negative.
+ SP = np.maximum(SP, 0)
+ return SP
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/steric.py b/gsw/gibbs/steric.py
new file mode 100644
index 0000000..62284a7
--- /dev/null
+++ b/gsw/gibbs/steric.py
@@ -0,0 +1,131 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+from ..utilities import match_args_return
+from .geostrophic_48 import geo_strf_dyn_height
+
+__all__ = ['steric_height']
+
+
+ at match_args_return
+def steric_height(SA, CT, p, p_ref):
+ r"""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 meters) 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
+ because 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
+ "infunnel(SA,CT,p)" is available to be used if one wants to test if some of
+ one's data lies outside this "funnel".
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ p_ref : int, float, optional
+ reference pressure, default = 0
+
+ Returns
+ -------
+ steric_height : array_like
+ dynamic height anomaly divided by 9.7963 m s^-2 [m]
+
+ Notes
+ -----
+ 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.
+
+ See Also
+ --------
+ TODO
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See section 3.27.
+
+ .. [2] 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.
+
+ .. [3] Griffies, S. M., 2004: Fundamentals of Ocean Climate Models.
+ Princeton, NJ: Princeton University Press, 518 pp + xxxiv.
+
+ Modifications:
+ 2010-05-20. Trevor McDougall and Paul Barker.
+ """
+
+ p_ref = np.asanyarray(p_ref)
+
+ p_ref = np.unique(p_ref)
+
+ if not np.isscalar(p_ref):
+ raise ValueError('The reference pressure p_ref must be unique')
+
+ if (p_ref < 0).any():
+ raise ValueError('The reference pressure p_ref must be positive')
+
+ if (SA < 0).any():
+ raise ValueError('The Absolute Salinity must be positive!')
+
+ # Start of the calculation.
+ if p.max() < p_ref.max():
+ raise ValueError('The reference pressure p_ref is deeper than bottles')
+
+ dynamic_height_anomaly = geo_strf_dyn_height(SA, CT, p, p_ref)
+ const_grav = 9.7963 # Griffies, 2004.
+
+ return dynamic_height_anomaly / const_grav
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/thermodynamics_from_t.py b/gsw/gibbs/thermodynamics_from_t.py
new file mode 100644
index 0000000..c17d6b0
--- /dev/null
+++ b/gsw/gibbs/thermodynamics_from_t.py
@@ -0,0 +1,1750 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+
+from .library import gibbs
+from .freezing import t_freezing
+from ..utilities import match_args_return, strip_mask
+from .conversions import (pt_from_CT, pt_from_t, pt0_from_t, CT_from_t,
+ t_from_CT)
+from .constants import Kelvin, db2Pascal, P0, SSO, cp0, R, sfac, M_S
+
+__all__ = ['adiabatic_lapse_rate_from_t',
+ 'adiabatic_lapse_rate_from_CT',
+ 'alpha_wrt_CT_t_exact',
+ 'alpha_wrt_pt_t_exact',
+ 'alpha_wrt_t_exact',
+ 'beta_const_CT_t_exact',
+ 'beta_const_pt_t_exact',
+ 'beta_const_t_exact',
+ 'chem_potential_relative_t_exact',
+ 'chem_potential_salt_t_exact',
+ 'chem_potential_water_t_exact',
+ 'cp_t_exact',
+ 'deltaSA_from_rho_t_exact',
+ 'dynamic_enthalpy_t_exact',
+ 'enthalpy_t_exact',
+ 'entropy_t_exact',
+ 'Helmholtz_energy_t_exact',
+ 'internal_energy_t_exact',
+ 'isochoric_heat_cap_t_exact',
+ 'kappa_const_t_exact',
+ 'kappa_t_exact',
+ 'osmotic_coefficient_t_exact',
+ 'osmotic_pressure_t_exact',
+ 'pot_rho_t_exact',
+ 'rho_t_exact',
+ 'SA_from_rho_t',
+ 'SA_from_rho_t_exact',
+ 'sigma0_pt0_exact',
+ 'sound_speed_t_exact',
+ 'specvol_anom_t_exact',
+ 'specvol_t_exact',
+ 't_from_rho_exact',
+ 't_maxdensity_exact']
+
+n0, n1, n2 = 0, 1, 2
+
+
+ at match_args_return
+def adiabatic_lapse_rate_from_t(SA, t, p):
+ """
+ gsw_adiabatic_lapse_rate_from_t adiabatic lapse rate
+ ==========================================================================
+
+ USAGE:
+ adiabatic_lapse_rate = gsw_adiabatic_lapse_rate_from_t(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 ]
+ ( 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 ]
+ 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 at teos-10.org ]
+
+ VERSION NUMBER: 3.03 (29th April, 2013)
+
+ 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.22.1) of this TEOS-10 Manual.
+
+ """
+ return -gibbs(n0, n1, n1, SA, t, p) / (gibbs(n0, n2, n0, SA, t, p))
+
+ at match_args_return
+def adiabatic_lapse_rate_from_CT(SA, CT, p):
+ """
+ gsw_adiabatic_lapse_rate_from_CT adiabatic lapse rate
+ ==========================================================================
+
+ USAGE:
+ adiabatic_lapse_rate = gsw_adiabatic_lapse_rate_from_CT(SA,CT,p)
+
+ DESCRIPTION:
+ Calculates the adiabatic lapse rate of sea water from Conservative
+ Temperature.
+
+ 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:
+ adiabatic_lapse_rate = 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 at teos-10.org ]
+
+ VERSION NUMBER: 3.03 (29th April, 2013)
+
+ 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.22.1) of this TEOS-10 Manual.
+
+ """
+ t = t_from_CT(SA, CT, p)
+
+ return -gibbs(n0, n1, n1, SA, t, p) / gibbs(n0, n2, n0, SA, t, p)
+
+
+ at match_args_return
+def alpha_wrt_CT_t_exact(SA, t, p):
+ r"""Calculates the thermal expansion coefficient of seawater with respect
+ to Conservative Temperature.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ alpha_wrt_CT : array_like
+ thermal expansion coefficient [K :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.alpha_wrt_CT_t_exact(SA, t, p)
+ array([ 0.00032471, 0.00032272, 0.00028118, 0.00017314, 0.00014627,
+ 0.00012943])
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.18.3).
+ Modifications:
+ 2011-03-29. Trevor McDougall and Paul Barker
+ """
+ pt0 = pt0_from_t(SA, t, p)
+ factor = -cp0 / ((Kelvin + pt0) * gibbs(n0, n2, n0, SA, t, p))
+ return factor * (gibbs(n0, n1, n1, SA, t, p) / gibbs(n0, n0, n1, SA, t, p))
+
+
+ at match_args_return
+def alpha_wrt_pt_t_exact(SA, t, p):
+ r"""Calculates the thermal expansion coefficient of seawater with respect
+ to potential temperature, with a reference pressure of zero.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ alpha_wrt_pt : array_like
+ thermal expansion coefficient [K :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.alpha_wrt_pt_t_exact(SA, t, p)
+ array([ 0.00032562, 0.00032355, 0.00028164, 0.00017314, 0.00014623,
+ 0.00012936])
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.18.2).
+ Modifications:
+ 2011-03-29. David Jackett, Trevor McDougall and Paul Barker
+ """
+ pt0 = pt0_from_t(SA, t, p)
+ factor = gibbs(n0, n2, n0, SA, pt0, 0) / gibbs(n0, n2, n0, SA, t, p)
+ return factor * (gibbs(n0, n1, n1, SA, t, p) / gibbs(n0, n0, n1, SA, t, p))
+
+
+ at match_args_return
+def alpha_wrt_t_exact(SA, t, p):
+ r"""Calculates the thermal expansion coefficient of seawater with respect
+ to in situ temperature.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ alpha_wrt_t : array_like
+ thermal expansion coefficient [K :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.alpha_wrt_t_exact(SA, t, p)
+ array([ 0.0003256 , 0.00032345, 0.00028141, 0.00017283, 0.00014557,
+ 0.00012836])
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.18.1)
+ .. [2] 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.
+ Modifications:
+ 2011-03-29. David Jackett, Trevor McDougall and Paul Barker
+ """
+ return gibbs(n0, n1, n1, SA, t, p) / gibbs(n0, n0, n1, SA, t, p)
+
+
+ at match_args_return
+def beta_const_CT_t_exact(SA, t, p):
+ r"""Calculates the saline (i.e. haline) contraction coefficient of seawater
+ at constant Conservative Temperature.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ beta_const_CT : array_like
+ saline contraction coefficient [kg g :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.beta_const_CT_t_exact(SA, t, p)
+ array([ 0.00071749, 0.00071765, 0.00072622, 0.00075051, 0.00075506,
+ 0.00075707])
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.19.3)
+ Modifications:
+ 2010-07-23. David Jackett, Trevor McDougall and Paul Barker
+ """
+ # TODO: Original GSW-V3 re-implements gibbs, check what to do here!
+ pt0 = pt0_from_t(SA, t, p)
+ factora = (gibbs(n1, n1, n0, SA, t, p) - gibbs(n1, n0, n0, SA, pt0, 0) /
+ (Kelvin + pt0))
+ factor = (factora / (gibbs(n0, n0, n1, SA, t, p) *
+ gibbs(n0, n2, n0, SA, t, p)))
+ return (gibbs(n0, n1, n1, SA, t, p) * factor -
+ gibbs(n1, n0, n1, SA, t, p) / gibbs(n0, n0, n1, SA, t, p))
+
+
+ at match_args_return
+def beta_const_pt_t_exact(SA, t, p):
+ r"""Calculates the saline (i.e. haline) contraction coefficient of seawater
+ at constant potential temperature with a reference pressure of 0 dbar.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ beta_const_pt : array_like
+ saline contraction coefficient [kg g :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.beta_const_pt_t_exact(SA, t, p)
+ array([ 0.00073112, 0.00073106, 0.00073599, 0.00075375, 0.00075712,
+ 0.00075843])
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.19.2)
+ Modifications:
+ 2011-04-10. Trevor McDougall and Paul Barker
+ """
+ # NOTE: The original Matlab toolbox re-implement some code here. Why?
+ pt0 = pt0_from_t(SA, t, p)
+ factora = gibbs(n1, n1, n0, SA, t, p) - gibbs(n1, n1, n0, SA, pt0, 0)
+ factor = (factora / (gibbs(n0, n0, n1, SA, t, p) *
+ gibbs(n0, n2, n0, SA, t, p)))
+ return (gibbs(n0, n1, n1, SA, t, p) * factor -
+ gibbs(n1, n0, n1, SA, t, p) / gibbs(n0, n0, n1, SA, t, p))
+
+
+ at match_args_return
+def beta_const_t_exact(SA, t, p):
+ r"""Calculates the saline (i.e. haline) contraction coefficient of seawater
+ at constant in situ temperature.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ beta_const_t : array_like
+ saline contraction coefficient [kg g :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.beta_const_t_exact(SA, t, p)
+ array([ 0.00073112, 0.00073107, 0.00073602, 0.00075381, 0.00075726,
+ 0.00075865])
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.19.1)
+ Modifications:
+ 2011-03-29. David Jackett, Trevor McDougall and Paul Barker
+ """
+ return -gibbs(n1, n0, n1, SA, t, p) / gibbs(n0, n0, n1, SA, t, p)
+
+
+ at match_args_return
+def chem_potential_relative_t_exact(SA, t, p):
+ r"""Calculates the adiabatic lapse rate of seawater.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ chem_potential_relative : array_like
+ relative chemical potential [J/g]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.chem_potential_relative_t_exact(SA, t, p)
+ array([ 79.4254481 , 79.25989214, 74.69154859, 65.64063719,
+ 61.22685656, 57.21298557])
+ References
+ ----------
+ .. [1] 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.
+ Modifications:
+ 2013-04-15. Trevor McDougall and Paul Barker
+ """
+ n0 = 0
+ n1 = 1
+ return gibbs(n1, n0, n0, SA, t, p)
+
+
+ at match_args_return
+def chem_potential_salt_t_exact(SA, t, p):
+ r"""Calculates the chemical potential of salt in seawater.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ chem_potential_salt : array_like
+ chemical potential of salt in seawater [J kg :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.chem_potential_salt_t_exact(SA, t, p)
+ array([-8466.13569818, -7928.8256562 , -5029.28859129, -568.42714556,
+ 3396.79366004, 7612.64743154])
+ References
+ ----------
+ .. [1] 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. See section 2.9.
+ Modifications:
+ 2010-03-29. Trevor McDougall and Paul Barker
+ """
+ return (chem_potential_relative_t_exact(SA, t, p) +
+ chem_potential_water_t_exact(SA, t, p))
+
+
+ at match_args_return
+def chem_potential_water_t_exact(SA, t, p):
+ r"""Calculates the chemical potential of water in seawater.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ chem_potential_water : array_like
+ chemical potential of water in seawater
+ [J/g]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.chem_potential_water_t_exact(SA, t, p)
+ array([-8545.56114628, -8008.08554834, -5103.98013987, -634.06778275,
+ 3335.56680347, 7555.43444597])
+ References
+ ----------
+ .. [1] 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.
+ Modifications:
+ 2013-04-15. Trevor McDougall and Paul Barker
+ """
+ SA, t, p, mask = strip_mask(SA, t, p)
+ # FIXME: Ugly copy from gibbs, why?
+ x2 = sfac * SA
+ x = np.sqrt(x2)
+ y = t * 0.025
+ z = p * 1e-4 # 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
+ # V3.03: convert from J/kg to J/g.
+ # See section 2.9 of TEOS-10 manual.
+ chem_potential_water *= 1e-3
+ return np.ma.array(chem_potential_water, mask=mask, copy=False)
+
+
+ at match_args_return
+def cp_t_exact(SA, t, p):
+ r"""Calculates the isobaric heat capacity of seawater.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ cp_t_exact : array_like
+ heat capacity of seawater [J kg :sup:`-1` K :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.cp_t_exact(SA, t, p)
+ array([ 4002.88800396, 4000.98028393, 3995.54646889, 3985.07676902,
+ 3973.59384348, 3960.18408479])
+ .. [1] 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.
+ Modifications:
+ 2011-03-29. David Jackett, Trevor McDougall and Paul Barker
+ """
+ return -(t + Kelvin) * gibbs(n0, n2, n0, SA, t, p)
+
+
+ at match_args_return
+def deltaSA_from_rho_t_exact(rho, SP, t, p):
+ pass
+
+
+ at match_args_return
+def dynamic_enthalpy_t_exact(SA, t, p):
+ r"""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)).
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ dynamic_enthalpy_t_exact : array_like
+ dynamic enthalpy [J :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ References
+ ----------
+ .. [1] 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.
+ .. [2] Young, W.R., 2010: Dynamic enthalpy, Conservative Temperature, and
+ the seawater. Boussinesq approximation. Journal of Physical Oceanography,
+ 40, 394-400.
+ Modifications:
+ 2011-04-11. Trevor McDougall and Paul Barker
+ """
+ CT = CT_from_t(SA, t, p)
+ return enthalpy_t_exact(SA, t, p) - cp0 * CT
+
+
+ at match_args_return
+def enthalpy_t_exact(SA, t, p):
+ r"""Calculates the specific enthalpy of seawater.
+ The specific enthalpy of seawater :math:`h` is given by:
+ .. math::
+ h(SA, t, p) = g + (T_0 + t)\eta =
+ g - (T_0 + t) \frac{\partial g}{\partial T}\Big|_{SA,p}
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ enthalpy : array_like
+ specific enthalpy [J kg :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.enthalpy(SA, t, p)
+ array([ 115103.26047838, 114014.8036012 , 92179.9209311 ,
+ 43255.32838089, 33087.21597002, 26970.5880448 ])
+ References
+ ----------
+ .. [1] 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. See appendix A.11.
+ Modifications:
+ 2011-03-29. David Jackett, Trevor McDougall and Paul Barker.
+ """
+ return (gibbs(n0, n0, n0, SA, t, p) -
+ (t + Kelvin) * gibbs(n0, n1, n0, SA, t, p))
+
+
+ at match_args_return
+def entropy_t_exact(SA, t, p):
+ r"""Calculates specific entropy of seawater.
+ The specific entropy of seawater :math:`\eta` is given by:
+ .. math::
+ \eta(SA, t, p) = -g_T = \frac{\partial g}{\partial T}\Big|_{SA,p}
+ When taking derivatives with respect to *in situ* temperature, the symbol
+ :math:`T` will be used for temperature in order that these derivatives not
+ be confused with time derivatives.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ entropy : array_like
+ specific entropy [J kg :sup:`-1` K :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.entropy_t_exact(SA, t, p)
+ array([ 400.38942528, 395.43817843, 319.8664982 , 146.79088159,
+ 98.64734087, 62.79150873])
+ References
+ ----------
+ .. [1] 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.
+ Modifications:
+ 2011-03-29. David Jackett, Trevor McDougall and Paul Barker.
+ """
+ return -gibbs(n0, n1, n0, SA, t, p)
+
+
+ at match_args_return
+def Helmholtz_energy_t_exact(SA, t, p):
+ r"""Calculates the Helmholtz energy of seawater.
+ The specific Helmholtz energy of seawater :math:`f` is given by:
+ .. math::
+ f(SA, t, p) = g - (p + P_0) \nu =
+ g - (p + P_0) \frac{\partial g}{\partial P}\Big|_{SA,T}
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ Helmholtz_energy : array_like
+ Helmholtz energy [J kg :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.Helmholtz_energy_t_exact(SA, t, p)
+ array([-5985.58288209, -5830.81845224, -3806.96617841, -877.66369421,
+ -462.17033905, -245.50407205])
+ References
+ ----------
+ .. [1] 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. See section 2.13.
+ Modifications:
+ 2011-03-29. Trevor McDougall
+ """
+ return (gibbs(n0, n0, n0, SA, t, p) -
+ (db2Pascal * p + P0) * gibbs(n0, n0, n1, SA, t, p))
+
+
+ at match_args_return
+def internal_energy_t_exact(SA, t, p):
+ r"""Calculates the Helmholtz energy of seawater.
+ The specific internal energy of seawater :math:`u` is given by:
+ .. math::
+ u(SA, t, p) = g + (T_0 + t)\eta - (p + P_0)\nu =
+ g - (T_0 + t)\frac{\partial g}{\partial T}\Big|_{SA,p} -
+ (p + P_0)\frac{\partial g}{\partial P}\Big|_{SA,T}
+ where :math:`T_0` is the Celsius zero point, 273.15 K and
+ :math:`P_0` = 101 325 Pa is the standard atmosphere pressure.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ internal_energy (u) : array_like
+ specific internal energy [J kg :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.internal_energy_t_exact(SA, t, p)
+ array([ 114906.23847309, 113426.57417062, 90860.81858842,
+ 40724.34005719, 27162.66600185, 17182.50522667])
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.11.1)
+ Modifications:
+ 2011-03-29. Trevor McDougall
+ """
+ return (gibbs(n0, n0, n0, SA, t, p) -
+ (Kelvin + t) * gibbs(n0, n1, n0, SA, t, p) -
+ (db2Pascal * p + P0) * gibbs(n0, n0, n1, SA, t, p))
+
+
+ at match_args_return
+def isochoric_heat_cap_t_exact(SA, t, p):
+ r"""Calculates the isochoric heat capacity of seawater.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ isochoric_heat_cap : array_like
+ isochoric heat capacity [J kg :sup:`-1` K :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.isochoric_heat_cap_t_exact(SA, t, p)
+ array([ 3928.13708702, 3927.27381633, 3941.36418525, 3966.26126146,
+ 3960.50903222, 3950.13901342])
+ References
+ ----------
+ .. [1] 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. See section 2.21.
+ Modifications:
+ 2011-03-29. Trevor McDougall
+ """
+ return (-(Kelvin + t) * (gibbs(n0, n2, n0, SA, t, p) -
+ gibbs(n0, n1, n1, SA, t, p) ** 2 / gibbs(n0, n0, n2, SA, t, p)))
+
+
+ at match_args_return
+def kappa_const_t_exact(SA, t, p):
+ r"""Calculates isothermal compressibility of seawater at constant in situ
+ temperature.
+ .. math::
+ \kappa^t(SA, t, p) =
+ \rho^{-1}\frac{\partial \rho}{\partial P}\Big|_{SA,T} =
+ -\nu^{-1}\frac{\partial \nu}{\partial P}\Big|_{SA,T} =
+ -\frac{g_{PP}}{g_P}
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ kappa : array_like
+ Isothermal compressibility [Pa :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ This is the compressibility of seawater at constant in situ temperature.
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.kappa_const_t_exact(SA, t, p)
+ array([ 4.19071646e-10, 4.18743202e-10, 4.22265764e-10,
+ 4.37735100e-10, 4.40373818e-10, 4.41156577e-10])
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.15.1)
+ Modifications:
+ 2011-03-29. David Jackett, Trevor McDougall and Paul Barker
+ """
+ return -gibbs(n0, n0, n2, SA, t, p) / gibbs(n0, n0, n1, SA, t, p)
+
+
+ at match_args_return
+def kappa_t_exact(SA, t, p):
+ r"""Calculates the isentropic compressibility of seawater.
+ When the entropy and Absolute Salinity are held constant while the pressure
+ is changed, the isentropic and isohaline compressibility
+ :math:`kappa` is obtained:
+ .. math::
+ \kappa(SA, t, p) =
+ \rho^{-1}\frac{\partial \rho}{\partial P}\Big|_{SA,\eta} =
+ -\nu^{-1}\frac{\partial \nu}{\partial P}\Big|_{SA,\eta} =
+ \rho^{-1}\frac{\partial \rho}{\partial P}\Big|_{SA,\theta} =
+ -\nu^{-1}\frac{\partial \nu}{\partial P}\Big|_{SA,\theta} =
+ -\frac{ (g_{TP}^2 - g_{TT} g_{PP} ) }{g_P g_{TT}}
+ The isentropic and isohaline compressibility is sometimes called simply the
+ isentropic compressibility (or sometimes the "adiabatic compressibility"),
+ on the unstated understanding that there is also no transfer of salt during
+ the isentropic or adiabatic change in pressure.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ kappa : array_like
+ Isentropic compressibility [Pa :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ The output is Pascal and not dbar.
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.kappa_t_exact(SA, t, p)
+ array([ 4.11245799e-10, 4.11029072e-10, 4.16539558e-10,
+ 4.35668338e-10, 4.38923693e-10, 4.40037576e-10])
+ References
+ ----------
+ .. [1] 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. See Eqns. (2.16.1) and the row for kappa in
+ Table P.1 of appendix P
+ Modifications:
+ 2011-03-23. David Jackett, Trevor McDougall and Paul Barker
+ """
+ return ((gibbs(n0, n1, n1, SA, t, p) ** 2 - gibbs(n0, n2, n0, SA, t, p) *
+ gibbs(n0, n0, n2, SA, t, p)) / (gibbs(n0, n0, n1, SA, t, p) *
+ gibbs(n0, n2, n0, SA, t, p)))
+
+
+ at match_args_return
+def osmotic_coefficient_t_exact(SA, t, p):
+ r"""Calculates the osmotic coefficient of seawater.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ osmotic_coefficient : array_like
+ osmotic coefficient of seawater [unitless]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.osmotic_coefficient_t_exact(SA,t , p)
+ array([ 0.90284718, 0.90298624, 0.90238866, 0.89880927, 0.89801054,
+ 0.89767912])
+ References
+ ----------
+ .. [1] 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.
+ Modifications:
+ 2011-04-01. Trevor McDougall and Paul Barker.
+ 2012-11-15. Trevor McDougall and Paul Barker.
+ """
+ SA = np.maximum(SA, 0)
+ k = M_S / R
+ part = k * (1000 - SA) / (Kelvin + t)
+ x2 = sfac * SA
+ x = np.sqrt(x2)
+ y = t * 0.025
+ # Note that the input pressure (p) is sea pressure in units of dbar.
+ z = p / db2Pascal
+ oc = (7.231916621570606e1, 1.059039593127674e1, -3.025914794694813e1,
+ 5.040733670521486e1, -4.074543321119333e1, 1.864215613820487e1,
+ -3.022566485046178, -6.138647522851840, 1.353207379758663e1,
+ -7.316560781114737, 1.829232499785750, -5.358042980767074e-1,
+ -1.705887283375562, -1.246962174707332e-1, 1.228376913546017,
+ 1.089364009088042e-2, -4.264828939262248e-1, 6.213127679460041e-2,
+ 2.481543497315280, -1.363368964861909, -5.640491627443773e-1,
+ 1.344724779893754, -2.180866793244492, 4.765753255963401,
+ -5.726993916772165, 2.918303792060746, -6.506082399183509e-1,
+ -1.015695507663942e-1, 1.035024326471108, -6.742173543702397e-1,
+ 8.465642650849419e-1, -7.508472135244717e-1, -3.668086444057845e-1,
+ 3.189939162107803e-1, -4.245629194309487e-2)
+ tl = (oc[0] + oc[1] * y + x * (oc[2] + x * (oc[3] + x * (oc[4] + x *
+ (oc[5] + oc[6] * x))) + y * (oc[7] + x * (oc[8] + x *
+ (oc[9] + oc[10] * x)) + y * (oc[11] + oc[12] * x + y * (oc[13] +
+ oc[14] * x + y * (oc[15] + x * (oc[16] + oc[17] * y))))) + z *
+ (oc[18] + x * (oc[19] + oc[20] * y + oc[21] * x) + y * (oc[22] + y *
+ (oc[23] + y * (oc[24] + oc[25] * y))) + z * (oc[26] + oc[27] * x + y *
+ (oc[28] + oc[29] * y) + z * (oc[30] + oc[31] * x + y * (oc[32] +
+ oc[33] * y) + oc[34] * z)))))
+ return tl * part
+
+
+ at match_args_return
+def osmotic_pressure_t_exact(SA, t, pw):
+ r"""Calculates the osmotic pressure of seawater.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ pw : array_like
+ sea pressure of the pure water side [dbar]
+ Returns
+ -------
+ osmotic_pressure_t_exact : array_like
+ dynamic osmotic pressure of seawater [dbar]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ References
+ ----------
+ .. [1] 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. See section 3.41.
+ Modifications:
+ 2011-05-26. Trevor McDougall and Paul Barker
+ """
+ SA = np.maximum(SA, 0)
+ gibbs_pure_water = gibbs(0, 0, 0, 0, t, pw)
+ # Initial guess of p, in dbar.
+ p = pw + 235.4684
+ # Initial guess of df/dp.
+ df_dp = -db2Pascal * (gibbs(n0, n0, n1, SA, t, p) -
+ SA * gibbs(n1, n0, n1, SA, t, p))
+ for Number_of_iterations in range(0, 2):
+ p_old = p
+ f = gibbs_pure_water - chem_potential_water_t_exact(SA, t, p_old)
+ # This is half way through the modified N-R method.
+ p = p_old - f / df_dp
+ p_mean = 0.5 * (p + p_old)
+ df_dp = -db2Pascal * (gibbs(0, 0, 1, SA, t, p_mean) -
+ SA * gibbs(1, 0, 1, SA, t, p_mean))
+ p = p_old - f / df_dp
+ # After two iterations though the modified Newton-Raphson technique the
+ # maximum error is 6x10^-12 dbar.
+ # Osmotic pressure of seawater in dbar.
+ return p - pw
+
+
+ at match_args_return
+def pot_rho_t_exact(SA, t, p, p_ref=0):
+ r"""Calculates potential density of seawater.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ p_ref : int, float, optional
+ reference pressure, default = 0
+ Returns
+ -------
+ pot_rho : array_like
+ potential density [kg m :sup:`-3`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.pot_rho_t_exact(SA, t, p)
+ array([ 1021.79814581, 1022.05248442, 1023.89358365, 1026.66762112,
+ 1027.10723087, 1027.40963126])
+ >>> gsw.pot_rho(SA, t, p, p_ref=1000)
+ array([ 1025.95554512, 1026.21306986, 1028.12563226, 1031.1204547 ,
+ 1031.63768355, 1032.00240412])
+ References
+ ----------
+ .. [1] 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. See section 3.4.
+ Modifications:
+ 2011-03-29. David Jackett, Trevor McDougall and Paul Barker
+ """
+ pt = pt_from_t(SA, t, p, p_ref=p_ref)
+ return rho_t_exact(SA, pt, p_ref)
+
+
+ at match_args_return
+def rho_t_exact(SA, t, p):
+ r"""Calculates in situ density of seawater from Absolute Salinity and in
+ situ temperature.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ rho_t_exact : array_like
+ in situ density [kg m :sup:`-3`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.rho(SA, t, p)
+ array([ 1021.84017319, 1022.26268993, 1024.42771594, 1027.79020181,
+ 1029.83771473, 1032.00240412])
+ References
+ ----------
+ .. [1] 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. See section 2.8.
+ Modifications:
+ 2011-03-29. Paul Barker, David Jackett and Trevor McDougal
+ """
+ return 1. / gibbs(n0, n0, n1, SA, t, p)
+
+
+ at match_args_return
+def SA_from_rho_t(rho, t, p):
+ return None
+
+
+ at match_args_return
+def SA_from_rho_t_exact(rho, t, p):
+ r"""Calculates the Absolute Salinity of a seawater sample, for given values
+ of its density, in situ temperature and sea pressure (in dbar).
+ One use for this function is in the laboratory where a measured value of
+ the in situ density :math:`\rho` of a seawater sample may have been made at
+ the laboratory temperature :math:`t` and at atmospheric pressure :math:`p`.
+ The present function will return the Absolute Salinity SA of this seawater
+ sample.
+ Parameters
+ ----------
+ rho : array_like
+ in situ density [kg m :sup:`-3`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ This is expressed on the Reference-Composition Salinity Scale of
+ Millero et al. (2008).
+ After two iterations of a modified Newton-Raphson iteration,
+ the error in SA is typically no larger than
+ 2 :math:`^\times` 10 :sup:`-13` [g kg :sup:`-1`]
+ Examples
+ --------
+ >>> import gsw
+ >>> rho = [1021.839, 1022.262, 1024.426, 1027.792, 1029.839, 1032.002]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.SA_from_rho_t_exact(rho, t, p)
+ array([ 34.71022966, 34.89057683, 35.02332421, 34.84952096,
+ 34.73824809, 34.73188384])
+ References
+ ----------
+ .. [1] 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. See section 2.5.
+ .. [2] 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.
+ Modifications:
+ 2011-03-28. Trevor McDougall and Paul Barker.
+ """
+ v_lab = np.ones_like(rho) / rho
+ v_0 = gibbs(n0, n0, n1, 0, t, p)
+ v_120 = gibbs(n0, n0, n1, 120, t, p)
+ # Initial estimate of SA.
+ SA = 120 * (v_lab - v_0) / (v_120 - v_0)
+ Ior = np.logical_or(SA < 0, SA > 120)
+ # Initial estimate of v_SA, SA derivative of v
+ v_SA = (v_120 - v_0) / 120
+ for k in range(0, 2):
+ SA_old = SA
+ delta_v = gibbs(n0, n0, n1, SA_old, t, p) - v_lab
+ # Half way the mod. N-R method (McDougall and Wotherspoon, 2012)
+ SA = SA_old - delta_v / v_SA
+ SA_mean = 0.5 * (SA + SA_old)
+ v_SA = gibbs(n1, n0, n1, SA_mean, t, p)
+ SA = SA_old - delta_v / v_SA
+ SA[Ior] = np.ma.masked
+ return SA
+
+
+ at match_args_return
+def sigma0_pt0_exact(SA, pt0):
+ r"""Calculates potential density anomaly with reference sea pressure of
+ zero (0) dbar. The temperature input to this function is potential
+ temperature referenced to zero dbar.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ pt0 : array_like
+ potential temperature [:math:`^\circ` C (ITS-90)]
+ with respect to a reference sea pressure of 0 dbar
+ Returns
+ -------
+ sigma0_pt0_exact : array_like
+ potential density anomaly [kg m :sup:`-3`]
+ respect to a reference pressure of 0 dbar
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.rho(SA, t, p)
+ array([ 1021.84017319, 1022.26268993, 1024.42771594, 1027.79020181,
+ 1029.83771473, 1032.00240412])
+ References
+ ----------
+ .. [1] 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. See Eqn. (3.6.1).
+ Modifications:
+ 2011-03-29. Trevor McDougal and Paul Barker.
+ """
+ SA = np.maximum(SA, 0) # Ensure that SA is non-negative.
+ x2 = sfac * SA
+ x = np.sqrt(x2)
+ y = pt0 * 0.025
+ g03 = (100015.695367145 +
+ y * (-270.983805184062 +
+ y * (1455.0364540468 +
+ y * (-672.50778314507 +
+ y * (397.968445406972 +
+ y * (-194.618310617595 +
+ y * (63.5113936641785 -
+ y * 9.63108119393062)))))))
+ g08 = x2 * (-3310.49154044839 +
+ x * (199.459603073901 +
+ x * (-54.7919133532887 +
+ x * 36.0284195611086 -
+ y * 22.6683558512829) +
+ y * (-175.292041186547 +
+ y * (383.058066002476 +
+ y * (-460.319931801257 +
+ y * 234.565187611355)))) +
+ y * (729.116529735046 +
+ y * (-860.764303783977 +
+ y * (694.244814133268 +
+ y * (-297.728741987187)))))
+ """The above code is exactly the same as the following two lines of code.
+ sigma0_pt_exact = rho_t_exact(SA, pt0, 0.) - 1000
+ """
+ return 100000000. / (g03 + g08) - 1000.0
+
+
+ at match_args_return
+def sound_speed_t_exact(SA, t, p):
+ r"""Calculates the speed of sound in seawater.
+ The speed of sound in seawater :math:`c` is given by:
+ .. math::
+ c(SA, t, p) = \sqrt{ \partial P / \partial \rho |_{SA,\eta}} =
+ \sqrt{(\rho\kappa)^{-1}} =
+ g_P \sqrt{g_{TT}/(g^2_{TP} - g_{TT}g_{PP})}
+ Note that in these expressions, since sound speed is in m s :sup`-1` and
+ density has units of kg m :sup:`-3` it follows that the pressure of the
+ partial derivatives must be in Pa and the isentropic compressibility
+ :math:`kappa` must have units of Pa :sup:`-1`. The sound speed c produced
+ by both the SIA and the GSW software libraries (appendices M and N) has
+ units of m s :sup:`-1`.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ sound_speed : array_like
+ speed of sound in seawater [m s :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.sound_speed_t_exact(SA, t, p)
+ array([ 1542.61580359, 1542.70353407, 1530.84497914, 1494.40999692,
+ 1487.37710252, 1483.93460908])
+ References
+ ----------
+ .. [1] 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. See Eqn. (2.17.1)
+ Modifications:
+ 2011-03-29. David Jackett, Paul Barker and Trevor McDougall.
+ """
+ return (gibbs(n0, n0, n1, SA, t, p) * np.sqrt(gibbs(n0, n2, n0, SA, t, p) /
+ (gibbs(n0, n1, n1, SA, t, p) ** 2 - gibbs(n0, n2, n0, SA, t, p) *
+ gibbs(n0, n0, n2, SA, t, p))))
+
+
+ at match_args_return
+def specvol_anom_t_exact(SA, t, p):
+ r"""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 :math:`^\circ` C.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ specvol_anom_t_exact : array_like
+ specific volume anomaly [m :sup:`3` kg :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.specvol_anom_t_exact(SA, t, p)
+ array([ 6.01044463e-06, 5.78602432e-06, 4.05564999e-06,
+ 1.42198662e-06, 1.04351837e-06, 7.63964850e-07])
+ References
+ ----------
+ .. [1] 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. See Eqn. (3.7.3)
+ Modifications:
+ 2011-03-23. Trevor McDougall and Paul Barker
+ """
+ pt_zero = pt_from_CT(SSO, 0)
+ t_zero = pt_from_t(SSO, pt_zero, 0, p)
+ return (gibbs(n0, n0, n1, SA, t, p) -
+ gibbs(n0, n0, n1, SSO, t_zero, p))
+
+
+ at match_args_return
+def specvol_t_exact(SA, t, p):
+ r"""Calculates the specific volume of seawater.
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ specvol : array_like
+ specific volume [m :sup:`3` kg :sup:`-1`]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ >>> import gsw
+ >>> SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+ >>> t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+ >>> p = [10, 50, 125, 250, 600, 1000]
+ >>> gsw.specvol(SA, t, p)
+ array([ 0.00097863, 0.00097822, 0.00097615, 0.00097296, 0.00097103,
+ 0.00096899])
+ References
+ ----------
+ .. [1] 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. See section 2.7.
+ Modifications:
+ 2011-03-23. David Jackett and Paul Barker.
+ """
+ return gibbs(n0, n0, n1, SA, t, p)
+
+
+ at match_args_return
+def t_from_rho_exact(rho, SA, p):
+ r"""Calculates the in-situ temperature of a seawater sample, for given
+ values of its density, Absolute Salinity and sea pressure (in dbar).
+ Parameters
+ ----------
+ rho : array_like
+ in situ density [kg m :sup:`-3`]
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ t : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ t_multiple : array_like
+ in situ temperature [:math:`^\circ` C (ITS-90)]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ At low salinities, in brackish water, there are two possible temperatures
+ for a single density. This program will output both valid solutions
+ (t, t_multiple), if there is only one possible solution the second variable
+ will be set to NaN.
+ Examples
+ --------
+ TODO
+ References
+ ----------
+ .. [1] 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.
+ Modifications:
+ 2011-04-21. Trevor McDougall and Paul Barker.
+ """
+ """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_a, t_b = None, None
+ t = np.zeros_like(SA) * np.NaN
+ t_multiple = np.zeros_like(SA) * np.NaN
+ I_SA = np.logical_or(SA < 0, SA > 42)
+ I_p = np.logical_or(p < -1.5, p > 12000)
+ I_SA_p = np.logical_or(I_SA, I_p)
+ SA[I_SA_p] = np.ma.masked
+ rho_40 = rho_t_exact(SA, 40 * np.ones_like(SA), p)
+ SA[(rho - rho_40) < 0] = np.ma.masked
+ t_max_rho = t_maxdensity_exact(SA, p)
+ rho_max = rho_t_exact(SA, t_max_rho, p)
+ rho_extreme = rho_max.copy()
+ t_freeze = t_freezing(SA, p) # Assumes seawater is saturated with air.
+ rho_freezing = rho_t_exact(SA, t_freeze, p)
+ # Set rhos greater than those at the freezing point to be equal to the
+ # freezing point.
+ I_fr_gr_max = (t_freeze - t_max_rho) > 0
+ rho_extreme[I_fr_gr_max] = rho_freezing[I_fr_gr_max]
+ SA[rho > rho_extreme] = np.ma.masked
+ SA[np.isnan(SA * p * rho)] = np.ma.masked
+ alpha_freezing = alpha_wrt_t_exact(SA, t_freeze, p)
+ I_salty = alpha_freezing > alpha_limit
+ if I_salty.any():
+ t_diff = 40. * np.ones_like(I_salty) - t_freeze[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 ** 2)
+ b = -rho_freezing[I_salty] * alpha_freezing[I_salty]
+ c = rho_freezing[I_salty] - rho[I_salty]
+ sqrt_disc = np.sqrt(b ** 2 - 4 * a * c)
+ # The value of t[I_salty] is the initial guess `t` in the range of
+ # I_salty.
+ t[I_salty] = t_freeze[I_salty] + 0.5 * (-b - sqrt_disc) / a
+ I_fresh = alpha_freezing <= alpha_limit
+ if I_fresh.any():
+ t_diff = 40 * np.ones_like[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 * np.sqrt(factor)
+ I_fresh_NR = delta_t > 5
+ if I_fresh_NR.any():
+ t[I_fresh[I_fresh_NR]] = (t_max_rho[I_fresh[I_fresh_NR]] +
+ delta_t[I_fresh_NR])
+ I_quad = delta_t <= 5
+ if I_quad.any():
+ t_a = np.zeros_like(SA) * np.NaN
+ # Set the initial value of the quadratic solution roots.
+ t_a[I_fresh[I_quad]] = (t_max_rho[I_fresh[I_quad]] +
+ np.sqrt(rec_half_rho_TT *
+ (rho[I_fresh[I_quad]] -
+ rho_max[I_fresh[I_quad]])))
+ for Number_of_iterations in range(0, 6):
+ t_old = t_a
+ rho_old = 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) * np.sqrt(factorqa)
+ t_a[t_freezing - t_a < 0] = np.ma.masked
+ t_b = np.zeros_like(SA) * np.NaN
+ # Set the initial value of the quadratic solution routes.
+ t_b[I_fresh[I_quad]] = (t_max_rho[I_fresh[I_quad]] -
+ np.sqrt(rec_half_rho_TT *
+ (rho[I_fresh[I_quad]] -
+ rho_max[I_fresh[I_quad]])))
+ for Number_of_iterations in range(0, 6):
+ t_old = t_b.copy()
+ rho_old = 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) * np.sqrt(factorqb)
+ # After seven iterations of this quadratic iterative procedure,
+ # the error in rho is no larger than 4.6x10^-13 kg/m^3.
+ t_b[t_freezing - t_b < 0] = np.ma.masked
+ # Begin the modified Newton-Raphson iterative method, which will
+ # only operate on non-masked data.
+ v_lab = np.ones_like(rho) / rho
+ v_t = gibbs(0, 1, 1, SA, t, p)
+ for Number_of_iterations in range(0, 3):
+ t_old = t.copy()
+ delta_v = gibbs(0, 0, 1, SA, t_old, p) - v_lab
+ t = t_old - delta_v / v_t # Half way through the modified N-R method.
+ t_mean = 0.5 * (t + t_old)
+ v_t = gibbs(0, 1, 1, SA, t_mean, p)
+ t = t_old - delta_v / v_t
+ if t_a:
+ t[~np.isnan(t_a)] = t_a[~np.isnan(t_a)]
+ if t_b:
+ t_multiple[~np.isnan(t_b)] = t_b[~np.isnan(t_b)]
+ # After three iterations of this modified Newton-Raphson iteration,
+ # the error in rho is no larger than 4.6x10^-13 kg/m^3.
+ return t, t_multiple
+
+
+ at match_args_return
+def t_maxdensity_exact(SA, p):
+ r"""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).
+ Parameters
+ ----------
+ SA : array_like
+ Absolute salinity [g kg :sup:`-1`]
+ p : array_like
+ pressure [dbar]
+ Returns
+ -------
+ t_maxdensity_exact : array_like
+ max in-situ temperature [:math:`^\circ` C]
+ See Also
+ --------
+ TODO
+ Notes
+ -----
+ TODO
+ Examples
+ --------
+ References
+ ----------
+ .. [1] 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. See section 3.42.
+ Modifications:
+ 2011-04-03. Trevor McDougall and Paul Barker
+ """
+ # The temperature increment for calculating the gibbs_PTT derivative.
+ dt = 0.001
+ t = 3.978 - 0.22072 * SA # The initial guess of t_maxden.
+ gibbs_PTT = 1.1e-8 # The initial guess for g_PTT.
+ for Number_of_iterations in range(0, 3):
+ t_old = t
+ gibbs_PT = gibbs(n0, n1, n1, SA, t_old, p)
+ # Half way through the mod. method (McDougall and Wotherspoon, 2012)
+ t = t_old - gibbs_PT / gibbs_PTT
+ t_mean = 0.5 * (t + t_old)
+ gibbs_PTT = (gibbs(n0, n1, n1, SA, t_mean + dt, p) -
+ gibbs(n0, n1, n1, SA, t_mean - dt, p)) / (dt + dt)
+ t = t_old - gibbs_PT / gibbs_PTT
+ # After three iterations of this modified Newton-Raphson iteration, the
+ # error in t_maxdensity_exact is typically no larger than 1x10^-15 deg C.
+ return t
+
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/gibbs/water_column_48.py b/gsw/gibbs/water_column_48.py
new file mode 100644
index 0000000..1955066
--- /dev/null
+++ b/gsw/gibbs/water_column_48.py
@@ -0,0 +1,344 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import numpy as np
+
+from .earth import grav
+from .constants import db2Pascal
+from ..utilities import match_args_return
+from .density_enthalpy_48 import rho_alpha_beta
+
+__all__ = ['IPV_vs_fNsquared_ratio',
+ 'Nsquared',
+ 'Turner_Rsubrho']
+
+
+#FIXME: @match_args_return
+def IPV_vs_fNsquared_ratio(SA, CT, p, p_ref=0):
+ r"""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).
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+ p_ref : int, float, optional
+ reference pressure, default = 0
+
+ Returns
+ -------
+ IPV_vs_fNsquared_ratio : array_like
+ The ratio of the vertical gradient of potential density,
+ on the same (M-1)xN grid as p_mid. [unitless]
+ referenced to p_ref, to the vertical gradient of locally-
+ referenced potential density.
+
+ p_mid : array_like
+ Mid pressure between p grid [dbar]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ 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 "infunnel(SA, CT, p)" is
+ available to be used if one wants to test if some of one's data lies
+ outside this "funnel".
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Eqn. (3.20.5).
+
+ ..[2] 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.
+
+ Modifications:
+ 2011-03-23. Trevor McDougall & Paul Barker
+ """
+ p_ref = np.unique(np.asanyarray(p_ref))
+
+ # BUG
+ #if not np.isscalar(p_ref):
+ #raise ValueError('The reference pressure p_ref must be unique')
+
+ if SA.ndim == 1:
+ raise ValueError('There must be at least 2 columns.')
+
+ SA = np.maximum(SA, 0)
+
+ SA, CT, p, p_ref = np.broadcast_arrays(SA, CT, p, p_ref)
+
+ p_ref = p_ref[:-1, ...]
+
+ p_mid = 0.5 * (p[0:-1, ...] + p[1:, ...])
+ SA_mid = 0.5 * (SA[0:-1, ...] + SA[1:, ...])
+ CT_mid = 0.5 * (CT[0:-1, ...] + CT[1:, ...])
+
+ dSA = SA[0:-1, ...] - SA[1:, ...]
+ dCT = CT[0:-1, ...] - CT[1:, ...]
+
+ [dummy, alpha, beta] = rho_alpha_beta(SA_mid, CT_mid, p_mid)
+
+ _, alpha, beta = rho_alpha_beta(SA_mid, CT_mid, p_mid)
+ _, alpha_pref, beta_pref = 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 = pt_from_CT(SA_mid, CT_mid)
+ pr0 = np.zeros_like(SA_mid)
+ t_mid = pt_from_t(SA_mid, pt_mid, pr0, p_mid)
+ beta = beta_const_CT_t_exact(SA_mid, t_mid, p_mid)
+ alpha = alpha_wrt_CT_t_exact(SA_mid, t_mid, p_mid)
+ beta_pref = beta_const_CT_t_exact(SA_mid, t_mid, p_ref)
+ alpha_pref = alpha_wrt_CT_t_exact(SA_mid, t_mid, p_ref)
+ """
+
+ numerator = dCT * alpha_pref - dSA * beta_pref
+ denominator = dCT * alpha - dSA * beta
+
+ """IPV_vs_fNsquared_ratio = np.zeros_like(SA_mid) * np.NaN
+ I = denominator != 0.
+ IPV_vs_fNsquared_ratio[I] = numerator[I] / denominator[I]"""
+
+ IPV_vs_fNsquared_ratio = numerator / denominator
+
+ return IPV_vs_fNsquared_ratio, p_mid
+
+
+## In the following, we are assuming the p dimension comes
+# first. This follows the matlab code, (Fortran order)
+# but is unnatural in Python (C order).
+# We might need to deal with this in a better way.
+
+ at match_args_return
+def Nsquared(SA, CT, p, lat=None):
+ r"""Calculates the buoyancy frequency squared (N^2)
+ (i.e. the Brunt-Väisälä frequency squared) at the
+ mid pressure from the equation::
+
+ 2 2 beta.d(SA) - alpha.d(CT)
+ N = g rho_local ------------------------
+ dP
+
+ dP in the above formula is in Pascals
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+ lat : array_like, optional
+ latitude in decimal degrees north [-90..+90]
+ If lat is not supplied, a default gravitational acceleration of
+ 9.7963 m/s^2 (Griffies, 2004) will be used.
+
+ Returns
+ -------
+ N2 : array_like
+ Brunt-Väisälä frequency squared [1 s :math:`-2`]
+ p_mid : array_like
+ Mid pressure between p grid [dbar]
+
+ Notes
+ -----
+ This routine uses rho from the computationally efficient 48-term expression
+ for density in terms of SA, CT and p.
+
+ The 48-term equation has been fitted in a restricted range of parameter
+ space, and is most accurate inside the "oceanographic funnel" described in
+ IOC et al. (2010). The GSW library function "infunnel(SA, CT, p)" is
+ available to be used if one wants to test if some of one's data lies
+ outside this "funnel".
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See section 3.10 and Eqn. (3.10.2).
+
+ ..[2] Griffies, S. M., 2004: Fundamentals of Ocean Climate Models.
+ Princeton, NJ: Princeton University Press, 518 pp + xxxiv.
+
+ Modifications:
+ 2013-04-29. Trevor McDougall & Paul Barker
+ """
+
+ if lat is not None:
+ g = grav(lat, p)
+ SA, CT, p, g = np.broadcast_arrays(SA, CT, p, g)
+ else:
+ g = 9.7963 # Standard value from Griffies (2004).
+ SA, CT, p = np.broadcast_arrays(SA, CT, p)
+
+ ishallow = (slice(0, -1), Ellipsis)
+ ideep = (slice(1, None), Ellipsis)
+
+ def mid(x):
+ return 0.5 * (x[ideep] + x[ishallow])
+
+ def delta(x):
+ return x[ideep] - x[ishallow]
+
+ vars = SA, CT, p
+ SA_mid, CT_mid, p_mid = [mid(x) for x in vars]
+ dSA, dCT, dp = [delta(x) for x in vars]
+
+ rho_mid, alpha_mid, beta_mid = rho_alpha_beta(SA_mid, CT_mid, p_mid)
+
+ if lat is not None:
+ grav_mid = mid(g)
+ else:
+ grav_mid = g
+
+ N2 = (grav_mid ** 2 / db2Pascal) * (rho_mid / dp)
+ N2 *= (beta_mid * dSA - alpha_mid * dCT)
+
+ return N2, p_mid
+
+
+#FIXME: @match_args_return
+def Turner_Rsubrho(SA, CT, p):
+ r"""Calculates the Turner angle and the Rsubrho as a function of pressure
+ down a vertical water column. These quantities express the relative
+ contributions of the vertical gradients of Conservative Temperature and
+ Absolute Salinity to the vertical stability (the square of the
+ Brunt-Väisälä 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 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.
+
+ Parameters
+ ----------
+ SA : array_like
+ Absolute Salinity [g/kg]
+ CT : array_like
+ Conservative Temperature [:math:`^\circ` C (ITS-90)]
+ p : array_like
+ sea pressure [dbar]
+
+ Returns
+ -------
+ Tu : array_like
+ Turner angle, on the same (M-1)xN grid as p_mid. [degrees of rotation]
+ Rsubrho : array_like
+ Stability Ratio, on the same (M-1)xN grid as p_mid. [unitless]
+ p_mid : array_like
+ Mid pressure between p grid [dbar]
+
+ See Also
+ --------
+ TODO
+
+ Notes
+ -----
+ 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 "infunnel(SA, CT, p)" is
+ available to be used if one wants to test if some of one's data lies
+ outside this "funnel".
+
+ Examples
+ --------
+ TODO
+
+ References
+ ----------
+ .. [1] 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. See Eqns. (3.15.1) and (3.16.1).
+
+ ..[2] 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.
+
+ Modifications:
+ 2011-03-26. Trevor McDougall & Paul Barker
+ """
+
+ if SA.ndim == 1:
+ raise ValueError('There must be at least 2 columns.')
+
+ SA = np.maximum(SA, 0)
+
+ SA, CT, p = np.broadcast_arrays(SA, CT, p)
+
+ p_mid = 0.5 * (p[0:-1, ...] + p[1:, ...])
+ SA_mid = 0.5 * (SA[0:-1, ...] + SA[1:, ...])
+ CT_mid = 0.5 * (CT[0:-1, ...] + CT[1:, ...])
+
+ dSA = SA[0:-1, ...] - SA[1:, ...]
+ dCT = CT[0:-1, ...] - CT[1:, ...]
+
+ [dummy, alpha, beta] = rho_alpha_beta(SA_mid, CT_mid, p_mid)
+
+ """This function evaluates Tu and Rsubrho using the computationally
+ efficient 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 = pt_from_CT(SA_mid, CT_mid)
+ pr0 = np.zeros_like(SA_mid)
+ t_mid = pt_from_t(SA_mid, pt_mid, pr0, p_mid)
+ beta = beta_const_CT_t_exact(SA_mid, t_mid, p_mid)
+ alpha = alpha_wrt_CT_t_exact(SA_mid, t_mid, p_mid)
+ """
+
+ Tu = np.arctan2((alpha * dCT + beta * dSA), (alpha * dCT - beta * dSA))
+
+ Tu = Tu * (180 / np.pi)
+
+ Rsubrho = np.zeros_like(dSA) + np.NaN
+
+ Inz = dSA != 0
+ Rsubrho[Inz] = (alpha[Inz] * dCT[Inz]) / (beta[Inz] * dSA[Inz])
+
+ return Tu, Rsubrho, p_mid
+
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/gsw/test/__init__.py b/gsw/test/__init__.py
new file mode 100644
index 0000000..026fed5
--- /dev/null
+++ b/gsw/test/__init__.py
@@ -0,0 +1 @@
+# dummy--just to make it a sub-package
diff --git a/gsw/test/check_functions.py b/gsw/test/check_functions.py
new file mode 100644
index 0000000..3cc6d88
--- /dev/null
+++ b/gsw/test/check_functions.py
@@ -0,0 +1,194 @@
+import os
+import sys
+import logging
+
+import numpy as np
+
+
+import gsw
+from gsw.gibbs import *
+from gsw.utilities import Bunch
+
+log = logging.getLogger()
+logging.basicConfig()
+
+try:
+ mfiledir = sys.argv[1]
+except IndexError:
+ mfiledir = "../../../../TEOS-10/matlab_gsw_V3_03"
+
+mfile = os.path.join(mfiledir, "gsw_check_functions.m")
+mfilelines = open(mfile, 'rt').readlines()
+
+
+def find(x):
+ """
+ Numpy equivalent to Matlab find.
+ """
+ return np.nonzero(x.flatten())[0]
+
+
+first_pass = []
+
+concat = False
+for line in mfilelines:
+ line = line.strip()
+ if concat:
+ if line.endswith('...'):
+ line = line[:-3]
+ first_pass[-1] += line
+ if line.endswith(';'):
+ concat = False
+ continue
+ if '=' in line and (line.startswith('gsw_') or line.startswith('[gsw_')):
+ if line.endswith('...'):
+ line = line[:-3]
+ concat = True
+ first_pass.append(line)
+
+second_pass = []
+
+for line in first_pass:
+ if not '(' in line:
+ continue
+ if 'which' in line:
+ continue
+ line = line.replace('gsw_', '')
+ if line.startswith('['):
+ line = line[1:].replace(']', '')
+ if line.endswith(';'):
+ line = line[:-1]
+ line = line.replace('(I)', '') # For deltaSA_atlas.
+ second_pass.append(line)
+
+pairs = []
+
+for i in range(len(second_pass)):
+ if 'find(' in second_pass[i] and not 'find(' in second_pass[i-1]:
+ pairs.extend(second_pass[i-1:i+1])
+
+
+def group_or(line):
+ """
+ Numpy wart: using bitwise or as a fake elementwise logical or,
+ we need to add parentheses.
+ """
+ if not ('find(' in line and '|' in line):
+ return line
+ i0 = line.index('find(') + 5
+ head = line[:i0]
+ tail = line[i0:]
+ parts = tail.replace('|', ') | (')
+ new = head + '(' + parts + ')'
+ return new
+
+final = [group_or(line) for line in pairs]
+
+
+class FunctionCheck(object):
+ def __init__(self, linepair):
+ self.linepair = linepair
+ self.runline = linepair[0]
+ self.testline = linepair[1]
+
+ # parse the line that runs the function
+ head, tail = self.runline.split('=')
+ self.outstrings = [s.strip() for s in head.split(',')]
+ self.outstr = ','.join(self.outstrings)
+ funcstr, argpart = tail.split('(', 1)
+ self.name = funcstr.strip()
+ self.argstrings = [s.strip() for s in argpart[:-1].split(',')]
+ self.argstr = ','.join(self.argstrings)
+
+ # parse the line that checks the results
+ head, tail = self.testline.split('=', 1)
+ self.resultstr = head.strip() # cv.I*
+ head, tail = tail.split('(', 1)
+ self.teststr = tail.strip()[:-1] # argument of "find()"
+
+ # To be set when run() is successful
+ self.outlist = None
+ self.result = None # will be a reference to the cv.I* array
+ self.passed = None # will be set to True or False
+
+ # To be set if run() is not successful
+ self.exception = None
+
+ def __str__(self):
+ return self.runline
+
+ def run(self):
+ try:
+ exec(self.runline)
+ # In Matlab, the number of output arguments varies
+ # depending on the LHS of the assignment, but Python
+ # always returns the full set. Here we handle the
+ # case where Python is returning 2 (or more) but
+ # the LHS is assigning only the first.
+ if len(self.outstrings) == 1:
+ if isinstance(eval(self.outstr), tuple):
+ exec("%s = %s[0]" % (self.outstr, self.outstr))
+ self.outlist = [eval(s) for s in self.outstrings]
+ exec(self.testline)
+ self.result = eval(self.resultstr)
+ self.passed = len(self.result) == 0
+
+ except Exception as e:
+ self.exception = e
+
+checks = []
+for i in range(0, len(final), 2):
+ pair = final[i:i+2]
+ checks.append(FunctionCheck(pair))
+
+
+datadir = os.path.join(os.path.dirname(gsw.utilities.__file__), 'data')
+cv = Bunch(np.load(os.path.join(datadir, 'gsw_cv_v3_0.npz')))
+cf = Bunch()
+
+for fc in checks:
+ fc.run()
+
+passes = [f.name for f in checks if f.passed]
+failures = [f.name for f in checks if f.passed is False]
+
+run_problems = [f.name for f in checks if f.exception is not None]
+
+etypes = [NameError, UnboundLocalError, TypeError, AttributeError]
+ex_dict = dict()
+for exc in etypes:
+ elist = [(f.name, f.exception) for f in checks if
+ isinstance(f.exception, exc)]
+ ex_dict[exc] = elist
+
+print "\n%s tests were translated from gsw_check_functions.m" % len(checks)
+print "\n%s tests ran with no error and with correct output" % len(passes)
+print "\n%s tests had an output mismatch:" % len(failures)
+print " ", "\n ".join(failures)
+
+print "\n%s exceptions were raised as follows:" % len(run_problems)
+for exc in etypes:
+ print " ", exc.__name__
+ strings = [" %s : %s" % e for e in ex_dict[exc]]
+ print "\n".join(strings)
+ print ""
+
+checkbunch = Bunch([(c.name, c) for c in checks])
+
+
+def find_arguments():
+ argset = set()
+ for c in checks:
+ argset.update(c.argstrings)
+ argsetlist = list(argset)
+ argsetlist.sort()
+ return argsetlist
+
+
+def find_arglists():
+ alset = set()
+ for c in checks:
+ alset.update([c.argstr])
+ arglists = list(alset)
+ arglists.sort()
+ return arglists
diff --git a/gsw/test/signatures.py b/gsw/test/signatures.py
new file mode 100644
index 0000000..fddcdb1
--- /dev/null
+++ b/gsw/test/signatures.py
@@ -0,0 +1,178 @@
+"""
+Functions for parsing gsw mfiles.
+
+These might become useful in a scheme for automating docstring
+generation.
+"""
+
+import os
+import sys
+import glob
+from collections import OrderedDict
+
+import logging
+
+from gsw.gibbs import *
+
+log = logging.getLogger()
+logging.basicConfig()
+
+try:
+ mfiledir = sys.argv[1]
+except IndexError:
+ mfiledir = "../../../../TEOS-10/matlab_gsw_V3_03"
+
+subdirs = ['./', 'library', 'thermodynamics_from_t']
+
+mfile = os.path.join(mfiledir, "gsw_check_functions.m")
+mfilelines = open(mfile, 'rt').readlines()
+
+
+def funcline_parts(base, topline):
+ """
+ Parse the m-file function declaration.
+
+ Returns [base, arguments, outputs] where base is the
+ function name without the gsw_ prefix, arguments is a
+ tuple of strings, and outputs is a tuple of strings.
+ """
+
+ cmd = topline.split(None, 1)[1]
+
+ parts = cmd.split('=')
+ if len(parts) == 1:
+ out = ''
+ func_call = parts[0].strip()
+ else:
+ out = parts[0].strip()
+ if out.startswith('['):
+ out = out[1:-1]
+ func_call = parts[1].strip()
+ out = [a.strip() for a in out.split(',')]
+
+ parts = func_call.split('(')
+ if len(parts) == 1:
+ argstring = ''
+ else:
+ argstring = parts[1][:-1]
+
+ args = [a.strip() for a in argstring.split(',')]
+
+ parts = [base[4:], tuple(args), tuple(out)]
+ return parts
+
+help_sections = ['USAGE:',
+ 'DESCRIPTION:',
+ 'INPUT:',
+ 'OPTIONAL:',
+ 'OUTPUT:',
+ 'AUTHOR:',
+ 'VERSION NUMBER:',
+ 'REFERENCES:',
+ ]
+
+
+def helptext_parts(lines):
+ """
+ Parse the help text from gsw m-files.
+
+ Returns [lines, indexdict], where lines are the lines of
+ text with extraneous material removed, and indexdict is
+ a dictionary in which the keys are the help sections and
+ the values are the indices into lines where the section
+ titles are found.
+ """
+ helplines = []
+ parts = OrderedDict()
+ for line in lines[2:]:
+ line = line.rstrip()
+ if line.startswith('%'):
+ if line.endswith('=========================='):
+ continue
+ helplines.append(line[1:])
+ else:
+ break
+ for i, line in enumerate(helplines):
+ for section in help_sections:
+ if section in line:
+ parts[section] = i
+
+ return helplines, parts
+
+
+def function_parts(subdir='./'):
+ """
+ Parse the gsw m-files in a given subdirectory.
+
+ Returns a list of parts: function base name, arguments,
+ inputs, and the help lines with a section index dictionary.
+ """
+
+ d = os.path.join(mfiledir, subdir)
+ mfilelist = glob.glob(os.path.join(d, '*.m'))
+ partslist = []
+ for fpath in mfilelist:
+ base = os.path.basename(fpath)[:-2]
+ if not base.startswith('gsw_') or base == 'gsw_check_functions':
+ continue
+ lines = open(fpath).readlines()
+ topline = lines[0].strip()
+ if not topline.startswith('function'):
+ log.warn("path %s, topline is\n%s", fpath, topline)
+ continue
+
+ parts = funcline_parts(base, topline)
+
+ parts.append(helptext_parts(lines))
+
+ partslist.append(parts)
+
+ return partslist
+
+
+def arguments(partslist):
+ args = set()
+ for entry in partslist:
+ args.update(entry[1])
+
+ arglist = list(args)
+ arglist.sort()
+ return arglist
+
+
+def arglists(partslist):
+ args = set()
+ for entry in partslist:
+ args.update([', '.join(entry[1])])
+
+ arglist = list(args)
+ arglist.sort()
+ return arglist
+
+
+def funclist_by_arg(partslist):
+ out = dict()
+ for entry in partslist:
+ if entry[1] not in out:
+ out[entry[1]] = []
+ out[entry[1]].append(entry[0])
+ return out
+
+
+def help_chunk(helptuple, sect):
+ lines, secdict = helptuple
+ sections = secdict.keys()
+ ind = secdict.values()
+ try:
+ i0 = sections.index(sect)
+ except ValueError:
+ return [] # or None?
+ # Assuming the sections are always in the expected order, this will
+ # work; otherwise we would have to look for the nearest section index
+ # after the one found.
+ return lines[ind[i0]:ind[i0 + 1]]
+
+
+def funcs_with_descriptions(partslist):
+ fdlist = [(p[0], help_chunk(p[3], 'DESCRIPTION:')) for p in partslist]
+ return OrderedDict(fdlist)
diff --git a/gsw/test/test_check_values.py b/gsw/test/test_check_values.py
new file mode 100644
index 0000000..564eaaf
--- /dev/null
+++ b/gsw/test/test_check_values.py
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+
+"""Unit tests using the check values from the version 3 documentation,
+http://www.teos-10.org/pubs/gsw/html/gsw_contents.html."""
+
+import sys
+import unittest
+import numpy as np
+import numpy.testing
+
+import gsw
+
+# Standard values for arguments from
+# http://www.teos-10.org/pubs/gsw/html/gsw_contents.html
+C = [34.5487, 34.7275, 34.8605, 34.6810, 34.5680, 34.5600]
+t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+p = [10, 50, 125, 250, 600, 1000]
+
+# Salinities
+#SP = [34.5487, 34.7275, 34.8605, 34.6810, 34.5680, 34.5600]
+#SA = [34.7118, 34.8915, 35.0256, 34.8472, 34.7366, 34.7324]
+#Sstar = [34.7115, 34.8912, 35.0247, 34.8436, 34.7291, 34.7197]
+
+# Temperatures
+#t = [28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]
+#pt = [28.7832, 28.4209, 22.7850, 10.2305, 6.8292, 4.3245]
+#CT = [28.8099, 28.4392, 22.7862, 10.2262, 6.8272, 4.3236]
+#t48 = [29, 28, 23, 10, 7, 4]
+#t68 = [29, 28, 23, 10, 7, 4]
+
+# Other
+#p = [10, 50, 125, 250, 600, 1000]
+#z = [10, 50, 125, 250, 600, 1000]
+#rho = [1021.839, 1022.262, 1024.426, 1027.792, 1029.839, 1032.002]
+#entropy = [400.3892, 395.4378, 319.8668, 146.7910, 98.6471, 62.7919]
+#lon = 188
+#lat = 4
+
+
+class Test_standard(unittest.TestCase):
+#class Test_standard(numpy.testing.TestCase):
+
+ # ----------------------
+ # practical_salinity.py
+ # ----------------------
+
+ def test_SP_from_C(self):
+ """Practical Salinity from Conductivity"""
+ output = gsw.SP_from_C(C, t, p)
+ check_values = np.array((20.009869599086951,
+ 20.265511864874270,
+ 22.981513062527689,
+ 31.204503263727982,
+ 34.032315787432829,
+ 36.400308494388170))
+ numpy.testing.assert_array_equal(output, check_values)
+
+# -----------------------------------------------
+if __name__ == '__main__':
+ # Verbose output.
+ suite = unittest.TestLoader().loadTestsFromTestCase(Test_standard)
+ a = unittest.TextTestRunner(verbosity=2).run(suite)
+ if a.errors or a.failures:
+ sys.exit(1)
+ #unittest.main()
+ #numpy.testing.test()
diff --git a/gsw/test/test_octave.py b/gsw/test/test_octave.py
new file mode 100644
index 0000000..442996a
--- /dev/null
+++ b/gsw/test/test_octave.py
@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+#
+# test_octave.py
+#
+# purpose: Quick "compare test" with octave results.
+# author: Filipe P. A. Fernandes
+# e-mail: ocefpaf at gmail
+# web: http://ocefpaf.tiddlyspot.com/
+# created: 13-Jun-2013
+# modified: Tue 02 Jul 2013 07:45:17 PM BRT
+#
+# obs: This is different from `test_check_values.py`, that tests
+# against the results in the docs, `test_octave.py` uses same input values to
+# run both python and Matlab versions (using Octave).
+#
+# This is not a thorough test, just an "ad hoc" test to compare when a new
+# Matlab version is released.
+#
+
+import os
+import sys
+from collections import OrderedDict
+
+import numpy as np
+
+from oct2py import octave
+from oct2py._utils import Oct2PyError
+
+import gsw
+
+try:
+ path = sys.argv[1]
+except IndexError:
+ path = "./matlab_gsw_v3_03"
+
+
+# We have to supply a fake superiorfloat function for octave.
+# We are writing it in the local directory, which is not a nice
+# thing to do; maybe this can be improved later.
+
+_sfloat = """function out = superiorfloat(varargin)
+out = 'double';
+"""
+open('superiorfloat.m', 'wt').write(_sfloat)
+
+
+if not os.path.exists(path):
+ raise ValueError("matlab gsw path %s not found" % path)
+
+_ = octave.addpath(octave.genpath(path))
+_ = octave.addpath('./')
+
+
+def compare_results(name, function, args):
+ args = [values.get(arg) for arg in args]
+ print(name)
+
+ try: # Python.
+ res = function(*args)
+ except:
+ print('%s: python runtime error' % name)
+ raise
+ return 'no_python'
+
+ nout = 1
+ if isinstance(res, tuple):
+ nout = len(res)
+ res = res[0]
+
+ try: # Octave.
+ val = octave.call('gsw_%s' % name, *args, verbose=True, nout=nout)
+ if nout > 1:
+ val = val[0]
+ except Oct2PyError:
+ print('%s: Octave runtime error' % name)
+ print("python:\n%s" % res)
+ return 'no_octave'
+
+ try:
+ val = val.flatten()
+ perfect = (val == res).all()
+ except:
+ print('%s: Comparison failed' % name)
+ print("octave:\n%s" % val)
+ print("python:\n%s" % res)
+ return 'no_comparison'
+ if np.allclose(val, res, rtol=1e-15, atol=0):
+ print('%s: Passed' % name)
+ return 'passed'
+ else:
+ print('%s: Failed' % name)
+ print("octave:\n%s" % val)
+ print("python:\n%s" % res)
+ return 'failed'
+ print('')
+
+values = dict(C=np.array([34.5487, 34.7275, 34.8605, 34.6810, 34.568, 34.56]),
+ t=np.array([28.7856, 28.4329, 22.8103, 10.2600, 6.8863, 4.4036]),
+ p=np.array([10., 50., 125., 250., 600., 1000.]),
+ SP=np.array([34.5487, 34.7275, 34.8605, 34.6810, 34.5680,
+ 34.5600]),
+ SA=np.array([34.7118, 34.8915, 35.0256, 34.8472, 34.7366,
+ 34.7324]),
+ CT=np.array([28.7856, 28.4329, 22.8103, 10.2600, 6.8863,
+ 4.4036]),
+ rho=np.array([1021.8484, 1022.2647, 1024.4207, 1027.7841,
+ 1029.8287, 1031.9916]),
+ ps=0, pt=0, pp=0,
+ lat=np.array([4., 4., 4., 4., 4., 4.]),
+ lon=np.array([188., 188., 188., 188., 188., 188.]),
+ pt0=np.array([28.8099, 28.4392, 22.7862, 10.2262, 6.8272,
+ 4.3236]),
+ spycnl=np.array([21.8482, 22.2647, 24.4207, 27.7841, 29.8287,
+ 31.9916]),
+ A='gn', # or s2 for sigma2; but then spycnl would need to change
+ # Also, the matlab code is incorrect for the s2 case.
+ p_i=np.array([500.0, 600.0, 700.0]),
+ # Baltic.
+ SAb=np.array([6.6699, 6.7738, 6.9130, 7.3661, 7.5862, 10.3895]),
+ SPb=np.array([6.5683, 6.6719, 6.8108, 7.2629, 7.4825, 10.2796]),
+ latb=np.array([59., 59., 59., 59., 59., 59.]),
+ lonb=np.array([20., 20., 20., 20., 20., 20.])
+ )
+# Functions.
+library = OrderedDict({
+ # library.py
+ 'deltaSA_atlas': (gsw.library.deltaSA_atlas, ('p', 'lon', 'lat')),
+ 'enthalpy_SSO_0_p': (gsw.library.enthalpy_SSO_0_p, ('p')),
+ 'entropy_part': (gsw.library.entropy_part, ('SA', 't', 'p')),
+ 'entropy_part_zerop': (gsw.library.entropy_part_zerop, ('SA', 'pt0')),
+ 'Fdelta': (gsw.library.Fdelta, ('p', 'lon', 'lat')),
+ 'gibbs': (gsw.library.gibbs, ('ps', 'pt', 'pp', 'SA', 't', 'p')),
+ 'gibbs_pt0_pt0': (gsw.library.gibbs_pt0_pt0, ('SA', 'pt0')),
+ 'Hill_ratio_at_SP2': (gsw.library.Hill_ratio_at_SP2, ('t')),
+ 'infunnel': (gsw.library.infunnel, ('SA', 'CT', 'p')),
+ # FIXME: There is a problem with the argument handling in interp_SA_CT.
+ 'interp_ref_cast': (gsw.library.interp_ref_cast, ('spycnl', 'A')),
+ 'interp_SA_CT': (gsw.library.interp_SA_CT, ('SA', 'CT', 'p', 'p_i')),
+ 'SAAR': (gsw.library.SAAR, ('p', 'lon', 'lat')),
+ 'SA_from_SP_Baltic': (gsw.library.SA_from_SP_Baltic, ('SPb', 'lonb',
+ 'latb')),
+ 'specvol_SSO_0_p': (gsw.library.specvol_SSO_0_p, ('p')),
+ 'SP_from_SA_Baltic': (gsw.library.SP_from_SA_Baltic, ('SAb', 'lonb',
+ 'latb')),
+ # thermodynamics_from_t.py
+ #'adiabatic_lapse_rate_from_t': (gsw.adiabatic_lapse_rate_from_t,
+ #('SA', 't', 'p')),
+ 'alpha_wrt_CT_t_exact': (gsw.alpha_wrt_CT_t_exact, ('SA', 't', 'p')),
+ 'alpha_wrt_pt_t_exact': (gsw.alpha_wrt_pt_t_exact, ('SA', 't', 'p')),
+ 'alpha_wrt_t_exact': (gsw.alpha_wrt_t_exact, ('SA', 't', 'p')),
+ 'beta_const_CT_t_exact': (gsw.beta_const_CT_t_exact, ('SA', 't', 'p')),
+ 'beta_const_pt_t_exact': (gsw.beta_const_pt_t_exact, ('SA', 't', 'p')),
+ 'beta_const_t_exact': (gsw.beta_const_t_exact, ('SA', 't', 'p')),
+ 'chem_potential_relative_t_exact': (gsw.chem_potential_relative_t_exact,
+ ('SA', 't', 'p')),
+ 'chem_potential_salt_t_exact': (gsw.chem_potential_salt_t_exact,
+ ('SA', 't', 'p')),
+ 'chem_potential_water_t_exact': (gsw.chem_potential_water_t_exact,
+ ('SA', 't', 'p')),
+ 'cp_t_exact': (gsw.cp_t_exact, ('SA', 't', 'p')),
+ #'deltaSA_from_rho_t_exact': (gsw.deltaSA_from_rho_t_exact,
+ #('rho', 'SP', 't', 'p')),
+ 'dynamic_enthalpy_t_exact': (gsw.dynamic_enthalpy_t_exact,
+ ('SA', 't', 'p')),
+ 'enthalpy_t_exact': (gsw.enthalpy_t_exact, ('SA', 't', 'p')),
+ 'entropy_t_exact': (gsw.entropy_t_exact, ('SA', 't', 'p')),
+ 'Helmholtz_energy_t_exact': (gsw.Helmholtz_energy_t_exact,
+ ('SA', 't', 'p')),
+ 'internal_energy_t_exact': (gsw.internal_energy_t_exact, ('SA', 't', 'p')),
+ 'isochoric_heat_cap_t_exact': (gsw.isochoric_heat_cap_t_exact,
+ ('SA', 't', 'p')),
+ 'kappa_const_t_exact': (gsw.kappa_const_t_exact, ('SA', 't', 'p')),
+ 'kappa_t_exact': (gsw.kappa_t_exact, ('SA', 't', 'p')),
+ 'osmotic_coefficient_t_exact': (gsw.osmotic_coefficient_t_exact,
+ ('SA', 't', 'p')),
+ 'osmotic_pressure_t_exact': (gsw.osmotic_pressure_t_exact,
+ ('SA', 't', 'pw')),
+ 'pot_rho_t_exact': (gsw.pot_rho_t_exact, ('SA', 't', 'p', 'p_ref')),
+ 'rho_t_exact': (gsw.rho_t_exact, ('SA', 't', 'p')),
+ 'SA_from_rho_t_exact': (gsw.SA_from_rho_t_exact, ('rho', 't', 'p')),
+ #'SA_from_rho_t': (gsw.SA_from_rho_t, ('rho', 't', 'p')),
+ 'sigma0_pt0_exact': (gsw.sigma0_pt0_exact, ('SA', 'pt0')),
+ 'sound_speed_t_exact': (gsw.sound_speed_t_exact, ('SA', 't', 'p')),
+ 'specvol_anom_t_exact': (gsw.specvol_anom_t_exact, ('SA', 't', 'p')),
+ 'specvol_t_exact': (gsw.specvol_t_exact, ('SA', 't', 'p')),
+ 't_from_rho_exact': (gsw.t_from_rho_exact, ('rho', 'SA', 'p')),
+ 't_maxdensity_exact': (gsw.t_maxdensity_exact, ('SA', 'p')),
+ # absolute_salinity_sstar_ct.py
+ 'SA_from_SP': (gsw.SA_from_SP, ('SP', 'p', 'lon', 'lat'))})
+
+
+if __name__ == '__main__':
+ outcomes = ['passed', 'no_octave', 'no_python', 'failed', 'no_comparison']
+ results = dict([(k, list()) for k in outcomes])
+
+ for name, (function, args) in library.iteritems():
+ ret = compare_results(name=name, function=function, args=args)
+ results[ret].append(name)
+
+ #os.remove('superiorfloat.m')
+
+ print('\nSummary:')
+ print('passed:\n %s' % '\n '.join(results['passed']))
+ print('octave call failed:\n %s' % '\n '.join(results['no_octave']))
+ print('python call failed:\n %s' % '\n '.join(results['no_python']))
+ print('results did not match:\n %s' % '\n '.join(results['failed']))
+ print('comparison failed:\n %s' % '\n '.join(results['no_comparison']))
+ print('')
diff --git a/gsw/test/test_profiles.py b/gsw/test/test_profiles.py
new file mode 100644
index 0000000..62acae9
--- /dev/null
+++ b/gsw/test/test_profiles.py
@@ -0,0 +1,339 @@
+# -*- coding: utf-8 -*-
+
+"""Unit check for standard profiles for the Gibbs Sea Water python package."""
+
+# Auto generates and perform a set of test methods like:
+#
+# def test_funct(self):
+# out = gsw.func(arg1_chck_cast, arg2_chck_cast, ...)
+# maxdiff = np.nanmax(abs(out - cv.func)
+# self.assertTrue(maxdiff < cv.func_ca)
+#
+# cv is a Bunch instance with all the check values from
+# the profile-file
+# The func, args are taken from the main dictionary below
+# giving a alphabetical table of all functions and their arguments
+#
+# Extra aliasing attributes are added to cv if the naming
+# convention is broken, if the targets or the attributes
+# in the check file has "wrong" names
+#
+
+
+# Bjørn Ådlandsvik <bjorn at imr.no>
+# 2011-03-03
+
+import os
+import unittest
+import functools # Requires python 2.5.
+import numpy as np
+
+import gsw
+from gsw.utilities import Bunch
+
+
+# Read data file with check value profiles.
+datadir = os.path.join(os.path.dirname(gsw.utilities.__file__), 'data')
+cv = Bunch(np.load(os.path.join(datadir, 'gsw_cv_v3_0.npz')))
+cf = Bunch(np.load(os.path.join(datadir, 'gsw_cf.npz')))
+
+# Main dictionary of functions with arguments. Could perhaps be auto-generated.
+function_arguments = dict(
+ # absolute_salinity_sstar_ct.py
+ SA_from_SP=('SP', 'p', 'long', 'lat'), # uses SAAR
+ #Sstar_from_SP TODO
+ CT_from_t=('SA', 't', 'p'),
+ #
+ # thermodynamics_from_t.py
+ rho_t_exact=('SA', 't', 'p'),
+ pot_rho_t_exact=('SA', 't', 'p', 'pr'),
+ sigma0_pt0_exact=('SA', 'pt0'),
+ alpha_wrt_CT_t_exact=('SA', 't', 'p'),
+ alpha_wrt_pt_t_exact=('SA', 't', 'p'),
+ alpha_wrt_t_exact=('SA', 't', 'p'),
+ beta_const_CT_t_exact=('SA', 't', 'p'),
+ beta_const_pt_t_exact=('SA', 't', 'p'),
+ beta_const_t_exact=('SA', 't', 'p'),
+ specvol_t_exact=('SA', 't', 'p'),
+ specvol_anom_t_exact=('SA', 't', 'p'),
+ sound_speed_t_exact=('SA', 't', 'p'),
+ kappa_t_exact=('SA', 't', 'p'),
+ kappa_const_t_exact=('SA', 't', 'p'),
+ internal_energy_t_exact=('SA', 't', 'p'),
+ enthalpy_t_exact=('SA', 't', 'p'),
+ dynamic_enthalpy_t_exact=('SA', 't', 'p'),
+ SA_from_rho_t_exact=('rho', 't', 'p'),
+ #t_from_rho_exact=('rho', 'SA', 'p'),
+ t_maxdensity_exact=('SA', 'p'),
+ #entropy_t_exact=('SA', 't', 'p'), # Not in V3.03
+ cp_t_exact=('SA', 't', 'p'),
+ isochoric_heat_cap_t_exact=('SA', 't', 'p'),
+ chem_potential_relative_t_exact=('SA', 't', 'p'),
+ chem_potential_water_t_exact=('SA', 't', 'p'),
+ chem_potential_salt_t_exact=('SA', 't', 'p'),
+ Helmholtz_energy_t_exact=('SA', 't', 'p'),
+ # adiabatic_lapse_rate_t_exact=('SA', 't', 'p'), # Not in V3.03
+ osmotic_coefficient_t_exact=('SA', 't', 'p'),
+ osmotic_pressure_t_exact=('SA', 't', 'p'),
+ #
+ # conversion.py
+ #deltaSA_from_SP TODO
+ #SA_Sstar_from_SP TODO
+ SR_from_SP=('SP',),
+ SP_from_SR=('SR',),
+ #SP_from_SA=('SA', 'p', 'long', 'lat'), TODO
+ #Sstar_from_SA=('SA', 'p', 'long', 'lat'), TODO
+ #SA_from_Sstar=('Sstar', 'p', 'long', 'lat'), TODO
+ #SP_from_Sstar=('Sstar', 'p', 'long', 'lat'), TODO
+ pt_from_CT=('SA', 'CT'),
+ t_from_CT=('SA', 'CT', 'p'),
+ CT_from_pt=('SA', 'pt'),
+ pot_enthalpy_from_pt=('SA', 'pt'),
+ pt0_from_t=('SA', 't', 'p'),
+ pt_from_t=('SA', 't', 'p', 'pr'),
+ t90_from_t48=('t',),
+ t90_from_t68=('t',),
+ z_from_p=('p', 'lat'),
+ p_from_z=('z', 'lat'),
+ depth_from_z=('z'),
+ z_from_depth=('depth',),
+ Abs_Pressure_from_p=('p',),
+ p_from_Abs_Pressure=('Abs_Pressure_from_p',),
+ entropy_from_CT=('SA', 'CT'),
+ CT_from_entropy=('SA', 'entropy'),
+ entropy_from_pt=('SA', 'pt'),
+ pt_from_entropy=('SA', 'entropy'),
+ molality_from_SA=('SA',),
+ ionic_strength_from_SA=('SA',),
+ #
+ # density_enthalpy_48_ct.py
+ #rho_CT TODO
+ #alpha_CT TODO
+ #beta_CT TODO
+ #rho_alpha_beta_CT TODO
+ #specvol_CT TODO
+ #specvol_anom_CT TODO
+ #sigma0_CT TODO
+ #sigma1_CT TODO
+ #sigma2_CT TODO
+ #sigma3_CT TODO
+ #sigma4_CT TODO
+ #sound_speed_CT TODO
+ #internal_energy_CT TODO
+ #enthalpy_CT TODO
+ #enthalpy_diff_CT TODO
+ #dynamic_enthalpy_CT TODO
+ #SA_from_rho_CT TODO
+ #CT_from_rho TODO
+ #CT_maxdensity TODO
+ #
+ # density_enthalpy_48.py NOTE: None are tested on Matlab.
+ rho=('SA', 'CT', 'p'),
+ alpha=('SA', 'CT', 'p'),
+ beta=('SA', 'CT', 'p'),
+ rho_alpha_beta=('SA', 'CT', 'p'),
+ specvol=('SA', 'CT', 'p'),
+ specvol_anom=('SA', 'CT', 'p'),
+ sigma0=('SA', 'CT'),
+ sigma1=('SA', 'CT'),
+ sigma2=('SA', 'CT'),
+ sigma3=('SA', 'CT'),
+ sigma4=('SA', 'CT'),
+ sound_speed=('SA', 'CT', 'p'),
+ internal_energy=('SA', 'CT', 'p'),
+ enthalpy=('SA', 'CT', 'p'),
+ enthalpy_diff=('SA', 'CT', 'p_shallow', 'p_deep'),
+ dynamic_enthalpy=('SA', 'CT', 'p'),
+ SA_from_rho=('rho_cf', 'CT', 'p'),
+ #
+ # density_enthalpy_ct_exact.py
+ rho_CT_exact=('SA', 'CT', 'p'),
+ alpha_CT_exact=('SA', 'CT', 'p'),
+ beta_CT_exact=('SA', 'CT', 'p'),
+ rho_alpha_beta_CT_exact=('SA', 'CT', 'p'),
+ specvol_CT_exact=('SA', 'CT', 'p'),
+ specvol_anom_CT_exact=('SA', 'CT', 'p'),
+ sigma0_CT_exact=('SA', 'CT'),
+ sigma1_CT_exact=('SA', 'CT'),
+ sigma2_CT_exact=('SA', 'CT'),
+ sigma3_CT_exact=('SA', 'CT'),
+ sigma4_CT_exact=('SA', 'CT'),
+ sound_speed_CT_exact=('SA', 'CT', 'p'),
+ internal_energy_CT_exact=('SA', 'CT', 'p'),
+ enthalpy_CT_exact=('SA', 'CT', 'p'),
+ enthalpy_diff_CT_exact=('SA', 'CT', 'p_shallow', 'p_deep'),
+ dynamic_enthalpy_CT_exact=('SA', 'CT', 'p'),
+ SA_from_rho_CT_exact=('rho', 'CT', 'p'),
+ # FIXME: NameError: 't_from_rho_exact' not defined
+ #CT_from_rho_exact=('rho', 'SA', 'p'),
+ CT_maxdensity_exact=('SA', 'p'),
+ #
+ # derivatives.py
+ #CT_first_derivatives=('SA', 'pt'), FIXME: out should tuple.
+ #CT_second_derivatives=('SA', 'pt'), FIXME: out should tuple.
+ #enthalpy_first_derivatives=('SA', 'CT', 'p'), FIXME: out should tuple.
+ #enthalpy_second_derivatives=('SA', 'CT', 'p'), FIXME: out should tuple.
+ #entropy_first_derivatives=('SA', 'CT'), FIXME: out should tuple.
+ #entropy_second_derivatives=('SA', 'CT'), FIXME: out should tuple.
+ #pt_first_derivatives=('SA', 'CT'), FIXME: out should tuple.
+ #pt_second_derivatives=('SA', 'CT'), FIXME: out should tuple.
+ #
+ # earth.py
+ f=('lat',),
+ grav=('lat', 'p'),
+ distance=('long', 'lat', 'p'),
+ #
+ # freezing.py
+ # NOTE: The matlab test does not use saturation_fraction=1 which is the
+ # default! It uses saturation_fraction=0.
+ CT_freezing=('SA', 'p', 'sat0'),
+ t_freezing=('SA', 'p', 'sat0'),
+ brineSA_CT=('CT_freezing', 'p', 'sat05'),
+ brineSA_t=('t_freezing', 'p', 'sat05'),
+ #
+ # geostrophic.py
+ #geostrophic_velocity TODO
+ #
+ # geostrophic_48.py
+ #geo_strf_dyn_height TODO
+ #geo_strf_dyn_height_pc TODO
+ #geo_strf_isopycnal TODO
+ #geof_str_isopycnal_pc TODO
+ #geo_strf_Montgomery TODO
+ #geo_strf_Cunningham TODO
+ #
+ # isobaric.py
+ #latentheat_melting TODO
+ #latentheat_evap_CT TODO
+ #latentheat_evap_t=('SA', 't'),
+ #
+ # library.py
+ #gibbs
+ #SAAR=('p', 'long', 'lat'), # not directly tested on Matlab
+ Fdelta=('p', 'long', 'lat'),
+ deltaSA_atlas=('p', 'long', 'lat'),
+ #SA_from_SP_Baltic=('SP', 'long', 'lat'), NOTE: Not tested on Matlab.
+ #SP_from_SA_Baltic=('SA', 'long', 'lat'), NOTE: Not tested on Matlab.
+ #infunnel=('SA', 'CT', 'p'), NOTE: Not tested on Matlab.
+ #entropy_part=('SA', 'CT', 'p'), NOTE: Not tested on Matlab.
+ #entropy_part_zerop=('SA', 'pt0'), NOTE: Not tested on Matlab.
+ #interp_ref_cast=('spycnl', 'gn'), NOTE: Not tested on Matlab.
+ #interp_SA_CT=('SA', 'CT', 'p', 'p_i'), NOTE: Not tested on Matlab.
+ #gibbs_pt0_pt0=('SA', 'pt0'), NOTE: Not tested on Matlab.
+ #specvol_SSO_0_p=('p'), NOTE: Not tested on Matlab.
+ #enthalpy_SSO_0_p=('p',), FIXME: No enthalpy_SSO_0_p.
+ #Hill_ratio_at_SP2= ('t'), FIXME: No Hill_ratio_at_SP2.
+ #
+ #neutral_nonlinear_48.py
+ #cabbeling, TODO
+ #thermobaric, TODO
+ #isopycnal_slope_ratio, TODO
+ #isopycnal_vs_ntp_CT_ratio, TODO
+ #ntp_pt_vs_CT_ratio TODO
+ #
+ # practical_salinity.py
+ SP_from_C=('C', 't', 'p'),
+ C_from_SP=('SP', 't', 'p'),
+ SP_from_R=('R_cf', 't', 'p'),
+ R_from_SP=('SP', 't', 'p'),
+ SP_salinometer=('Rt', 't'),
+ #SP_from_SK=('SK',), NOTE: Not tested on Matlab.
+ #SK_from_SP=('SP',), NOTE: Not tested on Matlab.
+ #
+ # steric.py
+ #steric_height=TODO
+ #
+ # water_column_48.py
+ Nsquared=('SA', 'CT', 'p', 'lat'),
+ Turner_Rsubrho=('SA', 'CT', 'p'),
+ IPV_vs_fNsquared_ratio=('SA', 'CT', 'p'))
+
+
+# Make aliases for some values to be used as arguments
+cv.entropy_chck_cast = cv.entropy_from_CT
+cv.Abs_Pressure_from_p_chck_cast = cv.Abs_Pressure_from_p
+cv.depth_chck_cast = cv.depth_from_z
+cv.C_chck_cast = cv.C_from_SP
+cv.pt_chck_cast = cv.pt_from_t
+cv.z_chck_cast = cv.z_from_p
+cv.SR_chck_cast = cv.SR_from_SP
+cv.pr_chck_cast = cv.pr
+cv.p_shallow_chck_cast = cv.p_chck_cast_shallow
+cv.p_deep_chck_cast = cv.p_chck_cast_deep
+cv.rho_chck_cast = cv.rho_CT_exact
+cv.rho_CTrab_exact_ca = cv.rho_CT_exact_rab_ca
+cv.CT_freezing_chck_cast = cv.CT_freezing
+cv.t_freezing_chck_cast = cv.t_freezing
+cv.sat0_chck_cast = 0
+cv.sat05_chck_cast = 0.5
+
+# Aliases from computed values.
+cv.R_cf_chck_cast = cf.R
+cv.rho_cf_chck_cast = cf.rho
+cv.pt0_chck_cast = cf.pt0_from_t
+
+# Functions and targets which does not follow the naming convention.
+not_match = {
+ 'CT_first_derivatives': 'CT_SA',
+ 'CT_second_derivatives': 'CT_SA_SA',
+ 'enthalpy_first_derivatives': 'h_SA',
+ 'enthalpy_second_derivatives': 'h_SA_SA',
+ 'entropy_first_derivatives': 'eta_SA',
+ 'entropy_second_derivatives': 'eta_SA_SA',
+ 'pt_first_derivatives': 'pt_SA',
+ 'pt_second_derivatives': 'pt_SA_SA',
+ 'Turner_Rsubrho': 'Tu',
+ 'IPV_vs_fNsquared_ratio': 'IPVfN2',
+ 'Nsquared': 'n2',
+ #'chem_potential_relative_t_exact': 'chem_potential_t_exact',
+ 'rho_alpha_beta_CT_exact': 'rho_CTrab_exact',
+ 'rho_alpha_beta': 'rho_rab'}
+
+# Add target aliases to cv.
+for f in not_match:
+ setattr(cv, f, getattr(cv, not_match[f]))
+ setattr(cv, f + '_ca', getattr(cv, not_match[f] + '_ca'))
+
+
+# Generic test method.
+def generic_test(self, func=None, argnames=None):
+ """Generic test function, to be specialized by functools.partial."""
+ # Transform argument names to name convention in cv dataset.
+ args = [getattr(cv, a + '_chck_cast') for a in argnames]
+ # Perform the function call
+ out = getattr(gsw, func)(*args)
+ # FIXME: Testing just the first output!
+ # Check that the maximal error is less than the given tolerance
+ if isinstance(out, tuple):
+ out = out[0]
+ #print("""%s returns a tuple.""" % func)
+ target = getattr(cv, func)
+ maxdiff = np.nanmax(abs(out - target))
+ maxallowed = getattr(cv, func + '_ca')
+ try:
+ self.assertTrue(maxdiff < maxallowed)
+ except AssertionError as e:
+ print(out)
+ print(target)
+ raise AssertionError("Error in %s %s, maxdiff is %s vs %s allowed" %
+ (func, e.args, maxdiff, maxallowed))
+
+
+# Dictionary of functions with corresponding test methods.
+function_test = {}
+for f in function_arguments:
+ function_test[f] = functools.partial(generic_test, func=f,
+ argnames=function_arguments[f])
+
+
+# Auto-generated TestCase.
+class Test_profiles(unittest.TestCase):
+
+ for f in function_test:
+ method_def = ("test_" + f +
+ " = lambda self: function_test['" + f + "'](self)")
+ exec(method_def)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/gsw/test/test_tuples.py b/gsw/test/test_tuples.py
new file mode 100644
index 0000000..3bfe3e6
--- /dev/null
+++ b/gsw/test/test_tuples.py
@@ -0,0 +1,99 @@
+# -*- coding: utf-8 -*-
+
+"""Unit check for standard profiles for the Gibbs Sea Water python package."""
+
+import os
+import sys
+import unittest
+import functools # Requires python 2.5.
+import numpy as np
+
+import gsw
+from gsw.utilities import Bunch
+
+
+# Read data file with check value profiles
+datadir = os.path.join(os.path.dirname(gsw.utilities.__file__), 'data')
+fname = 'gsw_cv_v3_0.npz'
+cv = Bunch(np.load(os.path.join(datadir, fname)))
+cf = Bunch(np.load(os.path.join(datadir, 'gsw_cf.npz')))
+
+# derivatives.py
+#CT_first_derivatives=('SA', 'pt'), # NOTE: TI, BUG
+#CT_second_derivatives=('SA', 'pt'), # NOTE: TI FIXME BUG
+#enthalpy_first_derivatives=('SA', 'CT', 'p'), FIXME name match
+#enthalpy_second_derivatives=('SA', 'CT', 'p'), FIXME name match
+#entropy_first_derivatives=('SA', 'CT'), #NOTE: TI FIXME name match
+#entropy_second_derivatives=('SA', 'pt'), #NOTE: TI FIXME name match
+#pt_first_derivatives':, #NOTE: TI FIXME name match
+#pt_second_derivatives= #NOTE: TI FIXME name match
+
+# Make aliases for some values to be used as arguments
+cv.entropy_chck_cast = cv.entropy_from_CT
+cv.Abs_Pressure_from_p_chck_cast = cv.Abs_Pressure_from_p
+cv.depth_chck_cast = cv.depth_from_z
+cv.C_chck_cast = cv.C_from_SP
+cv.pt_chck_cast = cv.pt_from_t
+cv.z_chck_cast = cv.z_from_p
+cv.SR_chck_cast = cv.SR_from_SP
+cv.pr_chck_cast = cv.pr
+cv.p_shallow_chck_cast = cv.p_chck_cast_shallow
+cv.p_deep_chck_cast = cv.p_chck_cast_deep
+cv.rho_chck_cast = cv.rho_CT_exact
+cv.R_cf_chck_cast = cf.R
+cv.rho_cf_chck_cast = cf.rho
+
+
+def generic_test(self, func=None, argnames=None):
+ """Generic test function, to be specialized by functools.partial"""
+ # Transform argument names to name convention in cv dataset
+ args = [getattr(cv, a + '_chck_cast') for a in argnames]
+ # Perform the function call
+ out = getattr(gsw, func)(*args)
+ # FIXME: Testing just the first output!
+ # TODO: Create the tuples and compare all together.
+ # Check that the maximal error is less than the given tolerance
+ if isinstance(out, tuple):
+ out = out[0]
+ maxdiff = np.nanmax(abs(out - getattr(cv, func)))
+ try:
+ self.assertTrue(maxdiff < getattr(cv, func + '_ca'))
+ except AssertionError, e:
+ raise AssertionError("Error in %s %s" % (func, e.args))
+
+
+# Dictionary of functions with corresponding test methods
+function_test = {}
+for f in function_arguments:
+ function_test[f] = functools.partial(generic_test,
+ argnames=function_arguments[f],
+ func=f)
+
+
+# Auto-generated TestCase.
+class Test_profiles(unittest.TestCase):
+
+ for f in function_test:
+ method_def = ("test_%s = lambda self: function_test['%s'](self)" %
+ (f, f))
+ #print method_def
+ exec(method_def)
+
+
+if __name__ == '__main__':
+ # A more verbose output
+ suite = unittest.TestLoader().loadTestsFromTestCase(Test_profiles)
+ a = unittest.TextTestRunner(verbosity=2).run(suite)
+ if a.errors or a.failures:
+ sys.exit(256)
+ #unittest.main()
+
+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 = np.where(np.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 gsw_cf.ICT_first_deriv:
+ print(2, 'gsw_CT_first_derivatives: Failed\n')
+ gsw_cf.gsw_chks = 0
diff --git a/gsw/utilities/__init__.py b/gsw/utilities/__init__.py
new file mode 100644
index 0000000..c1de93c
--- /dev/null
+++ b/gsw/utilities/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+from .utilities import (Bunch, match_args_return, read_data, strip_mask,
+ loadmatbunch)
diff --git a/gsw/utilities/data/gsw_cf.npz b/gsw/utilities/data/gsw_cf.npz
new file mode 100644
index 0000000..f387803
Binary files /dev/null and b/gsw/utilities/data/gsw_cf.npz differ
diff --git a/gsw/utilities/data/gsw_cv_v3_0.npz b/gsw/utilities/data/gsw_cv_v3_0.npz
new file mode 100644
index 0000000..7668c3e
Binary files /dev/null and b/gsw/utilities/data/gsw_cv_v3_0.npz differ
diff --git a/gsw/utilities/data/gsw_data_v3_0.npz b/gsw/utilities/data/gsw_data_v3_0.npz
new file mode 100644
index 0000000..b963c5b
Binary files /dev/null and b/gsw/utilities/data/gsw_data_v3_0.npz differ
diff --git a/gsw/utilities/data/gsw_demo_data_v3_0.npz b/gsw/utilities/data/gsw_demo_data_v3_0.npz
new file mode 100644
index 0000000..ea4ae9c
Binary files /dev/null and b/gsw/utilities/data/gsw_demo_data_v3_0.npz differ
diff --git a/gsw/utilities/list_npz.py b/gsw/utilities/list_npz.py
new file mode 100644
index 0000000..da5ed08
--- /dev/null
+++ b/gsw/utilities/list_npz.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+"""
+List to stdout the contents of an npz file used in testing.
+
+The filename is the sole command-line argument.
+"""
+
+import sys
+import numpy as np
+
+fname = sys.argv[1]
+
+dat = np.load(fname)
+keys = dat.keys()
+keys.sort()
+klens = [len(str(k)) for k in keys]
+klen = max(klens)
+
+str_fmt = "{0!s:<{klen}} : {1!s:>10} {2!s:>12}\n"
+
+slist = [str_fmt.format(k, dat[k].dtype, dat[k].shape, klen=klen)
+ for k in keys]
+
+print ''.join(slist)
+
+
diff --git a/gsw/utilities/mat2npz.py b/gsw/utilities/mat2npz.py
new file mode 100644
index 0000000..5e47576
--- /dev/null
+++ b/gsw/utilities/mat2npz.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# mat2npz.py
+#
+# purpose: Convert matlab file from TEOS-10 group to a npz file
+# author: Filipe P. A. Fernandes
+# e-mail: ocefpaf at gmail
+# web: http://ocefpaf.tiddlyspot.com/
+# created: 06-Jun-2011
+# modified: Mon 16 Sep 2013 01:40:54 PM BRT
+#
+# obs:
+#
+
+import numpy as np
+
+from gsw.utilities import loadmatbunch
+
+data_ver = 'v3_0'
+gsw_data = loadmatbunch('gsw_data_%s.mat' % data_ver, masked=False)
+
+print('Data version number: %s' % gsw_data.version_number)
+print('Data version date: %s' % gsw_data.version_date)
+
+# Delta SA Atlas.
+ref_table = dict()
+for k in gsw_data:
+ if k == u'gsw_cv' or k == u'#refs#' or k == 'gsw_demo_data':
+ pass
+ else:
+ ref_table[k] = gsw_data[k]
+np.savez("data/gsw_data_%s" % data_ver, **ref_table)
+
+# Save demo data values gsw_demo_data in a separate file.
+gsw_demo_data = gsw_data['gsw_demo_data']
+
+np.savez("data/gsw_demo_data_%s" % data_ver, **gsw_data['gsw_demo_data'])
+
+# Save compare values `gsw_cv` in a separate file.
+cv_vars = gsw_data['gsw_cv']
+
+np.savez("data/gsw_cv_%s" % data_ver, **cv_vars)
+
+# NOTE: The matfile gsw_cf.mat contains the results from
+# `gsw_check_functions.m.` and is used later for tests. Remember to save it as
+# MatlabTM '-v6' otherwise will have to use hdf5 instead of loadmat to read it.
+if True:
+ gsw_cf = loadmatbunch('gsw_cf.mat', masked=False)
+ np.savez("data/gsw_cf", **gsw_cf)
diff --git a/gsw/utilities/utilities.py b/gsw/utilities/utilities.py
new file mode 100644
index 0000000..6688095
--- /dev/null
+++ b/gsw/utilities/utilities.py
@@ -0,0 +1,333 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import division
+
+import os
+from functools import wraps
+
+import numpy as np
+from scipy.io import loadmat
+
+__all__ = ['Bunch',
+ 'Cache_npz',
+ 'match_args_return',
+ 'read_data',
+ 'strip_mask']
+
+
+# Based on Robert Kern's Bunch.
+class Bunch(dict):
+ """
+ A dictionary that also provides access via attributes.
+
+ Additional methods update_values and update_None provide
+ control over whether new keys are added to the dictionary
+ when updating, and whether an attempt to add a new key is
+ ignored or raises a KeyError.
+
+ The Bunch also prints differently than a normal
+ dictionary, using str() instead of repr() for its
+ keys and values, and in key-sorted order. The printing
+ format can be customized by subclassing with a different
+ str_ftm class attribute. Do not assign directly to this
+ class attribute, because that would substitute an instance
+ attribute which would then become part of the Bunch, and
+ would be reported as such by the keys() method.
+
+ To output a string representation with
+ a particular format, without subclassing, use the
+ formatted() method.
+ """
+
+ str_fmt = "{0!s:<{klen}} : {1!s:>{vlen}}\n"
+
+ def __init__(self, *args, **kwargs):
+ """
+ *args* can be dictionaries, bunches, or sequences of
+ key,value tuples. *kwargs* can be used to initialize
+ or add key, value pairs.
+ """
+ dict.__init__(self)
+ self.__dict__ = self
+ for arg in args:
+ self.update(arg)
+ self.update(kwargs)
+
+ def __str__(self):
+ return self.formatted()
+
+ def formatted(self, fmt=None):
+ """
+ Return a string with keys and/or values.
+
+ *fmt* is a format string as used in the str.format() method.
+
+ The str.format() method is called with key, value as positional
+ arguments, and klen, vlen as kwargs. The latter are the maxima
+ of the string lengths for the keys and values, respectively,
+ up to respective maxima of 20 and 40.
+ """
+ if fmt is None:
+ fmt = self.str_fmt
+ klens = [len(str(k)) for k in self.keys()]
+ vlens = [len(str(v)) for v in self.values()]
+ klen = min(20, max(klens))
+ vlen = min(40, max(vlens))
+ items = self.items()
+ items.sort()
+ slist = [fmt.format(k, v, klen=klen, vlen=vlen) for k, v in items]
+ return ''.join(slist)
+
+ def update_values(self, *args, **kw):
+ """
+ arguments are dictionary-like; if present, they act as
+ additional sources of kwargs, with the actual kwargs
+ taking precedence.
+
+ One reserved optional kwarg is "strict". If present and
+ True, then any attempt to update with keys that are not
+ already in the Bunch instance will raise a KeyError.
+ """
+ strict = kw.pop("strict", False)
+ newkw = dict()
+ for d in args:
+ newkw.update(d)
+ newkw.update(kw)
+ self._check_strict(strict, newkw)
+ dsub = dict([(k, v) for (k, v) in newkw.items() if k in self])
+ self.update(dsub)
+
+ def update_None(self, *args, **kw):
+ """
+ Similar to update_values, except that an existing value
+ will be updated only if it is None.
+ """
+ strict = kw.pop("strict", False)
+ newkw = dict()
+ for d in args:
+ newkw.update(d)
+ newkw.update(kw)
+ self._check_strict(strict, newkw)
+ dsub = dict([(k, v) for (k, v) in newkw.items() if k in self and
+ self[k] is None])
+ self.update(dsub)
+
+ def _check_strict(self, strict, kw):
+ if strict:
+ bad = set(kw.keys()) - set(self.keys())
+ if bad:
+ bk = list(bad)
+ bk.sort()
+ ek = self.keys()
+ ek.sort()
+ raise KeyError(
+ "Update keys %s don't match existing keys %s" % (bk, ek))
+
+
+class Cache_npz(object):
+ def __init__(self):
+ self._cache = dict()
+ self._default_path = os.path.join(os.path.dirname(__file__), 'data')
+
+ def __call__(self, fname, datadir=None):
+ if datadir is None:
+ datadir = self._default_path
+ fpath = os.path.join(datadir, fname)
+ try:
+ return self._cache[fpath]
+ except KeyError:
+ pass
+ d = np.load(fpath)
+ ret = Bunch(d)
+ self._cache[fpath] = ret
+ return ret
+
+_npz_cache = Cache_npz()
+
+
+def repair_npzfile_with_objects(infile, outfile):
+ """
+ Read an npz file written based on scipy.io.loadmat,
+ and write out a new npz file in which arrays have been
+ extracted from object arrays.
+
+ This might be needed only during the development process.
+ It is motivated by the need to fix gsw_cf.npz so that
+ the special object array handling in to_masked is not needed
+ for the tests.
+ """
+ dat = np.load(infile)
+ out = dict()
+ for k, v in dat.iteritems():
+ if v.dtype.kind == 'O':
+ v = v.item()
+ out[k] = v
+ np.savez(outfile, **out)
+
+
+def to_masked(arg):
+ r"""
+ Ensure an argument is a floating-point masked array.
+
+ This is a helper for match_args_return.
+ """
+ if not np.iterable(arg):
+ arg = [arg]
+ try:
+ arg = np.ma.array(arg, copy=False, dtype=float)
+ except ValueError:
+ # We might not want to keep this here. It handles the
+ # case where reading a matfile with scipy has yielded
+ # an object array containing a single object, which is
+ # the array one actually wants.
+ if arg.dtype.kind == 'O':
+ arg = np.ma.array(arg.item(), copy=False, dtype=float)
+ else:
+ raise
+ return np.ma.masked_invalid(arg)
+
+
+def match_args_return(f):
+ """
+ Decorator for most functions that operate on profile data.
+ """
+ @wraps(f)
+ def wrapper(*args, **kw):
+ p = kw.get('p', None)
+ if p is not None:
+ args = list(args)
+ args.append(p)
+
+ isarray = np.any([hasattr(a, '__iter__') for a in args])
+ ismasked = np.any([np.ma.isMaskedArray(a) for a in args])
+
+ def fixup(ret):
+ if not ismasked:
+ ret = np.ma.filled(ret, np.nan)
+ if not isarray:
+ ret = ret[0]
+ return ret
+
+ newargs = [to_masked(a) for a in args]
+ if p is not None:
+ kw['p'] = newargs.pop()
+
+ ret = f(*newargs, **kw)
+
+ if isinstance(ret, tuple):
+ retlist = [fixup(arg) for arg in ret]
+ ret = tuple(retlist)
+ else:
+ ret = fixup(ret)
+ return ret
+ wrapper.__wrapped__ = f
+ return wrapper
+
+
+def read_data(fname, datadir=None):
+ """
+ Read variables from a numpy '.npz' file into a minimal class providing
+ attribute access. A cache is used to avoid re-reading the same file.
+ """
+ return _npz_cache(fname, datadir=datadir)
+
+
+def strip_mask(*args):
+ """
+ Process the standard arguments for efficient calculation.
+
+ Return unmasked arguments, plus a mask.
+
+ The first argument, SA, is handled specially so that it can be
+
+ This could be absorbed into a decorator, but it would
+ require redefining functions to take the additional
+ mask argument or kwarg.
+ """
+ mask = np.ma.getmaskarray(args[-1])
+ SA = args[0]
+ if SA.shape:
+ SA = np.ma.asarray(SA)
+ SA[SA < 0] = np.ma.masked
+ for a in args[:-1]:
+ mask = np.ma.mask_or(mask, np.ma.getmask(a))
+ newargs = [SA.filled(0)]
+ elif SA < 0:
+ SA = 0
+ for a in args[1:-1]:
+ mask = np.ma.mask_or(mask, np.ma.getmask(a))
+ newargs = [SA]
+ newargs.extend([np.ma.filled(a, 0) for a in args[1:]])
+ newargs.append(mask)
+ return newargs
+
+
+def _unicode(arr):
+ r"""
+ loadmat seems to be mishandling strings when there is a difference
+ in byte order between the machine that wrote the file and the one
+ that is reading the file. The result is, e.g.,
+
+ u'\U31000000\U34000000' instead of u'14'
+
+ """
+ try:
+ return unicode(arr)
+ except UnicodeEncodeError:
+ dt = arr.dtype.newbyteorder('S')
+ return unicode(arr.view(dt))
+
+
+def crunch(arr, masked=True):
+ arr = arr.squeeze()
+ if arr.ndim == 0:
+ kind = arr.dtype.kind
+ if kind == 'f':
+ return float(arr)
+ if kind in 'ui':
+ return int(arr)
+ if kind == 'U':
+ try:
+ return _unicode(arr)
+ except UnicodeDecodeError:
+ return "Could not decode."
+ if kind == 'S':
+ return str(arr)
+ if kind == 'O':
+ return arr
+ return arr # Warn? Other kinds need to be handled?
+ if masked and arr.dtype.kind == 'f': # Check for complex also.
+ arrm = np.ma.masked_invalid(arr)
+ if arrm.count() < arrm.size:
+ arr = arrm
+ else:
+ arr = np.array(arr) # Copy to force a read.
+ else:
+ arr = np.array(arr)
+ return arr
+
+
+def structured_to_bunch(arr, masked=True):
+ if arr.dtype.kind == 'V' and arr.shape == (1, 1):
+ b = Bunch()
+ x = arr[0, 0]
+ for name in x.dtype.names:
+ b[name] = structured_to_bunch(x[name], masked=masked)
+ return b
+ return crunch(arr, masked=masked)
+
+
+def loadmatbunch(fname, masked=True):
+ """
+ Wrapper for loadmat that dereferences (1,1) object arrays,
+ converts floating point arrays to masked arrays, and uses
+ nested Bunch objects in place of the MatlabTM structures.
+ """
+ out = Bunch()
+ fobj = open(fname, 'rb')
+ xx = loadmat(fobj)
+ keys = [k for k in xx.keys() if not k.startswith("__")]
+ for k in keys:
+ out[k] = structured_to_bunch(xx[k], masked=masked)
+ fobj.close()
+ return out
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..861a9f5
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,5 @@
+[egg_info]
+tag_build =
+tag_date = 0
+tag_svn_revision = 0
+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..dbd5bcd
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import
+
+import io
+import re
+from setuptools import setup
+
+
+def read(*filenames, **kwargs):
+ encoding = kwargs.get('encoding', 'utf-8')
+ sep = kwargs.get('sep', '\n')
+ buf = []
+ for filename in filenames:
+ with io.open(filename, encoding=encoding) as f:
+ buf.append(f.read())
+ return sep.join(buf)
+
+
+VERSIONFILE = "gsw/__init__.py"
+verstrline = open(VERSIONFILE, "rt").read()
+VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]"
+mo = re.search(VSRE, verstrline, re.M)
+if mo:
+ verstr = mo.group(1)
+else:
+ raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,))
+
+email = "ocefpaf at gmail.com"
+maintainer = "Filipe Fernandes"
+authors = ['Eric Firing', u'Bjørn Ådlandsvik', 'Filipe Fernandes']
+
+install_requires = ['numpy', 'nose']
+
+LICENSE = read('LICENSE.txt')
+long_description = read('README.txt', 'CHANGES.txt')
+
+config = dict(name='gsw',
+ version=verstr,
+ packages=['gsw', 'gsw/gibbs', 'gsw/utilities', 'gsw/test'],
+ package_data={'gsw': ['utilities/data/*.npz']},
+ test_suite='tests',
+ use_2to3=True,
+ license=LICENSE,
+ long_description=long_description,
+ classifiers=['Development Status :: 4 - Beta',
+ 'Environment :: Console',
+ 'Intended Audience :: Science/Research',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Education',
+ 'License :: OSI Approved :: MIT License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Topic :: Education',
+ 'Topic :: Scientific/Engineering',
+ ],
+ description='Gibbs SeaWater Oceanographic Package of TEOS-10',
+ author=authors,
+ author_email=email,
+ maintainer=maintainer,
+ maintainer_email=email,
+ url='http://pypi.python.org/pypi/seawater/',
+ download_url='https://pypi.python.org/pypi/gsw/',
+ platforms='any',
+ keywords=['oceanography', 'seawater', 'TEOS-10', 'gibbs'],
+ install_requires=install_requires)
+
+setup(**config)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/gsw.git
More information about the debian-science-commits
mailing list