diff --git a/conda_recipe/meta.yaml b/conda_recipe/meta.yaml index e2c9080..d6d8d77 100644 --- a/conda_recipe/meta.yaml +++ b/conda_recipe/meta.yaml @@ -22,6 +22,7 @@ requirements: - python - wrapt - libgcc 4.8.5 + - xarray test: requires: diff --git a/doc/.DS_Store b/doc/.DS_Store new file mode 100644 index 0000000..fdfe969 Binary files /dev/null and b/doc/.DS_Store differ diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..b5ec978 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,230 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) + $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don\'t have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @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 " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " epub3 to make an epub3" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + @echo " dummy to check syntax errors of document sources" + +.PHONY: clean +clean: + rm -rf $(BUILDDIR)/* + +.PHONY: html +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +.PHONY: dirhtml +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +.PHONY: singlehtml +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +.PHONY: pickle +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +.PHONY: json +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +.PHONY: htmlhelp +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." + +.PHONY: qthelp +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/wrf-python.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/wrf-python.qhc" + +.PHONY: applehelp +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +.PHONY: devhelp +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/wrf-python" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/wrf-python" + @echo "# devhelp" + +.PHONY: epub +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +.PHONY: epub3 +epub3: + $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 + @echo + @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." + +.PHONY: latex +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +.PHONY: latexpdf +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: latexpdfja +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: text +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +.PHONY: man +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +.PHONY: texinfo +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +.PHONY: info +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +.PHONY: gettext +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +.PHONY: changes +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +.PHONY: linkcheck +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." + +.PHONY: doctest +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +.PHONY: coverage +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +.PHONY: xml +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +.PHONY: pseudoxml +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." + +.PHONY: dummy +dummy: + $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy + @echo + @echo "Build finished. Dummy builder generates no files." diff --git a/doc/make.bat b/doc/make.bat new file mode 100644 index 0000000..6834f05 --- /dev/null +++ b/doc/make.bat @@ -0,0 +1,281 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source +set I18NSPHINXOPTS=%SPHINXOPTS% source +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + 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. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. epub3 to make an epub3 + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + echo. coverage to run coverage check of the documentation if enabled + echo. dummy to check syntax errors of document sources + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +REM Check if sphinx-build is available and fallback to Python version if any +%SPHINXBUILD% 1>NUL 2>NUL +if errorlevel 9009 goto sphinx_python +goto sphinx_ok + +:sphinx_python + +set SPHINXBUILD=python -m sphinx.__init__ +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +:sphinx_ok + + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\wrf-python.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\wrf-python.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "epub3" ( + %SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3 + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub3 file is in %BUILDDIR%/epub3. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "coverage" ( + %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage + if errorlevel 1 exit /b 1 + echo. + echo.Testing of coverage in the sources finished, look at the ^ +results in %BUILDDIR%/coverage/python.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +if "%1" == "dummy" ( + %SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. Dummy builder generates no files. + goto end +) + +:end diff --git a/doc/source/conf.py b/doc/source/conf.py new file mode 100644 index 0000000..9fafa25 --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,288 @@ +# -*- coding: utf-8 -*- +# +# wrf-python documentation build configuration file, created by +# sphinx-quickstart on Wed Jun 29 14:57:16 2016. +# +# 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 +import 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.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# 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.napoleon' +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'wrf-python' +copyright = u'2016, Bill Ladwig' +author = u'Bill Ladwig' + +# 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 = u'0.0.1' +# The full version, including alpha/beta/rc tags. +release = u'0.0.1' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +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 patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = [] + +# 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 = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'alabaster' + +# 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. +# " v documentation" by default. +#html_title = u'wrf-python v0.0.1' + +# 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 (relative to this directory) to use as a 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'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not None, a 'Last updated on:' timestamp is inserted at every page +# bottom, using the given strftime format. +# The empty string is equivalent to '%b %d, %Y'. +#html_last_updated_fmt = None + +# 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_domain_indices = 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, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# 'ja' uses this config value. +# 'zh' user can custom change `jieba` dictionary path. +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'wrf-pythondoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'wrf-python.tex', u'wrf-python Documentation', + u'Bill Ladwig', '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 + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'wrf-python', u'wrf-python Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'wrf-python', u'wrf-python Documentation', + author, 'wrf-python', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 0000000..1365f5d --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,36 @@ +.. wrf-python documentation master file, created by + sphinx-quickstart on Wed Jun 29 14:57:16 2016. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to wrf-python's documentation! +====================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + +Extraction Routine +------------------ +.. autofunction:: wrf.getvar + +Interpolation Routines +---------------------- + +.. autofunction:: wrf.interplevel + +.. autofunction:: wrf.vertcross + +.. autofunction:: wrf.interpline + +.. autofunction:: wrf.vinterp + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/fortran/calc_uh.f90 b/fortran/calc_uh.f90 new file mode 100644 index 0000000..262d954 --- /dev/null +++ b/fortran/calc_uh.f90 @@ -0,0 +1,126 @@ +!NCLFORTSTART +SUBROUTINE DCALCUH(nx, ny, nz, nzp1, zp, mapfct, dx, dy, uhmnhgt, uhmxhgt, us, & + vs, w, uh, tem1, tem2) + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: uh + + INTEGER, INTENT(IN) :: nx, ny, nz, nzp1 + REAL(KIND=8), DIMENSION(nx,ny,nzp1), INTENT(IN) :: zp + REAL(KIND=8), DIMENSION(nx,ny), INTENT(IN) :: mapfct + REAL(KIND=8), INTENT(IN) :: dx, dy + REAL(KIND=8), INTENT(IN) :: uhmnhgt, uhmxhgt + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: us + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: vs + REAL(KIND=8), DIMENSION(nx,ny,nzp1), INTENT(IN) :: w + REAL(KIND=8), DIMENSION(nx,ny), INTENT(OUT) :: uh + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(INOUT) :: tem1 + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(INOUT) :: tem2 + +!NCLEND + + ! Misc local variables + INTEGER :: i, j, k, kbot, ktop + REAL(KIND=8) :: twodx, twody, wgtlw, sum, wmean, wsum, wavg + REAL(KIND=8) :: helbot, heltop, wbot, wtop + REAL(KIND=8) :: zbot, ztop + + ! Initialize arrays + uh = 0.0 + tem1 = 0.0 + + ! Calculate vertical component of helicity at scalar points + ! us: u at scalar points + ! vs: v at scalar points + + twodx = 2.0*dx + twody = 2.0*dy + DO k=2,nz-2 + DO j=2,ny-1 + DO i=2,nx-1 + wavg = 0.5*(w(i,j,k)+w(i,j,k+1)) + tem1(i,j,k) = wavg * ((vs(i+1,j,k) - vs(i-1,j,k))/(twodx * mapfct(i,j)) - & + (us(i,j+1,k) - us(i,j-1,k))/(twody * mapfct(i,j))) + tem2(i,j,k) = 0.5*(zp(i,j,k) + zp(i,j,k+1)) + END DO + END DO + END DO + + ! Integrate over depth uhminhgt to uhmxhgt AGL + ! + ! WRITE(6,'(a,f12.1,a,f12.1,a)') & + ! 'Calculating UH from ',uhmnhgt,' to ',uhmxhgt,' m AGL' + DO j=2,ny-2 + DO i=2,nx-2 + zbot = zp(i,j,2) + uhmnhgt + ztop = zp(i,j,2) + uhmxhgt + ! + ! Find wbar, weighted-mean vertical velocity in column + ! Find w at uhmnhgt AGL (bottom) + ! + DO k=2,nz-3 + IF(zp(i,j,k) > zbot) EXIT + END DO + kbot = k + wgtlw = (zp(i,j,kbot) - zbot)/(zp(i,j,kbot) - zp(i,j,kbot-1)) + wbot = (wgtlw*w(i,j,kbot-1)) + ((1.-wgtlw)*w(i,j,kbot)) + + ! Find w at uhmxhgt AGL (top) + DO k=2,nz-3 + IF(zp(i,j,k) > ztop) EXIT + END DO + ktop = k + wgtlw = (zp(i,j,ktop) - ztop)/(zp(i,j,ktop) - zp(i,j,ktop-1)) + wtop = (wgtlw*w(i,j,ktop-1)) + ((1.-wgtlw)*w(i,j,ktop)) + + ! First part, uhmnhgt to kbot + wsum = 0.5*(w(i,j,kbot) + wbot) * (zp(i,j,kbot) - zbot) + + ! Integrate up through column + DO k=(kbot+1),(ktop-1) + wsum = wsum + 0.5*(w(i,j,k) + w(i,j,k-1)) * (zp(i,j,k) - zp(i,j,k-1)) + END DO + + ! Last part, ktop-1 to uhmxhgt + wsum = wsum + 0.5*(wtop + w(i,j,ktop-1)) * (ztop - zp(i,j,ktop-1)) + wmean = wsum/(uhmxhgt - uhmnhgt) + + IF (wmean > 0.) THEN ! column updraft, not downdraft + + ! Find helicity at uhmnhgt AGL (bottom) + DO k=2,nz-3 + IF (tem2(i,j,k) > zbot) EXIT + END DO + kbot = k + wgtlw = (tem2(i,j,kbot) - zbot)/(tem2(i,j,kbot) - tem2(i,j,kbot-1)) + helbot = (wgtlw*tem1(i,j,kbot-1)) + ((1.-wgtlw)*tem1(i,j,kbot)) + + ! Find helicity at uhmxhgt AGL (top) + DO k=2,nz-3 + IF (tem2(i,j,k) > ztop) EXIT + END DO + ktop = k + wgtlw = (tem2(i,j,ktop) - ztop)/(tem2(i,j,ktop) - tem2(i,j,ktop-1)) + heltop = (wgtlw*tem1(i,j,ktop-1)) + ((1.-wgtlw)*tem1(i,j,ktop)) + + ! First part, uhmnhgt to kbot + sum = 0.5*(tem1(i,j,kbot) + helbot) * (tem2(i,j,kbot) - zbot) + + ! Integrate up through column + DO k=(kbot+1),(ktop-1) + sum = sum + 0.5*(tem1(i,j,k) + tem1(i,j,k-1)) * (tem2(i,j,k) - tem2(i,j,k-1)) + END DO + + ! Last part, ktop-1 to uhmxhgt + uh(i,j) = sum + 0.5*(heltop + tem1(i,j,ktop-1)) * (ztop - tem2(i,j,ktop-1)) + END IF + END DO + END DO + + uh = uh * 1000. ! Scale according to Kain et al. (2008) + + RETURN + +END SUBROUTINE DCALCUH diff --git a/fortran/cloud_fracf.f90 b/fortran/cloud_fracf.f90 new file mode 100644 index 0000000..99a8c63 --- /dev/null +++ b/fortran/cloud_fracf.f90 @@ -0,0 +1,56 @@ +! NCLFORTSTART +SUBROUTINE DCLOUDFRAC(pres, rh, lowc, midc, highc, nz, ns, ew) + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: lowc, midc, highc + + INTEGER nz, ns, ew + REAL(KIND=8), DIMENSION(ew, ns, nz), INTENT(IN) :: pres, rh + REAL(KIND=8), DIMENSION(ew, ns), INTENT(OUT) :: lowc, midc, highc + +! NCLEND + + INTEGER i, j, k + INTEGER kchi, kcmi, kclo + + ! Remove compiler warnings + kchi = 0 + kcmi = 0 + kclo = 0 + + DO j = 1,ns + DO i = 1,ew + DO k = 1,nz-1 + IF ( pres(i,j,k) .GT. 97000. ) kclo=k + IF ( pres(i,j,k) .GT. 80000. ) kcmi=k + IF ( pres(i,j,k) .GT. 45000. ) kchi=k + END DO + + DO k = 1,nz-1 + IF (k .GE. kclo .AND. k .LT. kcmi) THEN + lowc(i,j) = AMAX1(rh(i,j,k), lowc(i,j)) + ELSE IF (k .GE. kcmi .AND. k .LT. kchi) THEN ! mid cloud + midc(i,j) = AMAX1(rh(i,j,k), midc(i,j)) + ELSE if (k .GE. kchi) THEN ! high cloud + highc(i,j) = AMAX1(rh(i,j,k), highc(i,j)) + END IF + END DO + + lowc(i,j) = 4.0 * lowc(i,j)/100. - 3.0 + midc(i,j) = 4.0 * midc(i,j)/100. - 3.0 + highc(i,j) = 2.5 * highc(i,j)/100. - 1.5 + + lowc(i,j) = amin1(lowc(i,j), 1.0) + lowc(i,j) = amax1(lowc(i,j), 0.0) + midc(i,j) = amin1(midc(i,j), 1.0) + midc(i,j) = amax1(midc(i,j), 0.0) + highc(i,j) = amin1(highc(i,j), 1.0) + highc(i,j) = amax1(highc(i,j), 0.0) + + END DO + END DO + + RETURN + +END SUBROUTINE DCLOUDFRAC diff --git a/fortran/constants.f90 b/fortran/constants.f90 index c74985c..81594f1 100644 --- a/fortran/constants.f90 +++ b/fortran/constants.f90 @@ -1,10 +1,66 @@ +! These are chosen to match the wrf module_model_constants.F where +! applicable MODULE constants INTEGER :: ERRLEN=512 - REAL(KIND=8), PARAMETER :: P1000MB=100000.D0 - REAL(KIND=8), PARAMETER :: R_D=287.D0 - REAL(KIND=8), PARAMETER :: CP=7.D0*R_D/2.D0 - REAL(KIND=8), PARAMETER :: R=287.04D0 - REAL(KIND=8), PARAMETER :: G=9.81D0 - REAL(KIND=8), PARAMETER :: GAMMA=0.0065D0 + INTEGER :: ALGERR=64 + + REAL(KIND=8), PARAMETER :: WRF_EARTH_RADIUS = 6370000.D0 + REAL(KIND=8), PARAMETER :: T_BASE = 300.0 + REAL(KIND=8), PARAMETER :: PI = 3.1415926535897932384626433D0 + REAL(KIND=8), PARAMETER :: RAD_PER_DEG = PI/180.D0 + REAL(KIND=8), PARAMETER :: DEG_PER_RAD = 180.D0/PI + REAL(KIND=8), PARAMETER :: DEFAULT_FILL = 9.9692099683868690D36 + + REAL(KIND=8), PARAMETER :: P1000MB = 100000.D0 + ! j/k/kg + REAL(KIND=8), PARAMETER :: RD = 287.D0 + REAL(KIND=8), PARAMETER :: RV = 461.6D0 + !REAL(KIND=8), PARAMETER :: RV = 461.5D0 + ! j/k/kg note: not using bolton's value of 1005.7 + REAL(KIND=8), PARAMETER :: CP = 1004.5D0 + !REAL(KIND=8), PARAMETER :: CP = 1004D0 + + REAL(KIND=8), PARAMETER :: G = 9.81D0 + REAL(KIND=8), PARAMETER :: USSALR = 0.0065D0 ! deg C per m + + REAL(KIND=8), PARAMETER :: CELKEL = 273.15D0 + REAL(KIND=8), PARAMETER :: CELKEL_TRIPLE = 273.16D0 + !REAL(KIND=8), PARAMETER :: GRAV = 9.81D0 + ! hpa + REAL(KIND=8), PARAMETER :: EZERO = 6.112D0 + REAL(KIND=8), PARAMETER :: ESLCON1 = 17.67D0 + REAL(KIND=8), PARAMETER :: ESLCON2 = 29.65D0 + REAL(KIND=8), PARAMETER :: EPS = 0.622D0 + REAL(KIND=8), PARAMETER :: GAMMA = RD/CP + ! cp_moist=cp*(1.+cpmd*qvp) + REAL(KIND=8), PARAMETER :: CPMD = .887D0 + ! rgas_moist=rgas*(1.+rgasmd*qvp) + REAL(KIND=8), PARAMETER :: RGASMD = .608D0 + ! gamma_moist=gamma*(1.+gammamd*qvp) + REAL(KIND=8), PARAMETER :: GAMMAMD = RGASMD - CPMD + REAL(KIND=8), PARAMETER :: TLCLC1 = 2840.D0 + REAL(KIND=8), PARAMETER :: TLCLC2 = 3.5D0 + REAL(KIND=8), PARAMETER :: TLCLC3 = 4.805D0 + REAL(KIND=8), PARAMETER :: TLCLC4 = 55.D0 + ! k + REAL(KIND=8), PARAMETER :: THTECON1 = 3376.D0 + REAL(KIND=8), PARAMETER :: THTECON2 = 2.54D0 + REAL(KIND=8), PARAMETER :: THTECON3 = .81D0 + + REAL(KIND=8), PARAMETER :: ABSCOEFI = .272D0 ! cloud ice absorption coefficient in m^2/g + REAL(KIND=8), PARAMETER :: ABSCOEF = .145D0 ! cloud water absorption coefficient in m^2/g + + REAL(KIND=8), PARAMETER :: GAMMA_SEVEN = 720.D0 + REAL(KIND=8), PARAMETER :: RHOWAT = 1000.D0 + REAL(KIND=8), PARAMETER :: RHO_R = RHOWAT + REAL(KIND=8), PARAMETER :: RHO_S = 100.D0 + REAL(KIND=8), PARAMETER :: RHO_G = 400.D0 + REAL(KIND=8), PARAMETER :: ALPHA = 0.224D0 + + REAL(KIND=8), PARAMETER :: SCLHT = RD*256.D0/G + REAL(KIND=8), PARAMETER :: EXPON = RD*USSALR/G + REAL(KIND=8), PARAMETER :: EXPONI = 1./EXPON + + END MODULE constants diff --git a/fortran/eqthecalc.f90 b/fortran/eqthecalc.f90 new file mode 100644 index 0000000..9bbd03c --- /dev/null +++ b/fortran/eqthecalc.f90 @@ -0,0 +1,51 @@ +! Theta-e +!NCLFORTSTART +SUBROUTINE DEQTHECALC(qvp, tmk, prs, eth, miy, mjx, mkzh) + USE constants, ONLY : EPS, GAMMA, GAMMAMD, TLCLC1, TLCLC2, TLCLC3, TLCLC4, & + THTECON1, THTECON2, THTECON3 + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: eth + + ! Input variables + ! Sizes + INTEGER,INTENT(IN) :: miy, mjx, mkzh + ! Qvapor [g/kg] + REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(IN) :: qvp + ! Temperature [K] + REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(IN) :: tmk + ! full pressure (=P+PB) [hPa] + REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(IN) :: prs + ! Output variable + ! equivalent potential temperature [K] + REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(OUT) :: eth + +!NCLEND + + ! local variables + REAL(KIND=8) :: q + REAL(KIND=8) :: t + REAL(KIND=8) :: p + REAL(KIND=8) :: e + REAL(KIND=8) :: tlcl + INTEGER :: i, j, k + + DO k = 1,mkzh + DO j = 1,mjx + DO i = 1,miy + q = MAX(qvp(i,j,k), 1.D-15) + t = tmk(i,j,k) + p = prs(i,j,k)/100. + e = q*p/(EPS + q) + tlcl = TLCLC1/(LOG(t**TLCLC2/e) - TLCLC3) + TLCLC4 + eth(i,j,k) = t*(1000.D0/p)**(GAMMA*(1.D0 + GAMMAMD*q))* & + EXP((THTECON1/tlcl - THTECON2)*q*(1.D0 + THTECON3*q)) + END DO + END DO + END DO + + RETURN + +END SUBROUTINE DEQTHECALC diff --git a/src/wrf/wrfcape.f90 b/fortran/reference/wrfcape.f90 similarity index 100% rename from src/wrf/wrfcape.f90 rename to fortran/reference/wrfcape.f90 diff --git a/src/wrf/wrfcape.pyf b/fortran/reference/wrfcape.pyf similarity index 100% rename from src/wrf/wrfcape.pyf rename to fortran/reference/wrfcape.pyf diff --git a/src/wrf/wrfext.f90 b/fortran/reference/wrfext.f90 similarity index 100% rename from src/wrf/wrfext.f90 rename to fortran/reference/wrfext.f90 diff --git a/src/wrf/wrfext.pyf b/fortran/reference/wrfext.pyf similarity index 100% rename from src/wrf/wrfext.pyf rename to fortran/reference/wrfext.pyf diff --git a/src/wrf/wrfext2.f90.BAK b/fortran/reference/wrfext2.f90.BAK similarity index 100% rename from src/wrf/wrfext2.f90.BAK rename to fortran/reference/wrfext2.f90.BAK diff --git a/fortran/ripW.c b/fortran/ripW.c new file mode 100644 index 0000000..b750b28 --- /dev/null +++ b/fortran/ripW.c @@ -0,0 +1,1018 @@ +#include +#include +#include "wrapper.h" + +#define ERRLEN 512 + +extern void NGCALLF(dcapecalc3d,DCAPECALC3D)(double *prs, double *tmk, + double *qvp, double *ght, + double *ter, double *sfp, + double *cape, double *cin, + double *cmsg, + int *miy, int *mjx, int *mkzh, + int *i3dflag, int *ter_follow, + char *,int); + + +/* + * Function for calculating cape (from the RIP code). This function + * depends on the "psadilookup.dat" file, which by default will be + * searched for in $NCARG_ROOT/lib/ncarg/data/asc/), unless + * NCARG_PSADILOOKUP is set to the location of this file. + */ + +/* + * The rip_cape_3d wrapper is for the case where I3DFLAG is set to + * 1 in the Fortran rip_cape.f file. + */ +NhlErrorTypes rip_cape_3d_W( void ) +{ +/* + * Input array variables + */ + void *p, *t, *q, *z, *zsfc, *psfc; + logical *ter_follow; + double *tmp_p = NULL; + double *tmp_t = NULL; + double *tmp_q = NULL; + double *tmp_z = NULL; + double *tmp_zsfc = NULL; + double *tmp_psfc = NULL; + int ndims_p, ndims_t, ndims_q, ndims_z, ndims_zsfc, ndims_psfc; + ng_size_t dsizes_p[NCL_MAX_DIMENSIONS], dsizes_t[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_q[NCL_MAX_DIMENSIONS], dsizes_z[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_zsfc[NCL_MAX_DIMENSIONS], dsizes_psfc[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_p, type_t, type_q, type_z, type_zsfc, type_psfc; + +/* + * Output array variables + */ + void *cape; + double *tmp_cape = NULL, cmsg; + double *tmp_cin = NULL; + NclBasicDataTypes type_cape; + int ndims_cape; + ng_size_t *dsizes_cape; + NclScalar missing_cape; +/* + * File input variables. + */ + const char *path = NULL; + char psa_file[_NhlMAXFNAMELEN]; + int errstat; + char *errmsg; + +/* + * Declare various variables for random purposes. + */ + ng_size_t i; + ng_size_t miy = 0; + ng_size_t mjx = 0; + ng_size_t mkzh = 0; + ng_size_t ntime = 0; + ng_size_t size_cape, size_output, size_zsfc; + ng_size_t index_cape, index_zsfc, index_cin; + int i3dflag=1, scalar_zsfc; + int iter, ret; + int imiy, imjx, imkzh; + +/* + * The default is to use $NCARG_ROOT/lib/ncarg/data/asc/psadilookup.dat + * for the input data file, unless PSADILOOKUP_PATH is set by the + * user, then it will try to use this path. + */ + path = getenv("PSADILOOKUP_PATH"); + if ((void *)path == (void *)NULL) { + path = _NGGetNCARGEnv("data"); + if ((void *)path != (void *)NULL) { + strcpy(psa_file,path); + strcat(psa_file,_NhlPATHDELIMITER); + strcat(psa_file,"asc"); + strcat(psa_file,_NhlPATHDELIMITER); + strcat(psa_file,"psadilookup.dat"); + } + } + else { + strcpy(psa_file,path); + strcat(psa_file,_NhlPATHDELIMITER); + strcat(psa_file,"psadilookup.dat"); + } + +/* + * Retrieve parameters + * + * Note that any of the pointer parameters can be set to NULL, + * which implies you don't care about its value. + * + */ + p = (void*)NclGetArgValue( + 0, + 7, + &ndims_p, + dsizes_p, + NULL, + NULL, + &type_p, + DONT_CARE); + + t = (void*)NclGetArgValue( + 1, + 7, + &ndims_t, + dsizes_t, + NULL, + NULL, + &type_t, + DONT_CARE); + + + q = (void*)NclGetArgValue( + 2, + 7, + &ndims_q, + dsizes_q, + NULL, + NULL, + &type_q, + DONT_CARE); + + z = (void*)NclGetArgValue( + 3, + 7, + &ndims_z, + dsizes_z, + NULL, + NULL, + &type_z, + DONT_CARE); + + zsfc = (void*)NclGetArgValue( + 4, + 7, + &ndims_zsfc, + dsizes_zsfc, + NULL, + NULL, + &type_zsfc, + DONT_CARE); + + psfc = (void*)NclGetArgValue( + 5, + 7, + &ndims_psfc, + dsizes_psfc, + NULL, + NULL, + &type_psfc, + DONT_CARE); + + ter_follow = (logical*)NclGetArgValue( + 6, + 7, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + + if(*ter_follow) iter = 1; + else iter = 0; + +/* + * Check the input dimension sizes. There are three possible cases + * for the input dimension sizes: + * + * - p,t,q,z (time,lev,lat,lon) and psfc,zsfc (time,lat,lon) + * - p,t,q,z (lev,lat,lon) and psfc,zsfc (lat,lon) + * - p,t,q,z (lev) and psfc,zsfc (scalars) + */ + if(ndims_p != ndims_t || ndims_p != ndims_q || ndims_p != ndims_z) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: The p, t, q, and z arrays must all have the same number of dimensions"); + return(NhlFATAL); + } + if(ndims_p != 1 && ndims_p != 3 && ndims_p != 4) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: The p, t, q, and z arrays must be 1-, 3-, or 4-dimensional\n"); + return(NhlFATAL); + } +/* + * zsfc and psfc can be scalars, if the other input arrays are 1D. + */ + scalar_zsfc = is_scalar(ndims_zsfc,dsizes_zsfc); + + if((ndims_zsfc != ndims_psfc) || (scalar_zsfc && ndims_p != 1) || + (!scalar_zsfc && ndims_zsfc != ndims_p-1)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: The zsfc and psfc arrays must have the same number of dimensions, and either be scalars or one less dimension than the other input arrays"); + return(NhlFATAL); + } + +/* + * Now check that the dimension sizes are equal to each other. + */ + for(i = 0; i < ndims_p; i++) { + if(dsizes_p[i] != dsizes_t[i] || dsizes_p[i] != dsizes_q[i] || + dsizes_p[i] != dsizes_z[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: p, t, q, and z must be the same dimensionality"); + return(NhlFATAL); + } + } + + for(i = 0; i < ndims_psfc; i++) { + if(dsizes_psfc[i] != dsizes_zsfc[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: psfc and zsfc must be the same dimensionality"); + return(NhlFATAL); + } + } +/* + * Get sizes of input arrays. + */ + if(ndims_p == 4) { + ntime = dsizes_p[0]; /* time, serves as a leftmost dimension */ + mkzh = dsizes_p[1]; /* lev */ + mjx = dsizes_p[2]; /* lat */ + miy = dsizes_p[3]; /* lon */ + } + else if(ndims_p == 3) { + ntime = 1; + mkzh = dsizes_p[0]; /* lev */ + mjx = dsizes_p[1]; /* lat */ + miy = dsizes_p[2]; /* lon */ + } + else if(ndims_p == 1) { + ntime = 1; + mkzh = dsizes_p[0]; /* lev */ + mjx = 1; /* lat */ + miy = 1; /* lon */ + } + +/* + * Test input dimension sizes. + */ + if((miy > INT_MAX) || (mjx > INT_MAX) || (mkzh > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: one or more input dimension sizes is greater than INT_MAX"); + return(NhlFATAL); + } + imiy = (int) miy; + imjx = (int) mjx; + imkzh = (int) mkzh; + +/* + * Check some more dimension sizes. + */ + if(ndims_p == 4) { + if(dsizes_psfc[0] != ntime || dsizes_psfc[1] != mjx || + dsizes_psfc[2] != miy) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: If p,q,t,z are 4-dimensional (time x lev x lat x lon), psfc,zsfc must be 3-dimensional (time x lat x lon)"); + return(NhlFATAL); + } + } + if(ndims_p == 3) { + if(dsizes_psfc[0] != mjx || dsizes_psfc[1] != miy) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: If p,q,t,z are 3-dimensional (time x lev x lat x lon), psfc,zsfc must be 2-dimensional (lat x lon)"); + return(NhlFATAL); + } + } +/* + * Calculate size of output array. The output array size depends on + * the size of p,t,q,z: + * + * - p,t,q,z (time,lev,lat,lon) and psfc,zsfc (time,lat,lon) + * output array: (2,time,lev,lat,lon) + * - p,t,q,z (lev,lat,lon) and psfc,zsfc (lat,lon) + * output array: (2,lev,lat,lon) + * - p,t,q,z (lev) and psfc,zsfc (scalars) + * output array: (2,lev) + */ + ndims_cape = ndims_p+1; + dsizes_cape = (ng_size_t *)calloc(ndims_cape,sizeof(ng_size_t)); + if(dsizes_cape == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: Unable to allocate memory for array dimensionality"); + return(NhlFATAL); + } + + dsizes_cape[0] = 2; /* 0 = cape, 1 = cin */ + for(i = 0; i < ndims_p; i++ ) { + dsizes_cape[i+1] = dsizes_p[i]; + } + size_zsfc = mjx * miy; + size_cape = mkzh * size_zsfc; /* Also size of cin array */ + size_output = 2 * size_cape * ntime; + +/* + * Allocate space for output arrays. If any of the input is already double, + * then we don't need to allocate space for temporary arrays, because + * we'll just change the pointer into the void array appropriately. + */ + if(type_p == NCL_double || type_t == NCL_double || type_q == NCL_double || + type_z == NCL_double) { + type_cape = NCL_double; + cape = (double *)calloc(size_output,sizeof(double)); + missing_cape.doubleval = ((NclTypeClass)nclTypedoubleClass)->type_class.default_mis.doubleval; + cmsg = missing_cape.doubleval; + if(cape == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + else { + type_cape = NCL_float; + cape = (float *)calloc(size_output,sizeof(float)); + tmp_cape = (double *)calloc(size_cape,sizeof(double)); + tmp_cin = (double *)calloc(size_cape,sizeof(double)); + if(cape == NULL || tmp_cape == NULL || tmp_cin == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: Unable to allocate memory for output arrays"); + return(NhlFATAL); + } + missing_cape.floatval = ((NclTypeClass)nclTypefloatClass)->type_class.default_mis.floatval; + cmsg = (double)missing_cape.floatval; + } + +/* + * Allocate memory for allocating input arrays to double, if necessary. + */ + if(type_p != NCL_double) { + tmp_p = (double *)calloc(size_cape,sizeof(double)); + if(tmp_p == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_t != NCL_double) { + tmp_t = (double *)calloc(size_cape,sizeof(double)); + if(tmp_t == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_q != NCL_double) { + tmp_q = (double *)calloc(size_cape,sizeof(double)); + if(tmp_q == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_z != NCL_double) { + tmp_z = (double *)calloc(size_cape,sizeof(double)); + if(tmp_z == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_zsfc != NCL_double) { + tmp_zsfc = (double *)calloc(size_zsfc,sizeof(double)); + if(tmp_zsfc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_psfc != NCL_double) { + tmp_psfc = (double *)calloc(size_zsfc,sizeof(double)); + if(tmp_psfc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_3d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + /* Allocate space for errmsg*/ + errmsg = (char *) calloc(ERRLEN, sizeof(char)) + +/* + * Call the Fortran routine. + */ + index_cape = index_zsfc = 0; + index_cin = ntime * size_cape; /* Second half of output array */ + + for(i = 0; i < ntime; i++) { +/* + * Coerce subset of input arrays to double if necessary. + */ + if(type_p != NCL_double) { + coerce_subset_input_double(p,tmp_p,index_cape,type_p,size_cape,0,NULL,NULL); + } + else { +/* + * Point tmp_p to appropriate location in p. + */ + tmp_p = &((double*)p)[index_cape]; + } + if(type_t != NCL_double) { + coerce_subset_input_double(t,tmp_t,index_cape,type_t,size_cape,0,NULL,NULL); + } + else { +/* + * Point tmp_t to appropriate location in t. + */ + tmp_t = &((double*)t)[index_cape]; + } + if(type_q != NCL_double) { + coerce_subset_input_double(q,tmp_q,index_cape,type_q,size_cape,0,NULL,NULL); + } + else { +/* + * Point tmp_q to appropriate location in q. + */ + tmp_q = &((double*)q)[index_cape]; + } + if(type_z != NCL_double) { + coerce_subset_input_double(z,tmp_z,index_cape,type_z,size_cape,0,NULL,NULL); + } + else { +/* + * Point tmp_z to appropriate location in z. + */ + tmp_z = &((double*)z)[index_cape]; + } + + if(type_psfc != NCL_double) { + coerce_subset_input_double(psfc,tmp_psfc,index_zsfc,type_psfc, + size_zsfc,0,NULL,NULL); + } + else { +/* + * Point tmp_psfc to appropriate location in psfc. + */ + tmp_psfc = &((double*)psfc)[index_zsfc]; + } + if(type_zsfc != NCL_double) { + coerce_subset_input_double(zsfc,tmp_zsfc,index_zsfc,type_zsfc, + size_zsfc,0,NULL,NULL); + } + else { +/* + * Point tmp_zsfc to appropriate location in zsfc. + */ + tmp_zsfc = &((double*)zsfc)[index_zsfc]; + } + +/* + * Point tmp_cape and tmp_cin to appropriate location in cape + * if necessary + */ + if(type_cape == NCL_double) { + tmp_cape = &((double*)cape)[index_cape]; + tmp_cin = &((double*)cape)[index_cin]; + } + + + errstat = 0; + errmsg = ""; +/* + * Call Fortran routine. + */ + NGCALLF(dcapecalc3d,DCAPECALC3D)(tmp_p, tmp_t, tmp_q, tmp_z, tmp_zsfc, + tmp_psfc, tmp_cape, tmp_cin, &cmsg, + &imiy, &imjx, &imkzh, &i3dflag, &iter, + psa_file,errstat,errmsg,strlen(psa_file), + ERRLEN); + +/* Terminate if there was an error */ + if (errstat != 0) { + fprintf(stderr, errmsg); + exit(errstat); + } + +/* + * If the output is to be float, then do the coercion here. + */ + if(type_cape == NCL_float) { + coerce_output_float_only(cape,tmp_cape,size_cape,index_cape); + coerce_output_float_only(cape,tmp_cin,size_cape,index_cin); + } +/* + * Implement the pointers into the arrays. + */ + index_cape += size_cape; + index_cin += size_cape; + index_zsfc += size_zsfc; + } +/* + * Free memory. + */ + if(type_p != NCL_double) NclFree(tmp_p); + if(type_t != NCL_double) NclFree(tmp_t); + if(type_q != NCL_double) NclFree(tmp_q); + if(type_z != NCL_double) NclFree(tmp_z); + if(type_zsfc != NCL_double) NclFree(tmp_zsfc); + if(type_psfc != NCL_double) NclFree(tmp_psfc); + if(type_cape != NCL_double) NclFree(tmp_cape); + if(type_cape != NCL_double) NclFree(tmp_cin); + NclFree(errmsg); +/* + * Set up variable to return. + */ + ret = NclReturnValue(cape,ndims_cape,dsizes_cape,&missing_cape,type_cape,0); + NclFree(dsizes_cape); + return(ret); +} + + +/* + * The rip_cape_2d wrapper is for the case where I3DFLAG is set to + * 0 in the Fortran rip_cape.f file. In this case, 4 2D arrays + * are returned: cape, cin, lcl, and lfc, but they are all returned + * in one big array whose leftmost dimension is 4: + * + * index 0 = cape + * index 1 = cin + * index 2 = lcl + * index 3 = lfc + */ +NhlErrorTypes rip_cape_2d_W( void ) +{ +/* + * Input array variables + */ + void *p, *t, *q, *z, *zsfc, *psfc; + logical *ter_follow; + double *tmp_p = NULL; + double *tmp_t = NULL; + double *tmp_q = NULL; + double *tmp_z = NULL; + double *tmp_zsfc = NULL; + double *tmp_psfc = NULL; + int ndims_p, ndims_t, ndims_q, ndims_z, ndims_zsfc, ndims_psfc; + ng_size_t dsizes_p[NCL_MAX_DIMENSIONS], dsizes_t[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_q[NCL_MAX_DIMENSIONS], dsizes_z[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_zsfc[NCL_MAX_DIMENSIONS], dsizes_psfc[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_p, type_t, type_q, type_z, type_zsfc, type_psfc; + +/* + * Output array variables + */ + void *cape; + double *tmp_cape = NULL, cmsg; + double *tmp_cin = NULL; + NclBasicDataTypes type_cape; + int ndims_cape = 0; + NclScalar missing_cape; + ng_size_t *dsizes_cape; +/* + * File input variables. + */ + const char *path = NULL; + char psa_file[_NhlMAXFNAMELEN]; + int errstat; + char *errmsg; + +/* + * Declare various variables for random purposes. + */ + ng_size_t i; + ng_size_t miy = 0; + ng_size_t mjx = 0; + ng_size_t mkzh = 0; + ng_size_t ntime = 0; + ng_size_t size_cape, size_output, size_zsfc; + ng_size_t size_left_zsfc; + int i3dflag=0; + ng_size_t index_cape, index_zsfc; + ng_size_t index_output_cape, index_output_cin, index_output_lcl; + ng_size_t index_output_lfc, mkzh0_index, mkzh1_index, mkzh2_index; + int iter, ret; + int imiy, imjx, imkzh; + +/* + * The default is to use $NCARG_ROOT/lib/ncarg/data/asc/psadilookup.dat + * for the input data file, unless PSADILOOKUP_PATH is set by the + * user, then it will try to use this path. + */ + path = getenv("PSADILOOKUP_PATH"); + if ((void *)path == (void *)NULL) { + path = _NGGetNCARGEnv("data"); + if ((void *)path != (void *)NULL) { + strcpy(psa_file,path); + strcat(psa_file,_NhlPATHDELIMITER); + strcat(psa_file,"asc"); + strcat(psa_file,_NhlPATHDELIMITER); + strcat(psa_file,"psadilookup.dat"); + } + } + else { + strcpy(psa_file,path); + strcat(psa_file,_NhlPATHDELIMITER); + strcat(psa_file,"psadilookup.dat"); + } + +/* + * Retrieve parameters + * + * Note that any of the pointer parameters can be set to NULL, + * which implies you don't care about its value. + * + */ + p = (void*)NclGetArgValue( + 0, + 7, + &ndims_p, + dsizes_p, + NULL, + NULL, + &type_p, + DONT_CARE); + + t = (void*)NclGetArgValue( + 1, + 7, + &ndims_t, + dsizes_t, + NULL, + NULL, + &type_t, + DONT_CARE); + + + q = (void*)NclGetArgValue( + 2, + 7, + &ndims_q, + dsizes_q, + NULL, + NULL, + &type_q, + DONT_CARE); + + z = (void*)NclGetArgValue( + 3, + 7, + &ndims_z, + dsizes_z, + NULL, + NULL, + &type_z, + DONT_CARE); + + zsfc = (void*)NclGetArgValue( + 4, + 7, + &ndims_zsfc, + dsizes_zsfc, + NULL, + NULL, + &type_zsfc, + DONT_CARE); + + psfc = (void*)NclGetArgValue( + 5, + 7, + &ndims_psfc, + dsizes_psfc, + NULL, + NULL, + &type_psfc, + DONT_CARE); + + ter_follow = (logical*)NclGetArgValue( + 6, + 7, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + + if(*ter_follow) iter = 1; + else iter = 0; + + +/* + * Check the input dimension sizes. There are two possible cases + * for the input dimension sizes: + * + * - p,t,q,z (time,lev,lat,lon) and psfc,zsfc (time,lat,lon) + * - p,t,q,z (lev,lat,lon) and psfc,zsfc (lat,lon) + */ + if(ndims_p != ndims_t || ndims_p != ndims_q || ndims_p != ndims_z) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: The p, t, q, and z arrays must all have the same number of dimensions"); + return(NhlFATAL); + } + if(ndims_p != 3 && ndims_p != 4) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: The p, t, q, and z arrays must be 3 or 4-dimensional\n"); + return(NhlFATAL); + } +/* + * Check zsfc and psfc dimension sizes. + */ + if((ndims_zsfc != ndims_psfc) || (ndims_zsfc != ndims_p-1)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: The zsfc and psfc arrays must have the same number of dimensions and be one less dimension than the other input arrays"); + return(NhlFATAL); + } + +/* + * Now check that the dimension sizes are equal to each other. + */ + for(i = 0; i < ndims_p; i++) { + if(dsizes_p[i] != dsizes_t[i] || dsizes_p[i] != dsizes_q[i] || + dsizes_p[i] != dsizes_z[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: p, t, q, and z must be the same dimensionality"); + return(NhlFATAL); + } + } + + for(i = 0; i < ndims_psfc; i++) { + if(dsizes_psfc[i] != dsizes_zsfc[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: psfc and zsfc must be the same dimensionality"); + return(NhlFATAL); + } + } + if(ndims_p == 4) { +/* + * Store dimension sizes. + */ + ntime = dsizes_p[0]; /* time */ + mkzh = dsizes_p[1]; /* lev */ + mjx = dsizes_p[2]; /* lat */ + miy = dsizes_p[3]; /* lon */ + ndims_cape = 4; + if(dsizes_psfc[0] != ntime || dsizes_psfc[1] != mjx || + dsizes_psfc[2] != miy) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: If p,q,t,z are 4-dimensional (time x lev x lat x lon), psfc,zsfc must be 3-dimensional (time x lat x lon)"); + return(NhlFATAL); + + } + } + else if(ndims_p == 3) { +/* + * Store dimension sizes. + */ + ntime = 1; + mkzh = dsizes_p[0]; /* lev */ + mjx = dsizes_p[1]; /* lat */ + miy = dsizes_p[2]; /* lon */ + ndims_cape = 3; + if(dsizes_psfc[0] != mjx || dsizes_psfc[1] != miy) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: If p,q,t,z are 3-dimensional (time x lev x lat x lon), psfc,zsfc must be 2-dimensional (lat x lon)"); + return(NhlFATAL); + } + } +/* + * If mkzh is not at least size 3, then this dimension won't be big + * enough to contain the cin, lcl, and lfc values. + */ + if(mkzh < 3) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: The level dimension must have at least 3 elements"); + return(NhlFATAL); + } + +/* + * Test input dimension sizes. + */ + if((miy > INT_MAX) || (mjx > INT_MAX) || (mkzh > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: one or more input dimension sizes is greater than INT_MAX"); + return(NhlFATAL); + } + imiy = (int) miy; + imjx = (int) mjx; + imkzh = (int) mkzh; + + +/* + * Calculate size of output array. The output array size depends on + * the size of p,t,q,z: + * + * - p,t,q,z (time,lev,lat,lon) and psfc,zsfc (time,lat,lon) + * output array: (4,time,lat,lon) + * - p,t,q,z (lev,lat,lon) and psfc,zsfc (lat,lon) + * output array: (4,lat,lon) + */ + dsizes_cape = (ng_size_t *)calloc(ndims_cape,sizeof(ng_size_t)); + if(dsizes_cape == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: Unable to allocate memory for array dimensionality"); + return(NhlFATAL); + } + + dsizes_cape[0] = 4; /* To hold the 4 different variables. */ + /* 0=cape, 1=cin, 2=lcl, 3=lfc */ + dsizes_cape[ndims_cape-1] = miy; + dsizes_cape[ndims_cape-2] = mjx; + if(ndims_cape == 4) dsizes_cape[1] = ntime; + + size_zsfc = mjx * miy; + size_cape = mkzh * size_zsfc; + mkzh0_index = (mkzh-1) * size_zsfc; /* Indexes into cin array for */ + mkzh1_index = (mkzh-2) * size_zsfc; /* returning cin, lcl, and lfc */ + mkzh2_index = (mkzh-3) * size_zsfc; /* respectively. */ + size_left_zsfc = size_zsfc * ntime; + size_output = 4 * size_left_zsfc; + +/* + * Allocate space for output and temporary arrays. Even if the input + * arrays are already double, go ahead and allocate some space for + * them b/c we have to copy the values back to 4 different locations. + * + * The addition of missing values was added in V6.1.0. + */ + if(type_p == NCL_double || type_t == NCL_double || type_q == NCL_double || + type_z == NCL_double) { + type_cape = NCL_double; + cape = (double *)calloc(size_output,sizeof(double)); + missing_cape.doubleval = ((NclTypeClass)nclTypedoubleClass)->type_class.default_mis.doubleval; + cmsg = missing_cape.doubleval; + } + else { + type_cape = NCL_float; + cape = (float *)calloc(size_output,sizeof(float)); + missing_cape.floatval = ((NclTypeClass)nclTypefloatClass)->type_class.default_mis.floatval; + cmsg = (double)missing_cape.floatval; + } + tmp_cape = (double *)calloc(size_cape,sizeof(double)); + tmp_cin = (double *)calloc(size_cape,sizeof(double)); + if(cape == NULL || tmp_cape == NULL || tmp_cin == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: Unable to allocate memory for output arrays"); + return(NhlFATAL); + } + +/* + * Allocate memory for allocating input arrays to double, if necessary. + */ + if(type_p != NCL_double) { + tmp_p = (double *)calloc(size_cape,sizeof(double)); + if(tmp_p == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_t != NCL_double) { + tmp_t = (double *)calloc(size_cape,sizeof(double)); + if(tmp_t == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_q != NCL_double) { + tmp_q = (double *)calloc(size_cape,sizeof(double)); + if(tmp_q == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_z != NCL_double) { + tmp_z = (double *)calloc(size_cape,sizeof(double)); + if(tmp_z == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_zsfc != NCL_double) { + tmp_zsfc = (double *)calloc(size_zsfc,sizeof(double)); + if(tmp_zsfc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_psfc != NCL_double) { + tmp_psfc = (double *)calloc(size_zsfc,sizeof(double)); + if(tmp_psfc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"rip_cape_2d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + /* Allocate space for errmsg*/ + errmsg = (char *) calloc(ERRLEN, sizeof(char)) + +/* + * Call the Fortran routine. + */ + index_cape = index_zsfc = 0; + index_output_cape = 0; + index_output_cin = size_left_zsfc; + index_output_lcl = 2 * size_left_zsfc; + index_output_lfc = 3 * size_left_zsfc; + + for(i = 0; i < ntime; i++) { +/* + * Coerce subset of input arrays to double if necessary. + */ + if(type_p != NCL_double) { + coerce_subset_input_double(p,tmp_p,index_cape,type_p,size_cape,0,NULL,NULL); + } + else { +/* + * Point tmp_p to appropriate location in p. + */ + tmp_p = &((double*)p)[index_cape]; + } + if(type_t != NCL_double) { + coerce_subset_input_double(t,tmp_t,index_cape,type_t,size_cape,0,NULL,NULL); + } + else { +/* + * Point tmp_t to appropriate location in t. + */ + tmp_t = &((double*)t)[index_cape]; + } + if(type_q != NCL_double) { + coerce_subset_input_double(q,tmp_q,index_cape,type_q,size_cape,0,NULL,NULL); + } + else { +/* + * Point tmp_q to appropriate location in q. + */ + tmp_q = &((double*)q)[index_cape]; + } + if(type_z != NCL_double) { + coerce_subset_input_double(z,tmp_z,index_cape,type_z,size_cape,0,NULL,NULL); + } + else { +/* + * Point tmp_z to appropriate location in z. + */ + tmp_z = &((double*)z)[index_cape]; + } + + if(type_psfc != NCL_double) { + coerce_subset_input_double(psfc,tmp_psfc,index_zsfc,type_psfc, + size_zsfc,0,NULL,NULL); + } + else { +/* + * Point tmp_psfc to appropriate location in psfc. + */ + tmp_psfc = &((double*)psfc)[index_zsfc]; + } + if(type_zsfc != NCL_double) { + coerce_subset_input_double(zsfc,tmp_zsfc,index_zsfc,type_zsfc, + size_zsfc,0,NULL,NULL); + } + else { +/* + * Point tmp_zsfc to appropriate location in zsfc. + */ + tmp_zsfc = &((double*)zsfc)[index_zsfc]; + } + +/* + * Call Fortran routine. + */ + NGCALLF(dcapecalc3d,DCAPECALC3D)(tmp_p, tmp_t, tmp_q, tmp_z, tmp_zsfc, + tmp_psfc, tmp_cape, tmp_cin, &cmsg, + &imiy, &imjx, &imkzh, &i3dflag, &iter, + psa_file,errstat,errmsg,strlen(psa_file), + ERRLEN); + +/* Terminate if there was an error */ + if (errstat != 0) { + fprintf(stderr, errmsg); + exit(errstat); + } + +/* + * Copy the values back out to the correct places in the "cape" array. + * + * This is a bit whacky, because the Fortran code is doing something + * fancy to save memory. The "tmp_cin" array contains the cin values in + * the last mkzh section, the lcl values in the 2nd-to-last mkzh + * section, and the lfc values in the 3rd-to-last mkzh section. + * + * The "tmp_cape" array contains its values in the last mkzh section + * of the tmp_cape array. + */ + coerce_output_float_or_double(cape,&tmp_cape[mkzh0_index],type_cape, + size_zsfc,index_output_cape); + coerce_output_float_or_double(cape,&tmp_cin[mkzh0_index],type_cape, + size_zsfc,index_output_cin); + coerce_output_float_or_double(cape,&tmp_cin[mkzh1_index],type_cape, + size_zsfc,index_output_lcl); + coerce_output_float_or_double(cape,&tmp_cin[mkzh2_index],type_cape, + size_zsfc,index_output_lfc); +/* + * Implement the pointers into the arrays. + */ + index_cape += size_cape; + index_zsfc += size_zsfc; + index_output_cape += size_zsfc; + index_output_cin += size_zsfc; + index_output_lcl += size_zsfc; + index_output_lfc += size_zsfc; + } +/* + * Free memory. + */ + if(type_p != NCL_double) NclFree(tmp_p); + if(type_t != NCL_double) NclFree(tmp_t); + if(type_q != NCL_double) NclFree(tmp_q); + if(type_z != NCL_double) NclFree(tmp_z); + if(type_zsfc != NCL_double) NclFree(tmp_zsfc); + if(type_psfc != NCL_double) NclFree(tmp_psfc); + NclFree(tmp_cape); + NclFree(tmp_cin); + NclFree(errmsg); +/* + * Set up variable to return. + */ + ret = NclReturnValue(cape,ndims_cape,dsizes_cape,&missing_cape,type_cape,0); + NclFree(dsizes_cape); + return(ret); +} + diff --git a/fortran/rip_cape.f90 b/fortran/rip_cape.f90 new file mode 100644 index 0000000..b97adb9 --- /dev/null +++ b/fortran/rip_cape.f90 @@ -0,0 +1,617 @@ +!====================================================================== +! +! !IROUTINE: VIRTUAL -- Calculate virtual temperature (K) +! +! !DESCRIPTION: +! +! This function returns a single value of virtual temperature in +! K, given temperature in K and mixing ratio in kg/kg. For an +! array of virtual temperatures, use subroutine VIRTUAL_TEMP. +! +! !INPUT: +! RATMIX - water vapor mixing ratio (kg/kg) +! TEMP - temperature (K) +! +! !OUTPUT: +! TV - Virtual temperature (K) +! + +! NCLFORTSTART +REAL(KIND=8) FUNCTION TVIRTUAL(temp, ratmix) + USE constants, ONLY : EPS + + !f2py threadsafe + + IMPLICIT NONE + REAL(KIND=8), INTENT(IN) :: temp, ratmix + +! NCLEND + + TVIRTUAL = temp*(EPS + ratmix)/(EPS*(1.D0 + ratmix)) + + RETURN + +END FUNCTION TVIRTUAL + +! NCLFORTSTART +REAL(KIND=8) FUNCTION TONPSADIABAT(thte,prs,psadithte,psadiprs,psaditmk,gamma,& + errstat, errmsg) + USE constants, ONLY : ALGERR + + !f2py threadsafe + !f2py intent(in,out) :: cape, cin + + IMPLICIT NONE + REAL(KIND=8), INTENT(IN) :: thte + REAL(KIND=8), INTENT(IN) :: prs + REAL(KIND=8), DIMENSION(150), INTENT(IN) :: psadithte + REAL(KIND=8), DIMENSION(150), INTENT(IN) :: psadiprs + REAL(KIND=8), DIMENSION(150,150), INTENT(IN) :: psaditmk + REAL(KIND=8), INTENT(IN) :: gamma + INTEGER, INTENT(INOUT) :: errstat + CHARACTER(LEN=*), INTENT(INOUT) :: errmsg + +! NCLEND + + REAL(KIND=8) :: fracjt + REAL(KIND=8) :: fracjt2 + REAL(KIND=8) :: fracip + REAL(KIND=8) :: fracip2 + + INTEGER :: ip, ipch, jt, jtch + + ! This function gives the temperature (in K) on a moist adiabat + ! (specified by thte in K) given pressure in hPa. It uses a + ! lookup table, with data that was generated by the Bolton (1980) + ! formula for theta_e. + + ! First check if pressure is less than min pressure in lookup table. + ! If it is, assume parcel is so dry that the given theta-e value can + ! be interpretted as theta, and get temperature from the simple dry + ! theta formula. + + IF (prs .LE. psadiprs(150)) THEN + TONPSADIABAT = thte * (prs/1000.D0)**gamma + RETURN + END IF + + ! Otherwise, look for the given thte/prs point in the lookup table. + + jt = -1 + DO jtch = 1, 150-1 + IF (thte .GE. psadithte(jtch) .AND. thte .LT. psadithte(jtch+1)) THEN + jt = jtch + EXIT + !GO TO 213 + END IF + END DO + + ip = -1 + DO ipch = 1, 150-1 + IF (prs .LE. psadiprs(ipch) .AND. prs .GT. psadiprs(ipch+1)) THEN + ip = ipch + EXIT + !GO TO 215 + END IF + END DO + + IF (jt .EQ. -1 .OR. ip .EQ. -1) THEN + ! Set the error and return + TONPSADIABAT = -1 + errstat = ALGERR + WRITE(errmsg, *) "capecalc3d: Outside of lookup table bounds. prs,thte=", prs, thte + RETURN + END IF + + fracjt = (thte-psadithte(jt)) / (psadithte(jt+1)-psadithte(jt)) + fracjt2 = 1.D0 - fracjt + fracip = (psadiprs(ip)-prs) / (psadiprs(ip)-psadiprs(ip+1)) + fracip2 = 1.D0 - fracip + + IF (psaditmk(ip,jt) .GT. 1D9 .OR. psaditmk(ip+1,jt) .GT. 1D9 .OR. & + psaditmk(ip,jt+1) .GT. 1D9 .OR. psaditmk(ip+1,jt+1) .GT. 1D9) THEN + ! Set the error and return + TONPSADIABAT = -1 + errstat = ALGERR + WRITE(errmsg, *) "capecalc3d: Tried to access missing temperature in lookup table. ", & + "Prs and Thte probably unreasonable. prs,thte=", prs, thte + RETURN + END IF + + TONPSADIABAT = fracip2*fracjt2*psaditmk(ip,jt) + fracip*fracjt2*psaditmk(ip+1,jt) + & + fracip2*fracjt*psaditmk(ip,jt+1) + fracip*fracjt*psaditmk(ip+1,jt+1) + + RETURN + +END FUNCTION TONPSADIABAT + +!NCLFORTSTART +SUBROUTINE DLOOKUP_TABLE(psadithte, psadiprs, psaditmk, fname, errstat, errmsg) + USE constants, ONLY : ALGERR + + !f2py threadsafe + + REAL(KIND=8), DIMENSION(150), INTENT(INOUT) :: psadithte, psadiprs + REAL(KIND=8), DIMENSION(150,150), INTENT(INOUT) :: psaditmk + CHARACTER(LEN=*), INTENT(IN) :: fname + INTEGER, INTENT(INOUT) :: errstat + CHARACTER(LEN=*), INTENT(INOUT) :: errmsg + +!NCLEND + + ! Locals + INTEGER :: iustnlist, i, nthte, nprs, ip, jt + + ! FNAME = 'psadilookup.dat' + iustnlist = 33 + OPEN (UNIT=iustnlist, FILE=fname, FORM='formatted', STATUS='old') + + DO i = 1,14 + READ (iustnlist, FMT=*) + END DO + + READ (iustnlist, FMT=*) nthte, nprs + + IF (nthte .NE. 150 .OR. nprs .NE. 150) THEN + errstat = ALGERR + errmsg = "Number of pressure or theta_e levels in lookup table file not 150" + RETURN + END IF + + READ (iustnlist, FMT="(5D15.7)") (psadithte(jt),jt=1,nthte) + READ (iustnlist, FMT="(5D15.7)") (psadiprs(ip),ip=1,nprs) + READ (iustnlist, FMT="(5D15.7)") ((psaditmk(ip,jt),ip=1,nprs),jt=1,nthte) + + CLOSE (iustnlist) + + RETURN + +END SUBROUTINE DLOOKUP_TABLE + + +! Historically, this routine calculated the pressure at full sigma +! levels when RIP was specifically designed for MM4/MM5 output. +! With the new generalized RIP (Feb '02), this routine is still +! intended to calculate a set of pressure levels that bound the +! layers represented by the vertical grid points, although no such +! layer boundaries are assumed to be defined. The routine simply +! uses the midpoint between the pressures of the vertical grid +! points as the bounding levels. The array only contains mkzh +! levels, so the pressure of the top of the uppermost layer is +! actually excluded. The kth value of pf is the lower bounding +! pressure for the layer represented by kth data level. At the +! lower bounding level of the lowest model layer, it uses the +! surface pressure, unless the data set is pressure-level data, in +! which case it assumes the lower bounding pressure level is as far +! below the lowest vertical level as the upper bounding pressure +! level is above. +SUBROUTINE DPFCALC(prs, sfp, pf, miy, mjx, mkzh, ter_follow) + + REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(IN) :: prs + REAL(KIND=8), DIMENSION(miy,mjx), INTENT(IN) :: sfp + REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(OUT) :: pf + INTEGER, INTENT(IN) :: ter_follow,miy,mjx,mkzh + + INTEGER :: i,j,k + + ! do j=1,mjx-1 Artifact of MM5 + DO j = 1,mjx + ! do i=1,miy-1 staggered grid + DO i = 1,miy + DO k = 1,mkzh + IF (k .EQ. mkzh) THEN + ! terrain-following data + IF (ter_follow .EQ. 1) THEN + pf(i,j,k) = sfp(i,j) + ! pressure-level data + ELSE + pf(i,j,k) = .5D0 * (3.D0*prs(i,j,k) - prs(i,j,k-1)) + END IF + ELSE + pf(i,j,k) = .5D0 * (prs(i,j,k+1) + prs(i,j,k)) + END IF + END DO + END DO + END DO + + RETURN + +END SUBROUTINE DPFCALC + +!====================================================================== +! +! !IROUTINE: capecalc3d -- Calculate CAPE and CIN +! +! !DESCRIPTION: +! +! If i3dflag=1, this routine calculates CAPE and CIN (in m**2/s**2, +! or J/kg) for every grid point in the entire 3D domain (treating +! each grid point as a parcel). If i3dflag=0, then it +! calculates CAPE and CIN only for the parcel with max theta-e in +! the column, (i.e. something akin to Colman's MCAPE). By "parcel", +! we mean a 500-m deep parcel, with actual temperature and moisture +! averaged over that depth. +! +! In the case of i3dflag=0, +! CAPE and CIN are 2D fields that are placed in the k=mkzh slabs of +! the cape and cin arrays. Also, if i3dflag=0, LCL and LFC heights +! are put in the k=mkzh-1 and k=mkzh-2 slabs of the cin array. +! + + +! Important! The z-indexes must be arranged so that mkzh (max z-index) is the +! surface pressure. So, pressure must be ordered in ascending order before +! calling this routine. Other variables must be ordered the same (p,tk,q,z). + +! Also, be advised that missing data values are not checked during the computation. +! Also also, Pressure must be hPa + +! NCLFORTSTART +SUBROUTINE DCAPECALC3D(prs,tmk,qvp,ght,ter,sfp,cape,cin,& + cmsg,miy,mjx,mkzh,i3dflag,ter_follow,& + psafile, errstat, errmsg) + USE constants, ONLY : ALGERR, CELKEL, G, EZERO, ESLCON1, ESLCON2, & + EPS, RD, CP, GAMMA, CPMD, RGASMD, GAMMAMD, TLCLC1, & + TLCLC2, TLCLC3, TLCLC4, THTECON1, THTECON2, THTECON3 + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: cape, cin + + INTEGER, INTENT(IN) :: miy,mjx,mkzh,i3dflag,ter_follow + REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(IN) :: prs + REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(IN) :: tmk + REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(IN) :: qvp + REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(IN) :: ght + REAL(KIND=8), DIMENSION(miy,mjx), INTENT(IN) :: ter + REAL(KIND=8), DIMENSION(miy,mjx), INTENT(IN) ::sfp + REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(OUT) :: cape + REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(OUT) :: cin + REAL(KIND=8), INTENT(IN) :: cmsg + CHARACTER(LEN=*), INTENT(IN) :: psafile + INTEGER, INTENT(INOUT) :: errstat + CHARACTER(LEN=*), INTENT(INOUT) :: errmsg + +! NCLFORTEND + + ! local variables + INTEGER :: i, j, k, ilcl, kel, kk, klcl, klev, klfc, kmax, kpar, kpar1, kpar2 + REAL(KIND=8) :: davg, ethmax, q, t, p, e, eth, tlcl, zlcl + REAL(KIND=8) :: pavg, tvirtual, p1, p2, pp1, pp2, th, totthe, totqvp, totprs + REAL(KIND=8) :: cpm, deltap, ethpari, gammam, ghtpari, qvppari, prspari, tmkpari + REAL(KIND=8) :: facden, fac1, fac2, qvplift, tmklift, tvenv, tvlift, ghtlift + REAL(KIND=8) :: eslift, tmkenv, qvpenv, tonpsadiabat + REAL(KIND=8) :: benamin, dz, pup, pdn + REAL(KIND=8), DIMENSION(150) :: buoy, zrel, benaccum + REAL(KIND=8), DIMENSION(miy,mjx,mkzh) :: prsf + REAL(KIND=8), DIMENSION(150) :: psadithte, psadiprs + REAL(KIND=8), DIMENSION(150,150) :: psaditmk + LOGICAL :: elfound + + ! To remove compiler warnings + tmkpari = 0 + qvppari = 0 + klev = 0 + klcl = 0 + kel = 0 + + + ! the comments were taken from a mark stoelinga email, 23 apr 2007, + ! in response to a user getting the "outside of lookup table bounds" + ! error message. + + ! tmkpari - initial temperature of parcel, k + ! values of 300 okay. (not sure how much from this you can stray.) + + ! prspari - initial pressure of parcel, hpa + ! values of 980 okay. (not sure how much from this you can stray.) + + ! thtecon1, thtecon2, thtecon3 + ! these are all constants, the first in k and the other two have + ! no units. values of 3376, 2.54, and 0.81 were stated as being + ! okay. + + ! tlcl - the temperature at the parcel's lifted condensation level, k + ! should be a reasonable atmospheric temperature around 250-300 k + ! (398 is "way too high") + + ! qvppari - the initial water vapor mixing ratio of the parcel, + ! kg/kg (should range from 0.000 to 0.025) + ! + + ! calculated the pressure at full sigma levels (a set of pressure + ! levels that bound the layers represented by the vertical grid points) + + CALL DPFCALC(prs, sfp, prsf, miy, mjx, mkzh, ter_follow) + + ! before looping, set lookup table for getting temperature on + ! a pseudoadiabat. + + CALL DLOOKUP_TABLE(psadithte, psadiprs, psaditmk, psafile, errstat, errmsg) + + IF (errstat .NE. 0) THEN + RETURN + END IF + + ! do j=1,mjx-1 + DO j = 1,mjx + ! do i=1,miy-1 + DO i = 1,miy + cape(i,j,1) = 0.d0 + cin(i,j,1) = 0.d0 + + IF (i3dflag .EQ. 1) THEN + kpar1 = 2 + kpar2 = mkzh + ELSE + ! find parcel with max theta-e in lowest 3 km agl. + ethmax = -1.d0 + DO k = mkzh,1,-1 + IF (ght(i,j,k)-ter(i,j) .LT. 3000.d0) THEN + q = MAX(qvp(i,j,k), 1.d-15) + t = tmk(i,j,k) + p = prs(i,j,k) + e = q*p/(EPS + q) + tlcl = TLCLC1 / (LOG(t**TLCLC2/e)-TLCLC3) + TLCLC4 + eth = t * (1000.d0/p)**(GAMMA*(1.d0 + GAMMAMD*q))*& + EXP((THTECON1/tlcl - THTECON2)*q*(1.d0 + THTECON3*q)) + IF (eth .GT. ethmax) THEN + klev = k + ethmax = eth + END IF + END IF + END DO + kpar1 = klev + kpar2 = klev + + ! Establish average properties of that parcel + ! (over depth of approximately davg meters) + + ! davg=.1 + davg = 500.d0 + pavg = davg*prs(i,j,kpar1)*& + G/(RD*tvirtual(tmk(i,j,kpar1), qvp(i,j,kpar1))) + p2 = MIN(prs(i,j,kpar1)+.5d0*pavg, prsf(i,j,mkzh)) + p1 = p2 - pavg + totthe = 0.d0 + totqvp = 0.d0 + totprs = 0.d0 + DO k = mkzh,2,-1 + IF (prsf(i,j,k) .LE. p1) EXIT !GOTO 35 + IF (prsf(i,j,k-1) .GE. p2) CYCLE !GOTO 34 + p = prs(i,j,k) + pup = prsf(i,j,k) + pdn = prsf(i,j,k-1) + q = MAX(qvp(i,j,k),1.d-15) + th = tmk(i,j,k)*(1000.d0/p)**(GAMMA*(1.d0 + GAMMAMD*q)) + pp1 = MAX(p1,pdn) + pp2 = MIN(p2,pup) + IF (pp2 .GT. pp1) THEN + deltap = pp2 - pp1 + totqvp = totqvp + q*deltap + totthe = totthe + th*deltap + totprs = totprs + deltap + END IF +! 34 CONTINUE + END DO +! 35 CONTINUE + qvppari = totqvp/totprs + tmkpari = (totthe/totprs)*& + (prs(i,j,kpar1)/1000.d0)**(GAMMA*(1.d0+GAMMAMD*qvp(i,j,kpar1))) + END IF + + DO kpar = kpar1, kpar2 + + ! Calculate temperature and moisture properties of parcel + ! (note, qvppari and tmkpari already calculated above for 2d case.) + + IF (i3dflag .EQ. 1) THEN + qvppari = qvp(i,j,kpar) + tmkpari = tmk(i,j,kpar) + END IF + prspari = prs(i,j,kpar) + ghtpari = ght(i,j,kpar) + gammam = GAMMA * (1.d0 + GAMMAMD*qvppari) + cpm = CP * (1.d0 + CPMD*qvppari) + + e = MAX(1.d-20,qvppari*prspari/(EPS + qvppari)) + tlcl = TLCLC1/(LOG(tmkpari**TLCLC2/e) - TLCLC3) + TLCLC4 + ethpari = tmkpari*(1000.d0/prspari)**(GAMMA*(1.d0 + GAMMAMD*qvppari))*& + EXP((THTECON1/tlcl - THTECON2)*qvppari*(1.d0 + THTECON3*qvppari)) + zlcl = ghtpari + (tmkpari - tlcl)/(G/cpm) + + ! Calculate buoyancy and relative height of lifted parcel at + ! all levels, and store in bottom up arrays. add a level at the lcl, + ! and at all points where buoyancy is zero. + ! + ! For arrays that go bottom to top + kk = 0 + ilcl = 0 + + IF (ghtpari .GE. zlcl) THEN + ! Initial parcel already saturated or supersaturated. + ilcl = 2 + klcl = 1 + END IF + + k = kpar + DO WHILE (k .GE. 1)!k = kpar, 1, -1 + !DO k = kpar, 1, -1 + ! For arrays that go bottom to top +! 33 kk = kk + 1 + kk = kk + 1 + + ! Model level is below lcl + IF (ght(i,j,k) .LT. zlcl) THEN + qvplift = qvppari + tmklift = tmkpari - G/cpm*(ght(i,j,k) - ghtpari) + tvenv = tvirtual(tmk(i,j,k), qvp(i,j,k)) + tvlift = tvirtual(tmklift, qvplift) + ghtlift = ght(i,j,k) + ELSE IF (ght(i,j,k) .GE. zlcl .AND. ilcl .EQ. 0) THEN + ! This model level and previous model level straddle the lcl, + ! so first create a new level in the bottom-up array, at the lcl. + tmklift = tlcl + qvplift = qvppari + facden = ght(i,j,k) - ght(i,j,k+1) + fac1 = (zlcl-ght(i,j,k+1))/facden + fac2 = (ght(i,j,k)-zlcl)/facden + tmkenv = tmk(i,j,k+1)*fac2 + tmk(i,j,k)*fac1 + qvpenv = qvp(i,j,k+1)*fac2 + qvp(i,j,k)*fac1 + tvenv = tvirtual(tmkenv, qvpenv) + tvlift = tvirtual(tmklift, qvplift) + ghtlift = zlcl + ilcl = 1 + ELSE + tmklift = TONPSADIABAT(ethpari, prs(i,j,k), psadithte, psadiprs,& + psaditmk, GAMMA, errstat, errmsg) + eslift = EZERO*EXP(ESLCON1*(tmklift - CELKEL)/(tmklift - ESLCON2)) + qvplift = EPS*eslift/(prs(i,j,k) - eslift) + tvenv = tvirtual(tmk(i,j,k), qvp(i,j,k)) + tvlift = tvirtual(tmklift, qvplift) + ghtlift = ght(i,j,k) + END IF + ! Buoyancy + buoy(kk) = G*(tvlift - tvenv)/tvenv + zrel(kk) = ghtlift - ghtpari + + IF ((kk .GT. 1) .AND. (buoy(kk)*buoy(kk-1) .LT. 0.0d0)) THEN + ! Parcel ascent curve crosses sounding curve, so create a new level + ! in the bottom-up array at the crossing. + kk = kk + 1 + buoy(kk) = buoy(kk-1) + zrel(kk) = zrel(kk-1) + buoy(kk-1) = 0.d0 + zrel(kk-1) = zrel(kk-2) + buoy(kk-2)/& + (buoy(kk-2) - buoy(kk))*(zrel(kk) - zrel(kk-2)) + END IF + + IF (ilcl .EQ. 1) THEN + klcl = kk + ilcl = 2 + !GOTO 33 + CYCLE + END IF + + k = k - 1 + END DO + + kmax = kk + IF (kmax .GT. 150) THEN + errstat = ALGERR + WRITE(errmsg, *) 'capecalc3d: kmax got too big. kmax=',kmax + RETURN + END IF + + ! If no lcl was found, set klcl to kmax. it is probably not really + ! at kmax, but this will make the rest of the routine behave + ! properly. + IF (ilcl .EQ. 0) klcl=kmax + + ! Get the accumulated buoyant energy from the parcel's starting + ! point, at all levels up to the top level. + benaccum(1) = 0.0d0 + benamin = 9d9 + DO k = 2,kmax + dz = zrel(k) - zrel(k-1) + benaccum(k) = benaccum(k-1) + .5d0*dz*(buoy(k-1) + buoy(k)) + IF (benaccum(k) .LT. benamin) THEN + benamin = benaccum(k) + END IF + END DO + + ! Determine equilibrium level (el), which we define as the highest + ! level of non-negative buoyancy above the lcl. note, this may be + ! the top level if the parcel is still buoyant there. + + elfound = .FALSE. + DO k = kmax,klcl,-1 + IF (buoy(k) .GE. 0.d0) THEN + ! k of equilibrium level + kel = k + elfound = .TRUE. + EXIT + !GOTO 50 + END IF + END DO + + ! If we got through that loop, then there is no non-negative + ! buoyancy above the lcl in the sounding. in these situations, + ! both cape and cin will be set to -0.1 j/kg. (see below about + ! missing values in v6.1.0). also, where cape is + ! non-zero, cape and cin will be set to a minimum of +0.1 j/kg, so + ! that the zero contour in either the cin or cape fields will + ! circumscribe regions of non-zero cape. + + ! In v6.1.0 of ncl, we added a _fillvalue attribute to the return + ! value of this function. at that time we decided to change -0.1 + ! to a more appropriate missing value, which is passed into this + ! routine as cmsg. + + ! cape(i,j,kpar) = -0.1d0 + ! cin(i,j,kpar) = -0.1d0 + IF (.NOT. elfound) THEN + cape(i,j,kpar) = cmsg + cin(i,j,kpar) = cmsg + klfc = kmax + CYCLE + END IF + +! GOTO 102 + +! 50 CONTINUE + + ! If there is an equilibrium level, then cape is positive. we'll + ! define the level of free convection (lfc) as the point below the + ! el, but at or above the lcl, where accumulated buoyant energy is a + ! minimum. the net positive area (accumulated buoyant energy) from + ! the lfc up to the el will be defined as the cape, and the net + ! negative area (negative of accumulated buoyant energy) from the + ! parcel starting point to the lfc will be defined as the convective + ! inhibition (cin). + + ! First get the lfc according to the above definition. + benamin = 9d9 + klfc = kmax + DO k = klcl,kel + IF (benaccum(k) .LT. benamin) THEN + benamin = benaccum(k) + klfc = k + END IF + END DO + + ! Now we can assign values to cape and cin + + cape(i,j,kpar) = MAX(benaccum(kel)-benamin, 0.1d0) + cin(i,j,kpar) = MAX(-benamin, 0.1d0) + + ! cin is uninteresting when cape is small (< 100 j/kg), so set + ! cin to -0.1 (see note about missing values in v6.1.0) in + ! that case. + + ! In v6.1.0 of ncl, we added a _fillvalue attribute to the return + ! value of this function. at that time we decided to change -0.1 + ! to a more appropriate missing value, which is passed into this + ! routine as cmsg. + + ! IF (cape(i,j,kpar).lt.100.d0) cin(i,j,kpar) = -0.1d0 + IF (cape(i,j,kpar) .LT. 100.d0) cin(i,j,kpar) = cmsg +! 102 CONTINUE + + END DO + + IF (i3dflag .EQ. 0) THEN + cape(i,j,mkzh) = cape(i,j,kpar1) + cin(i,j,mkzh) = cin(i,j,kpar1) + ! meters agl + cin(i,j,mkzh-1) = zrel(klcl) + ghtpari - ter(i,j) + ! meters agl + cin(i,j,mkzh-2) = zrel(klfc) + ghtpari - ter(i,j) + + ENDIF + END DO + END DO + + RETURN +END SUBROUTINE DCAPECALC3D diff --git a/fortran/wrfW.c b/fortran/wrfW.c new file mode 100644 index 0000000..83420d3 --- /dev/null +++ b/fortran/wrfW.c @@ -0,0 +1,13330 @@ +#include +#include +#include +#include "wrapper.h" + +#define ERRLEN 512 + +extern void NGCALLF(dcomputetk,DCOMPUTETK)(double *,double *,double *,int *); +extern void NGCALLF(dcomputetd,DCOMPUTETD)(double *,double *,double *,int *); +extern void NGCALLF(dcomputerh,DCOMPUTERH)(double *,double *,double *, + double *,int *); +extern void NGCALLF(dcomputeseaprs,DCOMPUTESEAPRS)(int *,int *,int *, + double *,double *, + double *,double *, + double *,double *, + double *,double *, + int *, char *, int); + +extern void NGCALLF(dinterp3dz,DINTERP3DZ)(double *,double *,double *, + double *,int *,int *, int*, + double *); + +extern void NGCALLF(dinterp2dxy,DINTERP2DXY)(double *,double *,double *, + int *,int *,int *, int*); + +extern void NGCALLF(dinterp1d,DINTERP1D)(double *,double *,double *,double *, + int *, int *, double *); + +extern void NGCALLF(dfilter2d,DFILTER2D)(double *, double *, int *, int *, + int *, double *); + +extern void NGCALLF(filter2d,FILTER2D)(float *, float *, int *, int *, + int *, float *); + +extern void NGCALLF(dgetijlatlong,DGETIJLATLONG)(double *, double *, double *, + double *, int *, int *, + int *, int *, int *); + + +extern void NGCALLF(dcomputeuvmet,DCOMPUTEUVMET)(double *, double *, double *, + double *, double *, double *, + double *, double *, double *, + double *, int *, int *, + int *, int *, int *, + logical *,double *, double*, + double *); + +extern void NGCALLF(dcomputeiclw,DCOMPUTEICLW)(double *, double *, double *, + int *, int *, int *); + +extern void NGCALLF(dbint3d,DBINT3D)(double *,double *,double *, double *, + int *, int *, int *, int *, + int *, int *, int *); + + +extern void NGCALLF(dcomputepv,DCOMPUTEPV)(double *, double *, double *, + double *, double *, double *, + double *, double *, double *, + double *, double *, int *, int *, + int *, int *, int *); + +extern void NGCALLF(dcomputeabsvort,DCOMPUTEABSVORT)(double *, double *, + double *, double *, + double *, double *, + double *, double *, + double *, int *, int *, + int *, int *, int *); + +extern void NGCALLF(calcdbz,CALCDBZ)(double *, double *, double *, double *, + double *, double *, double *, int *, + int *, int *, int *, int *, int *); + +extern void NGCALLF(dlltoij,DLLTOIJ)(int *, double *, double *, double *, + double *, double *, double *, double *, + double *, double *, double *, double *, + double *, double *, double *, double *, + double *, int *, char *, int); + +extern void NGCALLF(dijtoll,DIJTOLL)(int *, double *, double *, double *, + double *, double *, double *, double *, + double *, double *, double *, double *, + double *, double *, double *, double *, + double *, int *, char *, int); + +extern void NGCALLF(deqthecalc,DEQTHECALC)(double *, double *, double *, + double *, int *, int *, int *); + +extern void NGCALLF(dcapecalc3d,DCAPECALC3D)(double *prs, double *tmk, + double *qvp, double *ght, + double *ter, double *sfp, + double *cape, double *cin, + double *cmsg, + int *miy, int *mjx, int *mkzh, + int *i3dflag, int *ter_follow, + char *psafile, + int *errstat, char *errmsg, + int, int); + +extern void NGCALLF(dcalrelhl,DCALRELHL)(double *u, double *v, double *z, + double *ter, double *top, + double *sreh, int *miy, int *mjx, + int *mkzh); + +extern void NGCALLF(dcalcuh,DCALCUH)(int *, int *, int *, int *, double *, + double *, double *, double *, double *, + double *, double *, double *, double *, + double *, double *, double *); + +extern void NGCALLF(plotgrids_var,PLOTGRIDS_VAR)(char *fname, float *plotvar, int); + +extern void NGCALLF(plotfmt_open,PLOTFMT_OPEN)(char *cfilename, int *istatus, + int); + +extern void NGCALLF(plotfmt_close,PLOTFMT_CLOSE)(); + +extern void NGCALLF(plotfmt_rdhead,PLOTFMT_RDHEAD)(int *istatus, + float *rhead, + char *cfield, + char *chdate, + char *cunits, + char *cmapsc, + char *cdesc, + int,int,int,int,int); + +extern void NGCALLF(plotfmt_rddata,PLOTFMT_RDDATA)(int *istatus, + int *nx, int *ny, + float *slab); + +extern void NGCALLF(wetbulbcalc,WETBULBCALC)(double *prs,double *tmk, + double *qvp, double *twb, + int *nx, int *ny,int *nz, + char *,int); + +extern void NGCALLF(omgcalc,OMGCALC)(double *qvp, double *tmk, double *www, + double *prs, double *omg, + int *mx,int *my, int *mz); + +extern void NGCALLF(virtual_temp,VIRTUAL_TEMP)(double *temp,double *ratmix, + double *tv,int *,int *,int *); + +extern NclDimRec *get_wrf_dim_info(int,int,int,ng_size_t*); + +extern char *get_psa_file(); + +extern void var_zero(double *, ng_size_t); + +extern void convert_to_hPa(double *, ng_size_t); + +extern void flip_it(double *, double *, ng_size_t, ng_size_t); + +NhlErrorTypes wrf_tk_W( void ) +{ +/* + * Input array variables + */ + void *p, *theta; + double *tmp_p = NULL; + double *tmp_theta = NULL; + int ndims_p, ndims_theta; + ng_size_t dsizes_p[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_theta[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_p, type_theta; +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info; + +/* + * Output variable and attributes. + */ + void *t; + NclQuark *description, *units; + char *cdescription, *cunits; + double *tmp_t = NULL; + int size_tt; + NclBasicDataTypes type_t; + NclObjClass type_obj_t; +/* + * Various + */ + ng_size_t i, nx, size_leftmost, index_p; + int inx; + +/* + * Variables for returning the output array with attributes attached. + */ + int att_id; + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ + p = (void*)NclGetArgValue( + 0, + 2, + &ndims_p, + dsizes_p, + NULL, + NULL, + &type_p, + DONT_CARE); + + theta = (void*)NclGetArgValue( + 1, + 2, + &ndims_theta, + dsizes_theta, + NULL, + NULL, + &type_theta, + DONT_CARE); +/* + * Error checking. Input variables must be same size. + */ + if(ndims_p != ndims_theta) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_tk: The p and theta arrays must have the same number of dimensions"); + return(NhlFATAL); + } + for(i = 0; i < ndims_p; i++) { + if(dsizes_p[i] != dsizes_theta[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_tk: p and theta must be the same dimensionality"); + return(NhlFATAL); + } + } + +/* + * Retrieve dimension names from the "theta" variable, if any. + * These dimension names will later be attached to the output variable. + */ + dim_info = get_wrf_dim_info(1,2,ndims_theta,dsizes_theta); + +/* + * Calculate size of leftmost dimensions. + */ + size_leftmost = 1; + for(i = 0; i < ndims_p-1; i++) size_leftmost *= dsizes_p[i]; + nx = dsizes_p[ndims_p-1]; + size_tt = size_leftmost * nx; + +/* + * Test dimension sizes. + */ + if(nx > INT_MAX) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_tk: nx = %ld is greater than INT_MAX", nx); + return(NhlFATAL); + } + inx = (int) nx; + +/* + * Allocate space for coercing input arrays. If the input p or theta + * are already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * The output type defaults to float, unless any of the two input arrays + * are double. + */ + type_t = NCL_float; + type_obj_t = nclTypefloatClass; + if(type_p != NCL_double) { + tmp_p = (double *)calloc(nx,sizeof(double)); + if(tmp_p == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_tk: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_t = NCL_double; + type_obj_t = nclTypedoubleClass; + } + + if(type_theta != NCL_double) { + tmp_theta = (double *)calloc(nx,sizeof(double)); + if(tmp_theta == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_tk: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_t = NCL_double; + type_obj_t = nclTypedoubleClass; + } + +/* + * Allocate space for output array. + */ + if(type_t == NCL_double) { + t = (double *)calloc(size_tt,sizeof(double)); + if(t == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_tk: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + else { + t = (float *)calloc(size_tt,sizeof(float)); + tmp_t = (double *)calloc(nx,sizeof(double)); + if(tmp_t == NULL || t == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_tk: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } +/* + * Loop across leftmost dimensions and call the Fortran routine for each + * one-dimensional subsection. + */ + index_p = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of p (tmp_p) to double if necessary. + */ + if(type_p != NCL_double) { + coerce_subset_input_double(p,tmp_p,index_p,type_p,nx,0,NULL,NULL); + } + else { + tmp_p = &((double*)p)[index_p]; + } +/* + * Coerce subsection of theta (tmp_theta) to double if ncessary. + */ + if(type_theta != NCL_double) { + coerce_subset_input_double(theta,tmp_theta,index_p,type_theta,nx, + 0,NULL,NULL); + } + else { + tmp_theta = &((double*)theta)[index_p]; + } + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_t == NCL_double) tmp_t = &((double*)t)[index_p]; +/* + * Call Fortran routine. + */ + NGCALLF(dcomputetk,DCOMPUTETK)(tmp_t,tmp_p,tmp_theta,&inx); + +/* + * Coerce output back to float if necessary. + */ + if(type_t == NCL_float) { + coerce_output_float_only(t,tmp_t,nx,index_p); + } + + index_p += nx; /* Increment index */ + } +/* + * Free up memory. + */ + if(type_p != NCL_double) NclFree(tmp_p); + if(type_theta != NCL_double) NclFree(tmp_theta); + if(type_t != NCL_double) NclFree(tmp_t); + +/* + * Set up some attributes ("description" and "units") to return. + * Note that if the input arrays are anything but 2D, the units + * will be "Temperature", and "2m Temperature" otherwise. + */ + if(ndims_p != 2) { + cdescription = (char *)calloc(12,sizeof(char)); + strcpy(cdescription,"Temperature"); + } + else { + cdescription = (char *)calloc(15,sizeof(char)); + strcpy(cdescription,"2m Temperature"); + } + cunits = (char *)calloc(2,sizeof(char)); + strcpy(cunits,"K"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + *units = NrmStringToQuark(cunits); + free(cunits); + free(cdescription); + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)t, + NULL, + ndims_p, + dsizes_p, + TEMPORARY, + NULL, + type_obj_t + ); +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + + NclFree(dim_info); +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); + +} + +NhlErrorTypes wrf_td_W( void ) +{ +/* + * Input array variables + */ + void *p, *qv; + double *tmp_p, *tmp_qv; + int ndims_p, ndims_qv; + ng_size_t dsizes_p[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_qv[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_p, type_qv; +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info; + +/* + * Output variable and attributes. + */ + void *t; + NclQuark *description, *units; + char *cdescription, *cunits; + double *tmp_t = NULL; + int size_tt; + NclBasicDataTypes type_t; + NclObjClass type_obj_t; +/* + * Various + */ + ng_size_t i, np, nx, size_leftmost, index_p; + int inx; + +/* + * Variables for returning the output array with attributes attached. + */ + int att_id; + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ + p = (void*)NclGetArgValue( + 0, + 2, + &ndims_p, + dsizes_p, + NULL, + NULL, + &type_p, + DONT_CARE); + + qv = (void*)NclGetArgValue( + 1, + 2, + &ndims_qv, + dsizes_qv, + NULL, + NULL, + &type_qv, + DONT_CARE); + +/* + * Error checking. Input variables must be same size. + */ + if(ndims_p != ndims_qv) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_td: The p and qv arrays must have the same number of dimensions"); + return(NhlFATAL); + } + for(i = 0; i < ndims_p; i++) { + if(dsizes_p[i] != dsizes_qv[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_td: p and qv must be the same dimensionality"); + return(NhlFATAL); + } + } + +/* + * Retrieve dimension names from the "qvapor" variable, if any. + * These dimension names will later be attached to the output variable. + */ + dim_info = get_wrf_dim_info(1,2,ndims_qv,dsizes_qv); + +/* + * Calculate size of leftmost dimensions. + */ + size_leftmost = 1; + for(i = 0; i < ndims_p-1; i++) size_leftmost *= dsizes_p[i]; + nx = dsizes_p[ndims_p-1]; + size_tt = size_leftmost * nx; + +/* + * Test dimension sizes. + */ + if(nx > INT_MAX) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_td: nx = %ld is greater than INT_MAX", nx); + return(NhlFATAL); + } + inx = (int) nx; + +/* + * Allocate space for coercing input arrays. If the input p or qv + * are already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * The output type defaults to float, unless any of the two input arrays + * are double. + */ + type_t = NCL_float; + type_obj_t = nclTypefloatClass; +/* + * Allocate space for tmp_p no matter what, because we have to + * convert the values from hPa to Pa, and we don't want to do + * this to the original array. + */ + tmp_p = (double *)calloc(nx,sizeof(double)); + if(tmp_p == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_td: Unable to allocate memory for coercing 't' to double"); + return(NhlFATAL); + } + + if(type_p == NCL_double) { + type_t = NCL_double; + type_obj_t = nclTypedoubleClass; + } + +/* + * Allocate space for tmp_qv no matter what, because we want to set + * values of qv that are less than zero to zero, but we don't want + * these values retained when the function is done. + */ + tmp_qv = (double *)malloc(nx*sizeof(double)); + if(tmp_qv == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_td: Unable to allocate memory for coercing 'qv' to double"); + return(NhlFATAL); + } + if(type_qv == NCL_double) { + type_t = NCL_double; + type_obj_t = nclTypedoubleClass; + } + +/* + * Allocate space for output array. + */ + if(type_t == NCL_double) { + t = (double *)calloc(size_tt,sizeof(double)); + if(t == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_td: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + else { + t = (float *)calloc(size_tt,sizeof(float)); + tmp_t = (double *)calloc(nx,sizeof(double)); + if(tmp_t == NULL || t == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_td: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } +/* + * Loop across leftmost dimensions and call the Fortran routine for each + * one-dimensional subsection. + */ + index_p = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of p (tmp_p) to double if necessary. Otherwise, + * just do a memcpy. Afterwards, convert the p values to Pa units, + * as they are coming in as hPa. + */ + if(type_p != NCL_double) { + coerce_subset_input_double(p,tmp_p,index_p,type_p,nx,0,NULL,NULL); + } + else { + (void *)memcpy((void*)((char*)tmp_p), + (void*)((char*)p + (index_p*sizeof(double))), + sizeof(double)*nx); + } + for(np = 0; np < nx; np++) tmp_p[np] *= 0.01; +/* + * Coerce subsection of qv (tmp_qv) to double if ncessary. Otherwise, + * just do a memcpy. Afterwards, set all values < 0 to 0. + */ + if(type_qv != NCL_double) { + coerce_subset_input_double(qv,tmp_qv,index_p,type_qv,nx, + 0,NULL,NULL); + } + else { + (void *)memcpy((void*)((char*)tmp_qv), + (void*)((char*)qv + (index_p*sizeof(double))), + sizeof(double)*nx); + } + var_zero(tmp_qv, nx); /* Set all values < 0 to 0. */ + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_t == NCL_double) tmp_t = &((double*)t)[index_p]; +/* + * Call Fortran routine. + */ + NGCALLF(dcomputetd,DCOMPUTETD)(tmp_t,tmp_p,tmp_qv,&inx); + +/* + * Coerce output back to float if necessary. + */ + if(type_t == NCL_float) { + coerce_output_float_only(t,tmp_t,nx,index_p); + } + + index_p += nx; /* Increment index */ + } +/* + * Free up memory. + */ + NclFree(tmp_qv); + NclFree(tmp_p); + if(type_t != NCL_double) NclFree(tmp_t); + +/* + * Set up some attributes ("description" and "units") to return. + * Note that if the input arrays are anything but 2D, the units + * will be "Temperature", and "2m Temperature" otherwise. + */ + if(ndims_p != 2) { + cdescription = (char *)calloc(21,sizeof(char)); + strcpy(cdescription,"Dewpoint Temperature"); + } + else { + cdescription = (char *)calloc(24,sizeof(char)); + strcpy(cdescription,"2m Dewpoint Temperature"); + } + cunits = (char *)calloc(2,sizeof(char)); + strcpy(cunits,"C"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + *units = NrmStringToQuark(cunits); + free(cdescription); + free(cunits); + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)t, + NULL, + ndims_p, + dsizes_p, + TEMPORARY, + NULL, + type_obj_t + ); +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + + NclFree(dim_info); +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); + +} + +NhlErrorTypes wrf_rh_W( void ) +{ +/* + * Input array variables + */ + void *qv, *p, *t; + double *tmp_qv = NULL; + double *tmp_p = NULL; + double *tmp_t = NULL; + int ndims_qv, ndims_p, ndims_t; + ng_size_t dsizes_qv[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_p[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_t[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_qv, type_p, type_t; +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info; + +/* + * Output variable and attributes. + */ + void *rh; + NclQuark *description, *units; + char *cdescription, *cunits; + double *tmp_rh = NULL; + int size_rh; + NclBasicDataTypes type_rh; + NclObjClass type_obj_rh; +/* + * Various + */ + ng_size_t i, nx, size_leftmost, index_qv; + int inx; + +/* + * Variables for returning the output array with attributes and/or + * dimension names attached. + */ + int att_id; + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ + qv = (void*)NclGetArgValue( + 0, + 3, + &ndims_qv, + dsizes_qv, + NULL, + NULL, + &type_qv, + DONT_CARE); + + p = (void*)NclGetArgValue( + 1, + 3, + &ndims_p, + dsizes_p, + NULL, + NULL, + &type_p, + DONT_CARE); + + t = (void*)NclGetArgValue( + 2, + 3, + &ndims_t, + dsizes_t, + NULL, + NULL, + &type_t, + DONT_CARE); + +/* + * Error checking. Input variables must be same size. + */ + if(ndims_qv != ndims_t || ndims_p != ndims_t) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_rh: The qv, p, and t arrays must have the same number of dimensions"); + return(NhlFATAL); + } + for(i = 0; i < ndims_qv; i++) { + if(dsizes_qv[i] != dsizes_t[i] || dsizes_p[i] != dsizes_t[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_rh: qv, p, and t must be the same dimensionality"); + return(NhlFATAL); + } + } + +/* + * Retrieve dimension names from the "t" variable, if any. + * These dimension names will later be attached to the output variable. + */ + dim_info = get_wrf_dim_info(2,3,ndims_t,dsizes_t); + +/* + * Calculate size of leftmost dimensions. + */ + size_leftmost = 1; + for(i = 0; i < ndims_qv-1; i++) size_leftmost *= dsizes_qv[i]; + nx = dsizes_qv[ndims_qv-1]; + size_rh = size_leftmost * nx; + +/* + * Test dimension sizes. + */ + if(nx > INT_MAX) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_rh: nx = %ld is greater than INT_MAX", nx); + return(NhlFATAL); + } + inx = (int) nx; + +/* + * Allocate space for coercing input arrays. If the input p or t + * are already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * The output type defaults to float, unless any of the two input arrays + * are double. + */ + type_rh = NCL_float; + type_obj_rh = nclTypefloatClass; +/* + * Allocate space for tmp_qv no matter what, because we want to set + * values of qv that are less than zero to zero, but we don't want + * these values retained when the function is done. + */ + tmp_qv = (double*)malloc(nx * sizeof(double)); + if(tmp_qv == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_rh: Unable to allocate memory for coercing 'qv' to double"); + return(NhlFATAL); + } + + if(type_qv == NCL_double) { + type_rh = NCL_double; + type_obj_rh = nclTypedoubleClass; + } + + if(type_p != NCL_double) { + tmp_p = (double *)calloc(nx,sizeof(double)); + if(tmp_p == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_rh: Unable to allocate memory for coercing 'p' to double"); + return(NhlFATAL); + } + } + else { + type_rh = NCL_double; + type_obj_rh = nclTypedoubleClass; + } + + if(type_t != NCL_double) { + tmp_t = (double *)calloc(nx,sizeof(double)); + if(tmp_t == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_rh: Unable to allocate memory for coercing 't' to double"); + return(NhlFATAL); + } + } + else { + type_rh = NCL_double; + type_obj_rh = nclTypedoubleClass; + } + +/* + * Allocate space for output array. + */ + if(type_rh == NCL_double) { + rh = (double *)calloc(size_rh,sizeof(double)); + if(rh == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_rh: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + else { + rh = (float *)calloc(size_rh,sizeof(float)); + tmp_rh = (double *)calloc(nx,sizeof(double)); + if(tmp_rh == NULL || rh == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_rh: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } +/* + * Loop across leftmost dimensions and call the Fortran routine for each + * one-dimensional subsection. + */ + index_qv = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of qv (tmp_qv) to double if necessary. Otherwise, + * just do a memcpy. Afterwards, set all values < 0 to 0. + */ + if(type_qv != NCL_double) { + coerce_subset_input_double(qv,tmp_qv,index_qv,type_qv,nx,0,NULL,NULL); + } + else { + (void *)memcpy((void*)((char*)tmp_qv), + (void*)((char*)qv + (index_qv*sizeof(double))), + sizeof(double)*nx); + } + var_zero(tmp_qv, nx); /* Set all values < 0 to 0. */ +/* + * Coerce subsection of p (tmp_p) to double if necessary. + */ + if(type_p != NCL_double) { + coerce_subset_input_double(p,tmp_p,index_qv,type_p,nx,0,NULL,NULL); + } + else { + tmp_p = &((double*)p)[index_qv]; + } +/* + * Coerce subsection of t (tmp_t) to double if ncessary. + */ + if(type_t != NCL_double) { + coerce_subset_input_double(t,tmp_t,index_qv,type_t,nx, + 0,NULL,NULL); + } + else { + tmp_t = &((double*)t)[index_qv]; + } + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_rh == NCL_double) tmp_rh = &((double*)rh)[index_qv]; +/* + * Call Fortran routine. + */ + NGCALLF(dcomputerh,DCOMPUTERH)(tmp_qv,tmp_p,tmp_t,tmp_rh,&inx); + +/* + * Coerce output back to float if necessary. + */ + if(type_rh == NCL_float) { + coerce_output_float_only(rh,tmp_rh,nx,index_qv); + } + + index_qv += nx; /* Increment index */ + } +/* + * Free up memory. + */ + NclFree(tmp_qv); + if(type_p != NCL_double) NclFree(tmp_p); + if(type_t != NCL_double) NclFree(tmp_t); + if(type_rh != NCL_double) NclFree(tmp_rh); + +/* + * Set up some attributes ("description" and "units") to return. + */ + cdescription = (char *)calloc(18,sizeof(char)); + cunits = (char *)calloc(2,sizeof(char)); + strcpy(cdescription,"Relative Humidity"); + strcpy(cunits,"%"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + *units = NrmStringToQuark(cunits); + free(cdescription); + free(cunits); + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)rh, + NULL, + ndims_qv, + dsizes_qv, + TEMPORARY, + NULL, + type_obj_rh + ); +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + + NclFree(dim_info); +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); +} + +NhlErrorTypes wrf_slp_W( void ) +{ +/* + * Input array variables + */ + void *z, *t, *p, *q; + double *tmp_z = NULL; + double *tmp_t = NULL; + double *tmp_p = NULL; + double *tmp_q = NULL; + int ndims_z, ndims_t, ndims_p, ndims_q; + ng_size_t dsizes_z[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_t[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_p[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_q[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_z, type_t, type_p, type_q; +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info = NULL; + NclDimRec *dim_info_t = NULL; + +/* + * Output variable. + */ + void *slp; + NclQuark *description, *units; + char *cdescription, *cunits; + double *tmp_slp = NULL; + int ndims_slp; + ng_size_t *dsizes_slp; + ng_size_t size_slp; + NclBasicDataTypes type_slp; + NclObjClass type_obj_slp; + int errstat; + char* errmsg; +/* + * Various + */ + ng_size_t i, nx, ny, nz, nxy, nxyz, size_leftmost, index_nxy, index_nxyz; + double *tmp_t_sea_level, *tmp_t_surf, *tmp_level; + int inx, iny, inz; +/* + * Variables for returning the output array with attributes and/or + * dimension names attached. + */ + int att_id; + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ + z = (void*)NclGetArgValue( + 0, + 4, + &ndims_z, + dsizes_z, + NULL, + NULL, + &type_z, + DONT_CARE); + + t = (void*)NclGetArgValue( + 1, + 4, + &ndims_t, + dsizes_t, + NULL, + NULL, + &type_t, + DONT_CARE); + + p = (void*)NclGetArgValue( + 2, + 4, + &ndims_p, + dsizes_p, + NULL, + NULL, + &type_p, + DONT_CARE); + + q = (void*)NclGetArgValue( + 3, + 4, + &ndims_q, + dsizes_q, + NULL, + NULL, + &type_q, + DONT_CARE); + +/* + * Error checking. Input variables must be same size, and must have at least + * 3 dimensions. + */ + if(ndims_z != ndims_t || ndims_z != ndims_p || ndims_z != ndims_q) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_slp: The z, t, p, and q arrays must have the same number of dimensions"); + return(NhlFATAL); + } + if(ndims_z < 3) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_slp: The z, t, p, and q arrays must have at least 3 dimensions"); + return(NhlFATAL); + } + for(i = 0; i < ndims_z; i++) { + if(dsizes_z[i] != dsizes_t[i] || dsizes_z[i] != dsizes_p[i] || + dsizes_z[i] != dsizes_q[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_slp: z, t, p, and q must be the same dimensionality"); + return(NhlFATAL); + } + } +/* + * Allocate space to set dimension sizes. + */ + ndims_slp = ndims_z-1; + dsizes_slp = (ng_size_t*)calloc(ndims_slp,sizeof(ng_size_t)); + if( dsizes_slp == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_slp: Unable to allocate memory for holding dimension sizes"); + return(NhlFATAL); + } +/* + * Set sizes for output array and calculate size of leftmost dimensions. + * The output array will have one less dimension than the four input arrays. + */ + size_leftmost = 1; + for(i = 0; i < ndims_z-3; i++) { + dsizes_slp[i] = dsizes_z[i]; + size_leftmost *= dsizes_z[i]; + } + nx = dsizes_z[ndims_z-1]; + ny = dsizes_z[ndims_z-2]; + nz = dsizes_z[ndims_z-3]; + dsizes_slp[ndims_slp-1] = nx; + dsizes_slp[ndims_slp-2] = ny; + nxy = nx * ny; + nxyz = nxy * nz; + size_slp = size_leftmost * nxy; +/* + * Test dimension sizes. + */ + if((nx > INT_MAX) || (ny > INT_MAX) || (nz > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_slp: nx, ny, and/or nz is greater than INT_MAX"); + return(NhlFATAL); + } + inx = (int) nx; + iny = (int) ny; + inz = (int) nz; + +/* + * Get dimension info to see if we have named dimensions. + * This will be used for return variable. + */ + dim_info_t = get_wrf_dim_info(1,4,ndims_t,dsizes_t); + if(dim_info_t != NULL) { + dim_info = malloc(sizeof(NclDimRec)*ndims_slp); + if(dim_info == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_slp: Unable to allocate memory for holding dimension information"); + return(NhlFATAL); + } + for(i = 0; i < ndims_z-3; i++) { + dim_info[i] = dim_info_t[i]; + } + dim_info[ndims_slp-1] = dim_info_t[ndims_t-1]; + dim_info[ndims_slp-2] = dim_info_t[ndims_t-2]; + } + +/* + * Allocate space for coercing input arrays. If the input q, p, or t + * are already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * The output type defaults to float, unless any of the two input arrays + * are double. + */ + type_slp = NCL_float; + type_obj_slp = nclTypefloatClass; + +/* + * Allocate space for tmp_q no matter what, because we want to set + * values of q that are less than zero to zero, but we don't want + * these values retained when the function is done. + */ + tmp_q = (double*)malloc(nxyz * sizeof(double)); + if(tmp_q == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_slp: Unable to allocate memory for coercing 'q' to double"); + return(NhlFATAL); + } + + if(type_q == NCL_double) { + type_slp = NCL_double; + type_obj_slp = nclTypedoubleClass; + } + + if(type_z != NCL_double) { + tmp_z = (double *)calloc(nxyz,sizeof(double)); + if(tmp_z == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_slp: Unable to allocate memory for coercing 'z' to double"); + return(NhlFATAL); + } + } + else { + type_slp = NCL_double; + type_obj_slp = nclTypedoubleClass; + } + + if(type_t != NCL_double) { + tmp_t = (double *)calloc(nxyz,sizeof(double)); + if(tmp_t == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_slp: Unable to allocate memory for coercing 't' to double"); + return(NhlFATAL); + } + } + else { + type_slp = NCL_double; + type_obj_slp = nclTypedoubleClass; + } + + if(type_p != NCL_double) { + tmp_p = (double *)calloc(nxyz,sizeof(double)); + if(tmp_p == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_slp: Unable to allocate memory for coercing 'p' to double"); + return(NhlFATAL); + } + } + else { + type_slp = NCL_double; + type_obj_slp = nclTypedoubleClass; + } + +/* + * Allocate space for work arrays. + */ + tmp_t_sea_level = (double *)calloc(nxy,sizeof(double)); + tmp_t_surf = (double *)calloc(nxy,sizeof(double)); + tmp_level = (double *)calloc(nxy,sizeof(double)); + if(tmp_t_sea_level == NULL || tmp_t_surf == NULL || tmp_level == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_slp: Unable to allocate memory for temporary arrays"); + return(NhlFATAL); + } + +/* + * Allocate space for output array. + */ + if(type_slp == NCL_double) { + slp = (double *)calloc(size_slp,sizeof(double)); + if(slp == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_slp: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + else { + slp = (float *)calloc(size_slp,sizeof(float)); + tmp_slp = (double *)calloc(nxy,sizeof(double)); + if(tmp_slp == NULL || slp == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_slp: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + + /* Allocate space for errmsg*/ + errmsg = (char *) calloc(ERRLEN, sizeof(char)) + +/* + * Loop across leftmost dimensions and call the Fortran routine + * for each three-dimensional subsection. + */ + index_nxy = index_nxyz = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of q (tmp_q) to double if necessary. Otherwise, + * just do a memcpy. Afterwards, set all values < 0 to 0. + */ + if(type_q != NCL_double) { + coerce_subset_input_double(q,tmp_q,index_nxyz,type_q,nxyz,0,NULL,NULL); + } + else { + (void *)memcpy((void*)((char*)tmp_q), + (void*)((char*)q + (index_nxyz*sizeof(double))), + sizeof(double)*nxyz); + } + var_zero(tmp_q, nxyz); /* Set all values < 0 to 0. */ +/* + * Coerce subsection of z (tmp_z) to double if necessary. + */ + if(type_z != NCL_double) { + coerce_subset_input_double(z,tmp_z,index_nxyz,type_z,nxyz,0,NULL,NULL); + } + else { + tmp_z = &((double*)z)[index_nxyz]; + } +/* + * Coerce subsection of p (tmp_p) to double if necessary. + */ + if(type_p != NCL_double) { + coerce_subset_input_double(p,tmp_p,index_nxyz,type_p,nxyz,0,NULL,NULL); + } + else { + tmp_p = &((double*)p)[index_nxyz]; + } +/* + * Coerce subsection of t (tmp_t) to double if ncessary. + */ + if(type_t != NCL_double) { + coerce_subset_input_double(t,tmp_t,index_nxyz,type_t,nxyz,0,NULL,NULL); + } + else { + tmp_t = &((double*)t)[index_nxyz]; + } + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_slp == NCL_double) tmp_slp = &((double*)slp)[index_nxy]; +/* + * Call Fortran routine. + */ + errstat = 0; + errmsg = ""; + NGCALLF(dcomputeseaprs,DCOMPUTESEAPRS)(&inx,&iny,&inz,tmp_z,tmp_t,tmp_p, + tmp_q,tmp_slp,tmp_t_sea_level, + tmp_t_surf,tmp_level,&errstat, + errmsg, ERRLEN); + + /* Terminate if there was an error */ + if (errstat != 0) { + fprintf(stderr, errmsg); + exit(errstat); + } +/* + * Coerce output back to float if necessary. + */ + if(type_slp == NCL_float) { + coerce_output_float_only(slp,tmp_slp,nxy,index_nxy); + } + + index_nxyz += nxyz; /* Increment indices */ + index_nxy += nxy; + } +/* + * Free up memory. + */ + NclFree(tmp_q); + if(type_p != NCL_double) NclFree(tmp_p); + if(type_t != NCL_double) NclFree(tmp_t); + if(type_z != NCL_double) NclFree(tmp_z); + if(type_slp != NCL_double) NclFree(tmp_slp); + + NclFree(tmp_t_sea_level); + NclFree(tmp_t_surf); + NclFree(tmp_level); + + NclFree(errmsg); + +/* + * Set up some attributes ("description" and "units") to return. + */ + cdescription = (char *)calloc(19,sizeof(char)); + cunits = (char *)calloc(4,sizeof(char)); + strcpy(cdescription,"Sea Level Pressure"); + strcpy(cunits,"hPa"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + *units = NrmStringToQuark(cunits); + free(cdescription); + free(cunits); + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)slp, + NULL, + ndims_slp, + dsizes_slp, + TEMPORARY, + NULL, + type_obj_slp + ); +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + + NclFree(dsizes_slp); + if(dim_info != NULL) NclFree(dim_info); + NclFree(dim_info_t); + +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); + +} + +NhlErrorTypes wrf_interp_3d_z_W( void ) +{ +/* + * Input array variables + */ + void *v3d, *z, *loc; + double *tmp_v3d = NULL; + double *tmp_z = NULL; + double *tmp_loc = NULL; + int ndims_v3d, ndims_z; + ng_size_t dsizes_v3d[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_z[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_v3d, type_z, type_loc; +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info_v3d; + NclDimRec *dim_info = NULL; + +/* + * Variables for retrieving attributes from "v3d". + */ + NclAttList *attr_list; + NclAtt attr_obj; + NclStackEntry stack_entry; + NrmQuark *description, *units; + char *cdesc = NULL; + char *cunits = NULL; + logical found_desc = False, found_units = False; +/* + * Output variable. + */ + void *v2d; + double *tmp_v2d = NULL; + int ndims_v2d; + ng_size_t *dsizes_v2d; + ng_size_t size_v2d; + NclBasicDataTypes type_v2d; + NclObjClass type_obj_v2d; + NclScalar missing_v2d; + +/* + * Variables for returning the output array with attributes attached. + */ + int att_id; + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + NclQuark *qdesc, *qunits; + +/* + * Various + */ + ng_size_t i, nx, ny, nz, nxy, nxyz, size_leftmost, index_v3d, index_v2d; + int inx, iny, inz; + double vmsg; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ + v3d = (void*)NclGetArgValue( + 0, + 3, + &ndims_v3d, + dsizes_v3d, + NULL, + NULL, + &type_v3d, + DONT_CARE); + + z = (void*)NclGetArgValue( + 1, + 3, + &ndims_z, + dsizes_z, + NULL, + NULL, + &type_z, + DONT_CARE); + + loc = (void*)NclGetArgValue( + 2, + 3, + NULL, + NULL, + NULL, + NULL, + &type_loc, + DONT_CARE); + +/* + * Error checking. First two input variables must be same size. + */ + if(ndims_v3d < 3) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_3d_z: The v3d and z arrays must have at least 3 dimensions"); + return(NhlFATAL); + } + + if(ndims_v3d != ndims_z) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_3d_z: The v3d and z arrays must have the same number of dimensions"); + return(NhlFATAL); + } + + for(i = 0; i < ndims_v3d; i++) { + if(dsizes_v3d[i] != dsizes_z[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_3d_z: v3d and z must be the same dimensionality"); + return(NhlFATAL); + } + } + +/* + * Check if v3d has any attributes, namely "description" or "units". + * These attributes will be attached to the return variable v2d. + */ + stack_entry = _NclGetArg(0, 3, DONT_CARE); + switch (stack_entry.kind) { + case NclStk_VAR: + if (stack_entry.u.data_var->var.att_id != -1) { + attr_obj = (NclAtt) _NclGetObj(stack_entry.u.data_var->var.att_id); + if (attr_obj == NULL) { + break; + } + } + else { +/* + * att_id == -1 ==> no optional args given. + */ + break; + } +/* + * Get optional arguments. If none are specified, then return + * missing values. + */ + if (attr_obj->att.n_atts == 0) { + break; + } + else { +/* + * Get list of attributes. + */ + attr_list = attr_obj->att.att_list; +/* + * Loop through attributes and check them. + */ + while (attr_list != NULL) { + if ((strcmp(attr_list->attname, "description")) == 0) { + description = (NrmQuark *) attr_list->attvalue->multidval.val; + cdesc = NrmQuarkToString(*description); + found_desc = True; + } + if ((strcmp(attr_list->attname, "units")) == 0) { + units = (NrmQuark *) attr_list->attvalue->multidval.val; + cunits = NrmQuarkToString(*units); + found_units = True; + } + attr_list = attr_list->next; + } + } + default: + break; + } + +/* + * Calculate size of leftmost dimensions and set dimension sizes for + * output array. + * + * The output array will have one less dimension than v3d/z input arrays. + */ + nx = dsizes_v3d[ndims_v3d-1]; + ny = dsizes_v3d[ndims_v3d-2]; + nz = dsizes_v3d[ndims_v3d-3]; + nxy = nx * ny; + nxyz = nxy * nz; + +/* + * Test dimension sizes. + */ + if((nx > INT_MAX) || (ny > INT_MAX) || (nz > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_3d_z: nx, ny, and/or nz is greater than INT_MAX"); + return(NhlFATAL); + } + inx = (int) nx; + iny = (int) ny; + inz = (int) nz; + + ndims_v2d = ndims_v3d-1; + dsizes_v2d = (ng_size_t*)calloc(ndims_v2d,sizeof(ng_size_t)); + if( dsizes_v2d == NULL ) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_3d_z: Unable to allocate memory for holding dimension sizes"); + return(NhlFATAL); + } + size_leftmost = 1; + for(i = 0; i < ndims_v3d-3; i++) { + dsizes_v2d[i] = dsizes_v3d[i]; + size_leftmost *= dsizes_v3d[i]; + } + dsizes_v2d[ndims_v2d-2] = ny; + dsizes_v2d[ndims_v2d-1] = nx; + + size_v2d = size_leftmost * nxy; + +/* + * Retrieve dimension names from the "v3d" variable, if any. + * These dimension names will later be attached to the output variable. + */ + dim_info_v3d = get_wrf_dim_info(0,3,ndims_v3d,dsizes_v3d); + if(dim_info_v3d != NULL) { + dim_info = malloc(sizeof(NclDimRec)*ndims_v2d); + if(dim_info == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_3d_z: Unable to allocate memory for holding dimension information"); + return(NhlFATAL); + } + for(i = 0; i < ndims_v3d-3; i++) { + dim_info[i] = dim_info_v3d[i]; + } + dim_info[ndims_v2d-1] = dim_info_v3d[ndims_v3d-1]; + dim_info[ndims_v2d-2] = dim_info_v3d[ndims_v3d-2]; + } + +/* + * Allocate space for coercing input arrays. If the input v3d or z + * are already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * The output type defaults to float, unless any of the two input arrays + * are double. + */ + type_v2d = NCL_float; + type_obj_v2d = nclTypefloatClass; + if(type_v3d != NCL_double) { + tmp_v3d = (double *)calloc(nxyz,sizeof(double)); + if(tmp_v3d == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_3d_z: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_v2d = NCL_double; + type_obj_v2d = nclTypedoubleClass; + } + if(type_z != NCL_double) { + tmp_z = (double *)calloc(nxyz,sizeof(double)); + if(tmp_z == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_3d_z: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_v2d = NCL_double; + type_obj_v2d = nclTypedoubleClass; + } +/* + * Coerce loc (tmp_loc) to double if ncessary. + */ + tmp_loc = coerce_input_double(loc,type_loc,1,0,NULL,NULL); + +/* + * Allocate space for output array. + */ + if(type_v2d == NCL_double) { + v2d = (double *)calloc(size_v2d,sizeof(double)); + if(v2d == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_3d_z: Unable to allocate memory for output array"); + return(NhlFATAL); + } + missing_v2d.doubleval = ((NclTypeClass)nclTypedoubleClass)->type_class.default_mis.doubleval; + vmsg = missing_v2d.doubleval; + } + else { + v2d = (float *)calloc(size_v2d,sizeof(float)); + tmp_v2d = (double *)calloc(nxy,sizeof(double)); + if(tmp_v2d == NULL || v2d == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_3d_z: Unable to allocate memory for output array"); + return(NhlFATAL); + } + missing_v2d.floatval = ((NclTypeClass)nclTypefloatClass)->type_class.default_mis.floatval; + vmsg = (double)missing_v2d.floatval; + + } +/* + * Loop across leftmost dimensions and call the Fortran routine + * for each three-dimensional subsection. + */ + index_v2d = index_v3d = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of v3d (tmp_v3d) to double if necessary. + */ + if(type_v3d != NCL_double) { + coerce_subset_input_double(v3d,tmp_v3d,index_v3d,type_v3d,nxyz, + 0,NULL,NULL); + } + else { + tmp_v3d = &((double*)v3d)[index_v3d]; + } +/* + * Coerce subsection of z (tmp_z) to double if necessary. + */ + if(type_z != NCL_double) { + coerce_subset_input_double(z,tmp_z,index_v3d,type_z,nxyz,0,NULL,NULL); + } + else { + tmp_z = &((double*)z)[index_v3d]; + } + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_v2d == NCL_double) tmp_v2d = &((double*)v2d)[index_v2d]; +/* + * Call Fortran routine. + */ + NGCALLF(dinterp3dz,DINTERP3DZ)(tmp_v3d,tmp_v2d,tmp_z,tmp_loc, + &inx,&iny,&inz,&vmsg); +/* + * Coerce output back to float if necessary. + */ + if(type_v2d == NCL_float) { + coerce_output_float_only(v2d,tmp_v2d,nxy,index_v2d); + } + + index_v3d += nxyz; + index_v2d += nxy; + } +/* + * Free up memory. + */ + if(type_v3d != NCL_double) NclFree(tmp_v3d); + if(type_z != NCL_double) NclFree(tmp_z); + if(type_loc != NCL_double) NclFree(tmp_loc); + if(type_v2d != NCL_double) NclFree(tmp_v2d); + +/* + * If v3d had a "description" or units attribute, return them with + * the output variable as an attribute. Otherwise, return a + * blank string for description, and nothing for units. + */ + if(!found_desc) { + cdesc = (char *)calloc(2,sizeof(char)); + strcpy(cdesc," "); + } +/* + * I don't think we can return "description" or "units" here, because + * they are attached to an NCL input parameter. It could screw things up + * if we try to return it as an attribute with the output variable. + * Instead, create a new description and units "quark" variable. + */ + qdesc = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *qdesc = NrmStringToQuark(cdesc); + if (!found_desc) + free(cdesc); + + if(found_units) { + qunits = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *qunits = NrmStringToQuark(cunits); + } + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)v2d, + &missing_v2d, + ndims_v2d, + dsizes_v2d, + TEMPORARY, + NULL, + type_obj_v2d + ); +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)qdesc, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + if(found_units) { + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)qunits, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + } + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + NclFree(dsizes_v2d); + if(dim_info != NULL) NclFree(dim_info); + NclFree(dim_info_v3d); + +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); +} + + +NhlErrorTypes wrf_interp_2d_xy_W( void ) +{ +/* + * Input array variables + */ + void *v3d, *xy; + double *tmp_v3d = NULL; + double *tmp_xy = NULL; + int ndims_v3d, ndims_xy; + ng_size_t dsizes_v3d[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_xy[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_v3d, type_xy; + +/* + * Variables for retrieving attributes from "v3d". + */ + NclAttList *attr_list; + NclAtt attr_obj; + NclStackEntry stack_entry; + NrmQuark *description, *units; + char *cdesc = NULL; + char *cunits = NULL; + logical found_desc = False, found_units = False; +/* + * Output variable. + */ + void *v2d; + double *tmp_v2d = NULL; + int ndims_v2d; + ng_size_t *dsizes_v2d, size_v2d; + NclBasicDataTypes type_v2d; + NclObjClass type_obj_v2d; + NclScalar missing_v2d; + +/* + * Variables for returning the output array with attributes attached. + */ + int att_id; + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + NclQuark *qdesc, *qunits; + +/* + * Various + */ + ng_size_t i, nx, ny, nz, nxnynz, nxy, nxy_nz , nxy_2, size_leftmost; + ng_size_t index_v3d, index_v2d, index_xy; + int inx, iny, inz, inxy; +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ + v3d = (void*)NclGetArgValue( + 0, + 2, + &ndims_v3d, + dsizes_v3d, + NULL, + NULL, + &type_v3d, + DONT_CARE); + + xy = (void*)NclGetArgValue( + 1, + 2, + &ndims_xy, + dsizes_xy, + NULL, + NULL, + &type_xy, + DONT_CARE); + +/* + * Error checking. + */ + if(ndims_v3d < 3) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_2d_xy: The v3d array must be at least 3-dimensional"); + return(NhlFATAL); + } + if(ndims_v3d != (ndims_xy+1)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_2d_xy: The v3d array must have one more dimension than the xy array"); + return(NhlFATAL); + } + if(dsizes_xy[ndims_xy-1] != 2) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_2d_xy: The rightmost dimension of xy must be 2"); + return(NhlFATAL); + } + nz = dsizes_v3d[ndims_v3d-3]; + ny = dsizes_v3d[ndims_v3d-2]; + nx = dsizes_v3d[ndims_v3d-1]; + nxy = dsizes_xy[ndims_xy-2]; + nxnynz = nx * ny * nz; + nxy_nz = nxy * nz; + nxy_2 = nxy * 2; + +/* + * Test dimension sizes. + */ + if((nxy > INT_MAX) || (nx > INT_MAX) || (ny > INT_MAX) || (nz > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_2d_xy: one or more dimension sizes is greater than INT_MAX", nxy); + return(NhlFATAL); + } + inx = (int) nx; + iny = (int) ny; + inz = (int) nz; + inxy = (int) nxy; + +/* + * Check leftmost dimensions, if any, and calculate their size. + * Also set dimension sizes for output array. + */ + ndims_v2d = ndims_xy; /* leftmost dims x nz x nxy */ + dsizes_v2d = (ng_size_t*)calloc(ndims_v2d,sizeof(ng_size_t)); + if( dsizes_v2d == NULL ) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_2d_xy: Unable to allocate memory for holding dimension sizes"); + return(NhlFATAL); + } + size_leftmost = 1; + for(i = 0; i < ndims_v3d-3; i++) { + if(dsizes_v3d[i] != dsizes_xy[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_2d_xy: The leftmost dimensions of v3d and xy must be the same"); + return(NhlFATAL); + } + dsizes_v2d[i] = dsizes_v3d[i]; + size_leftmost *= dsizes_v3d[i]; + } + dsizes_v2d[ndims_v2d-2] = nz; + dsizes_v2d[ndims_v2d-1] = nxy; + + size_v2d = size_leftmost * nxy_nz; + +/* + * Check if v3d has any attributes, namely "description" or "units". + * These attributes will be attached to the return variable v2d. + */ + stack_entry = _NclGetArg(0, 2, DONT_CARE); + switch (stack_entry.kind) { + case NclStk_VAR: + if (stack_entry.u.data_var->var.att_id != -1) { + attr_obj = (NclAtt) _NclGetObj(stack_entry.u.data_var->var.att_id); + if (attr_obj == NULL) { + break; + } + } + else { +/* + * att_id == -1 ==> no optional args given. + */ + break; + } +/* + * Get optional arguments. If none are specified, then return + * missing values. + */ + if (attr_obj->att.n_atts == 0) { + break; + } + else { +/* + * Get list of attributes. + */ + attr_list = attr_obj->att.att_list; +/* + * Loop through attributes and check them. + */ + while (attr_list != NULL) { + if ((strcmp(attr_list->attname, "description")) == 0) { + description = (NrmQuark *) attr_list->attvalue->multidval.val; + cdesc = NrmQuarkToString(*description); + found_desc = True; + } + if ((strcmp(attr_list->attname, "units")) == 0) { + units = (NrmQuark *) attr_list->attvalue->multidval.val; + cunits = NrmQuarkToString(*units); + found_units = True; + } + attr_list = attr_list->next; + } + } + default: + break; + } + +/* + * Allocate space for coercing input arrays. If the input v3d or xy + * are already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * The output type defaults to float, unless any of the two input arrays + * are double. + */ + type_v2d = NCL_float; + type_obj_v2d = nclTypefloatClass; + if(type_v3d != NCL_double) { + tmp_v3d = (double *)calloc(nxnynz,sizeof(double)); + if(tmp_v3d == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_2d_xy: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_v2d = NCL_double; + type_obj_v2d = nclTypedoubleClass; + } + if(type_xy != NCL_double) { + tmp_xy = (double *)calloc(nxy_2,sizeof(double)); + if(tmp_xy == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_2d_xy: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_v2d = NCL_double; + type_obj_v2d = nclTypedoubleClass; + } + +/* + * Allocate space for output array. + */ + if(type_v2d == NCL_double) { + v2d = (double *)calloc(size_v2d,sizeof(double)); + if(v2d == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_2d_xy: Unable to allocate memory for output array"); + return(NhlFATAL); + } + missing_v2d.doubleval = ((NclTypeClass)nclTypedoubleClass)->type_class.default_mis.doubleval; + } + else { + v2d = (float *)calloc(size_v2d,sizeof(float)); + tmp_v2d = (double *)calloc(nxy_nz,sizeof(double)); + if(tmp_v2d == NULL || v2d == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_2d_xy: Unable to allocate memory for output array"); + return(NhlFATAL); + } + missing_v2d.floatval = ((NclTypeClass)nclTypefloatClass)->type_class.default_mis.floatval; + } + +/* + * Loop across leftmost dimensions and call the Fortran routine + * for reach three-dimensional subsection. + */ + index_v3d = index_v2d = index_xy = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of v3d (tmp_v3d) to double if necessary. + */ + if(type_v3d != NCL_double) { + coerce_subset_input_double(v3d,tmp_v3d,index_v3d,type_v3d,nxnynz, + 0,NULL,NULL); + } + else { + tmp_v3d = &((double*)v3d)[index_v3d]; + } +/* + * Coerce subsection of xy (tmp_xy) to double if necessary. + */ + if(type_xy != NCL_double) { + coerce_subset_input_double(xy,tmp_xy,index_xy,type_xy,nxy_2,0,NULL,NULL); + } + else { + tmp_xy = &((double*)xy)[index_xy]; + } + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_v2d == NCL_double) tmp_v2d = &((double*)v2d)[index_v2d]; +/* + * Call Fortran routine. + */ + NGCALLF(dinterp2dxy,DINTERP2DXY)(tmp_v3d,tmp_v2d,tmp_xy,&inx,&iny,&inz,&inxy); +/* + * Coerce output back to float if necessary. + */ + if(type_v2d == NCL_float) { + coerce_output_float_only(v2d,tmp_v2d,nxy_nz,index_v2d); + } + + index_v3d += nxnynz; /* Increment indices */ + index_v2d += nxy_nz; + index_xy += nxy_2; + } +/* + * Free up memory. + */ + if(type_v3d != NCL_double) NclFree(tmp_v3d); + if(type_xy != NCL_double) NclFree(tmp_xy); + if(type_v2d != NCL_double) NclFree(tmp_v2d); + +/* + * If v3d had a "description" or units attribute, return them with + * the output variable as an attribute. Otherwise, return a + * blank string for description, and nothing for units. + */ + if(!found_desc) { + cdesc = (char *)calloc(2,sizeof(char)); + strcpy(cdesc," "); + } +/* + * I don't think we can return "description" or "units" here, because + * they are attached to an NCL input parameter. It could screw things up + * if we try to return it as an attribute with the output variable. + * Instead, create a new description and units "quark" variable. + */ + qdesc = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *qdesc = NrmStringToQuark(cdesc); + if (!found_desc) + free(cdesc); + if(found_units) { + qunits = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *qunits = NrmStringToQuark(cunits); + } +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)v2d, + &missing_v2d, + ndims_v2d, + dsizes_v2d, + TEMPORARY, + NULL, + type_obj_v2d + ); +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)qdesc, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + if(found_units) { + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)qunits, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + } + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + NULL, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + NclFree(dsizes_v2d); +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); +} + + +NhlErrorTypes wrf_interp_1d_W( void ) +{ +/* + * Input array variables + */ + void *v_in, *z_in, *z_out; + double *tmp_v_in = NULL; + double *tmp_z_in = NULL; + double *tmp_z_out = NULL; + int ndims_v_in, ndims_z_in, ndims_z_out; + ng_size_t dsizes_v_in[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_z_in[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_z_out[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_v_in, type_z_in, type_z_out; +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info; + +/* + * Variables for retrieving attributes from "v3d". + */ + NclAttList *attr_list; + NclAtt attr_obj; + NclStackEntry stack_entry; + NrmQuark *description, *units; + char *cdesc = NULL; + char *cunits = NULL; + logical found_desc = False, found_units = False; + +/* + * Output variable. + */ + void *v_out; + double *tmp_v_out = NULL; + double v_out_msg; + ng_size_t *dsizes_v_out, size_v_out; + NclBasicDataTypes type_v_out; + NclObjClass type_obj_v_out; + NclScalar missing_v_out; + +/* + * Variables for returning the output array with attributes attached. + */ + int att_id; + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + NclQuark *qdesc, *qunits; + +/* + * Various + */ + ng_size_t i, nz_in, nz_out, size_leftmost, index_v_in, index_v_out; + int inz_in, inz_out; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ + v_in = (void*)NclGetArgValue( + 0, + 3, + &ndims_v_in, + dsizes_v_in, + NULL, + NULL, + &type_v_in, + DONT_CARE); + + z_in = (void*)NclGetArgValue( + 1, + 3, + &ndims_z_in, + dsizes_z_in, + NULL, + NULL, + &type_z_in, + DONT_CARE); + + z_out = (void*)NclGetArgValue( + 2, + 3, + &ndims_z_out, + dsizes_z_out, + NULL, + NULL, + &type_z_out, + DONT_CARE); + +/* + * Error checking. + */ + if(ndims_v_in != ndims_z_in || ndims_v_in != ndims_z_out) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_1d: The v_in, z_in, and z_out arrays must be the same number of dimensions"); + return(NhlFATAL); + } + nz_in = dsizes_z_in[ndims_z_in-1]; + nz_out = dsizes_z_out[ndims_z_out-1]; + if(dsizes_v_in[ndims_v_in-1] != nz_in) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_1d: The rightmost dimension of v_in and z_in must be the same"); + return(NhlFATAL); + } + +/* + * Test dimension sizes. + */ + if((nz_in > INT_MAX) || (nz_out > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_1d: nz_in and/or nz_out is greater than INT_MAX"); + return(NhlFATAL); + } + inz_in = (int) nz_in; + inz_out = (int) nz_out; + +/* + * Retrieve dimension names from the "v3d" variable, if any. + * These dimension names will later be attached to the output variable. + */ + dim_info = get_wrf_dim_info(0,3,ndims_v_in,dsizes_v_in); + +/* + * Check if v_in has any attributes, namely "description" or "units". + * These attributes will be attached to the return variable v_out. + */ + stack_entry = _NclGetArg(0, 3, DONT_CARE); + switch (stack_entry.kind) { + case NclStk_VAR: + if (stack_entry.u.data_var->var.att_id != -1) { + attr_obj = (NclAtt) _NclGetObj(stack_entry.u.data_var->var.att_id); + if (attr_obj == NULL) { + break; + } + } + else { +/* + * att_id == -1 ==> no optional args given. + */ + break; + } +/* + * Get optional arguments. If none are specified, then return + * missing values. + */ + if (attr_obj->att.n_atts == 0) { + break; + } + else { +/* + * Get list of attributes. + */ + attr_list = attr_obj->att.att_list; +/* + * Loop through attributes and check them. + */ + while (attr_list != NULL) { + if ((strcmp(attr_list->attname, "description")) == 0) { + description = (NrmQuark *) attr_list->attvalue->multidval.val; + cdesc = NrmQuarkToString(*description); + found_desc = True; + } + if ((strcmp(attr_list->attname, "units")) == 0) { + units = (NrmQuark *) attr_list->attvalue->multidval.val; + cunits = NrmQuarkToString(*units); + found_units = True; + } + attr_list = attr_list->next; + } + } + default: + break; + } + +/* + * Calculate leftmost dimensions, if any, and check their sizes. + * Also set dimension sizes for output array. + */ + dsizes_v_out = (ng_size_t*)calloc(ndims_z_out,sizeof(ng_size_t)); + if( dsizes_v_out == NULL ) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_1d: Unable to allocate memory for holding dimension sizes"); + return(NhlFATAL); + } + + size_leftmost = 1; + for(i = 0; i < ndims_v_in-1; i++ ) { + if(dsizes_v_in[i] != dsizes_z_in[i] || + dsizes_v_in[i] != dsizes_z_out[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_1d: The input arrays must be the same dimensionality"); + return(NhlFATAL); + } + dsizes_v_out[i] = dsizes_v_in[i]; + size_leftmost *= dsizes_v_in[i]; + } + dsizes_v_out[ndims_v_in-1] = nz_out; + size_v_out = size_leftmost * nz_out; + +/* + * Allocate space for coercing input arrays. If the input arrays + * are already double, then we don't need to allocate space for the + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * The output type defaults to float, unless any of the two input arrays + * are double. + */ + type_v_out = NCL_float; + type_obj_v_out = nclTypefloatClass; + if(type_v_in != NCL_double) { + tmp_v_in = (double *)calloc(nz_in,sizeof(double)); + if(tmp_v_in == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_1d: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_v_out = NCL_double; + type_obj_v_out = nclTypedoubleClass; + } + if(type_z_in != NCL_double) { + tmp_z_in = (double *)calloc(nz_in,sizeof(double)); + if(tmp_z_in == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_1d: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_v_out = NCL_double; + type_obj_v_out = nclTypedoubleClass; + } + + if(type_z_out != NCL_double) { + tmp_z_out = (double *)calloc(nz_out,sizeof(double)); + if(tmp_z_out == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_1d: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_v_out = NCL_double; + type_obj_v_out = nclTypedoubleClass; + } + +/* + * Allocate space for output array. + */ + if(type_v_out == NCL_double) { + v_out = (double *)calloc(size_v_out,sizeof(double)); + if(v_out == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_1d: Unable to allocate memory for output array"); + return(NhlFATAL); + } + v_out_msg = missing_v_out.doubleval = ((NclTypeClass)nclTypedoubleClass)->type_class.default_mis.doubleval; + } + else { + v_out = (float *)calloc(size_v_out,sizeof(float)); + tmp_v_out = (double *)calloc(nz_out,sizeof(double)); + if(tmp_v_out == NULL || v_out == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_interp_1d: Unable to allocate memory for output array"); + return(NhlFATAL); + } + v_out_msg = (double)((NclTypeClass)nclTypefloatClass)->type_class.default_mis.floatval; + missing_v_out.floatval = ((NclTypeClass)nclTypefloatClass)->type_class.default_mis.floatval; + } + +/* + * Loop across leftmost dimensions and call the Fortran routine + * for reach one-dimensional subsection. + */ + index_v_out = index_v_in = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of v_in (tmp_v_in) to double if necessary. + */ + if(type_v_in != NCL_double) { + coerce_subset_input_double(v_in,tmp_v_in,index_v_in,type_v_in,nz_in, + 0,NULL,NULL); + } + else { + tmp_v_in = &((double*)v_in)[index_v_in]; + } +/* + * Coerce subsection of z_in (tmp_z_in) to double if necessary. + */ + if(type_z_in != NCL_double) { + coerce_subset_input_double(z_in,tmp_z_in,index_v_in,type_z_in,nz_in, + 0,NULL,NULL); + } + else { + tmp_z_in = &((double*)z_in)[index_v_in]; + } + +/* + * Coerce subsection of z_out (tmp_z_out) to double if necessary. + */ + if(type_z_out != NCL_double) { + coerce_subset_input_double(z_out,tmp_z_out,index_v_out,type_z_out, + nz_out,0,NULL,NULL); + } + else { + tmp_z_out = &((double*)z_out)[index_v_out]; + } + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_v_out == NCL_double) tmp_v_out = &((double*)v_out)[index_v_out]; +/* + * Call Fortran routine. + */ + NGCALLF(dinterp1d,DINTERP1D)(tmp_v_in,tmp_v_out,tmp_z_in,tmp_z_out,&inz_in, + &inz_out,&v_out_msg); +/* + * Coerce output back to float if necessary. + */ + if(type_v_out == NCL_float) { + coerce_output_float_only(v_out,tmp_v_out,nz_out,index_v_out); + } + + index_v_in += nz_in; + index_v_out += nz_out; + } +/* + * Free up memory. + */ + if(type_v_in != NCL_double) NclFree(tmp_v_in); + if(type_z_in != NCL_double) NclFree(tmp_z_in); + if(type_z_out != NCL_double) NclFree(tmp_z_out); + if(type_v_out != NCL_double) NclFree(tmp_v_out); + +/* + * If v3d had a "description" or units attribute, return them with + * the output variable as an attribute. Otherwise, return a + * blank string for description, and nothing for units. + */ + if(!found_desc) { + cdesc = (char *)calloc(2,sizeof(char)); + strcpy(cdesc," "); + } +/* + * I don't think we can return "description" or "units" here, because + * they are attached to an NCL input parameter. It could screw things up + * if we try to return it as an attribute with the output variable. + * Instead, create a new description and units "quark" variable. + */ + qdesc = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *qdesc = NrmStringToQuark(cdesc); + if (!found_desc) + free(cdesc); + if(found_units) { + qunits = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *qunits = NrmStringToQuark(cunits); + } +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)v_out, + &missing_v_out, + ndims_z_out, + dsizes_v_out, + TEMPORARY, + NULL, + type_obj_v_out + ); +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)qdesc, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + if(found_units) { + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)qunits, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + } + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + NclFree(dsizes_v_out); + NclFree(dim_info); +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); + +} + + +NhlErrorTypes wrf_smooth_2d_W( void ) +{ +/* + * Input variables + * + */ + void *a; + int has_missing_a, ndims_a; + ng_size_t dsizes_a[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_a; + NclScalar missing_a; + int *it; + +/* + * Various + */ + double *db = NULL; + float *fb = NULL; + ng_size_t i, index_a, size_leftmost; + int ny, nx, nynx; + double d_missing; + float f_missing; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ +/* + * Get argument # 0 + */ + a = (void*)NclGetArgValue( + 0, + 2, + &ndims_a, + dsizes_a, + &missing_a, + &has_missing_a, + &type_a, + 1); + +/* + * Check dimension sizes and input type. + */ + if(ndims_a < 2) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_smooth_2d: The 'a' array must have at least 2 dimensions"); + return(NhlFATAL); + } + if(type_a != NCL_double && type_a != NCL_float) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_smooth_2d: The 'a' array must be float or double"); + return(NhlFATAL); + } + ny = dsizes_a[ndims_a-2]; + nx = dsizes_a[ndims_a-1]; + nynx = ny * nx; + +/* + * Get argument # 1 + */ + it = (int*)NclGetArgValue( + 1, + 2, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + +/* + * Calculate size of leftmost dimensions. + */ + size_leftmost = 1; + for(i = 0; i < ndims_a-2; i++) size_leftmost *= dsizes_a[i]; + +/* + * Allocate space for "b", which "a" will be copied to inside + * Fortran routine. + */ + if(type_a == NCL_double) { + db = (double *)malloc(nynx*sizeof(double)); + if(db == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_smooth_2d: Unable to allocate memory for temporary array"); + return(NhlFATAL); + } + d_missing = has_missing_a ? missing_a.doubleval : ((NclTypeClass)nclTypedoubleClass)->type_class.default_mis.doubleval; + } + else { + fb = (float *)malloc(nynx*sizeof(float)); + if(fb == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_smooth_2d: Unable to allocate memory for temporary array"); + return(NhlFATAL); + } + f_missing = has_missing_a ? missing_a.floatval : ((NclTypeClass)nclTypedoubleClass)->type_class.default_mis.floatval; + } + +/* + * Loop across leftmost dimensions and call the Fortran routine for each + * two-dimensional subsection. + */ + index_a = 0; + + for(i = 0; i < size_leftmost; i++) { + if(type_a == NCL_double) { + NGCALLF(dfilter2d,DFILTER2D)(&((double*)a)[index_a], db, &nx, &ny, it, + &d_missing); + } + else { + NGCALLF(filter2d,FILTER2D)(&((float*)a)[index_a], fb, &nx, &ny, it, + &f_missing); + } + index_a += nynx; + } + + if(type_a == NCL_double) { + NclFree(db); + } + else { + NclFree(fb); + } +/* + * This is a procedure, so no values are returned. + */ + return(NhlNOERROR); +} + +NhlErrorTypes wrf_latlon_to_ij_W( void ) +{ + +/* + * Input variables + */ + void *lat_array, *lon_array, *lat_loc, *lon_loc; + double *tmp_lat_array = NULL; + double *tmp_lon_array = NULL; + double *tmp_lat_loc = NULL; + double *tmp_lon_loc = NULL; + int ndims_lat_array; + ng_size_t dsizes_lat_array[NCL_MAX_DIMENSIONS]; + int ndims_lon_array; + ng_size_t dsizes_lon_array[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_lat_loc[1]; + ng_size_t dsizes_lon_loc[1]; + NclBasicDataTypes type_lat_array, type_lon_array; + NclBasicDataTypes type_lat_loc, type_lon_loc; + int is_scalar_latlon_loc; + +/* + * Return variable + */ + int iret, *ret; + int ndims_ret; + ng_size_t *dsizes_ret; + NclScalar missing_ret; + +/* + * Various + */ + ng_size_t ny, nx, nynx, nretlocs; + ng_size_t index_array, index_ret; + ng_size_t i, j, ndims_leftmost, size_leftmost, size_output; + int inx, iny; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ +/* + * Get argument # 0 + */ + lat_array = (void*)NclGetArgValue( + 0, + 4, + &ndims_lat_array, + dsizes_lat_array, + NULL, + NULL, + &type_lat_array, + DONT_CARE); + +/* + * Get argument # 1 + */ + lon_array = (void*)NclGetArgValue( + 1, + 4, + &ndims_lon_array, + dsizes_lon_array, + NULL, + NULL, + &type_lon_array, + DONT_CARE); + +/* + * Check dimension sizes of lat,lon arrays and calculate size of + * leftmost dimensions. + */ + if(ndims_lat_array < 2 || ndims_lon_array < 2 || + ndims_lon_array != ndims_lat_array) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_latlon_to_ij: The lat,lon arrays must have at least two dimensions and the same number of dimensions as each other"); + return(NhlFATAL); + } + + ny = dsizes_lat_array[ndims_lat_array-2]; + nx = dsizes_lat_array[ndims_lat_array-1]; + nynx = ny * nx; + +/* + * Test dimension sizes. + */ + if((nx > INT_MAX) || (ny > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_latlon_to_ij: nx and/or ny is greater than INT_MAX"); + return(NhlFATAL); + } + inx = (int) nx; + iny = (int) ny; + + size_leftmost = 1; + ndims_leftmost = ndims_lat_array-2; + for(i = 0; i < ndims_lon_array; i++) { + if(dsizes_lon_array[i] != dsizes_lat_array[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_latlon_to_ij: The dimension sizes of the lat,lon arrays must be the same"); + return(NhlFATAL); + } + if(i < ndims_leftmost) size_leftmost *= dsizes_lat_array[i]; + } + +/* + * Get argument # 2 + */ + lat_loc = (void*)NclGetArgValue( + 2, + 4, + NULL, + dsizes_lat_loc, + NULL, + NULL, + &type_lat_loc, + DONT_CARE); + +/* + * Get argument # 3 + */ + lon_loc = (void*)NclGetArgValue( + 3, + 4, + NULL, + dsizes_lon_loc, + NULL, + NULL, + &type_lon_loc, + DONT_CARE); + +/* + * Check dimension sizes of lat,lon locations. + */ + if(dsizes_lon_loc[0] != dsizes_lat_loc[0]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_latlon_to_ij: The lat,lon locations must be the same length"); + return(NhlFATAL); + } + if(dsizes_lon_loc[0] == 1) { + is_scalar_latlon_loc = 1; + } + else { + is_scalar_latlon_loc = 0; + } + +/* + * Allocate space for coercing input arrays. If any of the input + * is already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * Allocate space for tmp_lat_array. + */ + if(type_lat_array != NCL_double) { + tmp_lat_array = (double *)calloc(nynx,sizeof(double)); + if(tmp_lat_array == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_latlon_to_ij: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for tmp_lon_array. + */ + if(type_lon_array != NCL_double) { + tmp_lon_array = (double *)calloc(nynx,sizeof(double)); + if(tmp_lon_array == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_latlon_to_ij: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for tmp_lat_loc. + */ + if(type_lat_loc != NCL_double) { + tmp_lat_loc = (double *)calloc(1,sizeof(double)); + if(tmp_lat_loc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_latlon_to_ij: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for tmp_lon_loc. + */ + if(type_lon_loc != NCL_double) { + tmp_lon_loc = (double *)calloc(1,sizeof(double)); + if(tmp_lon_loc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_latlon_to_ij: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } +/* + * Calculate size of output array. The output array will have dimension + * sizes equal to the leftmost dimensions of the lat,lon arrays (minus + * the last two dimensions), the length of the lat,lon locations + * (if not a scalar), and the last dimension will be 2, which holds the + * i,j location on the grid. + */ + nretlocs = size_leftmost * dsizes_lat_loc[0]; + size_output = 2 * nretlocs; + +/* + * Allocate space for output array. + */ + ret = (int*)calloc(size_output, sizeof(int)); + if(ret == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_latlon_to_ij: Unable to allocate memory for output array"); + return(NhlFATAL); + } + +/* + * Allocate space for output dimension sizes and set them. The last dimension + * will always be 2, in order to hold the i,j locations. Some examples: + * + * Lat,lon array are 90 x 180, lat,lon locations are scalars: + * Output will be array with 2 elements. + * + * Lat,lon array are 5 x 90 x 180, lat,lon locations are scalars: + * Output will be array of length 5 x 2. + * + * Lat,lon array are 5 x 90 x 180, lat,lon locations are length 10: + * Output will be array of length 5 x 10 x 2. + * + * Lat,lon array are 3 x 5 x 90 x 180, lat,lon locations are length 4: + * Output will be array of length 3 x 5 x 4 x 2. + */ + if(is_scalar_latlon_loc) { + ndims_ret = ndims_leftmost + 1; + } + else { + ndims_ret = ndims_leftmost + 2; + } + dsizes_ret = (ng_size_t*)calloc(ndims_ret,sizeof(ng_size_t)); + if( dsizes_ret == NULL ) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_latlon_to_ij: Unable to allocate memory for holding dimension sizes"); + return(NhlFATAL); + } +/* + * Fill in dimension sizes for output array. See above examples. + */ + for(i = 0; i < ndims_leftmost; i++) { + dsizes_ret[i] = dsizes_lat_array[i]; + } + if(!is_scalar_latlon_loc) { + dsizes_ret[ndims_leftmost] = dsizes_lat_loc[0]; + } + dsizes_ret[ndims_ret-1] = 2; + +/* + * Loop across leftmost dimensions of lat,lon array, the lat,lon locations, + * and call the Fortran routine for each subsection of the input arrays. + */ + index_array = index_ret = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of lat_array (tmp_lat_array) to double if necessary. + */ + if(type_lat_array != NCL_double) { + coerce_subset_input_double(lat_array,tmp_lat_array,index_array, + type_lat_array,nynx,0,NULL,NULL); + } + else { + tmp_lat_array = &((double*)lat_array)[index_array]; + } + +/* + * Coerce subsection of lon_array (tmp_lon_array) to double if necessary. + */ + if(type_lon_array != NCL_double) { + coerce_subset_input_double(lon_array,tmp_lon_array,index_array, + type_lon_array,nynx,0,NULL,NULL); + } + else { + tmp_lon_array = &((double*)lon_array)[index_array]; + } + +/* + * Get default integer missing value. + */ + missing_ret.intval = ((NclTypeClass)nclTypeintClass)->type_class.default_mis.intval; + +/* + * Loop across lat,lon locations. + */ + for(j = 0; j < dsizes_lat_loc[0]; j++) { + +/* + * Coerce subsection of lat_loc (tmp_lat_loc) to double if necessary. + */ + if (type_lat_loc != NCL_double) { + coerce_subset_input_double(lat_loc,tmp_lat_loc,j,type_lat_loc,1,0, + NULL,NULL); + } + else { + tmp_lat_loc = &((double*)lat_loc)[j]; + } + +/* + * Coerce subsection of lon_loc (tmp_lon_loc) to double if necessary. + */ + if(type_lon_loc != NCL_double) { + coerce_subset_input_double(lon_loc,tmp_lon_loc,j,type_lon_loc,1,0, + NULL,NULL); + } + else { + tmp_lon_loc = &((double*)lon_loc)[j]; + } + +/* + * Call the Fortran routine. Make sure you return the i,j index + * swapped, since we are going from Fortran to C. + */ + NGCALLF(dgetijlatlong,DGETIJLATLONG)(tmp_lat_array, tmp_lon_array, + tmp_lat_loc, tmp_lon_loc, + &ret[index_ret+1], + &ret[index_ret], &inx, &iny, + &missing_ret.intval); + index_ret+=2; + } + index_array += nynx; + } + +/* + * Free unneeded memory. + */ + if(type_lat_array != NCL_double) NclFree(tmp_lat_array); + if(type_lon_array != NCL_double) NclFree(tmp_lon_array); + if(type_lat_loc != NCL_double) NclFree(tmp_lat_loc); + if(type_lon_loc != NCL_double) NclFree(tmp_lon_loc); + + iret = NclReturnValue(ret,ndims_ret,dsizes_ret,&missing_ret,NCL_int,0); + NclFree(dsizes_ret); + return(iret); +} + +NhlErrorTypes wrf_uvmet_W( void ) +{ + +/* + * Input variables + */ +/* + * Argument # 0 + */ + void *u; + double *tmp_u = NULL; + int ndims_u; + ng_size_t dsizes_u[NCL_MAX_DIMENSIONS]; + int has_missing_u; + NclBasicDataTypes type_u; + NclScalar missing_u, missing_du; + +/* + * Argument # 1 + */ + void *v; + double *tmp_v = NULL; + int ndims_v; + ng_size_t dsizes_v[NCL_MAX_DIMENSIONS]; + int has_missing_v; + NclBasicDataTypes type_v; + NclScalar missing_v, missing_dv; + +/* + * Argument # 2 + */ + void *lat; + double *tmp_lat = NULL; + int ndims_lat; + ng_size_t dsizes_lat[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_lat; + +/* + * Argument # 3 + */ + void *lon; + double *tmp_lon = NULL; + int ndims_lon; + ng_size_t dsizes_lon[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_lon; + +/* + * Argument # 4 + */ + void *cenlon; + double *tmp_cenlon; + NclBasicDataTypes type_cenlon; + +/* + * Argument # 5 + */ + void *cone; + double *tmp_cone; + NclBasicDataTypes type_cone; + +/* + * Return variable and attributes. + */ + void *uvmet; + double *tmp_uvmet, tmp_uvmet_msg; + int ndims_uvmet; + ng_size_t *dsizes_uvmet; + int has_missing; + NclScalar missing_uvmet; + NclBasicDataTypes type_uvmet; + NclObjClass type_obj_uvmet; + NclQuark *description, *units; + char *cdescription, *cunits; + NclDimRec *dim_info = NULL; + NclDimRec *dim_info_u, *dim_info_v; + +/* + * Various + */ + ng_size_t nx, ny, nz, nxp1, nynxp1, nyp1, nyp1nx, nynx, twonynx; + ng_size_t index_u, index_v, index_latlon, index_uvmet_u, index_uvmet_v; + ng_size_t i, j; + ng_size_t size_leftmost, size_leftmost_uvmet, size_uvmet, size_output; + double rpd, *longca, *longcb; + int istag, ndims_leftmost; + int inx, iny, inxp1, inyp1; + +/* + * Variables for returning the output array with attributes attached. + */ + int att_id; + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ +/* + * Get argument # 0 + */ + u = (void*)NclGetArgValue( + 0, + 6, + &ndims_u, + dsizes_u, + &missing_u, + &has_missing_u, + &type_u, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_u < 2) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: The u array must have at least 2 dimensions"); + return(NhlFATAL); + } + ny = dsizes_u[ndims_u-2]; + nxp1 = dsizes_u[ndims_u-1]; + nynxp1 = ny * nxp1; + +/* + * Get argument # 1 + */ + v = (void*)NclGetArgValue( + 1, + 6, + &ndims_v, + dsizes_v, + &missing_v, + &has_missing_v, + &type_v, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_v != ndims_u) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: The u and v arrays must have the same number of dimensions"); + return(NhlFATAL); + } + + nyp1 = dsizes_v[ndims_v-2]; + nx = dsizes_v[ndims_v-1]; + nyp1nx = nyp1 * nx; + +/* + * Test dimension sizes. + */ + if((nxp1 > INT_MAX) || (nyp1 > INT_MAX) || (nx > INT_MAX) || (ny > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: one or more dimension sizes is greater than INT_MAX"); + return(NhlFATAL); + } + inx = (int) nx; + iny = (int) ny; + inxp1 = (int) nxp1; + inyp1 = (int) nyp1; + +/* + * Coerce the missing values. + */ + coerce_missing(type_u,has_missing_u,&missing_u,&missing_du,NULL); + coerce_missing(type_v,has_missing_v,&missing_v,&missing_dv,NULL); + if(has_missing_u || has_missing_v) { + has_missing = True; + /*fprintf(stderr, "\n\nfile: %s, line: %d\n", __FILE__, __LINE__);*/ + /* fprintf(stderr, "\tu or v has missing.\n");*/ + } + else { + has_missing = False; + } +/* + * Check whether we have staggered or unstaggered grids. + * + * If unstaggered: + * - The rightmost two dimensions of u and v must be the same. + * + * If staggered: + * - The rightmost dimension of u must be one more than the + * rightmost dimension of v. + * - The second rightmost dimension of v must be one more + * than the second rightmost dimension of u. + */ + if(nxp1 == nx && nyp1 == ny) istag = 0; + else istag = 1; + +/* + * Get argument # 2 + */ + lat = (void*)NclGetArgValue( + 2, + 6, + &ndims_lat, + dsizes_lat, + NULL, + NULL, + &type_lat, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_lat != 2 && ndims_lat != ndims_u && + (ndims_u > 2 && ndims_lat != (ndims_u-1))) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: The lat array must either be 2D, the same dimensions as u,v, or one fewer dimensions than u,v"); + return(NhlFATAL); + } + if(dsizes_lat[ndims_lat-2] != ny || dsizes_lat[ndims_lat-1] != nx) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: The rightmost 2 dimensions of lat must be ny x nx"); + return(NhlFATAL); + } + nynx = ny * nx; + +/* + * Check dimension sizes for lat. It can be: + * - 2D (ny x nx) + * - Same dimensionality as U,V (but with rightmost dimemsions ny x nx) + * - One fewer dimension than U,V, with all leftmost up to the third + * rightmost dimensions the same as U,V. + */ + if(ndims_lat > 2) { + if(ndims_lat == ndims_u) { + for(i = 0; i < ndims_u-2; i++) { + if(dsizes_lat[i] != dsizes_u[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: if u and lat have the same number of dimensions, then all but the rightmost 2 dimensions must be the same"); + return(NhlFATAL); + } + } + } + else { + for(i = 0; i < ndims_u-3; i++) { + if(dsizes_lat[i] != dsizes_u[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: if lat has one fewer dimensions than u, then all but the rightmost 3 dimensions must be the same"); + return(NhlFATAL); + } + } + } + } + +/* + * Get argument # 3 + */ + lon = (void*)NclGetArgValue( + 3, + 6, + &ndims_lon, + dsizes_lon, + NULL, + NULL, + &type_lon, + DONT_CARE); + +/* + * Check dimension sizes for lon. This should be easier than lat, + * since we've done all the work for lat, and the lat,lon have to be + * exactly the same dimensions. + */ + if(ndims_lon != ndims_lat) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: The lat,lon arrays must have the same number of dimensions"); + return(NhlFATAL); + } + for(i = 0; i < ndims_lat; i++) { + if(dsizes_lat[i] != dsizes_lon[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: The lat,lon arrays must have the same dimension sizes"); + return(NhlFATAL); + } + } + +/* + * Get argument # 4 + */ + cenlon = (void*)NclGetArgValue( + 4, + 6, + NULL, + NULL, + NULL, + NULL, + &type_cenlon, + DONT_CARE); +/* + * Get argument # 5 + */ + cone = (void*)NclGetArgValue( + 5, + 6, + NULL, + NULL, + NULL, + NULL, + &type_cone, + DONT_CARE); + +/* + * Calculate size of leftmost dimensions. Note that u, v can have an + * extra leftmost dimension over lat, lon, so we need to separate these + * out. The third-from-the-rightmost dimension will be called "nz". + */ + size_leftmost = 1; + if(ndims_lat > 2 && ndims_lat == (ndims_u-1)) { + nz = dsizes_u[ndims_u-3]; + ndims_leftmost = ndims_u-3; + for(i = 0; i < ndims_leftmost; i++) size_leftmost *= dsizes_u[i]; + } + else { + nz = 1; + ndims_leftmost = ndims_u-2; + for(i = 0; i < ndims_leftmost; i++) size_leftmost *= dsizes_u[i]; + } + +/* + * The output type defaults to float, unless this input array is double. + */ + type_uvmet = NCL_float; + type_obj_uvmet = nclTypefloatClass; +/* + * Allocate space for coercing input arrays. If any of the input + * is already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * Allocate space for tmp_u. + */ + if(type_u != NCL_double) { + tmp_u = (double *)calloc(nynxp1,sizeof(double)); + if(tmp_u == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_uvmet = NCL_double; + type_obj_uvmet = nclTypedoubleClass; + } +/* + * Allocate space for tmp_v. + */ + if(type_v != NCL_double) { + tmp_v = (double *)calloc(nyp1nx,sizeof(double)); + if(tmp_v == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_uvmet = NCL_double; + type_obj_uvmet = nclTypedoubleClass; + } +/* + * Allocate space for tmp_lat and tmp_lon, depending on whether + * they are 2D or not. + */ + if(ndims_lat == 2) { + tmp_lat = coerce_input_double(lat,type_lat,nynx,0,NULL,NULL); + tmp_lon = coerce_input_double(lon,type_lon,nynx,0,NULL,NULL); + } + else { +/* + * Allocate space for tmp_lat + */ + if(type_lat != NCL_double) { + tmp_lat = (double *)calloc(nynx,sizeof(double)); + if(tmp_lat == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for tmp_lon. + */ + if(type_lon != NCL_double) { + tmp_lon = (double *)calloc(nynx,sizeof(double)); + if(tmp_lon == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + } + +/* + * Allocate space for tmp_cenlon. + */ + tmp_cenlon = coerce_input_double(cenlon,type_cenlon,1,0,NULL,NULL); + if(tmp_cenlon == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } +/* + * Allocate space for tmp_cone. + */ + tmp_cone = coerce_input_double(cone,type_cone,1,0,NULL,NULL); + if(tmp_cone == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + +/* + * Calculate size of output array. + */ + twonynx = 2 * ny * nx; + size_leftmost_uvmet = size_leftmost * nz; + size_uvmet = size_leftmost_uvmet * nynx; + size_output = 2 * size_uvmet; + +/* + * Allocate space for output array. + */ + tmp_uvmet = (double *)calloc(twonynx,sizeof(double)); + if(type_uvmet != NCL_double) { + uvmet = (void *)calloc(size_output, sizeof(float)); + missing_uvmet.floatval = ((NclTypeClass)nclTypefloatClass)->type_class.default_mis.floatval; + tmp_uvmet_msg = (double)missing_uvmet.floatval; + } + else { + uvmet = (void *)calloc(size_output, sizeof(double)); + missing_uvmet.doubleval = ((NclTypeClass)nclTypedoubleClass)->type_class.default_mis.doubleval; + tmp_uvmet_msg = missing_uvmet.doubleval; + } + if(uvmet == NULL || tmp_uvmet == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: Unable to allocate memory for output array"); + return(NhlFATAL); + } + +/* + * Allocate space for some dummy arrays. + */ + longca = (double*)calloc(nynx,sizeof(double)); + longcb = (double*)calloc(nynx,sizeof(double)); + if( longca == NULL || longcb == NULL ) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: Unable to allocate memory for output arrays"); + return(NhlFATAL); + } + +/* + * Allocate space for output dimension sizes and set them. + */ + ndims_uvmet = ndims_u + 1; + dsizes_uvmet = (ng_size_t*)calloc(ndims_uvmet,sizeof(ng_size_t)); + if( dsizes_uvmet == NULL ) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: Unable to allocate memory for holding dimension sizes"); + return(NhlFATAL); + } + dsizes_uvmet[0] = 2; + for(i = 1; i < ndims_uvmet-2; i++) dsizes_uvmet[i] = dsizes_u[i-1]; + dsizes_uvmet[ndims_uvmet-2] = ny; + dsizes_uvmet[ndims_uvmet-1] = nx; + +/* + * Loop across leftmost dimensions *and* nz, and call the Fortran + * routine for each subsection of the input arrays. + * + * The input lat, lon arrays don't have the "nz" dimension, + * so they have to be taken care of outside the nz loop. + */ + index_u = index_v = index_latlon = index_uvmet_u = 0; + index_uvmet_v = size_uvmet; + + rpd = 3.14159265/180.; + + for(i = 0; i < size_leftmost; i++) { + if(ndims_lat > 2) { +/* + * Coerce subsection of lat (tmp_lat) to double if necessary. + */ + if(type_lat != NCL_double) { + coerce_subset_input_double(lat,tmp_lat,index_latlon,type_lat,nynx, + 0,NULL,NULL); + } + else { + tmp_lat = &((double*)lat)[index_latlon]; + } +/* + * Coerce subsection of lon (tmp_lon) to double if necessary. + */ + if(type_lon != NCL_double) { + coerce_subset_input_double(lon,tmp_lon,index_latlon,type_lon,nynx, + 0,NULL,NULL); + } + else { + tmp_lon = &((double*)lon)[index_latlon]; + } + } + for(j = 0; j < nz; j++) { +/* + * Coerce subsection of u (tmp_u) to double if necessary. + */ + if(type_u != NCL_double) { + coerce_subset_input_double(u,tmp_u,index_u,type_u,nynxp1,0,NULL,NULL); + } + else { + tmp_u = &((double*)u)[index_u]; + } +/* + * Coerce subsection of v (tmp_v) to double if necessary. + */ + if(type_v != NCL_double) { + coerce_subset_input_double(v,tmp_v,index_v,type_v,nyp1nx,0,NULL,NULL); + } + else { + tmp_v = &((double*)v)[index_v]; + } +/* + * Call the Fortran routine. + */ + NGCALLF(dcomputeuvmet,DCOMPUTEUVMET)(tmp_u, tmp_v, tmp_uvmet, longca, + longcb, tmp_lon, tmp_lat, + tmp_cenlon, tmp_cone, &rpd, + &inx, &iny, &inxp1, &inyp1, &istag, + &has_missing,&missing_du.doubleval, + &missing_du.doubleval, + &tmp_uvmet_msg); + +/* + * Coerce output back to float if necessary. + */ + coerce_output_float_or_double(uvmet,&tmp_uvmet[0],type_uvmet,nynx, + index_uvmet_u); + coerce_output_float_or_double(uvmet,&tmp_uvmet[nynx],type_uvmet,nynx, + index_uvmet_v); + + index_u += nynxp1; + index_v += nyp1nx; + index_uvmet_u += nynx; + index_uvmet_v += nynx; + } + if(ndims_lat > 2) { + index_latlon += nynx; + } + } + +/* + * Free unneeded memory. + */ + if(type_u != NCL_double) NclFree(tmp_u); + if(type_v != NCL_double) NclFree(tmp_v); + if(type_lat != NCL_double) NclFree(tmp_lat); + if(type_lon != NCL_double) NclFree(tmp_lon); + if(type_cenlon != NCL_double) NclFree(tmp_cenlon); + if(type_cone != NCL_double) NclFree(tmp_cone); + NclFree(tmp_uvmet); + NclFree(longca); + NclFree(longcb); + +/* + * Set up some attributes ("description" and "units") to return. + * Note that if the input arrays are anything but 2D, the units + * will be "Temperature", and "2m Temperature" otherwise. + */ + cdescription = (char *)calloc(17,sizeof(char)); + strcpy(cdescription,"u,v met velocity"); + cunits = (char *)calloc(4,sizeof(char)); + strcpy(cunits,"m/s"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + *units = NrmStringToQuark(cunits); + free(cdescription); + free(cunits); + +/* + * Get dimension info of U and V to see if we have named dimensions. + * This will be used for return variable. The return value's + * dimension names will + */ + dim_info_u = get_wrf_dim_info(0,6,ndims_u,dsizes_u); + dim_info_v = get_wrf_dim_info(1,6,ndims_v,dsizes_v); + if(dim_info_u != NULL && dim_info_v != NULL) { + dim_info = malloc(sizeof(NclDimRec)*ndims_uvmet); + if(dim_info == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_uvmet: Unable to allocate memory for holding dimension information"); + return(NhlFATAL); + } + for(i = 0; i < ndims_uvmet; i++ ) { + dim_info[i].dim_num = i; + dim_info[i].dim_size = dsizes_uvmet[i]; + if(i != 0) dim_info[i].dim_quark = dim_info_u[i-1].dim_quark; + else dim_info[0].dim_quark = NrmStringToQuark("u_v"); + } +/* + * Just the rightmost dimension is different from u's named dimensions. + */ + dim_info[ndims_uvmet-1].dim_quark = dim_info_v[ndims_v-1].dim_quark; + } + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)uvmet, + &missing_uvmet, + ndims_uvmet, + dsizes_uvmet, + TEMPORARY, + NULL, + type_obj_uvmet + ); +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + NclFree(dsizes_uvmet); + NclFree(dim_info); + NclFree(dim_info_u); + NclFree(dim_info_v); +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); +} + +NhlErrorTypes wrf_dbz_W( void ) +{ +/* + * Input variables + */ +/* + * Argument # 0 + */ + void *prs; + double *tmp_prs = NULL; + int ndims_prs; + ng_size_t dsizes_prs[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_prs; + +/* + * Argument # 1 + */ + void *tmk; + double *tmp_tmk = NULL; + int ndims_tmk; + ng_size_t dsizes_tmk[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_tmk; + +/* + * Argument # 2 + */ + void *qvp; + double *tmp_qvp = NULL; + int ndims_qvp; + ng_size_t dsizes_qvp[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_qvp; + +/* + * Argument # 3 + */ + void *qra; + double *tmp_qra = NULL; + int ndims_qra; + ng_size_t dsizes_qra[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_qra; + +/* + * Argument # 4 + */ + void *qsn; + double *tmp_qsn; + double *tmp1_qsn = NULL; + int is_scalar_qsn, ndims_qsn; + ng_size_t dsizes_qsn[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_qsn; + +/* + * Argument # 5 + */ + void *qgr; + double *tmp_qgr = NULL; + double *tmp1_qgr = NULL; + int is_scalar_qgr, ndims_qgr; + ng_size_t dsizes_qgr[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_qgr; + +/* + * Argument # 6 + */ + int *ivarint; +/* + * Argument # 7 + */ + int *iliqskin; +/* + * Return variable + */ + void *dbz; + double *tmp_dbz = NULL; + NclBasicDataTypes type_dbz; + NclObjClass type_obj_dbz; + NclQuark *description, *units; + char *cdescription, *cunits; +/* + * Variables for returning the output array with dimension names attached. + */ + int att_id; + ng_size_t dsizes[1]; + NclMultiDValData return_md, att_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info; + +/* + * Various + */ + ng_size_t btdim, sndim, wedim, nbtsnwe, index_dbz; + ng_size_t i, j, size_leftmost, size_output; + int sn0 = 0, iwedim, isndim, ibtdim; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ +/* + * Get argument # 0 + */ + prs = (void*)NclGetArgValue( + 0, + 8, + &ndims_prs, + dsizes_prs, + NULL, + NULL, + &type_prs, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_prs < 3) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: The prs array must have at least 3 dimensions"); + return(NhlFATAL); + } + btdim = dsizes_prs[ndims_prs-3]; + sndim = dsizes_prs[ndims_prs-2]; + wedim = dsizes_prs[ndims_prs-1]; + nbtsnwe = btdim * sndim * wedim; + +/* + * Test dimension sizes. + */ + if((wedim > INT_MAX) || (sndim > INT_MAX) || (btdim > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: one or more dimension sizes is greater than INT_MAX"); + return(NhlFATAL); + } + iwedim = (int) wedim; + isndim = (int) sndim; + ibtdim = (int) btdim; + +/* + * Get argument # 1 + */ + tmk = (void*)NclGetArgValue( + 1, + 8, + &ndims_tmk, + dsizes_tmk, + NULL, + NULL, + &type_tmk, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_tmk != ndims_prs) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: The tmk array must have the same number of dimensions as the prs array"); + return(NhlFATAL); + } + +/* + * Get argument # 2 + */ + qvp = (void*)NclGetArgValue( + 2, + 8, + &ndims_qvp, + dsizes_qvp, + NULL, + NULL, + &type_qvp, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_qvp != ndims_prs) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: The qv array must have the same number of dimensions as the prs array"); + return(NhlFATAL); + } + + +/* + * Get argument # 3 + */ + qra = (void*)NclGetArgValue( + 3, + 8, + &ndims_qra, + dsizes_qra, + NULL, + NULL, + &type_qra, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_qra != ndims_prs) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: The qr array must have the same number of dimensions as the prs array"); + return(NhlFATAL); + } + + +/* + * Get argument # 4 + */ + qsn = (void*)NclGetArgValue( + 4, + 8, + &ndims_qsn, + dsizes_qsn, + NULL, + NULL, + &type_qsn, + DONT_CARE); + +/* + * Check dimension sizes. + */ + is_scalar_qsn = is_scalar(ndims_qsn,dsizes_qsn); + if(!is_scalar_qsn && ndims_qsn != ndims_prs) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: qs must either be a scalar or have the same number of dimensions as the prs array"); + return(NhlFATAL); + } + +/* + * Get argument # 5 + */ + qgr = (void*)NclGetArgValue( + 5, + 8, + &ndims_qgr, + dsizes_qgr, + NULL, + NULL, + &type_qgr, + DONT_CARE); + +/* + * Check dimension sizes. + */ + is_scalar_qgr = is_scalar(ndims_qgr,dsizes_qgr); + if(!is_scalar_qgr && ndims_qgr != ndims_prs) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: qg must either be a scalar or have the same number of dimensions as the prs array"); + return(NhlFATAL); + } + +/* + * Check that the first 6 input arrays all have the same dimensionality. + */ + for(i = 0; i < ndims_prs; i++) { + if(dsizes_tmk[i] != dsizes_prs[i] || dsizes_qvp[i] != dsizes_prs[i] || + dsizes_qra[i] != dsizes_prs[i] || + (!is_scalar_qsn && dsizes_qsn[i] != dsizes_prs[i]) || + (!is_scalar_qgr && dsizes_qgr[i] != dsizes_prs[i])) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: The prs, tmk, qv, qr, qs, and qg arrays must have the same dimensions (qs and qg can be scalars)"); + return(NhlFATAL); + } + } + +/* + * Get argument # 6 + */ + ivarint = (int*)NclGetArgValue( + 6, + 8, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); +/* + * Get argument # 7 + */ + iliqskin = (int*)NclGetArgValue( + 7, + 8, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + +/* + * Calculate size of leftmost dimensions. + */ + size_leftmost = 1; + for(i = 0; i < ndims_prs-3; i++) size_leftmost *= dsizes_prs[i]; + +/* + * The output type defaults to float, unless this input array is double. + */ + type_dbz = NCL_float; + type_obj_dbz = nclTypefloatClass; + +/* + * Allocate space for coercing input arrays. If any of the input + * is already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + */ +/* + * Allocate space for tmp_prs. + */ + if(type_prs != NCL_double) { + tmp_prs = (double *)calloc(nbtsnwe,sizeof(double)); + if(tmp_prs == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_dbz = NCL_double; + type_obj_dbz = nclTypedoubleClass; + } +/* + * Allocate space for tmp_tmk. + */ + if(type_tmk != NCL_double) { + tmp_tmk = (double *)calloc(nbtsnwe,sizeof(double)); + if(tmp_tmk == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_dbz = NCL_double; + type_obj_dbz = nclTypedoubleClass; + } +/* + * Allocate space for tmp_qvp. + */ + if(type_qvp != NCL_double) { + tmp_qvp = (double *)calloc(nbtsnwe,sizeof(double)); + if(tmp_qvp == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_dbz = NCL_double; + type_obj_dbz = nclTypedoubleClass; + } +/* + * Allocate space for tmp_qra no matter what, because qra might be + * changed by the Fortran routine, and we don't want those changes + * to propagate back here. + */ + tmp_qra = (double *)calloc(nbtsnwe,sizeof(double)); + if(tmp_qra == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + if(type_qra == NCL_double) { + type_dbz = NCL_double; + type_obj_dbz = nclTypedoubleClass; + } +/* + * Allocate space for tmp_qsn no matter what, because qsn might be + * changed by the Fortran routine, and we don't want those changes + * to propagate back here. + * + * qsn could be a scalar. If so, we'll need to propagate it to a full + * array. We'll do this later inside the do loop where the Fortran + * routine is called. + */ + tmp_qsn = (double *)calloc(nbtsnwe,sizeof(double)); + if(tmp_qsn == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + if(is_scalar_qsn) { + if(type_qsn != NCL_double) { + tmp1_qsn = coerce_input_double(qsn,type_qsn,1,0,NULL,NULL); + } + else { + tmp1_qsn = (double*)malloc(sizeof(double)); + *tmp1_qsn = ((double*)qsn)[0]; + } + } + if(type_qsn == NCL_double) { + type_dbz = NCL_double; + type_obj_dbz = nclTypedoubleClass; + } +/* + * Allocate space for tmp_qgr. + * + * If it is a scalar, then propagate the scalar to an array. + */ + if(is_scalar_qgr || type_qgr != NCL_double) { + tmp_qgr = (double *)calloc(nbtsnwe,sizeof(double)); + if(tmp_qgr == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + if(is_scalar_qgr) { + tmp1_qgr = coerce_input_double(qgr,type_qgr,1,0,NULL,NULL); + for(i = 0; i < nbtsnwe; i++) tmp_qgr[i] = *tmp1_qgr; + } + if(type_qgr == NCL_double) { + type_dbz = NCL_double; + type_obj_dbz = nclTypedoubleClass; + } + +/* + * Allocate space for output array. + */ + size_output = size_leftmost * nbtsnwe; + + if(type_dbz != NCL_double) { + dbz = (void *)calloc(size_output, sizeof(float)); + tmp_dbz = (double *)calloc(nbtsnwe,sizeof(double)); + if(tmp_dbz == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: Unable to allocate memory for temporary output array"); + return(NhlFATAL); + } + } + else { + dbz = (void *)calloc(size_output, sizeof(double)); + } + if(dbz == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_dbz: Unable to allocate memory for output array"); + return(NhlFATAL); + } + +/* + * Loop across leftmost dimensions and call the Fortran routine for each + * subsection of the input arrays. + */ + index_dbz = 0; + + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of prs (tmp_prs) to double if necessary. + */ + if(type_prs != NCL_double) { + coerce_subset_input_double(prs,tmp_prs,index_dbz,type_prs,nbtsnwe, + 0,NULL,NULL); + } + else { + tmp_prs = &((double*)prs)[index_dbz]; + } + +/* + * Coerce subsection of tmk (tmp_tmk) to double if necessary. + */ + if(type_tmk != NCL_double) { + coerce_subset_input_double(tmk,tmp_tmk,index_dbz,type_tmk,nbtsnwe, + 0,NULL,NULL); + } + else { + tmp_tmk = &((double*)tmk)[index_dbz]; + } + +/* + * Coerce subsection of qvp (tmp_qvp) to double if necessary. + */ + if(type_qvp != NCL_double) { + coerce_subset_input_double(qvp,tmp_qvp,index_dbz,type_qvp,nbtsnwe, + 0,NULL,NULL); + } + else { + tmp_qvp = &((double*)qvp)[index_dbz]; + } + +/* + * If qsn is a scalar, then propagate it to a full array. + */ + if(is_scalar_qsn) { + for(j = 0; j < nbtsnwe; j++) tmp_qsn[j] = *tmp1_qsn; + if(*tmp1_qsn == 0.) { + sn0 = 0; + } + } + else { +/* + * Force the coercion of qsn to tmp_qsn, because the original arrays may + * get changed by the Fortran routine, and we don't want those changes to + * propagate back here. + */ + coerce_subset_input_double(qsn,tmp_qsn,index_dbz,type_qsn,nbtsnwe, + 0,NULL,NULL); +/* + * Check values for qsn array. If all zero, then set sn0 to 0. Otherwise + * set sn0 to 1. + */ + j = 0; + sn0 = 0; + while( (j < nbtsnwe) && !sn0) { + if(tmp_qsn[j] != 0.) sn0 = 1; + j++; + } + } + +/* + * Force the coercion of qra to tmp_qra, because the original arrays may + * get changed by the Fortran routine, and we don't want those changes to + * propagate back here. + */ + coerce_subset_input_double(qra,tmp_qra,index_dbz,type_qra,nbtsnwe, + 0,NULL,NULL); +/* + * Coerce subsection of qgr (tmp_qgr) to double if necessary. + */ + if(!is_scalar_qgr) { + double *tmp_qgr_save = tmp_qgr; + if(type_qgr != NCL_double) { + coerce_subset_input_double(qgr,tmp_qgr,index_dbz,type_qgr,nbtsnwe, + 0,NULL,NULL); + } + else { + tmp_qgr = &((double*)qgr)[index_dbz]; + } + if (tmp_qgr_save != NULL && tmp_qgr_save != tmp_qgr) + NclFree(tmp_qgr); + } + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_dbz == NCL_double) tmp_dbz = &((double*)dbz)[index_dbz]; + +/* + * Call the Fortran routine. + */ + NGCALLF(calcdbz,CALCDBZ)(tmp_dbz, tmp_prs, tmp_tmk, tmp_qvp, tmp_qra, + tmp_qsn, tmp_qgr, &iwedim, &isndim, &ibtdim, + &sn0, ivarint, iliqskin); +/* + * Coerce output back to float if necessary. + */ + if(type_dbz == NCL_float) { + coerce_output_float_only(dbz,tmp_dbz,nbtsnwe,index_dbz); + } + index_dbz += nbtsnwe; + } + +/* + * Free unneeded memory. + */ + if(type_prs != NCL_double) NclFree(tmp_prs); + if(type_tmk != NCL_double) NclFree(tmp_tmk); + if(type_qvp != NCL_double) NclFree(tmp_qvp); + NclFree(tmp_qra); + NclFree(tmp_qsn); + if(type_qgr != NCL_double) NclFree(tmp_qgr); + if(type_dbz != NCL_double) NclFree(tmp_dbz); + if(is_scalar_qsn) NclFree(tmp1_qsn); + if(is_scalar_qgr && type_qgr != NCL_double) NclFree(tmp1_qgr); + +/* + * Retrieve dimension names from the "tmk" variable, if any. + * These dimension names will later be attached to the output variable. + */ + dim_info = get_wrf_dim_info(1,8,ndims_tmk,dsizes_tmk); + +/* + * Set up return value. + */ +/* + * Return value back to NCL script. + */ + + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)dbz, + NULL, + ndims_tmk, + dsizes_tmk, + TEMPORARY, + NULL, + type_obj_dbz + ); +/* + * Set up some attributes ("description" and "units") to return. + */ + cdescription = (char *)calloc(13,sizeof(char)); + strcpy(cdescription,"Reflectivity"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + free(cdescription); + + cunits = (char *)calloc(4,sizeof(char)); + strcpy(cunits,"dBZ"); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *units = NrmStringToQuark(cunits); + free(cunits); + + +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + NclFree(dim_info); + +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); + +} + +NhlErrorTypes wrf_pvo_W( void ) +{ + +/* + * Input variables + * + * Argument # 0 + */ + void *u; + double *tmp_u = NULL; + int ndims_u; + ng_size_t dsizes_u[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_u; + +/* + * Argument # 1 + */ + void *v; + double *tmp_v = NULL; + int ndims_v; + ng_size_t dsizes_v[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_v; + +/* + * Argument # 2 + */ + void *th; + double *tmp_th = NULL; + int ndims_th; + ng_size_t dsizes_th[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_th; + +/* + * Argument # 3 + */ + void *p; + double *tmp_p = NULL; + int ndims_p; + ng_size_t dsizes_p[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_p; + +/* + * Argument # 4 + */ + void *msfu; + double *tmp_msfu = NULL; + int ndims_msfu; + ng_size_t dsizes_msfu[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_msfu; + +/* + * Argument # 5 + */ + void *msfv; + double *tmp_msfv = NULL; + int ndims_msfv; + ng_size_t dsizes_msfv[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_msfv; + +/* + * Argument # 6 + */ + void *msft; + double *tmp_msft = NULL; + int ndims_msft; + ng_size_t dsizes_msft[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_msft; + +/* + * Argument # 7 + */ + void *cor; + double *tmp_cor = NULL; + int ndims_cor; + ng_size_t dsizes_cor[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_cor; + +/* + * Argument # 8 + */ + void *dx; + double *tmp_dx = NULL; + NclBasicDataTypes type_dx; + +/* + * Argument # 9 + */ + void *dy; + double *tmp_dy = NULL; + NclBasicDataTypes type_dy; + +/* + * Argument # 10 + */ + int *opt; + +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info; + +/* + * Return variable + */ + void *pv; + double *tmp_pv = NULL; + int att_id; + NclBasicDataTypes type_pv; + NclObjClass type_obj_pv; + NclQuark *description, *units; + char *cdescription, *cunits; + +/* + * Various + */ + ng_size_t nx, ny, nz, nxp1, nyp1; + ng_size_t nznynxp1, nznyp1nx, nznynx, nynxp1, nyp1nx, nynx; + ng_size_t i, size_pv, size_leftmost; + ng_size_t index_u, index_v, index_th, index_msfu, index_msfv, index_msft; + int inx, iny, inz, inxp1, inyp1; +/* + * Variables for returning the output array with dimension names attached. + */ + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ +/* + * Get argument # 0 + */ + u = (void*)NclGetArgValue( + 0, + 11, + &ndims_u, + dsizes_u, + NULL, + NULL, + &type_u, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_u < 3) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: u must have at least 3 dimensions"); + return(NhlFATAL); + } + nz = dsizes_u[ndims_u-3]; + ny = dsizes_u[ndims_u-2]; + nxp1 = dsizes_u[ndims_u-1]; + +/* + * Get argument # 1 + */ + v = (void*)NclGetArgValue( + 1, + 11, + &ndims_v, + dsizes_v, + NULL, + NULL, + &type_v, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_v != ndims_u) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: u, v, th, and p must have the same number of dimensions"); + return(NhlFATAL); + } + if(dsizes_v[ndims_v-3] != nz) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: The third-from-the-right dimension of v must be the same as the third-from-the-right dimension of u"); + return(NhlFATAL); + } +/* + * Error checking on leftmost dimension sizes. + */ + for(i = 0; i < ndims_u-3; i++) { + if(dsizes_u[i] != dsizes_v[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: The leftmost dimensions of u and v must be the same"); + return(NhlFATAL); + } + } + + nyp1 = dsizes_v[ndims_v-2]; + nx = dsizes_v[ndims_v-1]; + +/* + * Get argument # 2 + */ + th = (void*)NclGetArgValue( + 2, + 11, + &ndims_th, + dsizes_th, + NULL, + NULL, + &type_th, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_th != ndims_u) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: u, v, th, and p must have the same number of dimensions"); + return(NhlFATAL); + } + + if(dsizes_th[ndims_th-3] != nz || dsizes_th[ndims_th-2] != ny || + dsizes_th[ndims_th-1] != nx) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: The rightmost dimensions of th must be a combination of the dimensions of u and v (see documentation)"); + return(NhlFATAL); + } + +/* + * Error checking on leftmost dimension sizes. + */ + for(i = 0; i < ndims_u-3; i++) { + if(dsizes_th[i] != dsizes_u[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: The leftmost dimensions of th and u must be the same"); + return(NhlFATAL); + } + } + +/* + * Get argument # 3 + */ + p = (void*)NclGetArgValue( + 3, + 11, + &ndims_p, + dsizes_p, + NULL, + NULL, + &type_p, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_p != ndims_u) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: u, v, th, and p must have the same number of dimensions"); + return(NhlFATAL); + } + +/* + * Error checking on dimension sizes. + */ + for(i = 0; i < ndims_th; i++) { + if(dsizes_p[i] != dsizes_th[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: The dimensions of p and th must be the same"); + return(NhlFATAL); + } + } + +/* + * Get argument # 4 + */ + msfu = (void*)NclGetArgValue( + 4, + 11, + &ndims_msfu, + dsizes_msfu, + NULL, + NULL, + &type_msfu, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_msfu < 2) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: msfu must have at least 2 dimensions"); + return(NhlFATAL); + } + if(ndims_msfu !=2 && ndims_msfu != (ndims_u-1)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: msfu must be 2D or have one fewer dimensions than u"); + return(NhlFATAL); + } + if(dsizes_msfu[ndims_msfu-2] != ny || dsizes_msfu[ndims_msfu-1] != nxp1) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: The rightmost 2 dimensions of msfu must be the same as the rightmost 2 dimensions of u"); + return(NhlFATAL); + } + +/* + * Error checking on leftmost dimension sizes. msfu, msfv, msft, and + * cor can be 2D or nD. If they are nD, they must have same leftmost + * dimensions as other input arrays. + */ + if(ndims_msfu > 2) { + for(i = 0; i < ndims_u-3; i++) { + if(dsizes_msfu[i] != dsizes_u[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: If msfu is not 2-dimensional, then the leftmost dimensions of msfu and u must be the same"); + return(NhlFATAL); + } + } + } + +/* + * Get argument # 5 + */ + msfv = (void*)NclGetArgValue( + 5, + 11, + &ndims_msfv, + dsizes_msfv, + NULL, + NULL, + &type_msfv, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_msfv != ndims_msfu) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: msfu, msfv, msft, and cor must have the same number of dimensions"); + return(NhlFATAL); + } + if(dsizes_msfv[ndims_msfv-2] != nyp1 || dsizes_msfv[ndims_msfv-1] != nx) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: The rightmost 2 dimensions of msfv must be the same as the rightmost 2 dimensions of v"); + return(NhlFATAL); + } + +/* + * Error checking on leftmost dimension sizes. + */ + for(i = 0; i < ndims_msfu-2; i++) { + if(dsizes_msfv[i] != dsizes_msfu[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: The leftmost dimensions of msfv and msfu must be the same"); + return(NhlFATAL); + } + } + +/* + * Get argument # 6 + */ + msft = (void*)NclGetArgValue( + 6, + 11, + &ndims_msft, + dsizes_msft, + NULL, + NULL, + &type_msft, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_msft != ndims_msfu) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: msfu, msfv, msft, and cor must have the same number of dimensions"); + return(NhlFATAL); + } + if(dsizes_msft[ndims_msft-2] != ny || dsizes_msft[ndims_msft-1] != nx) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: The rightmost 2 dimensions of msft must be the same as the rightmost 2 dimensions of th"); + return(NhlFATAL); + } + +/* + * Error checking on leftmost dimension sizes. + */ + for(i = 0; i < ndims_msfu-2; i++) { + if(dsizes_msft[i] != dsizes_msfu[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: The leftmost dimensions of msft and msfu must be the same"); + return(NhlFATAL); + } + } + +/* + * Get argument # 7 + */ + cor = (void*)NclGetArgValue( + 7, + 11, + &ndims_cor, + dsizes_cor, + NULL, + NULL, + &type_cor, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_cor != ndims_msft) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: msfu, msfv, msft, and cor must have the same number of dimensions"); + return(NhlFATAL); + } + +/* + * Error checking on dimension sizes. + */ + for(i = 0; i < ndims_msft; i++) { + if(dsizes_cor[i] != dsizes_msft[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: The dimensions of cor and msft must be the same"); + return(NhlFATAL); + } + } + +/* + * Get argument # 8 + */ + dx = (void*)NclGetArgValue( + 8, + 11, + NULL, + NULL, + NULL, + NULL, + &type_dx, + DONT_CARE); + tmp_dx = coerce_input_double(dx,type_dx,1,0,NULL,NULL); + +/* + * Get argument # 9 + */ + dy = (void*)NclGetArgValue( + 9, + 11, + NULL, + NULL, + NULL, + NULL, + &type_dy, + DONT_CARE); + tmp_dy = coerce_input_double(dy,type_dy,1,0,NULL,NULL); + +/* + * Get argument # 10 + */ + opt = (int*)NclGetArgValue( + 10, + 11, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + + nynx = ny * nx; + nznynx = nz * nynx; + nynxp1 = ny * nxp1; + nyp1nx = nyp1 * nx; + nznynxp1 = nz * nynxp1; + nznyp1nx = nz * nyp1nx; + +/* + * Test dimension sizes. + */ + if((nxp1 > INT_MAX) || (nyp1 > INT_MAX) || (nz > INT_MAX) || + (nx > INT_MAX) ||(ny > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: one or more dimension sizes is greater than INT_MAX"); + return(NhlFATAL); + } + inx = (int) nx; + iny = (int) ny; + inz = (int) nz; + inxp1 = (int) nxp1; + inyp1 = (int) nyp1; + +/* + * Calculate size of leftmost dimensions. + */ + size_leftmost = 1; + for(i = 0; i < ndims_u-3; i++) size_leftmost *= dsizes_u[i]; + size_pv = size_leftmost * nznynx; + +/* + * Retrieve dimension names from the "th" variable, if any. + * These dimension names will later be attached to the output variable. + */ + dim_info = get_wrf_dim_info(2,11,ndims_th,dsizes_th); + +/* + * Allocate space for coercing input arrays. If any of the input + * is already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + */ + +/* + * Allocate space for tmp_u. + */ + if(type_u != NCL_double) { + tmp_u = (double *)calloc(nznynxp1,sizeof(double)); + if(tmp_u == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: Unable to allocate memory for coercing u to double"); + return(NhlFATAL); + } + } + +/* + * Allocate space for tmp_v. + */ + if(type_v != NCL_double) { + tmp_v = (double *)calloc(nznyp1nx,sizeof(double)); + if(tmp_v == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: Unable to allocate memory for coercing v to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for tmp_th. + */ + if(type_th != NCL_double) { + tmp_th = (double *)calloc(nznynx,sizeof(double)); + if(tmp_th == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: Unable to allocate memory for coercing th to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for tmp_p. + */ + if(type_p != NCL_double) { + tmp_p = (double *)calloc(nznynx,sizeof(double)); + if(tmp_p == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: Unable to allocate memory for coercing p to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for coercing msfu, msfv, and cor to double precision. + * These arrays can be 2D or nD, so take this into account. If one of + * them is 2D, then all three of them have to be 2D. + */ + if(ndims_msfu == 2) { + tmp_msfu = coerce_input_double(msfu,type_msfu,nynxp1,0,NULL,NULL); + tmp_msfv = coerce_input_double(msfv,type_msfv,nyp1nx,0,NULL,NULL); + tmp_msft = coerce_input_double(msft,type_msft,nynx,0,NULL,NULL); + tmp_cor = coerce_input_double(cor,type_cor,nynx,0,NULL,NULL); + } + else { +/* + * Allocate space for tmp_msfu. + */ + if(type_msfu != NCL_double) { + tmp_msfu = (double*)calloc(nynxp1,sizeof(double)); + if(tmp_msfu == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: Unable to allocate memory for coercing msfu to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for tmp_msfv. + */ + if(type_msfv != NCL_double) { + tmp_msfv = (double*)calloc(nyp1nx,sizeof(double)); + if(tmp_msfv == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: Unable to allocate memory for coercing msfv to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for tmp_msft. + */ + if(type_msft != NCL_double) { + tmp_msft = (double*)calloc(nynx,sizeof(double)); + if(tmp_msft == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: Unable to allocate memory for coercing msft to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for tmp_cor. + */ + if(type_cor != NCL_double) { + tmp_cor = (double *)calloc(nynx,sizeof(double)); + if(tmp_cor == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: Unable to allocate memory for coercing cor to double"); + return(NhlFATAL); + } + } + } + +/* + * The output type defaults to float, unless any input arrays are double. + */ + if(type_u == NCL_double || type_v == NCL_double || + type_th == NCL_double || type_p == NCL_double || + type_msfu == NCL_double || type_msfv == NCL_double || + type_msft == NCL_double || type_cor == NCL_double) { + type_pv = NCL_double; + type_obj_pv = nclTypedoubleClass; + } + else { + type_pv = NCL_float; + type_obj_pv = nclTypefloatClass; + } + +/* + * Allocate space for output array. + */ + if(type_pv != NCL_double) { + pv = (void *)calloc(size_pv, sizeof(float)); + tmp_pv = (double *)calloc(nznynx,sizeof(double)); + if(pv == NULL || tmp_pv == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + else { + pv = (void *)calloc(size_pv, sizeof(double)); + if(pv == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_pvo: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + +/* + * Call the Fortran routine. + */ + index_u = index_v = index_th = index_msfu = index_msfv = index_msft = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of u (tmp_u) to double if necessary. + */ + if(type_u != NCL_double) { + coerce_subset_input_double(u,tmp_u,index_u,type_u,nznynxp1,0,NULL,NULL); + } + else { + tmp_u = &((double*)u)[index_u]; + } + +/* + * Coerce subsection of v (tmp_v) to double if necessary. + */ + if(type_v != NCL_double) { + coerce_subset_input_double(v,tmp_v,index_v,type_v,nznyp1nx,0,NULL,NULL); + } + else { + tmp_v = &((double*)v)[index_v]; + } + +/* + * Coerce subsection of th (tmp_th) to double if necessary. + */ + if(type_th != NCL_double) { + coerce_subset_input_double(th,tmp_th,index_th,type_th,nznynx,0,NULL,NULL); + } + else { + tmp_th = &((double*)th)[index_th]; + } + +/* + * Coerce subsection of p (tmp_p) to double if necessary. + */ + if(type_p != NCL_double) { + coerce_subset_input_double(p,tmp_p,index_th,type_p,nznynx,0,NULL,NULL); + } + else { + tmp_p = &((double*)p)[index_th]; + } + +/* + * msfu, msfv, msft, and cor can be 2D or nD, so account + * for that here. If they are 2D, they've already been coerced + * before the loop. + */ + if(ndims_msfu > 2) { +/* + * Coerce subsection of msfu (tmp_msfu) to double if necessary. + */ + if(type_msfu != NCL_double) { + coerce_subset_input_double(msfu,tmp_msfu,index_msfu,type_msfu,nynxp1,0,NULL,NULL); + } + else { + tmp_msfu = &((double*)msfu)[index_msfu]; + } +/* + * Coerce subsection of msfv (tmp_msfv) to double if necessary. + */ + if(type_msfv != NCL_double) { + coerce_subset_input_double(msfv,tmp_msfv,index_msfv,type_msfv,nyp1nx,0,NULL,NULL); + } + else { + tmp_msfv = &((double*)msfv)[index_msfv]; + } +/* + * Coerce subsection of msft (tmp_msft) to double if necessary. + */ + if(type_msft != NCL_double) { + coerce_subset_input_double(msft,tmp_msft,index_msft,type_msft,nynx,0,NULL,NULL); + } + else { + tmp_msft = &((double*)msft)[index_msft]; + } + +/* + * Coerce subsection of cor (tmp_cor) to double if necessary. + */ + if(type_cor != NCL_double) { + coerce_subset_input_double(cor,tmp_cor,index_msft,type_cor,nynx,0,NULL,NULL); + } + else { + tmp_cor = &((double*)cor)[index_msft]; + } + } + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_pv == NCL_double) tmp_pv = &((double*)pv)[index_th]; + + NGCALLF(dcomputepv,DCOMPUTEPV)(tmp_pv, tmp_u, tmp_v, tmp_th, tmp_p, + tmp_msfu, tmp_msfv, tmp_msft, tmp_cor, + tmp_dx, tmp_dy, &inx, &iny, &inz, &inxp1, &inyp1); + if(type_pv != NCL_double) { + coerce_output_float_only(pv,tmp_pv,nznynx,index_th); + } + index_u += nznynxp1; + index_v += nznyp1nx; + index_th += nznynx; + if(ndims_msfu > 2) { + index_msfu += nynxp1; + index_msfv += nyp1nx; + index_msft += nynx; + } + } + +/* + * Free unneeded memory. + */ + if(type_u != NCL_double) NclFree(tmp_u); + if(type_v != NCL_double) NclFree(tmp_v); + if(type_th != NCL_double) NclFree(tmp_th); + if(type_p != NCL_double) NclFree(tmp_p); + if(type_msfu != NCL_double) NclFree(tmp_msfu); + if(type_msfv != NCL_double) NclFree(tmp_msfv); + if(type_msft != NCL_double) NclFree(tmp_msft); + if(type_cor != NCL_double) NclFree(tmp_cor); + if(type_pv != NCL_double) NclFree(tmp_pv); + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)pv, + NULL, + ndims_th, + dsizes_th, + TEMPORARY, + NULL, + type_obj_pv + ); + +/* + * Set up some attributes ("description" and "units") to return. + */ + cdescription = (char *)calloc(20,sizeof(char)); + strcpy(cdescription,"Potential Vorticity"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + free(cdescription); + + cunits = (char *)calloc(4,sizeof(char)); + strcpy(cunits,"PVU"); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *units = NrmStringToQuark(cunits); + free(cunits); + +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + + NclFree(dim_info); +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); +} + +NhlErrorTypes wrf_avo_W( void ) +{ + +/* + * Input variables + * + * Argument # 0 + */ + void *u; + double *tmp_u = NULL; + int ndims_u; + ng_size_t dsizes_u[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_u; + +/* + * Argument # 1 + */ + void *v; + double *tmp_v = NULL; + int ndims_v; + ng_size_t dsizes_v[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_v; + +/* + * Argument # 2 + */ + void *msfu; + double *tmp_msfu = NULL; + int ndims_msfu; + ng_size_t dsizes_msfu[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_msfu; + +/* + * Argument # 3 + */ + void *msfv; + double *tmp_msfv = NULL; + int ndims_msfv; + ng_size_t dsizes_msfv[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_msfv; + +/* + * Argument # 4 + */ + void *msft; + double *tmp_msft = NULL; + int ndims_msft; + ng_size_t dsizes_msft[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_msft; + +/* + * Argument # 5 + */ + void *cor; + double *tmp_cor = NULL; + int ndims_cor; + ng_size_t dsizes_cor[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_cor; + +/* + * Argument # 6 + */ + void *dx; + double *tmp_dx = NULL; + NclBasicDataTypes type_dx; + +/* + * Argument # 7 + */ + void *dy; + double *tmp_dy = NULL; + NclBasicDataTypes type_dy; + +/* + * Argument # 8 + */ + int *opt; + +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info, *dim_info_v; + +/* + * Return variable + */ + void *av; + double *tmp_av = NULL; + int att_id; + ng_size_t *dsizes_av; + NclBasicDataTypes type_av; + NclObjClass type_obj_av; + NclQuark *description, *units; + char *cdescription, *cunits; + +/* + * Various + */ + ng_size_t nx, ny, nz, nxp1, nyp1; + ng_size_t nznynxp1, nznyp1nx, nznynx, nynxp1, nyp1nx, nynx; + ng_size_t i, size_av, size_leftmost; + ng_size_t index_u, index_v, index_msfu, index_msfv, index_msft, index_av; + int inx, iny, inz, inxp1, inyp1; + +/* + * Variables for returning the output array with dimension names attached. + */ + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ +/* + * Get argument # 0 + */ + u = (void*)NclGetArgValue( + 0, + 9, + &ndims_u, + dsizes_u, + NULL, + NULL, + &type_u, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_u < 3) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: u must have at least 3 dimensions"); + return(NhlFATAL); + } + nz = dsizes_u[ndims_u-3]; + ny = dsizes_u[ndims_u-2]; + nxp1 = dsizes_u[ndims_u-1]; + +/* + * Get argument # 1 + */ + v = (void*)NclGetArgValue( + 1, + 9, + &ndims_v, + dsizes_v, + NULL, + NULL, + &type_v, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_v != ndims_u) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: u and v must have the same number of dimensions"); + return(NhlFATAL); + } + if(dsizes_v[ndims_v-3] != nz) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: The third-from-the-right dimension of v must be the same as the third-from-the-right dimension of u"); + return(NhlFATAL); + } +/* + * Error checking on leftmost dimension sizes. + */ + for(i = 0; i < ndims_u-3; i++) { + if(dsizes_u[i] != dsizes_v[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: The leftmost dimensions of u and v must be the same"); + return(NhlFATAL); + } + } + + nyp1 = dsizes_v[ndims_v-2]; + nx = dsizes_v[ndims_v-1]; + +/* + * Get argument # 2 + */ + msfu = (void*)NclGetArgValue( + 2, + 9, + &ndims_msfu, + dsizes_msfu, + NULL, + NULL, + &type_msfu, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_msfu < 2) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: msfu must have at least 2 dimensions"); + return(NhlFATAL); + } + if(ndims_msfu !=2 && ndims_msfu != (ndims_u-1)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: msfu must be 2D or have one fewer dimensions than u"); + return(NhlFATAL); + } + if(dsizes_msfu[ndims_msfu-2] != ny || dsizes_msfu[ndims_msfu-1] != nxp1) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: The rightmost 2 dimensions of msfu must be the same as the rightmost 2 dimensions of u"); + return(NhlFATAL); + } + +/* + * Error checking on leftmost dimension sizes. msfu, msfv, msft, and + * cor can be 2D or nD. If they are nD, they must have same leftmost + * dimensions as other input arrays. + */ + if(ndims_msfu > 2) { + for(i = 0; i < ndims_u-3; i++) { + if(dsizes_msfu[i] != dsizes_u[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: If msfu is not 2-dimensional, then the leftmost dimensions of msfu and u must be the same"); + return(NhlFATAL); + } + } + } + +/* + * Get argument # 3 + */ + msfv = (void*)NclGetArgValue( + 3, + 9, + &ndims_msfv, + dsizes_msfv, + NULL, + NULL, + &type_msfv, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_msfv != ndims_msfu) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: msfu, msfv, msft, and cor must have the same number of dimensions"); + return(NhlFATAL); + } + if(dsizes_msfv[ndims_msfv-2] != nyp1 || dsizes_msfv[ndims_msfv-1] != nx) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: The rightmost 2 dimensions of msfv must be the same as the rightmost 2 dimensions of v"); + return(NhlFATAL); + } + +/* + * Error checking on leftmost dimension sizes. + */ + for(i = 0; i < ndims_msfu-2; i++) { + if(dsizes_msfv[i] != dsizes_msfu[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: The leftmost dimensions of msfv and msfu must be the same"); + return(NhlFATAL); + } + } + +/* + * Get argument # 4 + */ + msft = (void*)NclGetArgValue( + 4, + 9, + &ndims_msft, + dsizes_msft, + NULL, + NULL, + &type_msft, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_msft != ndims_msfu) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: msfu, msfv, msft, and cor must have the same number of dimensions"); + return(NhlFATAL); + } + if(dsizes_msft[ndims_msft-2] != ny || dsizes_msft[ndims_msft-1] != nx) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: The rightmost 2 dimensions of msft must be the same as the rightmost 2 dimensions of th"); + return(NhlFATAL); + } + +/* + * Error checking on leftmost dimension sizes. + */ + for(i = 0; i < ndims_msfu-2; i++) { + if(dsizes_msft[i] != dsizes_msfu[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: The leftmost dimensions of msft and msfu must be the same"); + return(NhlFATAL); + } + } + +/* + * Get argument # 5 + */ + cor = (void*)NclGetArgValue( + 5, + 9, + &ndims_cor, + dsizes_cor, + NULL, + NULL, + &type_cor, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_cor != ndims_msft) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: msfu, msfv, msft, and cor must have the same number of dimensions"); + return(NhlFATAL); + } + +/* + * Error checking on dimension sizes. + */ + for(i = 0; i < ndims_msft; i++) { + if(dsizes_cor[i] != dsizes_msft[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: The dimensions of cor and msft must be the same"); + return(NhlFATAL); + } + } + +/* + * Get argument # 6 + */ + dx = (void*)NclGetArgValue( + 6, + 9, + NULL, + NULL, + NULL, + NULL, + &type_dx, + DONT_CARE); + tmp_dx = coerce_input_double(dx,type_dx,1,0,NULL,NULL); + +/* + * Get argument # 7 + */ + dy = (void*)NclGetArgValue( + 7, + 9, + NULL, + NULL, + NULL, + NULL, + &type_dy, + DONT_CARE); + tmp_dy = coerce_input_double(dy,type_dy,1,0,NULL,NULL); + +/* + * Get argument # 8 + */ + opt = (int*)NclGetArgValue( + 8, + 9, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + + nynx = ny * nx; + nznynx = nz * nynx; + nynxp1 = ny * nxp1; + nyp1nx = nyp1 * nx; + nznynxp1 = nz * nynxp1; + nznyp1nx = nz * nyp1nx; + +/* + * Test dimension sizes. + */ + if((nxp1 > INT_MAX) || (nyp1 > INT_MAX) || (nz > INT_MAX) || + (nx > INT_MAX) ||(ny > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: one or more dimension sizes is greater than INT_MAX"); + return(NhlFATAL); + } + inx = (int) nx; + iny = (int) ny; + inz = (int) nz; + inxp1 = (int) nxp1; + inyp1 = (int) nyp1; + +/* + * Calculate size of leftmost dimensions, and set + * dimension sizes for output array. + */ + dsizes_av = (ng_size_t*)calloc(ndims_u,sizeof(ng_size_t)); + if( dsizes_av == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: Unable to allocate memory for holding dimension sizes"); + return(NhlFATAL); + } + + size_leftmost = 1; + for(i = 0; i < ndims_u-3; i++) { + size_leftmost *= dsizes_u[i]; + dsizes_av[i] = dsizes_u[i]; + } + size_av = size_leftmost * nznynx; + dsizes_av[ndims_u-1] = nx; + dsizes_av[ndims_u-2] = ny; + dsizes_av[ndims_u-3] = nz; + +/* + * Retrieve dimension names from the "u" and "v" variables, if any. + * + * U's dimension names will be used for the output, except for the + * rightmost dimension which will be replaced by V's rightmost dimension + * name. + */ + dim_info = get_wrf_dim_info(0,9,ndims_u,dsizes_u); + dim_info_v = get_wrf_dim_info(1,9,ndims_v,dsizes_v); + + dim_info[ndims_u-1].dim_size = nx; + dim_info[ndims_u-2].dim_size = ny; + dim_info[ndims_u-3].dim_size = nz; + dim_info[ndims_u-1].dim_quark = dim_info_v[ndims_v-1].dim_quark; + +/* + * Allocate space for coercing input arrays. If any of the input + * is already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + */ + +/* + * Allocate space for tmp_u. + */ + if(type_u != NCL_double) { + tmp_u = (double *)calloc(nznynxp1,sizeof(double)); + if(tmp_u == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: Unable to allocate memory for coercing u to double"); + return(NhlFATAL); + } + } + +/* + * Allocate space for tmp_v. + */ + if(type_v != NCL_double) { + tmp_v = (double *)calloc(nznyp1nx,sizeof(double)); + if(tmp_v == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: Unable to allocate memory for coercing v to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for coercing msfu, msfv, and cor to double precision. + * These arrays can be 2D or nD, so take this into account. If one of + * them is 2D, then all three of them have to be 2D. + */ + if(ndims_msfu == 2) { + tmp_msfu = coerce_input_double(msfu,type_msfu,nynxp1,0,NULL,NULL); + tmp_msfv = coerce_input_double(msfv,type_msfv,nyp1nx,0,NULL,NULL); + tmp_msft = coerce_input_double(msft,type_msft,nynx,0,NULL,NULL); + tmp_cor = coerce_input_double(cor,type_cor,nynx,0,NULL,NULL); + } + else { +/* + * Allocate space for tmp_msfu. + */ + if(type_msfu != NCL_double) { + tmp_msfu = (double*)calloc(nynxp1,sizeof(double)); + if(tmp_msfu == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: Unable to allocate memory for coercing msfu to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for tmp_msfv. + */ + if(type_msfv != NCL_double) { + tmp_msfv = (double*)calloc(nyp1nx,sizeof(double)); + if(tmp_msfv == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: Unable to allocate memory for coercing msfv to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for tmp_msft. + */ + if(type_msft != NCL_double) { + tmp_msft = (double*)calloc(nynx,sizeof(double)); + if(tmp_msft == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: Unable to allocate memory for coercing msft to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for tmp_cor. + */ + if(type_cor != NCL_double) { + tmp_cor = (double *)calloc(nynx,sizeof(double)); + if(tmp_cor == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: Unable to allocate memory for coercing cor to double"); + return(NhlFATAL); + } + } + } +/* + * The output type defaults to float, unless any input arrays are double. + */ + if(type_u == NCL_double || type_v == NCL_double || + type_msfu == NCL_double || type_msfv == NCL_double || + type_msft == NCL_double || type_cor == NCL_double) { + type_av = NCL_double; + type_obj_av = nclTypedoubleClass; + } + else { + type_av = NCL_float; + type_obj_av = nclTypefloatClass; + } + +/* + * Allocate space for output array. + */ + if(type_av != NCL_double) { + av = (void *)calloc(size_av, sizeof(float)); + tmp_av = (double *)calloc(nznynx,sizeof(double)); + if(av == NULL || tmp_av == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + else { + av = (void *)calloc(size_av, sizeof(double)); + if(av == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_avo: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + +/* + * Call the Fortran routine. + */ + index_u = index_v = index_msfu = index_msfv = index_msft = index_av = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of u (tmp_u) to double if necessary. + */ + if(type_u != NCL_double) { + coerce_subset_input_double(u,tmp_u,index_u,type_u,nznynxp1,0,NULL,NULL); + } + else { + tmp_u = &((double*)u)[index_u]; + } + +/* + * Coerce subsection of v (tmp_v) to double if necessary. + */ + if(type_v != NCL_double) { + coerce_subset_input_double(v,tmp_v,index_v,type_v,nznyp1nx,0,NULL,NULL); + } + else { + tmp_v = &((double*)v)[index_v]; + } + +/* + * msfu, msfv, msft, and cor can be 2D or nD, so account + * for that here. If they are 2D, they've already been coerced + * before the loop. + */ + if(ndims_msfu > 2) { +/* + * Coerce subsection of msfu (tmp_msfu) to double if necessary. + */ + if(type_msfu != NCL_double) { + coerce_subset_input_double(msfu,tmp_msfu,index_msfu,type_msfu,nynxp1,0,NULL,NULL); + } + else { + tmp_msfu = &((double*)msfu)[index_msfu]; + } +/* + * Coerce subsection of msfv (tmp_msfv) to double if necessary. + */ + if(type_msfv != NCL_double) { + coerce_subset_input_double(msfv,tmp_msfv,index_msfv,type_msfv,nyp1nx,0,NULL,NULL); + } + else { + tmp_msfv = &((double*)msfv)[index_msfv]; + } +/* + * Coerce subsection of msft (tmp_msft) to double if necessary. + */ + if(type_msft != NCL_double) { + coerce_subset_input_double(msft,tmp_msft,index_msft,type_msft,nynx,0,NULL,NULL); + } + else { + tmp_msft = &((double*)msft)[index_msft]; + } + +/* + * Coerce subsection of cor (tmp_cor) to double if necessary. + */ + if(type_cor != NCL_double) { + coerce_subset_input_double(cor,tmp_cor,index_msft,type_cor,nynx,0,NULL,NULL); + } + else { + tmp_cor = &((double*)cor)[index_msft]; + } + } + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_av == NCL_double) tmp_av = &((double*)av)[index_av]; + + NGCALLF(dcomputeabsvort,DCOMPUTEABSVORT)(tmp_av, tmp_u, tmp_v, tmp_msfu, + tmp_msfv, tmp_msft, tmp_cor, + tmp_dx, tmp_dy, &inx, &iny, &inz, + &inxp1, &inyp1); + if(type_av != NCL_double) { + coerce_output_float_only(av,tmp_av,nznynx,index_av); + } + index_u += nznynxp1; + index_v += nznyp1nx; + index_av += nznynx; + if(ndims_msfu > 2) { + index_msfu += nynxp1; + index_msfv += nyp1nx; + index_msft += nynx; + } + } + +/* + * Free unneeded memory. + */ + if(type_u != NCL_double) NclFree(tmp_u); + if(type_v != NCL_double) NclFree(tmp_v); + if(type_msfu != NCL_double) NclFree(tmp_msfu); + if(type_msfv != NCL_double) NclFree(tmp_msfv); + if(type_msft != NCL_double) NclFree(tmp_msft); + if(type_cor != NCL_double) NclFree(tmp_cor); + if(type_av != NCL_double) NclFree(tmp_av); + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)av, + NULL, + ndims_u, + dsizes_av, + TEMPORARY, + NULL, + type_obj_av + ); + + NclFree(dsizes_av); +/* + * Set up some attributes ("description" and "units") to return. + */ + cdescription = (char *)calloc(19,sizeof(char)); + strcpy(cdescription,"Absolute Vorticity"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + free(cdescription); + + cunits = (char *)calloc(9,sizeof(char)); + strcpy(cunits,"10-5 s-1"); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *units = NrmStringToQuark(cunits); + free(cunits); + +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + +/* + * Return output grid and attributes to NCL. + */ + NclFree(dim_info); + NclFree(dim_info_v); + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); + +} + +NhlErrorTypes wrf_helicity_W( void ) +{ + +/* + * Input variables + * + * Argument # 0 + */ + void *u; + double *tmp_u = NULL; + int ndims_u; + ng_size_t dsizes_u[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_u; + +/* + * Argument # 1 + */ + void *v; + double *tmp_v = NULL; + int ndims_v; + ng_size_t dsizes_v[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_v; + +/* + * Argument # 2 + */ + void *z; + double *tmp_z = NULL; + int ndims_z; + ng_size_t dsizes_z[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_z; + +/* + * Argument # 3 + */ + void *ter; + double *tmp_ter = NULL; + int ndims_ter; + ng_size_t dsizes_ter[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_ter; + +/* + * Argument # 4 + */ + void *top; + double *tmp_top = NULL; + NclBasicDataTypes type_top; + +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info; + +/* + * Return variable + */ + void *sreh; + double *tmp_sreh = NULL; + int att_id; + NclBasicDataTypes type_sreh; + NclObjClass type_obj_sreh; + NclQuark *description, *units; + char *cdescription, *cunits; + +/* + * Various + */ + ng_size_t i, miy, mjx, mkzh, mxy, mxyz; + ng_size_t size_sreh, size_leftmost, index_u, index_ter; + int imiy, imjx, imkzh; +/* + * Variables for returning the output array with dimension names attached. + */ + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ +/* + * Get argument # 0 + */ + u = (void*)NclGetArgValue( + 0, + 5, + &ndims_u, + dsizes_u, + NULL, + NULL, + &type_u, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_u < 3) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_helicity: u must have at least 3 dimensions"); + return(NhlFATAL); + } + mkzh = dsizes_u[ndims_u-3]; + mjx = dsizes_u[ndims_u-2]; + miy = dsizes_u[ndims_u-1]; + +/* + * Get argument # 1 + */ + v = (void*)NclGetArgValue( + 1, + 5, + &ndims_v, + dsizes_v, + NULL, + NULL, + &type_v, + DONT_CARE); + +/* + * Get argument # 2 + */ + z = (void*)NclGetArgValue( + 2, + 5, + &ndims_z, + dsizes_z, + NULL, + NULL, + &type_z, + DONT_CARE); + +/* + * Error checking on dimension sizes. + */ + if(ndims_u != ndims_v || ndims_u != ndims_z) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_helicity: u, v, and z must have the same dimensions"); + return(NhlFATAL); + } + + for(i = 0; i < ndims_u; i++) { + if(dsizes_u[i] != dsizes_v[i] || dsizes_u[i] != dsizes_z[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_helicity: u, v, and z must have the same dimensions"); + return(NhlFATAL); + } + } + +/* + * Get argument # 3 + */ + ter = (void*)NclGetArgValue( + 3, + 5, + &ndims_ter, + dsizes_ter, + NULL, + NULL, + &type_ter, + DONT_CARE); + +/* + * Error checking on dimensions. + */ + if(ndims_ter != (ndims_u-1)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_helicity: ter must have one fewer dimension sizes than u, v, z"); + return(NhlFATAL); + } + + if(dsizes_ter[ndims_ter-2] != mjx || dsizes_ter[ndims_ter-1] != miy) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_helicity: The rightmost two dimensions of ter must be the same as the rightmost two dimensions of u, v, z"); + return(NhlFATAL); + } + +/* + * Error checking on leftmost dimension sizes. + */ + for(i = 0; i < ndims_ter-2; i++) { + if(dsizes_ter[i] != dsizes_u[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_helicity: The leftmost dimensions of ter and u, v, z must be the same"); + return(NhlFATAL); + } + } + +/* + * Get argument # 4 + */ + top = (void*)NclGetArgValue( + 4, + 5, + NULL, + NULL, + NULL, + NULL, + &type_top, + DONT_CARE); + tmp_top = coerce_input_double(top,type_top,1,0,NULL,NULL); + + mxy = mjx * miy; + mxyz = mxy * mkzh; + + if((miy > INT_MAX) || (mjx > INT_MAX) || (mkzh > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_helicity: one or more dimension sizes is greater than INT_MAX"); + return(NhlFATAL); + } + imiy = (int) miy; + imjx = (int) mjx; + imkzh = (int) mkzh; + +/* + * Calculate size of leftmost dimensions. + */ + size_leftmost = 1; + for(i = 0; i < ndims_ter-2; i++) size_leftmost *= dsizes_ter[i]; + + size_sreh = size_leftmost * mxy; + +/* + * Retrieve dimension names from the "ter", if any. + * + * ter's dimension names will be used for the output. + */ + dim_info = get_wrf_dim_info(3,5,ndims_ter,dsizes_ter); + +/* + * Allocate space for coercing input arrays. If any of the input + * is already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + */ + +/* + * Allocate space for tmp_u. + */ + if(type_u != NCL_double) { + tmp_u = (double *)calloc(mxyz,sizeof(double)); + if(tmp_u == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_helicity: Unable to allocate memory for coercing u to double"); + return(NhlFATAL); + } + } + +/* + * Allocate space for tmp_v. + */ + if(type_v != NCL_double) { + tmp_v = (double *)calloc(mxyz,sizeof(double)); + if(tmp_v == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_helicity: Unable to allocate memory for coercing v to double"); + return(NhlFATAL); + } + } + +/* + * Allocate space for tmp_z. + */ + if(type_z != NCL_double) { + tmp_z = (double *)calloc(mxyz,sizeof(double)); + if(tmp_z == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_helicity: Unable to allocate memory for coercing z to double"); + return(NhlFATAL); + } + } + +/* + * Allocate space for tmp_ter. + */ + if(type_ter != NCL_double) { + tmp_ter = (double *)calloc(mxy,sizeof(double)); + if(tmp_ter == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_helicity: Unable to allocate memory for coercing ter to double"); + return(NhlFATAL); + } + } + +/* + * The output type defaults to float, unless any input arrays are double. + */ + if(type_u == NCL_double || type_v == NCL_double || + type_z == NCL_double || type_ter == NCL_double) { + type_sreh = NCL_double; + type_obj_sreh = nclTypedoubleClass; + } + else { + type_sreh = NCL_float; + type_obj_sreh = nclTypefloatClass; + } + +/* + * Allocate space for output array. + */ + if(type_sreh != NCL_double) { + sreh = (void *)calloc(size_sreh, sizeof(float)); + tmp_sreh = (double *)calloc(mxy,sizeof(double)); + if(sreh == NULL || tmp_sreh == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_helicity: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + else { + sreh = (void *)calloc(size_sreh, sizeof(double)); + if(sreh == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_helicity: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + +/* + * Call the Fortran routine. + */ + index_u = index_ter = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of u (tmp_u) to double if necessary. + */ + if(type_u != NCL_double) { + coerce_subset_input_double(u,tmp_u,index_u,type_u,mxyz,0,NULL,NULL); + } + else { + tmp_u = &((double*)u)[index_u]; + } + +/* + * Coerce subsection of v (tmp_v) to double if necessary. + */ + if(type_v != NCL_double) { + coerce_subset_input_double(v,tmp_v,index_u,type_v,mxyz,0,NULL,NULL); + } + else { + tmp_v = &((double*)v)[index_u]; + } + +/* + * Coerce subsection of z (tmp_z) to double if necessary. + */ + if(type_z != NCL_double) { + coerce_subset_input_double(z,tmp_z,index_u,type_z,mxyz,0,NULL,NULL); + } + else { + tmp_z = &((double*)z)[index_u]; + } + +/* + * Coerce subsection of ter (tmp_ter) to double if necessary. + */ + if(type_ter != NCL_double) { + coerce_subset_input_double(ter,tmp_ter,index_ter,type_ter,mxy,0,NULL,NULL); + } + else { + tmp_ter = &((double*)ter)[index_ter]; + } + + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_sreh == NCL_double) tmp_sreh = &((double*)sreh)[index_ter]; + + NGCALLF(dcalrelhl,DCALRELHL)(tmp_u, tmp_v, tmp_z, tmp_ter, tmp_top, + tmp_sreh, &imiy, &imjx, &imkzh); + if(type_sreh != NCL_double) { + coerce_output_float_only(sreh,tmp_sreh,mxy,index_ter); + } + index_u += mxyz; + index_ter += mxy; + } + +/* + * Free unneeded memory. + */ + if(type_u != NCL_double) NclFree(tmp_u); + if(type_v != NCL_double) NclFree(tmp_v); + if(type_z != NCL_double) NclFree(tmp_z); + if(type_ter != NCL_double) NclFree(tmp_ter); + if(type_sreh != NCL_double) NclFree(tmp_sreh); + if(type_top != NCL_double) NclFree(tmp_top); + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)sreh, + NULL, + ndims_ter, + dsizes_ter, + TEMPORARY, + NULL, + type_obj_sreh + ); + +/* + * Set up some attributes ("description" and "units") to return. + */ + cdescription = (char *)calloc(24,sizeof(char)); + strcpy(cdescription,"Storm Relative Helicity"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + free(cdescription); + + cunits = (char *)calloc(8,sizeof(char)); + strcpy(cunits,"m-2/s-2"); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *units = NrmStringToQuark(cunits); + free(cunits); + +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + NclFree(dim_info); + +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); + +} + + +NhlErrorTypes wrf_updraft_helicity_W( void ) +{ + +/* + * Input variables + */ +/* + * Argument # 0 + */ + void *zp; + double *tmp_zp = NULL; + int ndims_zp; + ng_size_t dsizes_zp[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_zp; + +/* + * Argument # 1 + */ + void *mapfct; + double *tmp_mapfct = NULL; + int ndims_mapfct; + ng_size_t dsizes_mapfct[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_mapfct; + +/* + * Argument # 2 + */ + void *dx; + double *tmp_dx = NULL; + NclBasicDataTypes type_dx; + +/* + * Argument # 3 + */ + void *dy; + double *tmp_dy = NULL; + NclBasicDataTypes type_dy; + +/* + * Argument # 4 + */ + void *us; + double *tmp_us = NULL; + int ndims_us; + ng_size_t dsizes_us[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_us; + +/* + * Argument # 5 + */ + void *vs; + double *tmp_vs = NULL; + int ndims_vs; + ng_size_t dsizes_vs[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_vs; + +/* + * Argument # 6 + */ + void *w; + double *tmp_w = NULL; + int ndims_w; + ng_size_t dsizes_w[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_w; + +/* + * Argument # 7 + */ + logical *opt; + +/* + * Possible attributes. + */ + void *uhmnhgt = NULL; + void *uhmxhgt = NULL; + double *tmp_uhmnhgt, *tmp_uhmxhgt; + logical set_uhmnhgt, set_uhmxhgt; + NclBasicDataTypes type_uhmnhgt = NCL_none; + NclBasicDataTypes type_uhmxhgt = NCL_none; + +/* + * Variables for retrieving attributes from "opt". + */ + NclAttList *attr_list; + NclAtt attr_obj; + NclStackEntry stack_entry; + +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info = NULL; + NclDimRec *dim_info_us; + +/* + * Return variable + */ + void *uh; + double *tmp_uh = NULL; + int ndims_uh; + ng_size_t *dsizes_uh; + NclBasicDataTypes type_uh; + NclObjClass type_obj_uh; + int att_id; + NclQuark *description, *units; + char *cdescription, *cunits; + +/* + * Various + */ + ng_size_t nx, ny, nzp1, nzp1nynx, nynx, nz, nznynx; + ng_size_t index_zp, index_uh, index_us; + double *tem1, *tem2; + ng_size_t i, ndims_leftmost, size_leftmost, size_output; + int inx, iny, inz, inzp1; + +/* + * Variables for returning the output array with dimension names attached. + */ + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ +/* + * Get argument # 0 + */ + zp = (void*)NclGetArgValue( + 0, + 8, + &ndims_zp, + dsizes_zp, + NULL, + NULL, + &type_zp, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_zp < 3) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: The zp array must have at least 3 dimensions"); + return(NhlFATAL); + } + nzp1 = dsizes_zp[ndims_zp-3]; + ny = dsizes_zp[ndims_zp-2]; + nx = dsizes_zp[ndims_zp-1]; + nynx = ny * nx; + nzp1nynx = nynx * nzp1; + +/* + * Get argument # 1 + */ + mapfct = (void*)NclGetArgValue( + 1, + 8, + &ndims_mapfct, + dsizes_mapfct, + NULL, + NULL, + &type_mapfct, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_mapfct != 2 && ndims_mapfct != (ndims_zp-1)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: The mapfct array must either be two-dimensional or have one fewer dimensions than zp"); + return(NhlFATAL); + } + if(dsizes_mapfct[ndims_mapfct-2] != ny || + dsizes_mapfct[ndims_mapfct-1] != nx) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: The rightmost dimensions of mapfct must be ny x nx"); + return(NhlFATAL); + } + +/* + * Get argument # 2 + */ + us = (void*)NclGetArgValue( + 2, + 8, + &ndims_us, + dsizes_us, + NULL, + NULL, + &type_us, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_us != ndims_zp) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: The us array must have the same number of dimensions as zp"); + return(NhlFATAL); + } + if(dsizes_us[ndims_us-2] != ny || dsizes_us[ndims_us-1] != nx) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: The rightmost dimensions of us must be nz x ny x ny"); + return(NhlFATAL); + } + nz = dsizes_us[ndims_us-3]; + nznynx = nz * nynx; + +/* + * Test dimension sizes. + */ + if((nx > INT_MAX) || (ny > INT_MAX) || (nzp1 > INT_MAX) || (nz > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: one or more dimension sizes is greater than INT_MAX"); + return(NhlFATAL); + } + inx = (int) nx; + iny = (int) ny; + inz = (int) nz; + inzp1 = (int) nzp1; + +/* + * Get argument # 3 + */ + vs = (void*)NclGetArgValue( + 3, + 8, + &ndims_vs, + dsizes_vs, + NULL, + NULL, + &type_vs, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_vs != ndims_us) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: The vs array must have the same number of dimensions as us"); + return(NhlFATAL); + } + if(dsizes_vs[ndims_vs-3] != nz || dsizes_vs[ndims_vs-2] != ny || + dsizes_vs[ndims_vs-1] != nx) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: The rightmost dimensions of vs must be nz x ny x ny"); + return(NhlFATAL); + } +/* + * Get argument # 4 + */ + w = (void*)NclGetArgValue( + 4, + 8, + &ndims_w, + dsizes_w, + NULL, + NULL, + &type_w, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_w != ndims_zp || (dsizes_w[ndims_w-3] != nzp1 || + dsizes_w[ndims_w-2] != ny || + dsizes_w[ndims_w-1] != nx)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: The w array must be the same dimensionality as zp"); + return(NhlFATAL); + } + +/* + * Get argument # 5 + */ + dx = (void*)NclGetArgValue( + 5, + 8, + NULL, + NULL, + NULL, + NULL, + &type_dx, + DONT_CARE); +/* + * Get argument # 6 + */ + dy = (void*)NclGetArgValue( + 6, + 8, + NULL, + NULL, + NULL, + NULL, + &type_dy, + DONT_CARE); + +/* + * Get argument # 7 + */ + opt = (logical*)NclGetArgValue( + 7, + 8, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + +/* + * Start checking for attributes attached to "opt" + */ + set_uhmnhgt = set_uhmxhgt = False; + + stack_entry = _NclGetArg(7, 8, DONT_CARE); + switch (stack_entry.kind) { + case NclStk_VAR: + if (stack_entry.u.data_var->var.att_id != -1) { + attr_obj = (NclAtt) _NclGetObj(stack_entry.u.data_var->var.att_id); + if (attr_obj == NULL) { + break; + } + } + else { +/* + * att_id == -1 ==> no optional args given. + */ + break; + } +/* + * Get optional arguments. + */ + if (attr_obj->att.n_atts > 0) { +/* + * Get list of attributes. + */ + attr_list = attr_obj->att.att_list; +/* + * Loop through attributes and check them. We are looking for: + * + * uhmnhgt or uhmxhgt + */ + while (attr_list != NULL) { + if(!strcasecmp(attr_list->attname, "uhmnhgt")) { + uhmnhgt = attr_list->attvalue->multidval.val; + type_uhmnhgt = attr_list->attvalue->multidval.data_type; + set_uhmnhgt = True; + } + else if(!strcasecmp(attr_list->attname, "uhmxhgt")) { + uhmxhgt = attr_list->attvalue->multidval.val; + type_uhmxhgt = attr_list->attvalue->multidval.data_type; + set_uhmxhgt = True; + } + attr_list = attr_list->next; + } + default: + break; + } + } + if(set_uhmnhgt) { + tmp_uhmnhgt = coerce_input_double(uhmnhgt,type_uhmnhgt,1,0,NULL,NULL); + } + else { + type_uhmnhgt = NCL_double; + tmp_uhmnhgt = (double *)calloc(1,sizeof(double)); + *tmp_uhmnhgt = 2000.; + } + if(set_uhmxhgt) { + tmp_uhmxhgt = coerce_input_double(uhmxhgt,type_uhmxhgt,1,0,NULL,NULL); + } + else { + type_uhmxhgt = NCL_double; + tmp_uhmxhgt = (double *)calloc(1,sizeof(double)); + *tmp_uhmxhgt = 5000.; + } + +/* + * Calculate size of leftmost dimensions. + */ + size_leftmost = 1; + ndims_leftmost = ndims_zp-3; + for(i = 0; i < ndims_leftmost; i++) { + if(dsizes_us[i] != dsizes_zp[i] || dsizes_vs[i] != dsizes_zp[i] || + dsizes_w[i] != dsizes_zp[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: The leftmost dimensions of zp, us, vs, and w must be the same"); + return(NhlFATAL); + } + if(ndims_mapfct > 2 && dsizes_mapfct[i] != dsizes_zp[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: mapfct must either be two-dimensional or have the same leftmost dimensions as zp"); + return(NhlFATAL); + } + size_leftmost *= dsizes_zp[i]; + } + + +/* + * Allocate space for coercing input arrays. If any of the input + * is already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * Allocate space for tmp_zp. + */ + if(type_zp != NCL_double) { + type_uh = NCL_float; + type_obj_uh = nclTypefloatClass; + + tmp_zp = (double *)calloc(nzp1nynx,sizeof(double)); + if(tmp_zp == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_uh = NCL_double; + type_obj_uh = nclTypedoubleClass; + } +/* + * Allocate space for tmp_mapfct. This array can be 2D or nD. If it + * is 2D, go ahead and coerce the values now. Otherwise, create a temp + * 2D array and we'll coerce the values in the loop below along with + * everybody else. + */ + if(ndims_mapfct == 2) { + tmp_mapfct = coerce_input_double(mapfct,type_mapfct,nynx,0,NULL,NULL); + } + else { + if(type_mapfct != NCL_double) { + tmp_mapfct = (double *)calloc(nynx,sizeof(double)); + if(tmp_mapfct == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + } +/* + * Allocate space for tmp_dx. + */ + tmp_dx = coerce_input_double(dx,type_dx,1,0,NULL,NULL); + if(tmp_dx == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } +/* + * Allocate space for tmp_dy. + */ + tmp_dy = coerce_input_double(dy,type_dy,1,0,NULL,NULL); + if(tmp_dy == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + +/* + * Allocate space for tmp_us. + */ + if(type_us != NCL_double) { + tmp_us = (double *)calloc(nznynx,sizeof(double)); + if(tmp_us == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for tmp_vs. + */ + if(type_vs != NCL_double) { + tmp_vs = (double *)calloc(nznynx,sizeof(double)); + if(tmp_vs == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } +/* + * Allocate space for tmp_w. + */ + if(type_w != NCL_double) { + tmp_w = (double *)calloc(nzp1nynx,sizeof(double)); + if(tmp_w == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + +/* + * Calculate size of output array. + */ + size_output = size_leftmost * nynx; + +/* + * Allocate space for output array. + */ + if(type_uh != NCL_double) { + uh = (void *)calloc(size_output, sizeof(float)); + tmp_uh = (double *)calloc(nynx,sizeof(double)); + if(tmp_uh == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: Unable to allocate memory for temporary output array"); + return(NhlFATAL); + } + } + else { + uh = (void *)calloc(size_output, sizeof(double)); + } + if(uh == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: Unable to allocate memory for output array"); + return(NhlFATAL); + } + +/* + * Allocate space for work arrays. + */ + tem1 = (void *)calloc(nznynx, sizeof(double)); + tem2 = (void *)calloc(nznynx, sizeof(double)); + if( tem1 == NULL || tem2 == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: Unable to allocate memory for work arrays"); + return(NhlFATAL); + } + +/* + * Allocate space for output dimension sizes and set them. + */ + ndims_uh = ndims_leftmost + 2; + dsizes_uh = (ng_size_t*)calloc(ndims_uh,sizeof(ng_size_t)); + if( dsizes_uh == NULL ) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: Unable to allocate memory for holding dimension sizes"); + return(NhlFATAL); + } + for(i = 0; i < ndims_uh-2; i++) dsizes_uh[i] = dsizes_zp[i]; + dsizes_uh[ndims_uh-2] = ny; + dsizes_uh[ndims_uh-1] = nx; + +/* + * Retrieve dimension names from "u", if any. + * + * u's dimension names will be used for the output. + */ + dim_info_us = get_wrf_dim_info(2,8,ndims_us,dsizes_us); + + if(dim_info_us != NULL) { + dim_info = malloc(sizeof(NclDimRec)*ndims_uh); + if(dim_info == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_updraft_helicity: Unable to allocate memory for holding dimension information"); + return(NhlFATAL); + } + for(i = 0; i < ndims_uh-2; i++) dim_info[i] = dim_info_us[i]; + dim_info[ndims_uh-1] = dim_info_us[ndims_us-1]; + dim_info[ndims_uh-2] = dim_info_us[ndims_us-2]; + } + +/* + * Loop across leftmost dimensions and call the Fortran routine for each + * subsection of the input arrays. + */ + index_zp = index_uh = index_us = 0; + + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of zp (tmp_zp) to double if necessary. + */ + if(type_zp != NCL_double) { + coerce_subset_input_double(zp,tmp_zp,index_zp,type_zp,nzp1nynx, + 0,NULL,NULL); + } + else { + tmp_zp = &((double*)zp)[index_zp]; + } + +/* + * Coerce subsection of mapfct (tmp_mapfct) to double if necessary. + */ + if(ndims_mapfct > 2) { + if(type_mapfct != NCL_double) { + coerce_subset_input_double(mapfct,tmp_mapfct,index_uh, + type_mapfct,nynx,0,NULL,NULL); + } + else { + tmp_mapfct = &((double*)mapfct)[index_uh]; + } + } + +/* + * Coerce subsection of us (tmp_us) to double if necessary. + */ + if(type_us != NCL_double) { + coerce_subset_input_double(us,tmp_us,index_us,type_us,nznynx, + 0,NULL,NULL); + } + else { + tmp_us = &((double*)us)[index_us]; + } + +/* + * Coerce subsection of vs (tmp_vs) to double if necessary. + */ + if(type_vs != NCL_double) { + coerce_subset_input_double(vs,tmp_vs,index_us,type_vs,nznynx, + 0,NULL,NULL); + } + else { + tmp_vs = &((double*)vs)[index_us]; + } + +/* + * Coerce subsection of w (tmp_w) to double if necessary. + */ + if(type_w != NCL_double) { + coerce_subset_input_double(w,tmp_w,index_zp,type_w,nzp1nynx,0,NULL,NULL); + } + else { + tmp_w = &((double*)w)[index_zp]; + } + + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_uh == NCL_double) tmp_uh = &((double*)uh)[index_uh]; + + +/* + * Call the Fortran routine. + */ + NGCALLF(dcalcuh,DCALCUH)(&inx, &iny, &inz, &inzp1, tmp_zp, tmp_mapfct, + tmp_dx, tmp_dy, tmp_uhmnhgt, tmp_uhmxhgt, + tmp_us, tmp_vs, tmp_w, tmp_uh, tem1, tem2); +/* + * Coerce output back to float if necessary. + */ + if(type_uh == NCL_float) { + coerce_output_float_only(uh,tmp_uh,nynx,index_uh); + } + index_zp += nzp1nynx; + index_uh += nynx; + index_us += nznynx; + } + +/* + * Free unneeded memory. + */ + if(type_zp != NCL_double) NclFree(tmp_zp); + if(type_mapfct != NCL_double) NclFree(tmp_mapfct); + if(type_dx != NCL_double) NclFree(tmp_dx); + if(type_dy != NCL_double) NclFree(tmp_dy); + if(type_us != NCL_double) NclFree(tmp_us); + if(type_vs != NCL_double) NclFree(tmp_vs); + if(type_w != NCL_double) NclFree(tmp_w); + if(type_uh != NCL_double) NclFree(tmp_uh); + if(type_uhmnhgt != NCL_double || ! set_uhmnhgt) NclFree(tmp_uhmnhgt); + if(type_uhmxhgt != NCL_double || ! set_uhmxhgt) NclFree(tmp_uhmxhgt); + NclFree(tem1); + NclFree(tem2); + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)uh, + NULL, + ndims_uh, + dsizes_uh, + TEMPORARY, + NULL, + type_obj_uh + ); + + NclFree(dsizes_uh); +/* + * Set up some attributes ("description" and "units") to return. + */ + cdescription = (char *)calloc(17,sizeof(char)); + strcpy(cdescription,"Updraft Helicity"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + free(cdescription); + + cunits = (char *)calloc(8,sizeof(char)); + strcpy(cunits,"m-2/s-2"); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *units = NrmStringToQuark(cunits); + free(cunits); + +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + NclFree(dim_info); + NclFree(dim_info_us); + +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); +} + +NhlErrorTypes wrf_ll_to_ij_W( void ) +{ + +/* + * Input variables + */ +/* + * Argument # 0 + */ + void *lon; + double *tmp_lon = NULL; + int ndims_lon; + ng_size_t dsizes_lon[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_lon; +/* + * Argument # 1 + */ + void *lat; + double *tmp_lat = NULL; + int ndims_lat; + ng_size_t dsizes_lat[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_lat; + +/* + * Argument # 2 + */ + logical *opt; + +/* + * Variables for retrieving attributes from "opt". + */ + NclAttList *attr_list; + NclAtt attr_obj; + NclStackEntry stack_entry; + +/* + * Variables that can be set via attributes. + */ + int map_proj; + void *truelat1 = NULL; + void *truelat2 = NULL; + void *stand_lon = NULL; + void *ref_lat = NULL; + void *ref_lon = NULL; + void *pole_lat = NULL; + void *pole_lon = NULL; + void *knowni = NULL; + void *knownj = NULL; + void *dx = NULL; + void *dy = NULL; + void *latinc = NULL; + void *loninc = NULL; + + double *tmp_truelat1, *tmp_truelat2, *tmp_stand_lon; + double *tmp_ref_lat, *tmp_ref_lon, *tmp_pole_lat, *tmp_pole_lon; + double *tmp_knowni, *tmp_knownj, *tmp_dx, *tmp_dy, *tmp_latinc, *tmp_loninc; + + NclBasicDataTypes type_truelat1 = NCL_none; + NclBasicDataTypes type_truelat2 = NCL_none; + NclBasicDataTypes type_stand_lon = NCL_none; + NclBasicDataTypes type_ref_lat = NCL_none; + NclBasicDataTypes type_ref_lon = NCL_none; + NclBasicDataTypes type_pole_lat = NCL_none; + NclBasicDataTypes type_pole_lon = NCL_none; + NclBasicDataTypes type_knowni = NCL_none; + NclBasicDataTypes type_knownj = NCL_none; + NclBasicDataTypes type_dx = NCL_none; + NclBasicDataTypes type_dy = NCL_none; + NclBasicDataTypes type_latinc = NCL_none; + NclBasicDataTypes type_loninc = NCL_none; + + logical set_map_proj, set_truelat1, set_truelat2, set_stand_lon, set_ref_lat; + logical set_ref_lon, set_pole_lat, set_pole_lon, set_knowni, set_knownj; + logical set_dx, set_dy, set_latinc, set_loninc; + +/* + * Return variable + */ + void *loc; + double *tmp_loc; + int ndims_loc; + ng_size_t *dsizes_loc; + NclBasicDataTypes type_loc; + NclObjClass type_obj_loc; +/* + * Variables for returning the output array with attributes attached. + */ + NclMultiDValData return_md; + NclVar tmp_var; + NclStackEntry return_data; +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info; + +/* + * Various + */ + int npts, i; + int errstat; + char* errmsg; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ +/* + * Get argument # 0 + */ + lon = (void*)NclGetArgValue( + 0, + 3, + &ndims_lon, + dsizes_lon, + NULL, + NULL, + &type_lon, + DONT_CARE); + +/* + * Get argument # 1 + */ + lat = (void*)NclGetArgValue( + 1, + 3, + &ndims_lat, + dsizes_lat, + NULL, + NULL, + &type_lat, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_lon != ndims_lat) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: lat and lon must have the same number of dimensions"); + return(NhlFATAL); + } + + for(i = 0; i < ndims_lat; i++) { + if(dsizes_lon[i] != dsizes_lat[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: lat and lon must have the same dimension sizes"); + return(NhlFATAL); + } + } + +/* + * Get argument # 2 + */ + opt = (logical*)NclGetArgValue( + 2, + 3, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + +/* + * Calculate size of lat/lon dimensions. + */ + npts = 1; + for(i = 0; i < ndims_lat; i++) npts *= dsizes_lat[i]; + +/* + * Start checking for attributes attached to "opt". Some are optional, + * and some are not. We'll check them later. + */ + + set_map_proj = set_truelat1 = set_truelat2 = set_stand_lon = False; + set_ref_lat = set_ref_lon = set_pole_lat = set_pole_lon = False; + set_knowni = set_knownj = set_dx = set_dy = set_latinc = set_loninc = False; + + stack_entry = _NclGetArg(2, 3, DONT_CARE); + switch (stack_entry.kind) { + case NclStk_VAR: + if (stack_entry.u.data_var->var.att_id != -1) { + attr_obj = (NclAtt) _NclGetObj(stack_entry.u.data_var->var.att_id); + if (attr_obj == NULL) { + break; + } + } + else { +/* + * att_id == -1 ==> no optional args given. + */ + break; + } +/* + * Get optional arguments. + */ + if (attr_obj->att.n_atts > 0) { +/* + * Get list of attributes. + */ + attr_list = attr_obj->att.att_list; +/* + * Loop through attributes and check them. We are looking for: + * + * map_proj + * truelat1, truelat2 + * stand_lon + * ref_lat, ref_lon + * pole_lat, pole_lon + * knowni, knownj + * dx, dy + * latinc, loninc + */ + while (attr_list != NULL) { + if(!strcasecmp(attr_list->attname, "map_proj")) { + map_proj = *(int *)attr_list->attvalue->multidval.val; + set_map_proj = True; + } + else if(!strcasecmp(attr_list->attname, "truelat1")) { + truelat1 = attr_list->attvalue->multidval.val; + type_truelat1 = attr_list->attvalue->multidval.data_type; + set_truelat1 = True; + } + else if(!strcasecmp(attr_list->attname, "truelat2")) { + truelat2 = attr_list->attvalue->multidval.val; + type_truelat2 = attr_list->attvalue->multidval.data_type; + set_truelat2 = True; + } + else if(!strcasecmp(attr_list->attname, "stand_lon")) { + stand_lon = attr_list->attvalue->multidval.val; + type_stand_lon = attr_list->attvalue->multidval.data_type; + set_stand_lon = True; + } + else if(!strcasecmp(attr_list->attname, "ref_lat")) { + ref_lat = attr_list->attvalue->multidval.val; + type_ref_lat = attr_list->attvalue->multidval.data_type; + set_ref_lat = True; + } + else if(!strcasecmp(attr_list->attname, "ref_lon")) { + ref_lon = attr_list->attvalue->multidval.val; + type_ref_lon = attr_list->attvalue->multidval.data_type; + set_ref_lon = True; + } + else if(!strcasecmp(attr_list->attname, "pole_lat")) { + pole_lat = attr_list->attvalue->multidval.val; + type_pole_lat = attr_list->attvalue->multidval.data_type; + set_pole_lat = True; + } + else if(!strcasecmp(attr_list->attname, "pole_lon")) { + pole_lon = attr_list->attvalue->multidval.val; + type_pole_lon = attr_list->attvalue->multidval.data_type; + set_pole_lon = True; + } + else if(!strcasecmp(attr_list->attname, "knowni")) { + knowni = attr_list->attvalue->multidval.val; + type_knowni = attr_list->attvalue->multidval.data_type; + set_knowni = True; + } + else if(!strcasecmp(attr_list->attname, "knownj")) { + knownj = attr_list->attvalue->multidval.val; + type_knownj = attr_list->attvalue->multidval.data_type; + set_knownj = True; + } + else if(!strcasecmp(attr_list->attname, "dx")) { + dx = attr_list->attvalue->multidval.val; + type_dx = attr_list->attvalue->multidval.data_type; + set_dx = True; + } + else if(!strcasecmp(attr_list->attname, "dy")) { + dy = attr_list->attvalue->multidval.val; + type_dy = attr_list->attvalue->multidval.data_type; + set_dy = True; + } + else if(!strcasecmp(attr_list->attname, "latinc")) { + latinc = attr_list->attvalue->multidval.val; + type_latinc = attr_list->attvalue->multidval.data_type; + set_latinc = True; + } + else if(!strcasecmp(attr_list->attname, "loninc")) { + loninc = attr_list->attvalue->multidval.val; + type_loninc = attr_list->attvalue->multidval.data_type; + set_loninc = True; + } + attr_list = attr_list->next; + } + default: + break; + } + } + +/* + * Check for attributes that need to be set, or set to a certain value. + * + * Check MAP_PROJ. Must be set. + */ + if(!set_map_proj) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: The MAP_PROJ attribute must be set"); + return(NhlFATAL); + } + else if(map_proj != 1 && map_proj != 2 && map_proj != 3 && map_proj != 6) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: The MAP_PROJ attribute must be set to 1, 2, 3, or 6"); + return(NhlFATAL); + } + +/* + * Check TRUELAT1. Must be set in some cases. + */ + if( (map_proj == 1 || map_proj == 2 || map_proj == 3) && !set_truelat1) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: The TRUELAT1 attribute must be set if MAP_PROJ is 1, 2, or 3"); + return(NhlFATAL); + } + if(set_truelat1) { + tmp_truelat1 = coerce_input_double(truelat1,type_truelat1,1,0,NULL,NULL); + } + else { + tmp_truelat1 = (double *)calloc(1,sizeof(double)); + *tmp_truelat1 = 0.; + } + +/* + * Check TRUELAT2. Must be set in some cases. + */ + if( map_proj == 1 && !set_truelat2) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: The TRUELAT2 attribute must be set if MAP_PROJ is 1"); + return(NhlFATAL); + } + if(set_truelat2) { + tmp_truelat2 = coerce_input_double(truelat2,type_truelat2,1,0,NULL,NULL); + } + else { + tmp_truelat2 = (double *)calloc(1,sizeof(double)); + *tmp_truelat2 = 0.; + } + +/* + * Check STAND_LON. Must be set. + */ + if(!set_stand_lon) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: The STAND_LON attribute must be set"); + return(NhlFATAL); + } + else { + tmp_stand_lon = coerce_input_double(stand_lon,type_stand_lon,1,0,NULL,NULL); + } + +/* + * Check REF_LAT/REF_LON. Must be set. + */ + if(!set_ref_lat || !set_ref_lon) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: The REF_LAT/REF_LON attributes must be set"); + return(NhlFATAL); + } + else { + tmp_ref_lat = coerce_input_double(ref_lat,type_ref_lat,1,0,NULL,NULL); + tmp_ref_lon = coerce_input_double(ref_lon,type_ref_lon,1,0,NULL,NULL); + } + +/* + * Check POLE_LAT/POLE_LON. + */ + if(set_pole_lat) { + tmp_pole_lat = coerce_input_double(pole_lat,type_pole_lat,1,0,NULL,NULL); + } + else { + tmp_pole_lat = (double *)calloc(1,sizeof(double)); + *tmp_pole_lat = 90.; + } + + if(set_pole_lon) { + tmp_pole_lon = coerce_input_double(pole_lon,type_pole_lon,1,0,NULL,NULL); + } + else { + tmp_pole_lon = (double *)calloc(1,sizeof(double)); + *tmp_pole_lon = 0.; + } + +/* + * Check KNOWNI/KNOWNJ. Must be set. + */ + if(!set_knowni || !set_knownj) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: The KNOWNI/KNOWNJ attributes must be set"); + return(NhlFATAL); + } + else { + tmp_knowni = coerce_input_double(knowni,type_knowni,1,0,NULL,NULL); + tmp_knownj = coerce_input_double(knownj,type_knownj,1,0,NULL,NULL); + } + +/* + * Check DX/DY. Must be set in some cases. + */ + if( (map_proj == 1 || map_proj == 2 || map_proj == 3) && + (!set_dx || !set_dy)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: The DX/DY attributes must be set if MAP_PROJ is 1, 2, or 3"); + return(NhlFATAL); + } + if(set_dx) { + tmp_dx = coerce_input_double(dx,type_dx,1,0,NULL,NULL); + } + else { + tmp_dx = (double *)calloc(1,sizeof(double)); + *tmp_dx = 0.; + } + + if(set_dy) { + tmp_dy = coerce_input_double(dy,type_dy,1,0,NULL,NULL); + } + else { + tmp_dy = (double *)calloc(1,sizeof(double)); + *tmp_dy = 0.; + } + +/* + * Check LATINC/LONINC. Must be set in some cases. + */ + if( map_proj == 6 && (!set_latinc || !set_loninc)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: The LATINC/LONINC attributes must be set if MAP_PROJ is 6"); + return(NhlFATAL); + } + if(set_latinc) { + tmp_latinc = coerce_input_double(latinc,type_latinc,1,0,NULL,NULL); + } + else { + tmp_latinc = (double *)calloc(1,sizeof(double)); + *tmp_latinc = 0.; + } + + if(set_loninc) { + tmp_loninc = coerce_input_double(loninc,type_loninc,1,0,NULL,NULL); + } + else { + tmp_loninc = (double *)calloc(1,sizeof(double)); + *tmp_loninc = 0.; + } + +/* + * The output type defaults to float, unless either of the lat/lon arrays + * are double. + */ + type_loc = NCL_float; + type_obj_loc = nclTypefloatClass; + +/* + * Allocate space for coercing input arrays. If any of the input + * is already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + */ +/* + * Allocate space for tmp_lat. + */ + if(type_lat != NCL_double) { + tmp_lat = (double *)calloc(npts,sizeof(double)); + if(tmp_lat == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_loc = NCL_double; + type_obj_loc = nclTypedoubleClass; + } + +/* + * Allocate space for tmp_lon. + */ + if(type_lon != NCL_double) { + tmp_lon = (double *)calloc(npts,sizeof(double)); + if(tmp_lon == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_loc = NCL_double; + type_obj_loc = nclTypedoubleClass; + } + +/* + * Allocate space for output array. + */ + tmp_loc = (double *)calloc(2,sizeof(double)); + if(type_loc != NCL_double) loc = (void *)calloc(2*npts, sizeof(float)); + else loc = (void *)calloc(2*npts, sizeof(double)); + if(loc == NULL || tmp_loc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: Unable to allocate memory for output array"); + return(NhlFATAL); + } + +/* + * Allocate space for output dimension sizes and set them. + */ + if(is_scalar(ndims_lat,dsizes_lat)) { + ndims_loc = 1; + } + else { + ndims_loc = ndims_lat + 1; + } + dsizes_loc = (ng_size_t*)calloc(ndims_loc,sizeof(ng_size_t)); + if( dsizes_loc == NULL ) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ll_to_ij: Unable to allocate memory for holding dimension sizes"); + return(NhlFATAL); + } + for(i = 0; i < ndims_loc-1; i++) dsizes_loc[i+1] = dsizes_lat[i]; + dsizes_loc[0] = 2; + + /* Allocate space for errmsg*/ + errmsg = (char *) calloc(ERRLEN, sizeof(char)) + +/* + * Loop across all lat/lon points and call the Fortran routine for each + * point. + */ + for(i = 0; i < npts; i++) { +/* + * Coerce subsection of lat (tmp_lat) to double if necessary. + */ + if(type_lat != NCL_double) { + coerce_subset_input_double(lat,tmp_lat,i,type_lat,1,0,NULL,NULL); + } + else { + tmp_lat = &((double*)lat)[i]; + } + +/* + * Coerce subsection of lon (tmp_lon) to double if necessary. + */ + if(type_lon != NCL_double) { + coerce_subset_input_double(lon,tmp_lon,i,type_lon,1,0,NULL,NULL); + } + else { + tmp_lon = &((double*)lon)[i]; + } + +/* + * Call the Fortran routine. + */ + errstat=0; + errmsg=""; + NGCALLF(dlltoij,DLLTOIJ)(&map_proj, tmp_truelat1, tmp_truelat2, + tmp_stand_lon, tmp_ref_lat, tmp_ref_lon, + tmp_pole_lat, tmp_pole_lon, tmp_knowni, + tmp_knownj, tmp_dx, tmp_dy, tmp_latinc, + tmp_loninc, tmp_lat, tmp_lon, tmp_loc, + &errstat, errmsg, ERRLEN); + + /* Terminate if there was an error */ + if (errstat != 0) { + fprintf(stderr, errmsg); + exit(errstat); + } + +/* + * Coerce output back to float or double. What's returned is in + * j,i order, so be sure to return i,j order. + */ + coerce_output_float_or_double(loc,&tmp_loc[1],type_loc,1,i); + coerce_output_float_or_double(loc,&tmp_loc[0],type_loc,1,i+npts); + } + +/* + * Free unneeded memory. + */ + if(type_lat != NCL_double) NclFree(tmp_lat); + if(type_lon != NCL_double) NclFree(tmp_lon); + if(type_truelat1 != NCL_double) NclFree(tmp_truelat1); + if(type_truelat2 != NCL_double) NclFree(tmp_truelat2); + if(type_stand_lon != NCL_double) NclFree(tmp_stand_lon); + if(type_ref_lat != NCL_double) NclFree(tmp_ref_lat); + if(type_ref_lon != NCL_double) NclFree(tmp_ref_lon); + if(type_pole_lat != NCL_double) NclFree(tmp_pole_lat); + if(type_pole_lon != NCL_double) NclFree(tmp_pole_lon); + if(type_knowni != NCL_double) NclFree(tmp_knowni); + if(type_knownj != NCL_double) NclFree(tmp_knownj); + if(type_dx != NCL_double) NclFree(tmp_dx); + if(type_dy != NCL_double) NclFree(tmp_dy); + if(type_latinc != NCL_double) NclFree(tmp_latinc); + if(type_loninc != NCL_double) NclFree(tmp_loninc); + NclFree(tmp_loc); + + dim_info = malloc(sizeof(NclDimRec)*ndims_loc); + if(dim_info == NULL) { + NhlPError(NhlWARNING,NhlEUNKNOWN,"wrf_ll_to_ij: Unable to allocate memory for setting dimension names"); + return(NhlFATAL); + } + for(i = 0; i < ndims_loc; i++ ) { + dim_info[i].dim_num = i; + dim_info[i].dim_quark = -1; + dim_info[i].dim_size = dsizes_loc[i]; + } + dim_info[0].dim_quark = NrmStringToQuark("i_j_location"); + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)loc, + NULL, + ndims_loc, + dsizes_loc, + TEMPORARY, + NULL, + type_obj_loc + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + -1, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + + NclFree(dsizes_loc); + NclFree(dim_info); + +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); +} + + +NhlErrorTypes wrf_ij_to_ll_W( void ) +{ +/* + * Input variables + */ +/* + * Argument # 0 + */ + void *iloc; + double *tmp_iloc = NULL; + int ndims_iloc; + ng_size_t dsizes_iloc[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_iloc; + +/* + * Argument # 1 + */ + void *jloc; + double *tmp_jloc = NULL; + int ndims_jloc; + ng_size_t dsizes_jloc[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_jloc; + +/* + * Argument # 2 + */ + logical *opt; + +/* + * Variables for retrieving attributes from "opt". + */ + NclAttList *attr_list; + NclAtt attr_obj; + NclStackEntry stack_entry; + +/* + * Variables that can be set via attributes. + */ + int map_proj; + void *truelat1 = NULL; + void *truelat2 = NULL; + void *stand_lon = NULL; + void *ref_lat = NULL; + void *ref_lon = NULL; + void *pole_lat = NULL; + void *pole_lon = NULL; + void *knowni = NULL; + void *knownj = NULL; + void *dx = NULL; + void *dy = NULL; + void *latinc = NULL; + void *loninc = NULL; + + double *tmp_truelat1 = NULL; + double *tmp_truelat2 = NULL; + double *tmp_stand_lon = NULL; + double *tmp_ref_lat = NULL; + double *tmp_ref_lon = NULL; + double *tmp_pole_lat = NULL; + double *tmp_pole_lon = NULL; + double *tmp_knowni = NULL; + double *tmp_knownj = NULL; + double *tmp_dx = NULL; + double *tmp_dy = NULL; + double *tmp_latinc = NULL; + double *tmp_loninc = NULL; + + NclBasicDataTypes type_truelat1 = NCL_none; + NclBasicDataTypes type_truelat2 = NCL_none; + NclBasicDataTypes type_stand_lon = NCL_none; + NclBasicDataTypes type_ref_lat = NCL_none; + NclBasicDataTypes type_ref_lon = NCL_none; + NclBasicDataTypes type_pole_lat = NCL_none; + NclBasicDataTypes type_pole_lon = NCL_none; + NclBasicDataTypes type_knowni = NCL_none; + NclBasicDataTypes type_knownj = NCL_none; + NclBasicDataTypes type_dx = NCL_none; + NclBasicDataTypes type_dy = NCL_none; + NclBasicDataTypes type_latinc = NCL_none; + NclBasicDataTypes type_loninc = NCL_none; + + logical set_map_proj, set_truelat1, set_truelat2, set_stand_lon, set_ref_lat; + logical set_ref_lon, set_pole_lat, set_pole_lon, set_knowni, set_knownj; + logical set_dx, set_dy, set_latinc, set_loninc; + +/* + * Return variable + */ + void *loc; + double *tmp_loc; + int ndims_loc; + ng_size_t *dsizes_loc; + NclBasicDataTypes type_loc; + NclObjClass type_obj_loc; +/* + * Variables for returning the output array with attributes attached. + */ + NclMultiDValData return_md; + NclVar tmp_var; + NclStackEntry return_data; +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info; + +/* + * Various + */ + int npts, i; + int errstat; + char* errmsg; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ +/* + * Get argument # 0 + */ + iloc = (void*)NclGetArgValue( + 0, + 3, + &ndims_iloc, + dsizes_iloc, + NULL, + NULL, + &type_iloc, + DONT_CARE); + +/* + * Get argument # 1 + */ + jloc = (void*)NclGetArgValue( + 1, + 3, + &ndims_jloc, + dsizes_jloc, + NULL, + NULL, + &type_jloc, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_jloc != ndims_iloc) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: lat and lon must have the same number of dimensions"); + return(NhlFATAL); + } + + for(i = 0; i < ndims_iloc; i++) { + if(dsizes_jloc[i] != dsizes_iloc[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: lat and lon must have the same dimensionality"); + return(NhlFATAL); + } + } + +/* + * Get argument # 2 + */ + opt = (logical*)NclGetArgValue( + 2, + 3, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + +/* + * Calculate size of i/j dimensions. + */ + npts = 1; + for(i = 0; i < ndims_iloc; i++) npts *= dsizes_iloc[i]; + +/* + * Start checking for attributes attached to "opt". Some are optional, + * and some are not. We'll check them later. + */ + + set_map_proj = set_truelat1 = set_truelat2 = set_stand_lon = False; + set_ref_lat = set_ref_lon = set_pole_lat = set_pole_lon = False; + set_knowni = set_knownj = set_dx = set_dy = set_latinc = set_loninc = False; + + stack_entry = _NclGetArg(2, 3, DONT_CARE); + switch (stack_entry.kind) { + case NclStk_VAR: + if (stack_entry.u.data_var->var.att_id != -1) { + attr_obj = (NclAtt) _NclGetObj(stack_entry.u.data_var->var.att_id); + if (attr_obj == NULL) { + break; + } + } + else { +/* + * att_id == -1 ==> no optional args given. + */ + break; + } +/* + * Get optional arguments. + */ + if (attr_obj->att.n_atts > 0) { +/* + * Get list of attributes. + */ + attr_list = attr_obj->att.att_list; +/* + * Loop through attributes and check them. We are looking for: + * + * map_proj + * truelat1, truelat2 + * stand_lon + * ref_lat, ref_lon + * pole_lat, pole_lon + * knowni, knownj + * dx, dy + * latinc, loninc + */ + while (attr_list != NULL) { + if(!strcasecmp(attr_list->attname, "map_proj")) { + map_proj = *(int *)attr_list->attvalue->multidval.val; + set_map_proj = True; + } + else if(!strcasecmp(attr_list->attname, "truelat1")) { + truelat1 = attr_list->attvalue->multidval.val; + type_truelat1 = attr_list->attvalue->multidval.data_type; + set_truelat1 = True; + } + else if(!strcasecmp(attr_list->attname, "truelat2")) { + truelat2 = attr_list->attvalue->multidval.val; + type_truelat2 = attr_list->attvalue->multidval.data_type; + set_truelat2 = True; + } + else if(!strcasecmp(attr_list->attname, "stand_lon")) { + stand_lon = attr_list->attvalue->multidval.val; + type_stand_lon = attr_list->attvalue->multidval.data_type; + set_stand_lon = True; + } + else if(!strcasecmp(attr_list->attname, "ref_lat")) { + ref_lat = attr_list->attvalue->multidval.val; + type_ref_lat = attr_list->attvalue->multidval.data_type; + set_ref_lat = True; + } + else if(!strcasecmp(attr_list->attname, "ref_lon")) { + ref_lon = attr_list->attvalue->multidval.val; + type_ref_lon = attr_list->attvalue->multidval.data_type; + set_ref_lon = True; + } + else if(!strcasecmp(attr_list->attname, "pole_lat")) { + pole_lat = attr_list->attvalue->multidval.val; + type_pole_lat = attr_list->attvalue->multidval.data_type; + set_pole_lat = True; + } + else if(!strcasecmp(attr_list->attname, "pole_lon")) { + pole_lon = attr_list->attvalue->multidval.val; + type_pole_lon = attr_list->attvalue->multidval.data_type; + set_pole_lon = True; + } + else if(!strcasecmp(attr_list->attname, "knowni")) { + knowni = attr_list->attvalue->multidval.val; + type_knowni = attr_list->attvalue->multidval.data_type; + set_knowni = True; + } + else if(!strcasecmp(attr_list->attname, "knownj")) { + knownj = attr_list->attvalue->multidval.val; + type_knownj = attr_list->attvalue->multidval.data_type; + set_knownj = True; + } + else if(!strcasecmp(attr_list->attname, "dx")) { + dx = attr_list->attvalue->multidval.val; + type_dx = attr_list->attvalue->multidval.data_type; + set_dx = True; + } + else if(!strcasecmp(attr_list->attname, "dy")) { + dy = attr_list->attvalue->multidval.val; + type_dy = attr_list->attvalue->multidval.data_type; + set_dy = True; + } + else if(!strcasecmp(attr_list->attname, "latinc")) { + latinc = attr_list->attvalue->multidval.val; + type_latinc = attr_list->attvalue->multidval.data_type; + set_latinc = True; + } + else if(!strcasecmp(attr_list->attname, "loninc")) { + loninc = attr_list->attvalue->multidval.val; + type_loninc = attr_list->attvalue->multidval.data_type; + set_loninc = True; + } + attr_list = attr_list->next; + } + default: + break; + } + } + +/* + * Check for attributes that need to be set, or set to a certain value. + * + * Check MAP_PROJ. Must be set. + */ + if(!set_map_proj) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: The MAP_PROJ attribute must be set"); + return(NhlFATAL); + } + else if(map_proj != 1 && map_proj != 2 && map_proj != 3 && map_proj != 6) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: The MAP_PROJ attribute must be set to 1, 2, 3, or 6"); + return(NhlFATAL); + } + +/* + * Check TRUELAT1. Must be set in some cases. + */ + if( (map_proj == 1 || map_proj == 2 || map_proj == 3) && !set_truelat1) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: The TRUELAT1 attribute must be set if MAP_PROJ is 1, 2, or 3"); + return(NhlFATAL); + } + if(set_truelat1) { + tmp_truelat1 = coerce_input_double(truelat1,type_truelat1,1,0,NULL,NULL); + } + else { + tmp_truelat1 = (double *)calloc(1,sizeof(double)); + *tmp_truelat1 = 0.; + } + +/* + * Check TRUELAT2. Must be set in some cases. + */ + if( map_proj == 1 && !set_truelat2) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: The TRUELAT2 attribute must be set if MAP_PROJ is 1"); + return(NhlFATAL); + } + if(set_truelat2) { + tmp_truelat2 = coerce_input_double(truelat2,type_truelat2,1,0,NULL,NULL); + } + else { + tmp_truelat2 = (double *)calloc(1,sizeof(double)); + *tmp_truelat2 = 0.; + } + +/* + * Check STAND_LON. Must be set. + */ + if(!set_stand_lon) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: The STAND_LON attribute must be set"); + return(NhlFATAL); + } + else { + tmp_stand_lon = coerce_input_double(stand_lon,type_stand_lon,1,0,NULL,NULL); + } + +/* + * Check REF_LAT/REF_LON. Must be set. + */ + if(!set_ref_lat || !set_ref_lon) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: The REF_LAT/REF_LON attributes must be set"); + return(NhlFATAL); + } + else { + tmp_ref_lat = coerce_input_double(ref_lat,type_ref_lat,1,0,NULL,NULL); + tmp_ref_lon = coerce_input_double(ref_lon,type_ref_lon,1,0,NULL,NULL); + } + +/* + * Check POLE_LAT/POLE_LON. + */ + if(set_pole_lat) { + tmp_pole_lat = coerce_input_double(pole_lat,type_pole_lat,1,0,NULL,NULL); + } + else { + tmp_pole_lat = (double *)calloc(1,sizeof(double)); + *tmp_pole_lat = 90.; + } + + if(set_pole_lon) { + tmp_pole_lon = coerce_input_double(pole_lon,type_pole_lon,1,0,NULL,NULL); + } + else { + tmp_pole_lon = (double *)calloc(1,sizeof(double)); + *tmp_pole_lon = 0.; + } + +/* + * Check KNOWNI/KNOWNJ. Must be set. + */ + if(!set_knowni || !set_knownj) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: The KNOWNI/KNOWNJ attributes must be set"); + return(NhlFATAL); + } + else { + tmp_knowni = coerce_input_double(knowni,type_knowni,1,0,NULL,NULL); + tmp_knownj = coerce_input_double(knownj,type_knownj,1,0,NULL,NULL); + } + +/* + * Check DX/DY. Must be set in some cases. + */ + if( (map_proj == 1 || map_proj == 2 || map_proj == 3) && + (!set_dx || !set_dy)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: The DX/DY attributes must be set if MAP_PROJ is 1, 2, or 3"); + return(NhlFATAL); + } + if(set_dx) { + tmp_dx = coerce_input_double(dx,type_dx,1,0,NULL,NULL); + } + else { + tmp_dx = (double *)calloc(1,sizeof(double)); + *tmp_dx = 0.; + } + + if(set_dy) { + tmp_dy = coerce_input_double(dy,type_dy,1,0,NULL,NULL); + } + else { + tmp_dy = (double *)calloc(1,sizeof(double)); + *tmp_dy = 0.; + } + +/* + * Check LATINC/LONINC. Must be set in some cases. + */ + if( map_proj == 6 && (!set_latinc || !set_loninc)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: The LATINC/LONINC attributes must be set if MAP_PROJ is 6"); + return(NhlFATAL); + } + if(set_latinc) { + tmp_latinc = coerce_input_double(latinc,type_latinc,1,0,NULL,NULL); + } + else { + tmp_latinc = (double *)calloc(1,sizeof(double)); + *tmp_latinc = 0.; + } + + if(set_loninc) { + tmp_loninc = coerce_input_double(loninc,type_loninc,1,0,NULL,NULL); + } + else { + tmp_loninc = (double *)calloc(1,sizeof(double)); + *tmp_loninc = 0.; + } + +/* + * The output type defaults to float, unless either of the lat/lon arrays + * are double. + */ + type_loc = NCL_float; + type_obj_loc = nclTypefloatClass; + +/* + * Allocate space for coercing input arrays. If any of the input + * is already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + */ +/* + * Allocate space for tmp_iloc. + */ + if(type_iloc != NCL_double) { + tmp_iloc = (double *)calloc(npts,sizeof(double)); + if(tmp_iloc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_loc = NCL_double; + type_obj_loc = nclTypedoubleClass; + } + +/* + * Allocate space for tmp_jloc. + */ + if(type_jloc != NCL_double) { + tmp_jloc = (double *)calloc(npts,sizeof(double)); + if(tmp_jloc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_loc = NCL_double; + type_obj_loc = nclTypedoubleClass; + } + +/* + * Allocate space for output array. + */ + tmp_loc = (double *)calloc(2,sizeof(double)); + if(type_loc != NCL_double) loc = (void *)calloc(2*npts, sizeof(float)); + else loc = (void *)calloc(2*npts, sizeof(double)); + if(loc == NULL || tmp_loc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: Unable to allocate memory for output array"); + return(NhlFATAL); + } + +/* + * Allocate space for output dimension sizes and set them. + */ + if(is_scalar(ndims_iloc,dsizes_iloc)) { + ndims_loc = 1; + } + else { + ndims_loc = ndims_iloc + 1; + } + dsizes_loc = (ng_size_t*)calloc(ndims_loc,sizeof(ng_size_t)); + if( dsizes_loc == NULL ) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_ij_to_ll: Unable to allocate memory for holding dimension sizes"); + return(NhlFATAL); + } + for(i = 0; i < ndims_loc-1; i++) dsizes_loc[i+1] = dsizes_iloc[i]; + dsizes_loc[0] = 2; + + /* Allocate space for errmsg*/ + errmsg = (char *) calloc(ERRLEN, sizeof(char)) + +/* + * Loop across all lat/lon points and call the Fortran routine for each + * point. + */ + for(i = 0; i < npts; i++) { +/* + * Coerce subsection of iloc (tmp_iloc) to double if necessary. + */ + if(type_iloc != NCL_double) { + coerce_subset_input_double(iloc,tmp_iloc,i,type_iloc,1,0,NULL,NULL); + } + else { + tmp_iloc = &((double*)iloc)[i]; + } + +/* + * Coerce subsection of lon (tmp_jloc) to double if necessary. + */ + if(type_jloc != NCL_double) { + coerce_subset_input_double(jloc,tmp_jloc,i,type_jloc,1,0,NULL,NULL); + } + else { + tmp_jloc = &((double*)jloc)[i]; + } + +/* + * Call the Fortran routine. + */ + errstat = 0; + errmsg = ""; + NGCALLF(dijtoll,DIJTOLL)(&map_proj, tmp_truelat1, tmp_truelat2, + tmp_stand_lon, tmp_ref_lat, tmp_ref_lon, + tmp_pole_lat, tmp_pole_lon, tmp_knowni, + tmp_knownj, tmp_dx, tmp_dy, tmp_latinc, + tmp_loninc, tmp_iloc, tmp_jloc, tmp_loc, + &errstat, errmsg, ERRLEN); + + /* Terminate if there was an error */ + if (errstat != 0) { + fprintf(stderr, errmsg); + exit(errstat); + } + +/* + * Coerce output back to float or double. What's returned is in + * lat,lon (j,i) order, so be sure to return lon,lat (i,j) order. + */ + coerce_output_float_or_double(loc,&tmp_loc[1],type_loc,1,i); + coerce_output_float_or_double(loc,&tmp_loc[0],type_loc,1,i+npts); + } + +/* + * Free unneeded memory. + */ + if(type_iloc != NCL_double) NclFree(tmp_iloc); + if(type_jloc != NCL_double) NclFree(tmp_jloc); + if(type_truelat1 != NCL_double) NclFree(tmp_truelat1); + if(type_truelat2 != NCL_double) NclFree(tmp_truelat2); + if(type_stand_lon != NCL_double) NclFree(tmp_stand_lon); + if(type_ref_lat != NCL_double) NclFree(tmp_ref_lat); + if(type_ref_lon != NCL_double) NclFree(tmp_ref_lon); + if(type_pole_lat != NCL_double) NclFree(tmp_pole_lat); + if(type_pole_lon != NCL_double) NclFree(tmp_pole_lon); + if(type_knowni != NCL_double) NclFree(tmp_knowni); + if(type_knownj != NCL_double) NclFree(tmp_knownj); + if(type_dx != NCL_double) NclFree(tmp_dx); + if(type_dy != NCL_double) NclFree(tmp_dy); + if(type_latinc != NCL_double) NclFree(tmp_latinc); + if(type_loninc != NCL_double) NclFree(tmp_loninc); + NclFree(tmp_loc); + + dim_info = malloc(sizeof(NclDimRec)*ndims_loc); + if(dim_info == NULL) { + NhlPError(NhlWARNING,NhlEUNKNOWN,"wrf_ij_to_ll: Unable to allocate memory for setting dimension names"); + return(NhlFATAL); + } + for(i = 0; i < ndims_loc; i++ ) { + dim_info[i].dim_num = i; + dim_info[i].dim_quark = -1; + dim_info[i].dim_size = dsizes_loc[i]; + } + dim_info[0].dim_quark = NrmStringToQuark("lon_lat_location"); + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)loc, + NULL, + ndims_loc, + dsizes_loc, + TEMPORARY, + NULL, + type_obj_loc + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + -1, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + + NclFree(dsizes_loc); + NclFree(dim_info); + +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); +} + + +/* + * Function for calculating cape (from the RIP code). This function + * depends on the "psadilookup.dat" file, which by default will be + * searched for in $NCARG_ROOT/lib/ncarg/data/asc/), unless + * NCARG_PSADILOOKUP is set to the location of this file. + */ + +/* + * The wrf_cape_3d wrapper is for the case where I3DFLAG is set to + * 1 in the Fortran rip_cape.f file. This wrapper is similar to + * rip_cape_3d except it will flip the first four input arrays if + * the pressure values are not decreasing. It will also multiple the + * pressure values by 0.01 to convert from hPa to Pa. + * + */ +NhlErrorTypes wrf_cape_3d_W( void ) +{ +/* + * Input array variables + */ + void *p, *t, *q, *z, *zsfc, *psfc; + logical *ter_follow; + double *tmp_p = NULL; + double *tmp_t = NULL; + double *tmp_q = NULL; + double *tmp_z = NULL; + double *tmp_zsfc = NULL; + double *tmp_psfc = NULL; + double *tmp_p_orig = NULL; + double *tmp_t_orig = NULL; + double *tmp_q_orig = NULL; + double *tmp_z_orig = NULL; + int ndims_p, ndims_t, ndims_q, ndims_z, ndims_zsfc, ndims_psfc; + ng_size_t dsizes_p[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_t[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_q[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_z[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_zsfc[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_psfc[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_p, type_t, type_q, type_z, type_zsfc, type_psfc; + +/* + * Output array variables + */ + void *cape; + double *tmp_cape_orig, *tmp_cin_orig, cmsg; + double *tmp_cape, *tmp_cin; + NclBasicDataTypes type_cape; + NclObjClass type_obj_cape; + int ndims_cape; + NclScalar missing_cape; + ng_size_t *dsizes_cape; + +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info = NULL; + NclDimRec *dim_info_t; + +/* + * Variables for returning the output array with attributes and/or + * dimension names attached. + */ + NclMultiDValData return_md; + NclVar tmp_var; + NclStackEntry return_data; +/* + * Declare various variables for random purposes. + */ + ng_size_t i; + ng_size_t miy = 0; + ng_size_t mjx = 0; + ng_size_t mkzh = 0; + ng_size_t ntime = 0; + ng_size_t nz = 0; + ng_size_t size_cape, size_output, size_zsfc; + int i3dflag=1, scalar_zsfc; + ng_size_t index_cape, index_zsfc, index_cin; + int iter; + logical flip; + int imiy, imjx, imkzh; + char *psa_file; + int errstat; + char *errmsg; + +/* + * Retrieve parameters + * + * Note that any of the pointer parameters can be set to NULL, + * which implies you don't care about its value. + * + */ + p = (void*)NclGetArgValue( + 0, + 7, + &ndims_p, + dsizes_p, + NULL, + NULL, + &type_p, + DONT_CARE); + + t = (void*)NclGetArgValue( + 1, + 7, + &ndims_t, + dsizes_t, + NULL, + NULL, + &type_t, + DONT_CARE); + + + q = (void*)NclGetArgValue( + 2, + 7, + &ndims_q, + dsizes_q, + NULL, + NULL, + &type_q, + DONT_CARE); + + z = (void*)NclGetArgValue( + 3, + 7, + &ndims_z, + dsizes_z, + NULL, + NULL, + &type_z, + DONT_CARE); + + zsfc = (void*)NclGetArgValue( + 4, + 7, + &ndims_zsfc, + dsizes_zsfc, + NULL, + NULL, + &type_zsfc, + DONT_CARE); + + psfc = (void*)NclGetArgValue( + 5, + 7, + &ndims_psfc, + dsizes_psfc, + NULL, + NULL, + &type_psfc, + DONT_CARE); + + ter_follow = (logical*)NclGetArgValue( + 6, + 7, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + + if(*ter_follow) iter = 1; + else iter = 0; + +/* + * Check the input dimension sizes. There are four possible cases + * for the input dimension sizes: + * + * - p,t,q,z (nz,time,lev,lat,lon) and psfc,zsfc (nz,time,lat,lon) + * - p,t,q,z (time,lev,lat,lon) and psfc,zsfc (time,lat,lon) + * - p,t,q,z (lev,lat,lon) and psfc,zsfc (lat,lon) + * - p,t,q,z (lev) and psfc,zsfc (scalars) + */ + if(ndims_p != ndims_t || ndims_p != ndims_q || ndims_p != ndims_z) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: The p, t, q, and z arrays must all have the same number of dimensions"); + return(NhlFATAL); + } + if(ndims_p != 1 && ndims_p != 3 && ndims_p != 4 && ndims_p != 5) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: The p, t, q, and z arrays must be 1-, 3-, 4-, or 5-dimensional\n"); + return(NhlFATAL); + } +/* + * zsfc and psfc can be scalars, if the other input arrays are 1D. + */ + scalar_zsfc = is_scalar(ndims_zsfc,dsizes_zsfc); + + if((ndims_zsfc != ndims_psfc) || (scalar_zsfc && ndims_p != 1) || + (!scalar_zsfc && ndims_zsfc != ndims_p-1)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: The zsfc and psfc arrays must have the same number of dimensions, and either be scalars or one less dimension than the other input arrays"); + return(NhlFATAL); + } + +/* + * Now check that the dimension sizes are equal to each other. + */ + for(i = 0; i < ndims_p; i++) { + if(dsizes_p[i] != dsizes_t[i] || dsizes_p[i] != dsizes_q[i] || + dsizes_p[i] != dsizes_z[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: p, t, q, and z must be the same dimensionality"); + return(NhlFATAL); + } + } + + for(i = 0; i < ndims_psfc; i++) { + if(dsizes_psfc[i] != dsizes_zsfc[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: psfc and zsfc must be the same dimensionality"); + return(NhlFATAL); + } + } +/* + * Get sizes of input arrays. + */ + if(ndims_p == 5) { + nz = dsizes_p[0]; /* nz, serves as leftmost dimension */ + ntime = dsizes_p[1]; /* time, also serves as leftmost dimension */ + mkzh = dsizes_p[2]; /* lev */ + mjx = dsizes_p[3]; /* lat */ + miy = dsizes_p[4]; /* lon */ + } + else if(ndims_p == 4) { + nz = 1; + ntime = dsizes_p[0]; /* time, serves as a leftmost dimension */ + mkzh = dsizes_p[1]; /* lev */ + mjx = dsizes_p[2]; /* lat */ + miy = dsizes_p[3]; /* lon */ + } + else if(ndims_p == 3) { + nz = 1; + ntime = 1; + mkzh = dsizes_p[0]; /* lev */ + mjx = dsizes_p[1]; /* lat */ + miy = dsizes_p[2]; /* lon */ + } + else if(ndims_p == 1) { + nz = 1; + ntime = 1; + mkzh = dsizes_p[0]; /* lev */ + mjx = 1; /* lat */ + miy = 1; /* lon */ + } + +/* + * Test input dimension sizes. + */ + if((miy > INT_MAX) || (mjx > INT_MAX) || (mkzh > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: one or more dimension sizes is greater than INT_MAX"); + return(NhlFATAL); + } + imiy = (int) miy; + imjx = (int) mjx; + imkzh = (int) mkzh; + +/* + * Check some more dimension sizes. + */ + if(ndims_p == 5) { + if(dsizes_psfc[0] != nz || dsizes_psfc[1] != ntime || + dsizes_psfc[2] != mjx || dsizes_psfc[3] != miy) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: If p,q,t,z are 4-dimensional (time x lev x lat x lon), psfc,zsfc must be 3-dimensional (time x lat x lon)"); + return(NhlFATAL); + } + } + else if(ndims_p == 4) { + if(dsizes_psfc[0] != ntime || dsizes_psfc[1] != mjx || + dsizes_psfc[2] != miy) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: If p,q,t,z are 4-dimensional (time x lev x lat x lon), psfc,zsfc must be 3-dimensional (time x lat x lon)"); + return(NhlFATAL); + } + } + else if(ndims_p == 3) { + if(dsizes_psfc[0] != mjx || dsizes_psfc[1] != miy) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: If p,q,t,z are 3-dimensional (time x lev x lat x lon), psfc,zsfc must be 2-dimensional (lat x lon)"); + return(NhlFATAL); + } + } +/* + * Calculate size of output array. The output array size depends on + * the size of p,t,q,z: + * + * - p,t,q,z (nz,time,lev,lat,lon) and psfc,zsfc (nz,time,lat,lon) + * output array: (2,nz,time,lev,lat,lon) + * - p,t,q,z (time,lev,lat,lon) and psfc,zsfc (time,lat,lon) + * output array: (2,time,lev,lat,lon) + * - p,t,q,z (lev,lat,lon) and psfc,zsfc (lat,lon) + * output array: (2,lev,lat,lon) + * - p,t,q,z (lev) and psfc,zsfc (scalars) + * output array: (2,lev) + */ + ndims_cape = ndims_p+1; + dsizes_cape = (ng_size_t *)calloc(ndims_cape,sizeof(ng_size_t)); + if(dsizes_cape == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: Unable to allocate memory for array dimensionality"); + return(NhlFATAL); + } + + dsizes_cape[0] = 2; /* 0 = cape, 1 = cin */ + for(i = 0; i < ndims_p; i++ ) { + dsizes_cape[i+1] = dsizes_p[i]; + } + size_zsfc = mjx * miy; + size_cape = mkzh * size_zsfc; /* Also size of cin array */ + size_output = 2 * size_cape * ntime * nz; + +/* + * Allocate space for output arrays. We are allocating space for + * tmp_cape_orig and tmp_cin_orig even if the output will be double, + * because we may also need to flip the values before we're done. + * + * The addition of missing values was added in V6.1.0. + */ + if(type_p == NCL_double || type_t == NCL_double || type_q == NCL_double || + type_z == NCL_double) { + type_cape = NCL_double; + type_obj_cape = nclTypedoubleClass; + cape = (double *)calloc(size_output,sizeof(double)); + missing_cape.doubleval = ((NclTypeClass)nclTypedoubleClass)->type_class.default_mis.doubleval; + cmsg = missing_cape.doubleval; + } + else { + type_cape = NCL_float; + type_obj_cape = nclTypefloatClass; + cape = (float *)calloc(size_output,sizeof(float)); + missing_cape.floatval = ((NclTypeClass)nclTypefloatClass)->type_class.default_mis.floatval; + cmsg = (double)missing_cape.floatval; + } + tmp_cape_orig = (double *)calloc(size_cape,sizeof(double)); + tmp_cin_orig = (double *)calloc(size_cape,sizeof(double)); + if(cape == NULL || tmp_cape_orig == NULL || tmp_cin_orig == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: Unable to allocate memory for output arrays"); + return(NhlFATAL); + } + +/* + * Allocate memory for coercing input arrays to double, if necessary. + * Force a copy of variable p, because we need to multiply it by 0.01, + * and we don't want this to propagate back to the NCL script. + */ + tmp_p_orig = (double *)calloc(size_cape,sizeof(double)); + if(tmp_p_orig == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + + if(type_t != NCL_double) { + tmp_t_orig = (double *)calloc(size_cape,sizeof(double)); + if(tmp_t_orig == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_q != NCL_double) { + tmp_q_orig = (double *)calloc(size_cape,sizeof(double)); + if(tmp_q_orig == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_z != NCL_double) { + tmp_z_orig = (double *)calloc(size_cape,sizeof(double)); + if(tmp_z_orig == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_zsfc != NCL_double) { + tmp_zsfc = (double *)calloc(size_zsfc,sizeof(double)); + if(tmp_zsfc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_psfc != NCL_double) { + tmp_psfc = (double *)calloc(size_zsfc,sizeof(double)); + if(tmp_psfc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + +/* + * We need to coerce the pressure array once outside the loop to + * check if the values are in ascending order. + * + * If not, we need to flip the leftmost dimension (p = p(::-1,:,:) in + * NCL-ese), *and* flip the other 3 input arrays in the same fashion. + */ + coerce_subset_input_double(p,tmp_p_orig,0,type_p,size_cape,0,NULL,NULL); + + if(tmp_p_orig[0] > tmp_p_orig[(mkzh-1)*size_zsfc] ) { + flip = True; + tmp_p = (double *)calloc(size_cape,sizeof(double)); + tmp_t = (double *)calloc(size_cape,sizeof(double)); + tmp_q = (double *)calloc(size_cape,sizeof(double)); + tmp_z = (double *)calloc(size_cape,sizeof(double)); + tmp_cape = (double *)calloc(size_cape,sizeof(double)); + tmp_cin = (double *)calloc(size_cape,sizeof(double)); + + if(tmp_p == NULL || tmp_t == NULL || tmp_q == NULL || tmp_z == NULL || + tmp_cape == NULL || tmp_cin == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: Unable to allocate memory for flipping arrays"); + return(NhlFATAL); + } + } + else { + flip = False; + tmp_p = tmp_p_orig; + tmp_t = tmp_t_orig; + tmp_q = tmp_q_orig; + tmp_z = tmp_z_orig; + tmp_cape = tmp_cape_orig; + tmp_cin = tmp_cin_orig; + } + +/* + * Get path to psadilookup.dat file required by this routine. + */ + psa_file = get_psa_file(); + +/* Allocate space for errmsg*/ + errmsg = (char *) calloc(ERRLEN, sizeof(char)) + +/* + * Loop through time,nz and call the Fortran routine. + */ + index_cape = index_zsfc = 0; + index_cin = ntime * nz * size_cape; /* Second half of output array */ + + for(i = 0; i < ntime*nz; i++) { +/* + * Coerce subset of input arrays to double if necessary. + */ + if(i > 0) { + coerce_subset_input_double(p,tmp_p_orig,index_cape,type_p, + size_cape,0,NULL,NULL); + } +/* + * Multiple pressure values by 0.01 to convert from Pa to hPa. + * The assumption is that pressure values come in as Pa. + */ + convert_to_hPa(tmp_p_orig,size_cape); + + if(type_t != NCL_double) { + coerce_subset_input_double(t,tmp_t_orig,index_cape,type_t, + size_cape,0,NULL,NULL); + } + else { +/* + * Point tmp_t_orig to appropriate location in t. + */ + tmp_t_orig = &((double*)t)[index_cape]; + } + if(type_q != NCL_double) { + coerce_subset_input_double(q,tmp_q_orig,index_cape,type_q, + size_cape,0,NULL,NULL); + } + else { +/* + * Point tmp_q_orig to appropriate location in q. + */ + tmp_q_orig = &((double*)q)[index_cape]; + } + if(type_z != NCL_double) { + coerce_subset_input_double(z,tmp_z_orig,index_cape,type_z, + size_cape,0,NULL,NULL); + } + else { +/* + * Point tmp_z_orig to appropriate location in z. + */ + tmp_z_orig = &((double*)z)[index_cape]; + } + + if(type_psfc != NCL_double) { + coerce_subset_input_double(psfc,tmp_psfc,index_zsfc,type_psfc, + size_zsfc,0,NULL,NULL); + } + else { +/* + * Point tmp_psfc to appropriate location in psfc. + */ + tmp_psfc = &((double*)psfc)[index_zsfc]; + } + if(type_zsfc != NCL_double) { + coerce_subset_input_double(zsfc,tmp_zsfc,index_zsfc,type_zsfc, + size_zsfc,0,NULL,NULL); + } + else { +/* + * Point tmp_zsfc to appropriate location in zsfc. + */ + tmp_zsfc = &((double*)zsfc)[index_zsfc]; + } + +/* + * If the pressure values need to be flipped, we also need to flip + * the z, q, and t values in the same fashion. + */ + if(flip) { + flip_it(tmp_p_orig,tmp_p,mkzh,size_zsfc); + flip_it(tmp_t_orig,tmp_t,mkzh,size_zsfc); + flip_it(tmp_q_orig,tmp_q,mkzh,size_zsfc); + flip_it(tmp_z_orig,tmp_z,mkzh,size_zsfc); + } + else { + tmp_p = tmp_p_orig; + tmp_t = tmp_t_orig; + tmp_q = tmp_q_orig; + tmp_z = tmp_z_orig; + } + +/* + * Call Fortran routine. + */ + NGCALLF(dcapecalc3d,DCAPECALC3D)(tmp_p, tmp_t, tmp_q, tmp_z, tmp_zsfc, + tmp_psfc, tmp_cape_orig, tmp_cin_orig, + &cmsg,&imiy, &imjx, &imkzh, &i3dflag, + &iter,psa_file,&errstat,errmsg, + strlen(psa_file),ERRLEN); + +/* Terminate if there was an error */ + if (errstat != 0) { + fprintf(stderr, errmsg); + exit(errstat); + } + +/* + * If we flipped arrays before going into the Fortran routine, we need + * to flip the output values as well. + */ + if(flip) { + flip_it(tmp_cape_orig,tmp_cape,mkzh,size_zsfc); + flip_it(tmp_cin_orig,tmp_cin,mkzh,size_zsfc); + } + else { + tmp_cape = tmp_cape_orig; + tmp_cin = tmp_cin_orig; + } +/* + * If the output is to be float, then do the coercion here. + */ + coerce_output_float_or_double(cape,tmp_cape,type_cape,size_cape,index_cape); + coerce_output_float_or_double(cape,tmp_cin,type_cape,size_cape,index_cin); + +/* + * Implement the pointers into the arrays. + */ + index_cape += size_cape; + index_cin += size_cape; + index_zsfc += size_zsfc; + } +/* + * Free memory. + */ + NclFree(tmp_p_orig); + NclFree(tmp_cape_orig); + NclFree(tmp_cin_orig); + if(type_t != NCL_double) NclFree(tmp_t_orig); + if(type_q != NCL_double) NclFree(tmp_q_orig); + if(type_z != NCL_double) NclFree(tmp_z_orig); + if(type_zsfc != NCL_double) NclFree(tmp_zsfc); + if(type_psfc != NCL_double) NclFree(tmp_psfc); + if(flip) { + NclFree(tmp_p); + NclFree(tmp_t); + NclFree(tmp_q); + NclFree(tmp_z); + NclFree(tmp_cape); + NclFree(tmp_cin); + } + NclFree(psa_file); + NclFree(errmsg); + +/* + * Get dimension info to see if we have named dimensions. + * This will be used for return variable. + */ + dim_info_t = get_wrf_dim_info(1,7,ndims_t,dsizes_t); + if(dim_info_t != NULL) { + dim_info = malloc(sizeof(NclDimRec)*ndims_cape); + if(dim_info == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_3d: Unable to allocate memory for holding dimension information"); + return(NhlFATAL); + } + for(i = 0; i < ndims_cape; i++ ) { + dim_info[i].dim_num = i; + dim_info[i].dim_size = dsizes_cape[i]; + if(i != 0) dim_info[i].dim_quark = dim_info_t[i-1].dim_quark; + else dim_info[0].dim_quark = NrmStringToQuark("cape_cin"); + } + } + + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)cape, + &missing_cape, + ndims_cape, + dsizes_cape, + TEMPORARY, + NULL, + type_obj_cape + ); + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + -1, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + + NclFree(dsizes_cape); + if(dim_info != NULL) NclFree(dim_info); + NclFree(dim_info_t); + +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); +} + + +/* + * The wrf_cape_2d wrapper is for the case where I3DFLAG is set to + * 0 in the Fortran rip_cape.f file. In this case, 4 2D arrays + * are returned: cape, cin, lcl, and lfc, but they are all returned + * in one big array whose leftmost dimension is 4: + * + * This wrapper is similar to rip_cape_2d except it will flip the first + * four input arrays if the pressure values are not decreasing. + * It will also multiple the pressure values by 0.01 to convert + * from hPa to Pa. + * + * index 0 = cape + * index 1 = cin + * index 2 = lcl + * index 3 = lfc + */ +NhlErrorTypes wrf_cape_2d_W( void ) +{ +/* + * Input array variables + */ + void *p, *t, *q, *z, *zsfc, *psfc; + logical *ter_follow; + double *tmp_p = NULL; + double *tmp_t = NULL; + double *tmp_q = NULL; + double *tmp_z = NULL; + double *tmp_zsfc = NULL; + double *tmp_psfc = NULL; + double *tmp_p_orig = NULL; + double *tmp_t_orig = NULL; + double *tmp_q_orig = NULL; + double *tmp_z_orig = NULL; + int ndims_p, ndims_t, ndims_q, ndims_z, ndims_zsfc, ndims_psfc; + ng_size_t dsizes_p[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_t[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_q[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_z[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_zsfc[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_psfc[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_p, type_t, type_q, type_z, type_zsfc, type_psfc; + +/* + * Output array variables + */ + void *cape; + double *tmp_cape, *tmp_cin, cmsg; + NclBasicDataTypes type_cape; + NclObjClass type_obj_cape; + int ndims_cape = 0; + NclScalar missing_cape; + ng_size_t *dsizes_cape; + +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info = NULL; + NclDimRec *dim_info_t; + +/* + * Variables for returning the output array with attributes and/or + * dimension names attached. + */ + NclMultiDValData return_md; + NclVar tmp_var; + NclStackEntry return_data; +/* + * Declare various variables for random purposes. + */ + ng_size_t i; + ng_size_t miy = 0; + ng_size_t mjx = 0; + ng_size_t mkzh = 0; + ng_size_t ntime = 0; + ng_size_t nz = 0; + ng_size_t size_cape, size_output, size_zsfc; + ng_size_t size_left_zsfc; + ng_size_t index_cape, index_zsfc; + ng_size_t index_output_cape, index_output_cin, index_output_lcl; + ng_size_t index_output_lfc, mkzh0_index, mkzh1_index, mkzh2_index; + int imiy, imjx, imkzh, iter, i3dflag=0; + char *psa_file; + logical flip; + int errstat; + char* errmsg; + +/* + * Retrieve parameters + * + * Note that any of the pointer parameters can be set to NULL, + * which implies you don't care about its value. + * + */ + p = (void*)NclGetArgValue( + 0, + 7, + &ndims_p, + dsizes_p, + NULL, + NULL, + &type_p, + DONT_CARE); + + t = (void*)NclGetArgValue( + 1, + 7, + &ndims_t, + dsizes_t, + NULL, + NULL, + &type_t, + DONT_CARE); + + + q = (void*)NclGetArgValue( + 2, + 7, + &ndims_q, + dsizes_q, + NULL, + NULL, + &type_q, + DONT_CARE); + + z = (void*)NclGetArgValue( + 3, + 7, + &ndims_z, + dsizes_z, + NULL, + NULL, + &type_z, + DONT_CARE); + + zsfc = (void*)NclGetArgValue( + 4, + 7, + &ndims_zsfc, + dsizes_zsfc, + NULL, + NULL, + &type_zsfc, + DONT_CARE); + + psfc = (void*)NclGetArgValue( + 5, + 7, + &ndims_psfc, + dsizes_psfc, + NULL, + NULL, + &type_psfc, + DONT_CARE); + + ter_follow = (logical*)NclGetArgValue( + 6, + 7, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + + if(*ter_follow) iter = 1; + else iter = 0; + + +/* + * Check the input dimension sizes. There are three possible cases + * for the input dimension sizes: + * + * - p,t,q,z (nz,time,lev,lat,lon) and psfc,zsfc (nz,time,lat,lon) + * - p,t,q,z (time,lev,lat,lon) and psfc,zsfc (time,lat,lon) + * - p,t,q,z (lev,lat,lon) and psfc,zsfc (lat,lon) + */ + if(ndims_p != ndims_t || ndims_p != ndims_q || ndims_p != ndims_z) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: The p, t, q, and z arrays must all have the same number of dimensions"); + return(NhlFATAL); + } + if(ndims_p != 3 && ndims_p != 4 && ndims_p != 5) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: The p, t, q, and z arrays must be 3-, 4- or 5-dimensional\n"); + return(NhlFATAL); + } +/* + * Check zsfc and psfc dimension sizes. + */ + if((ndims_zsfc != ndims_psfc) || (ndims_zsfc != ndims_p-1)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: The zsfc and psfc arrays must have the same number of dimensions and be one less dimension than the other input arrays"); + return(NhlFATAL); + } + +/* + * Now check that the dimension sizes are equal to each other. + */ + for(i = 0; i < ndims_p; i++) { + if(dsizes_p[i] != dsizes_t[i] || dsizes_p[i] != dsizes_q[i] || + dsizes_p[i] != dsizes_z[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: p, t, q, and z must be the same dimensionality"); + return(NhlFATAL); + } + } + + for(i = 0; i < ndims_psfc; i++) { + if(dsizes_psfc[i] != dsizes_zsfc[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: psfc and zsfc must be the same dimensionality"); + return(NhlFATAL); + } + } + if(ndims_p == 5) { +/* + * Store dimension sizes. + */ + nz = dsizes_p[0]; /* nz */ + ntime = dsizes_p[1]; /* time */ + mkzh = dsizes_p[2]; /* lev */ + mjx = dsizes_p[3]; /* lat */ + miy = dsizes_p[4]; /* lon */ + ndims_cape = 5; + if(dsizes_psfc[0] != nz || dsizes_psfc[1] != ntime || + dsizes_psfc[2] != mjx || dsizes_psfc[3] != miy) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: If p,q,t,z are 5-dimensional (nz x time x lev x lat x lon), psfc,zsfc must be 4-dimensional (nz x time x lat x lon)"); + return(NhlFATAL); + + } + } + else if(ndims_p == 4) { +/* + * Store dimension sizes. + */ + nz = 1; + ntime = dsizes_p[0]; /* time */ + mkzh = dsizes_p[1]; /* lev */ + mjx = dsizes_p[2]; /* lat */ + miy = dsizes_p[3]; /* lon */ + ndims_cape = 4; + if(dsizes_psfc[0] != ntime || dsizes_psfc[1] != mjx || + dsizes_psfc[2] != miy) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: If p,q,t,z are 4-dimensional (time x lev x lat x lon), psfc,zsfc must be 3-dimensional (time x lat x lon)"); + return(NhlFATAL); + + } + } + else if(ndims_p == 3) { +/* + * Store dimension sizes. + */ + nz = 1; + ntime = 1; + mkzh = dsizes_p[0]; /* lev */ + mjx = dsizes_p[1]; /* lat */ + miy = dsizes_p[2]; /* lon */ + ndims_cape = 3; + if(dsizes_psfc[0] != mjx || dsizes_psfc[1] != miy) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: If p,q,t,z are 3-dimensional (time x lev x lat x lon), psfc,zsfc must be 2-dimensional (lat x lon)"); + return(NhlFATAL); + } + } +/* + * If mkzh is not at least size 3, then this dimension won't be big + * enough to contain the cin, lcl, and lfc values. + */ + if(mkzh < 3) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: The level dimension must have at least 3 elements"); + return(NhlFATAL); + } + +/* + * Test input dimension sizes. + */ + if((miy > INT_MAX) || (mjx > INT_MAX) || (mkzh > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: one or more dimension sizes is greater than INT_MAX"); + return(NhlFATAL); + } + imiy = (int) miy; + imjx = (int) mjx; + imkzh = (int) mkzh; + + +/* + * Calculate size of output array. The output array size depends on + * the size of p,t,q,z: + * + * - p,t,q,z (nz,time,lev,lat,lon) and psfc,zsfc (nz,time,lat,lon) + * output array: (4,nz,time,lat,lon) + * - p,t,q,z (time,lev,lat,lon) and psfc,zsfc (time,lat,lon) + * output array: (4,time,lat,lon) + * - p,t,q,z (lev,lat,lon) and psfc,zsfc (lat,lon) + * output array: (4,lat,lon) + */ + dsizes_cape = (ng_size_t *)calloc(ndims_cape,sizeof(ng_size_t)); + if(dsizes_cape == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: Unable to allocate memory for array dimensionality"); + return(NhlFATAL); + } + + /* 0=cape, 1=cin, 2=lcl, 3=lfc */ + if(ndims_cape == 5) { + dsizes_cape[0] = 4; /* To hold the 4 different variables. */ + dsizes_cape[1] = nz; + dsizes_cape[2] = ntime; + dsizes_cape[3] = mjx; + dsizes_cape[4] = miy; + } + else if(ndims_cape == 4) { + dsizes_cape[0] = 4; /* To hold the 4 different variables. */ + dsizes_cape[1] = ntime; + dsizes_cape[2] = mjx; + dsizes_cape[3] = miy; + } + else if(ndims_cape == 3) { + dsizes_cape[0] = 4; /* To hold the 4 different variables. */ + dsizes_cape[1] = mjx; + dsizes_cape[2] = miy; + } + + size_zsfc = mjx * miy; + size_cape = mkzh * size_zsfc; + mkzh0_index = (mkzh-1) * size_zsfc; /* Indexes into cin array for */ + mkzh1_index = (mkzh-2) * size_zsfc; /* returning cin, lcl, and lfc */ + mkzh2_index = (mkzh-3) * size_zsfc; /* respectively. */ + size_left_zsfc = size_zsfc * ntime * nz; + size_output = 4 * size_left_zsfc; + +/* + * Allocate space for output and temporary arrays. Even if the input + * arrays are already double, go ahead and allocate some space for + * them b/c we have to copy the values back to 4 different locations. + * + * The addition of missing values was added in V6.1.0. + */ + if(type_p == NCL_double || type_t == NCL_double || type_q == NCL_double || + type_z == NCL_double) { + type_cape = NCL_double; + type_obj_cape = nclTypedoubleClass; + cape = (double *)calloc(size_output,sizeof(double)); + missing_cape.doubleval = ((NclTypeClass)nclTypedoubleClass)->type_class.default_mis.doubleval; + cmsg = missing_cape.doubleval; + } + else { + type_cape = NCL_float; + type_obj_cape = nclTypefloatClass; + cape = (float *)calloc(size_output,sizeof(float)); + missing_cape.floatval = ((NclTypeClass)nclTypefloatClass)->type_class.default_mis.floatval; + cmsg = (double)missing_cape.floatval; + } + tmp_cape = (double *)calloc(size_cape,sizeof(double)); + tmp_cin = (double *)calloc(size_cape,sizeof(double)); + if(cape == NULL || tmp_cape == NULL || tmp_cin == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: Unable to allocate memory for output arrays"); + return(NhlFATAL); + } + +/* + * Allocate memory for coercing input arrays to double, if necessary. + * + * Force a copy of variable p, because we need to multiply it by 0.01, + * and we don't want this to propagate back to the NCL script. + */ + tmp_p_orig = (double *)calloc(size_cape,sizeof(double)); + if(tmp_p_orig == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + + if(type_t != NCL_double) { + tmp_t_orig = (double *)calloc(size_cape,sizeof(double)); + if(tmp_t_orig == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_q != NCL_double) { + tmp_q_orig = (double *)calloc(size_cape,sizeof(double)); + if(tmp_q_orig == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_z != NCL_double) { + tmp_z_orig = (double *)calloc(size_cape,sizeof(double)); + if(tmp_z_orig == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_zsfc != NCL_double) { + tmp_zsfc = (double *)calloc(size_zsfc,sizeof(double)); + if(tmp_zsfc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + + if(type_psfc != NCL_double) { + tmp_psfc = (double *)calloc(size_zsfc,sizeof(double)); + if(tmp_psfc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: Unable to allocate memory for coercing input arrays to double"); + return(NhlFATAL); + } + } + +/* + * We need to coerce the pressure array once outside the loop to + * check if the values are in ascending order. + * + * If not, we need to flip the leftmost dimension (p = p(::-1,:,:) in + * NCL-ese), *and* flip the other 3 input arrays in the same fashion. + */ + coerce_subset_input_double(p,tmp_p_orig,0,type_p,size_cape,0,NULL,NULL); + + if(tmp_p_orig[0] > tmp_p_orig[(mkzh-1)*size_zsfc] ) { + flip = True; + tmp_p = (double *)calloc(size_cape,sizeof(double)); + tmp_t = (double *)calloc(size_cape,sizeof(double)); + tmp_q = (double *)calloc(size_cape,sizeof(double)); + tmp_z = (double *)calloc(size_cape,sizeof(double)); + + if(tmp_p == NULL || tmp_t == NULL || tmp_q == NULL || tmp_z == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: Unable to allocate memory for flipping arrays"); + return(NhlFATAL); + } + } + else { + flip = False; + tmp_p = tmp_p_orig; + tmp_t = tmp_t_orig; + tmp_q = tmp_q_orig; + tmp_z = tmp_z_orig; + } +/* + * Get path to psadilookup.dat file required by this routine. + */ + psa_file = get_psa_file(); + + /* Allocate space for errmsg*/ + errmsg = (char *) calloc(ERRLEN, sizeof(char)) + +/* + * Loop through time,nz and call the Fortran routine. + */ + index_cape = index_zsfc = 0; + index_output_cape = 0; + index_output_cin = size_left_zsfc; + index_output_lcl = 2 * size_left_zsfc; + index_output_lfc = 3 * size_left_zsfc; + + for(i = 0; i < ntime*nz; i++) { +/* + * Coerce subset of input arrays to double if necessary. + */ + if(i > 0) { + coerce_subset_input_double(p,tmp_p_orig,index_cape,type_p, + size_cape,0,NULL,NULL); + } +/* + * Multiple pressure values by 0.01 to convert from Pa to hPa. + * The assumption is that pressure values come in as Pa. + */ + convert_to_hPa(tmp_p_orig,size_cape); + + if(type_t != NCL_double) { + coerce_subset_input_double(t,tmp_t_orig,index_cape,type_t, + size_cape,0,NULL,NULL); + } + else { +/* + * Point tmp_t_orig to appropriate location in t. + */ + tmp_t_orig = &((double*)t)[index_cape]; + } + if(type_q != NCL_double) { + coerce_subset_input_double(q,tmp_q_orig,index_cape,type_q, + size_cape,0,NULL,NULL); + } + else { +/* + * Point tmp_q_orig to appropriate location in q. + */ + tmp_q_orig = &((double*)q)[index_cape]; + } + if(type_z != NCL_double) { + coerce_subset_input_double(z,tmp_z_orig,index_cape,type_z, + size_cape,0,NULL,NULL); + } + else { +/* + * Point tmp_z_orig to appropriate location in z. + */ + tmp_z_orig = &((double*)z)[index_cape]; + } + + if(type_psfc != NCL_double) { + coerce_subset_input_double(psfc,tmp_psfc,index_zsfc,type_psfc, + size_zsfc,0,NULL,NULL); + } + else { +/* + * Point tmp_psfc to appropriate location in psfc. + */ + tmp_psfc = &((double*)psfc)[index_zsfc]; + } + if(type_zsfc != NCL_double) { + coerce_subset_input_double(zsfc,tmp_zsfc,index_zsfc,type_zsfc, + size_zsfc,0,NULL,NULL); + } + else { +/* + * Point tmp_zsfc to appropriate location in zsfc. + */ + tmp_zsfc = &((double*)zsfc)[index_zsfc]; + } + +/* + * If the pressure values need to be flipped, we also need to flip + * the z, q, and t values in the same fashion. + */ + if(flip) { + flip_it(tmp_p_orig,tmp_p,mkzh,size_zsfc); + flip_it(tmp_t_orig,tmp_t,mkzh,size_zsfc); + flip_it(tmp_q_orig,tmp_q,mkzh,size_zsfc); + flip_it(tmp_z_orig,tmp_z,mkzh,size_zsfc); + } + else { + tmp_p = tmp_p_orig; + tmp_t = tmp_t_orig; + tmp_q = tmp_q_orig; + tmp_z = tmp_z_orig; + } + + errstat = 0; + errmsg = ""; +/* + * Call Fortran routine. + */ + NGCALLF(dcapecalc3d,DCAPECALC3D)(tmp_p, tmp_t, tmp_q, tmp_z, tmp_zsfc, + tmp_psfc, tmp_cape, tmp_cin, &cmsg, + &imiy, &imjx, &imkzh, &i3dflag, &iter, + psa_file,&errstat,errmsg,strlen(psa_file), + ERRLEN); + + /* Terminate if there was an error */ + if (errstat != 0) { + fprintf(stderr, errmsg); + exit(errstat); + } +/* + * Even if we flipped arrays before going into the Fortran routine, do + * NOT flip them on the output. + * + * Copy the values back out to the correct places in the "cape" array. + * + * This is a bit whacky, because the Fortran code is doing something + * fancy to save memory. The "tmp_cin" array contains the cin values in + * the last mkzh section, the lcl values in the 2nd-to-last mkzh + * section, and the lfc values in the 3rd-to-last mkzh section. + * + * The "tmp_cape" array contains its values in the last mkzh section + * of the tmp_cape array. + */ + coerce_output_float_or_double(cape,&tmp_cape[mkzh0_index],type_cape, + size_zsfc,index_output_cape); + coerce_output_float_or_double(cape,&tmp_cin[mkzh0_index],type_cape, + size_zsfc,index_output_cin); + coerce_output_float_or_double(cape,&tmp_cin[mkzh1_index],type_cape, + size_zsfc,index_output_lcl); + coerce_output_float_or_double(cape,&tmp_cin[mkzh2_index],type_cape, + size_zsfc,index_output_lfc); +/* + * Implement the pointers into the arrays. + */ + index_cape += size_cape; + index_zsfc += size_zsfc; + index_output_cape += size_zsfc; + index_output_cin += size_zsfc; + index_output_lcl += size_zsfc; + index_output_lfc += size_zsfc; + } +/* + * Free memory. + */ + NclFree(tmp_p_orig); + if(type_t != NCL_double) NclFree(tmp_t_orig); + if(type_q != NCL_double) NclFree(tmp_q_orig); + if(type_z != NCL_double) NclFree(tmp_z_orig); + if(type_zsfc != NCL_double) NclFree(tmp_zsfc); + if(type_psfc != NCL_double) NclFree(tmp_psfc); + NclFree(tmp_cape); + NclFree(tmp_cin); + if(flip) { + NclFree(tmp_p); + NclFree(tmp_t); + NclFree(tmp_q); + NclFree(tmp_z); + } + NclFree(psa_file); + NclFree(errmsg); + +/* + * Get dimension info to see if we have named dimensions. + * This will be used for return variable. + */ + dim_info_t = get_wrf_dim_info(1,7,ndims_t,dsizes_t); + if(dim_info_t != NULL) { + dim_info = malloc(sizeof(NclDimRec)*ndims_cape); + if(dim_info == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_cape_2d: Unable to allocate memory for holding dimension information"); + return(NhlFATAL); + } + for(i = 0; i < ndims_cape; i++ ) { + dim_info[i].dim_num = i; + dim_info[i].dim_size = dsizes_cape[i]; + } + dim_info[0].dim_quark = NrmStringToQuark("mcape_mcin_lcl_lfc"); + for(i = 0; i < ndims_t-3; i++) { + dim_info[i+1].dim_quark = dim_info_t[i].dim_quark; + } + dim_info[ndims_cape-2].dim_quark = dim_info_t[ndims_t-2].dim_quark; + dim_info[ndims_cape-1].dim_quark = dim_info_t[ndims_t-1].dim_quark; + + } + + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)cape, + &missing_cape, + ndims_cape, + dsizes_cape, + TEMPORARY, + NULL, + type_obj_cape + ); + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + -1, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + + NclFree(dsizes_cape); + if(dim_info != NULL) NclFree(dim_info); + NclFree(dim_info_t); + +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); +} + + +/* + * Retrieve the dimension name info of a particular + * input argument to a WRF NCL function. If there are + * no named dimensions, *and* you have at least a 2D + * array, then set the last two dimension names to + * "south_north" x "west_east". + */ +NclDimRec *get_wrf_dim_info(int arg_num,int num_args,int ndims_arg,ng_size_t *dsizes_arg) +{ + NclDimRec *dim_info; + int i, is_named; + + /* this is now separately malloced */ + dim_info = get_dim_info(arg_num,num_args); + + is_named = 0; + if(ndims_arg >= 2) { + if(dim_info != NULL) { +/* + * Check if we actually have any named dimensions. + */ + i = 0; + while(i < ndims_arg && !is_named ) { + if(dim_info[i++].dim_quark != -1) is_named = 1; + } + } + if(!is_named) { +/* + * If we are here, then we know we have no named dimensions, + * and hence need to create some. + */ + if(dim_info == NULL) { + dim_info = malloc(sizeof(NclDimRec)*ndims_arg); + if(dim_info == NULL) { + NhlPError(NhlWARNING,NhlEUNKNOWN,"wrf_get_dim_info: Unable to allocate memory for setting dimension names"); + return(NULL); + } + } + for(i = 0; i < ndims_arg; i++ ) { + dim_info[i].dim_num = i; + dim_info[i].dim_quark = -1; + dim_info[i].dim_size = dsizes_arg[i]; + } + dim_info[ndims_arg-2].dim_quark = NrmStringToQuark("south_north"); + dim_info[ndims_arg-1].dim_quark = NrmStringToQuark("west_east"); + } + } + return(dim_info); +} + +NhlErrorTypes wrf_eth_W( void ) +{ +/* + * Input variables + */ +/* + * Argument # 0 + */ + void *qv; + double *tmp_qv = NULL; + int ndims_qv; + ng_size_t dsizes_qv[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_qv; + +/* + * Argument # 1 + */ + void *t; + double *tmp_t = NULL; + int ndims_t; + ng_size_t dsizes_t[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_t; + +/* + * Argument # 2 + */ + void *p; + double *tmp_p = NULL; + int ndims_p; + ng_size_t dsizes_p[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_p; + +/* + * Return variable + */ + void *eth; + double *tmp_eth = NULL; + NclBasicDataTypes type_eth; + NclObjClass type_obj_eth; + NclQuark *description, *units; + char *cdescription, *cunits; + +/* + * Variables for returning the output array with dimension names attached. + */ + int att_id; + ng_size_t dsizes[1]; + NclMultiDValData return_md, att_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info; + +/* + * Various + */ + int btdim, sndim, wedim, nbtsnwe; + ng_size_t index_eth, i, size_leftmost, size_eth; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ +/* + * Get argument # 0 + */ + qv = (void*)NclGetArgValue( + 0, + 3, + &ndims_qv, + dsizes_qv, + NULL, + NULL, + &type_qv, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_qv < 3) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_eth: The qv array must have at least 3 dimensions"); + return(NhlFATAL); + } + btdim = dsizes_qv[ndims_qv-3]; + sndim = dsizes_qv[ndims_qv-2]; + wedim = dsizes_qv[ndims_qv-1]; + nbtsnwe = btdim * sndim * wedim; + +/* + * Get argument # 1 + */ + t = (void*)NclGetArgValue( + 1, + 3, + &ndims_t, + dsizes_t, + NULL, + NULL, + &type_t, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_t != ndims_qv) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_eth: The qv and t arrays must have the same number of dimensions"); + return(NhlFATAL); + } + +/* + * Get argument # 2 + */ + p = (void*)NclGetArgValue( + 2, + 3, + &ndims_p, + dsizes_p, + NULL, + NULL, + &type_p, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_p != ndims_qv) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_eth: The p and t arrays must have the same number of dimensions"); + return(NhlFATAL); + } + + for(i = 0; i < ndims_qv; i++) { + if(dsizes_t[i] != dsizes_qv[i] || dsizes_p[i] != dsizes_qv[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_eth: The qv, t, and p arrays must have the same dimension sizes"); + return(NhlFATAL); + } + } + +/* + * Calculate size of leftmost dimensions. + */ + size_leftmost = 1; + for(i = 0; i < ndims_qv-3; i++) size_leftmost *= dsizes_qv[i]; + +/* + * The output type defaults to float, unless any input arrays are double. + */ + type_eth = NCL_float; + type_obj_eth = nclTypefloatClass; + +/* + * Allocate space for coercing input arrays. If any of the input + * is already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * Allocate space for tmp_qv. + */ + if(type_qv != NCL_double) { + tmp_qv = (double *)calloc(nbtsnwe,sizeof(double)); + if(tmp_qv == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_eth: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_eth = NCL_double; + type_obj_eth = nclTypedoubleClass; + } +/* + * Allocate space for tmp_t. + */ + if(type_t != NCL_double) { + tmp_t = (double *)calloc(nbtsnwe,sizeof(double)); + if(tmp_t == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_eth: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_eth = NCL_double; + type_obj_eth = nclTypedoubleClass; + } +/* + * Allocate space for tmp_p. + */ + if(type_p != NCL_double) { + tmp_p = (double *)calloc(nbtsnwe,sizeof(double)); + if(tmp_p == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_eth: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_eth = NCL_double; + type_obj_eth = nclTypedoubleClass; + } + +/* + * Calculate size of output array and allocate space for it. + */ + size_eth = size_leftmost * nbtsnwe; + + if(type_eth != NCL_double) { + eth = (void *)calloc(size_eth, sizeof(float)); + tmp_eth = (double *)calloc(nbtsnwe,sizeof(double)); + if(tmp_eth == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_eth: Unable to allocate memory for temporary output array"); + return(NhlFATAL); + } + } + else { + eth = (void *)calloc(size_eth, sizeof(double)); + } + if(eth == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_eth: Unable to allocate memory for output array"); + return(NhlFATAL); + } + +/* + * Loop across leftmost dimensions and call the Fortran routine for each + * subsection of the input arrays. + */ + index_eth = 0; + + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of qv (tmp_qv) to double if necessary. + */ + if(type_qv != NCL_double) { + coerce_subset_input_double(qv,tmp_qv,index_eth,type_qv,nbtsnwe, + 0,NULL,NULL); + } + else { + tmp_qv = &((double*)qv)[index_eth]; + } + +/* + * Coerce subsection of t (tmp_t) to double if necessary. + */ + if(type_t != NCL_double) { + coerce_subset_input_double(t,tmp_t,index_eth,type_t,nbtsnwe, + 0,NULL,NULL); + } + else { + tmp_t = &((double*)t)[index_eth]; + } + +/* + * Coerce subsection of p (tmp_p) to double if necessary. + */ + if(type_p != NCL_double) { + coerce_subset_input_double(p,tmp_p,index_eth,type_p,nbtsnwe, + 0,NULL,NULL); + } + else { + tmp_p = &((double*)p)[index_eth]; + } + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_eth == NCL_double) tmp_eth = &((double*)eth)[index_eth]; + +/* + * Call the Fortran routine. + */ + NGCALLF(deqthecalc,DEQTHECALC)(tmp_qv, tmp_t, tmp_p, tmp_eth, + &wedim, &sndim, &btdim); + +/* + * Coerce output back to float if necessary. + */ + if(type_eth == NCL_float) { + coerce_output_float_only(eth,tmp_eth,nbtsnwe,index_eth); + } + index_eth += nbtsnwe; + } + +/* + * Free unneeded memory. + */ + if(type_qv != NCL_double) NclFree(tmp_qv); + if(type_t != NCL_double) NclFree(tmp_t); + if(type_p != NCL_double) NclFree(tmp_p); + if(type_eth != NCL_double) NclFree(tmp_eth); + +/* + * Retrieve dimension names from the "t" variable, if any. + * These dimension names will later be attached to the output variable. + */ + dim_info = get_wrf_dim_info(1,3,ndims_t,dsizes_t); + +/* + * Set up return value. + */ +/* + * Return value back to NCL script. + */ + + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)eth, + NULL, + ndims_t, + dsizes_t, + TEMPORARY, + NULL, + type_obj_eth + ); +/* + * Set up some attributes ("description" and "units") to return. + */ + cdescription = (char *)calloc(33,sizeof(char)); + strcpy(cdescription,"Equivalent Potential Temperature"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + free(cdescription); + + cunits = (char *)calloc(2,sizeof(char)); + strcpy(cunits,"K"); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *units = NrmStringToQuark(cunits); + free(cunits); + +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + + NclFree(dim_info); +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); + +} + +/* + * The wrf_wps_xxx_int functions that follow are for reading + * WRF WPS intermediate files. You can use wrf_wps_read_int + * as an "all-in-one" function that creates one 3D variable + * with all the data and attributes attached, or you can + * use the three individual functions, wrf_wps_open_int, + * wrf_wps_rdhead_int, and wrf_wps_rddata_int that allows you + * to read the data in one 2D slab at a time. + */ + +/* + * This function simply opens the WRF/WPS intermediate file + * and returns a status. + */ +NhlErrorTypes wrf_wps_open_int_W( void ) +{ + +/* + * Argument # 0 + */ + NrmQuark *filename; + char *cfilename; +/* + * Return variable + */ + int *istatus; + +/* + * Various + */ + int ret, ndims; + ng_size_t dsizes[1]; + +/* + * Get argument # 0 + */ + filename = (NrmQuark *)NclGetArgValue( + 0, + 1, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); +/* + * Convert to character string. + */ + cfilename = NrmQuarkToString(*filename); + +/* + * Allocate space for output array. + */ + ndims = 1; + dsizes[0] = 1; + + +/* + * Allocate return integer + */ + istatus = (int*)calloc(1, sizeof(int)); +/* + * Call the Fortran routine. + */ + NGCALLF(plotfmt_open,PLOTFMT_open)(cfilename, istatus, + strlen(cfilename)); + if(*istatus != 0) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wps_open_int: The input file '%s' could not be opened.\nCheck that it exists and is spelled correctly",cfilename); + return(NhlFATAL); + } +/* + * Return value back to NCL script. + */ + ret = NclReturnValue(istatus,ndims,dsizes,NULL,NCL_int,0); + return(ret); +} + +/* + * This function simply closes a WRF/WPS intermediate file + * that was opened with wrf_wps_open/rddata/rhead_int. + * Note that nothing is currently done with the istatus + * variable. This might change if we decide that + * istatus can contain a "unit" attribute that indicates + * which Fortran unit was used to open the file. + */ +NhlErrorTypes wrf_wps_close_int_W( void ) +{ + int *istatus; + + istatus = (int *)NclGetArgValue( + 0, + 1, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + + NGCALLF(plotfmt_close,PLOTFMT_CLOSE)(); + return(NhlNOERROR); + +} + + +/* + * This function takes an open WRF/WPS intermediate file, + * and reads header information. This header information + * then gives you the info needed to read the slab via + * wrf_wps_rddata_int. + */ +NhlErrorTypes wrf_wps_rdhead_int_W( void ) +{ + +/* + * Argument # 0 + */ + int *istatus; + +/* + * Argument # 1 + */ + void *head; + float *rhead; + NclBasicDataTypes type_head; + ng_size_t dsizes_head[1]; + +/* + * Argument # 2 + */ + NrmQuark *field; + char *cfield; + int FIELD_LEN=9; +/* + * Argument # 3 + */ + NrmQuark *hdate; + char *chdate; + int HDATE_LEN=24; + +/* + * Argument # 4 + */ + NrmQuark *units; + char *cunits; + int UNITS_LEN=25; + +/* + * Argument # 5 + */ + NrmQuark *mapsc; + char *cmapsc; + int MAPSC_LEN=32; + +/* + * Argument # 6 + */ + NrmQuark *desc; + char *cdesc; + int DESC_LEN=46; + +/* + * Various + */ + int i; + +/* + * Get argument #0 + */ + istatus = (int *)NclGetArgValue( + 0, + 7, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + +/* + * Get arguments # 1-6 + */ + head = (void *)NclGetArgValue( + 1, + 7, + NULL, + dsizes_head, + NULL, + NULL, + &type_head, + DONT_CARE); + + rhead = coerce_input_float(head, type_head, dsizes_head[0], 0, + NULL, NULL); + + field = (NrmQuark *)NclGetArgValue( + 2, + 7, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + hdate = (NrmQuark *)NclGetArgValue( + 3, + 7, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + units = (NrmQuark *)NclGetArgValue( + 4, + 7, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + mapsc = (NrmQuark *)NclGetArgValue( + 5, + 7, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + desc = (NrmQuark *)NclGetArgValue( + 6, + 7, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + +/* + * Allocate space needed for each string + */ + cfield = (char *)malloc((FIELD_LEN+1)*sizeof(char)); + chdate = (char *)malloc((HDATE_LEN+1)*sizeof(char)); + cunits = (char *)malloc((UNITS_LEN+1)*sizeof(char)); + cmapsc = (char *)malloc((MAPSC_LEN+1)*sizeof(char)); + cdesc = (char *)malloc((DESC_LEN+1)*sizeof(char)); +/* + * Call the Fortran routine. + */ + NGCALLF(plotfmt_rdhead,PLOTFMT_RDHEAD)(istatus,rhead,cfield,chdate, + cunits,cmapsc,cdesc, + FIELD_LEN,HDATE_LEN, + UNITS_LEN,MAPSC_LEN, + DESC_LEN); + +/* + * Strip off potential white space at end of each string. + */ + i = FIELD_LEN-1; + while(i >=0 && (cfield[i] == ' ' || cfield[i] == '\t')) i--; + cfield[i+1] = '\0'; + + i = HDATE_LEN-1; + while(i >= 0 && (chdate[i] == ' ' || chdate[i] == '\t')) i--; + chdate[i+1] = '\0'; + + i = UNITS_LEN-1; + while( i >= 0 && (cunits[i] == ' ' || cunits[i] == '\t')) i--; + cunits[i+1] = '\0'; + + i = MAPSC_LEN-1; + while( i >= 0 && (cmapsc[i] == ' ' || cmapsc[i] == '\t')) i--; + cmapsc[i+1] = '\0'; + + i = DESC_LEN-1; + while( i >= 0 && (cdesc[i] == ' ' || cdesc[i] == '\t')) i--; + cdesc[i+1] = '\0'; + + *field = NrmStringToQuark(cfield); + *hdate = NrmStringToQuark(chdate); + *units = NrmStringToQuark(cunits); + *mapsc = NrmStringToQuark(cmapsc); + *desc = NrmStringToQuark(cdesc); + + return(NhlNOERROR); +} + +/* + * This function takes an open WRF/WPS intermediate file, + * and reads a 2D slab. + */ +NhlErrorTypes wrf_wps_rddata_int_W( void ) +{ + +/* + * Argument # 0 + */ + int *istatus; + +/* + * Arguments #1-2 + */ + void *tmp_nx, *tmp_ny; + ng_size_t *nx, *ny; + NclBasicDataTypes type_nx, type_ny; + int inx, iny; + +/* + * Return + */ + float *slab; + ng_size_t dsizes[2]; + int ret; + +/* + * Get argument #0 + */ + istatus = (int *)NclGetArgValue( + 0, + 3, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + +/* + * Get arguments #1-2 + */ + tmp_nx = (void *)NclGetArgValue( + 1, + 3, + NULL, + NULL, + NULL, + NULL, + &type_nx, + DONT_CARE); + + tmp_ny = (void *)NclGetArgValue( + 2, + 3, + NULL, + NULL, + NULL, + NULL, + &type_ny, + DONT_CARE); + +/* + * Convert the input dimensions to ng_size_t. + */ + nx = get_dimensions(tmp_nx,1,type_nx,"wrf_wps_rddata_int"); + ny = get_dimensions(tmp_ny,1,type_ny,"wrf_wps_rddata_int"); + if(nx == NULL || ny == NULL) + return(NhlFATAL); + + if((*nx > INT_MAX) || (*ny > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wps_rddata_int: nx and/or ny is greater than INT_MAX"); + return(NhlFATAL); + } + inx = (int) *nx; + iny = (int) *ny; + + slab = (float*)calloc(inx*iny,sizeof(float)); + if(slab == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wps_rddata_int: Unable to allocate memory for output array"); + return(NhlFATAL); + } + +/* + * Call the Fortran routine. + */ + NGCALLF(plotfmt_rddata,PLOTFMT_RDDATA)(istatus,&inx,&iny,slab); + +/* + * Return value back to NCL script. + */ + dsizes[0] = *ny; + dsizes[1] = *nx; + ret = NclReturnValue(slab,2,dsizes,NULL,NCL_float,0); + return(ret); +} + + +/* + * This function is a "3-in-1" function that does the + * work of wrf_wps_open_int, wrf_wps_rdhead_int, and + * wrf_wps_rddata_int. It returns a 3D float array + * that contains all the necessary data and attributes. + * + */ +NhlErrorTypes wrf_wps_read_int_W( void ) +{ + +/* + * Argument # 0 + */ + NrmQuark *filename; + char *cfilename; + +/* + * Return values. The slab will be returned, along with a bunch + * of attributes depending on the projection. + */ + int NHEAD=14, FIELD_LEN=9, HDATE_LEN=24, UNITS_LEN=25; + int MAPSC_LEN=32, DESCR_LEN=46; + float *slab, *rhead, *slab_s; + float rhead_s[NHEAD]; + ng_size_t dsizes_slab[3], dsizes_rhead[2], dsizes_field[1], dsizes_hdate[1]; + ng_size_t dsizes_units[1], dsizes_mapsc[1], dsizes_descr[1]; + NrmQuark *field, *hdate, *units, *mapsc, *descr; + char *cfield, *chdate, *cunits, *cmapsc, *cdescr; + NclScalar missing_slab; +/* + * Various + */ + int i, j, n, istatus, nx, ny, nxny, max_nx, max_ny, nfields; + int index_slab, index_rhead; + +/* + * Attribute variables + */ + int att_id; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + + +/* + * Get argument #0 + */ + filename = (NrmQuark *)NclGetArgValue( + 0, + 1, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + +/* + * Convert to character string. + */ + cfilename = NrmQuarkToString(*filename); + +/* + * Call the Fortran routine to open the file + */ + NGCALLF(plotfmt_open,PLOTFMT_open)(cfilename, &istatus, + strlen(cfilename)); + if(istatus != 0) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wps_read_int: The input file '%s' could not be opened.\nCheck that it exists and is spelled correctly",cfilename); + return(NhlFATAL); + } + + cfield = (char *)malloc((FIELD_LEN+1)*sizeof(char)); + chdate = (char *)malloc((HDATE_LEN+1)*sizeof(char)); + cunits = (char *)malloc((UNITS_LEN+1)*sizeof(char)); + cmapsc = (char *)malloc((MAPSC_LEN+1)*sizeof(char)); + cdescr = (char *)malloc((DESCR_LEN+1)*sizeof(char)); + +/* + * Read each field so we can count how many there are. + */ + nfields = 0; + while (istatus == 0) { + /* Read the header */ + + NGCALLF(plotfmt_rdhead,PLOTFMT_RDHEAD)(&istatus,&rhead_s[0],cfield, + chdate,cunits,cmapsc,cdescr, + FIELD_LEN,HDATE_LEN, + UNITS_LEN,MAPSC_LEN, + DESCR_LEN); + + if(istatus == 0) { + nx = (int)rhead_s[3]; + ny = (int)rhead_s[4]; + slab_s = (float*)calloc(nx*ny,sizeof(float)); + if(slab_s == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wps_read_int: Unable to allocate memory for output array"); + return(NhlFATAL); + } + if(nfields == 0) { + max_nx = nx; + max_ny = ny; + } + else { + max_nx = max(max_nx,nx); + max_ny = max(max_ny,ny); + } + /* Read the data */ + NGCALLF(plotfmt_rddata,PLOTFMT_RDDATA)(&istatus,&nx,&ny,slab_s); + NclFree(slab_s); + if(istatus == 0) nfields++; + } + } + nxny = max_nx * max_ny; + + /* Allocate the return arrays */ + rhead = (float*)calloc(nfields*NHEAD,sizeof(float)); + slab = (float*)calloc(nfields*nxny,sizeof(float)); + field = (NclQuark*)NclMalloc(nfields*sizeof(NclQuark)); + hdate = (NclQuark*)NclMalloc(nfields*sizeof(NclQuark)); + units = (NclQuark*)NclMalloc(nfields*sizeof(NclQuark)); + mapsc = (NclQuark*)NclMalloc(nfields*sizeof(NclQuark)); + descr = (NclQuark*)NclMalloc(nfields*sizeof(NclQuark)); + + if(rhead == NULL || slab == NULL || field == NULL || hdate == NULL || + units == NULL || mapsc == NULL || descr == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wps_read_int: Unable to allocate memory for output array and attributes"); + return(NhlFATAL); + } + + /* Close and reopen file. */ + NGCALLF(plotfmt_close,PLOTFMT_CLOSE)(); + NGCALLF(plotfmt_open,PLOTFMT_open)(cfilename, &istatus, + strlen(cfilename)); + + missing_slab.floatval = -1e30; + index_slab = index_rhead = 0; + + /* Now loop through again and fill up the output arrays */ + + for(n = 0; n < nfields; n++) { + + /* Read the header into allocated arrays */ + NGCALLF(plotfmt_rdhead,PLOTFMT_RDHEAD)(&istatus,&rhead[index_rhead], + cfield,chdate,cunits, + cmapsc,cdescr, + FIELD_LEN,HDATE_LEN, + UNITS_LEN,MAPSC_LEN, + DESCR_LEN); +/* + * Strip off potential white space at end of each string. + */ + i = FIELD_LEN-1; + while(i >=0 && (cfield[i] == ' ' || + cfield[i] == '\t')) i--; + cfield[i+1] = '\0'; + + i = HDATE_LEN-1; + while(i >= 0 && (chdate[i] == ' ' || + chdate[i] == '\t')) i--; + chdate[i+1] = '\0'; + + i = UNITS_LEN-1; + while( i >= 0 && (cunits[i] == ' ' || + cunits[i] == '\t')) i--; + cunits[i+1] = '\0'; + + i = MAPSC_LEN-1; + while( i >= 0 && (cmapsc[i] == ' ' || + cmapsc[i] == '\t')) i--; + cmapsc[i+1] = '\0'; + + i = DESCR_LEN-1; + while( i >= 0 && (cdescr[i] == ' ' || + cdescr[i] == '\t')) i--; + cdescr[i+1] = '\0'; + + field[n] = NrmStringToQuark(cfield); + hdate[n] = NrmStringToQuark(chdate); + units[n] = NrmStringToQuark(cunits); + mapsc[n] = NrmStringToQuark(cmapsc); + descr[n] = NrmStringToQuark(cdescr); + +/* + * We have to get nx and ny every time in the loop, because they + * can be different sizes. + */ + nx = (int)rhead[index_rhead+3]; + ny = (int)rhead[index_rhead+4]; + slab_s = (float*)calloc(nx*ny,sizeof(float)); + if(slab_s == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wps_read_int: Unable to allocate memory for output array"); + return(NhlFATAL); + } + /* Read data into temporary array */ + NGCALLF(plotfmt_rddata,PLOTFMT_RDDATA)(&istatus,&nx,&ny,&slab_s[0]); + + /* Copy slab subset back out to big slab array */ + for(i = 0; i < ny; i++) { + for(j = 0; j < nx; j++) { + slab[index_slab+(i*max_nx)+j] = slab_s[(i*nx)+j]; + } + /* Fill rest with missing values */ + for(j = nx; j < max_nx; j++) { + slab[index_slab+(i*max_nx)+j] = missing_slab.floatval; + } + } + + /* For next time through loop */ + index_slab += nxny; + index_rhead += NHEAD; + } + + /* Close the file. */ + NGCALLF(plotfmt_close,PLOTFMT_CLOSE)(); + + /* Free memory */ + free(slab_s); + free(cfield); + free(chdate); + free(cunits); + free(cmapsc); + free(cdescr); + +/* + * Return slab and attributes back to NCL script. + */ + dsizes_slab[0] = nfields; + dsizes_slab[1] = max_ny; + dsizes_slab[2] = max_nx; + dsizes_rhead[0] = nfields; + dsizes_rhead[1] = NHEAD; + dsizes_field[0] = nfields; + dsizes_hdate[0] = nfields; + dsizes_units[0] = nfields; + dsizes_mapsc[0] = nfields; + dsizes_descr[0] = nfields; + + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)slab, + &missing_slab, + 3, + dsizes_slab, + TEMPORARY, + NULL, + nclTypefloatClass + ); +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)field, + NULL, + 1, + dsizes_field, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "field", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)hdate, + NULL, + 1, + dsizes_hdate, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "hdate", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes_units, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)mapsc, + NULL, + 1, + dsizes_mapsc, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "map_source", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)descr, + NULL, + 1, + dsizes_descr, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)rhead, + NULL, + 2, + dsizes_rhead, + TEMPORARY, + NULL, + nclTypefloatClass + ); + + _NclAddAtt( + att_id, + "rhead", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + NULL, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + + return(NhlNOERROR); +} + + +/* + * This next section contains wrappers for wrf_bint and wrf_iclw. + * These wrappers have never been tested or documented, and are + * not registered in wrapper.c. I've let them here in case we need + * to resuscitate them. + */ + + +NhlErrorTypes wrf_wps_read_nml_W( void ) +{ + +/* + * Argument # 0 + */ + NrmQuark *namelist; + char *cnamelist; +/* + * Return variable + */ + float *pgrids_var; + int size_output, ndims_output; + ng_size_t dsizes_output[2]; + NclScalar missing_output; + +/* + * Various + */ + int NVAR=19, MAX_DOMAINS=21; + int ret; +/* + * Get argument # 0 + */ + namelist = (NrmQuark *)NclGetArgValue( + 0, + 1, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); +/* + * Convert to character string. + */ + cnamelist = NrmQuarkToString(*namelist); + +/* + * Allocate space for output array. + */ + ndims_output = 2; + dsizes_output[0] = MAX_DOMAINS; + dsizes_output[1] = NVAR; + size_output = NVAR*MAX_DOMAINS; + pgrids_var = (float*)calloc(size_output, sizeof(float)); + if(pgrids_var == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wps_read_nml: Unable to allocate memory for output array"); + return(NhlFATAL); + } + missing_output.floatval = -999.; + +/* + * Call the Fortran routine. + */ + NGCALLF(plotgrids_var,PLOTGRIDS_VAR)(cnamelist, pgrids_var, + strlen(cnamelist)); +/* + * Return value back to NCL script. + */ + ret = NclReturnValue(pgrids_var,ndims_output,dsizes_output, + &missing_output,NCL_float,0); + return(ret); +} + +NhlErrorTypes wrf_bint_W( void ) +{ +/* + * Input array variables + */ + void *data_in, *obsii, *obsjj; + double *tmp_data_in = NULL; + double *tmp_obsii = NULL; + double *tmp_obsjj = NULL; + + int *icrs, *jcrs; + int ndims_data_in, ndims_obsii, ndims_obsjj; + ng_size_t dsizes_data_in[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_obsii[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_obsjj[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_data_in, type_obsii, type_obsjj; + +/* + * Output variable. + */ + void *data_out; + double *tmp_data_out = NULL; + ng_size_t *dsizes_data_out, size_data_out; + NclBasicDataTypes type_data_out; +/* + * Various + */ + int ret; + ng_size_t i, nx, ny, nz, nobsicrs, nobsjcrs, size_leftmost; + ng_size_t nxyz, nobsij, nobsijz, index_data_in, index_data_out, index_nobsij; + int inx, iny, inz, inobsicrs, inobsjcrs; +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ + data_in = (void*)NclGetArgValue( + 0, + 5, + &ndims_data_in, + dsizes_data_in, + NULL, + NULL, + &type_data_in, + DONT_CARE); + + obsii = (void*)NclGetArgValue( + 1, + 5, + &ndims_obsii, + dsizes_obsii, + NULL, + NULL, + &type_obsii, + DONT_CARE); + + obsjj = (void*)NclGetArgValue( + 2, + 5, + &ndims_obsjj, + dsizes_obsjj, + NULL, + NULL, + &type_obsjj, + DONT_CARE); + + icrs = (int*)NclGetArgValue( + 3, + 5, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + + jcrs = (int*)NclGetArgValue( + 4, + 5, + NULL, + NULL, + NULL, + NULL, + NULL, + DONT_CARE); + +/* + * Error checking. + */ + if(ndims_data_in < 2 || ndims_obsii < 2 || ndims_obsjj < 2) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_bint: The data_in, obsii, and obsjj arrays must have at least two dimensions"); + return(NhlFATAL); + } + if(ndims_obsii != ndims_obsjj) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_bint: The obsii and obsjj arrays must have the same number of dimensions"); + return(NhlFATAL); + } + if((ndims_data_in == 2 && ndims_obsii != 2) || + (ndims_data_in > 2 && ndims_data_in != (ndims_obsii+1))) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_bint: The data_in, obsii, and obsjj arrays must all be two-dimensional, or data_in must be greater than two dimensions and have one more dimension than obsii and obsjj"); + return(NhlFATAL); + } + for(i = 0; i < ndims_obsii; i++) { + if(dsizes_obsii[i] != dsizes_obsjj[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_bint: The obsii and obsjj arrays must be the same dimension sizes"); + return(NhlFATAL); + } + } + +/* + * If data_in is greater than 3 dimensions, then check that these + * extra dimensions are all the same length in the three input + * arrays. + * + * While we're here, calculate the size of the leftmost dimensions. + */ + size_leftmost = 1; + if(ndims_data_in > 3) { + for(i = 0; i < ndims_data_in-3; i++) { + if(dsizes_data_in[i] != dsizes_obsii[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_bint: The rightmost dimensions of data_in, obsii, obsjj must be the same"); + return(NhlFATAL); + } + size_leftmost *= dsizes_data_in[i]; + } + } + +/* + * Store some dimension sizes and output data array sizes. + */ + nx = dsizes_data_in[ndims_data_in-1]; + ny = dsizes_data_in[ndims_data_in-2]; + if(ndims_data_in > 2) { + nz = dsizes_data_in[ndims_data_in-3]; + } + else { + nz = 1; + } + nobsicrs = dsizes_obsii[ndims_obsii-1]; + nobsjcrs = dsizes_obsii[ndims_obsii-2]; + nxyz = nx * ny * nz; + nobsij = nobsicrs * nobsjcrs; + nobsijz = nobsij * nz; + + size_data_out = size_leftmost * nobsijz; + +/* + * Test input dimension sizes. + */ + if((nx > INT_MAX) || (ny > INT_MAX) || (nobsicrs > INT_MAX) || + (nobsjcrs > INT_MAX) || (nz > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_bint: one or more dimension sizes is greater than INT_MAX"); + return(NhlFATAL); + } + inx = (int) nx; + iny = (int) ny; + inz = (int) nz; + inobsicrs = (int) nobsicrs; + inobsjcrs = (int) nobsjcrs; + +/* + * Allocate space for coercing input arrays. If the input data_in, obsii, + * or obsjj are already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * The output type defaults to float, unless any of the input arrays + * are double. + */ + type_data_out = NCL_float; + if(type_data_in != NCL_double) { + tmp_data_in = (double *)calloc(nxyz,sizeof(double)); + if(tmp_data_in == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_bint: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_data_out = NCL_double; + } + + if(type_obsii != NCL_double) { + tmp_obsii = (double *)calloc(nobsij,sizeof(double)); + if(tmp_obsii == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_bint: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_data_out = NCL_double; + } + + if(type_obsjj != NCL_double) { + tmp_obsjj = (double *)calloc(nobsij,sizeof(double)); + if(tmp_obsjj == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_bint: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_data_out = NCL_double; + } + +/* + * Allocate space for output array. + */ + if(type_data_out == NCL_double) { + data_out = (double *)calloc(size_data_out,sizeof(double)); + if(data_out == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_bint: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + else { + data_out = (float *)calloc(size_data_out,sizeof(float)); + tmp_data_out = (double *)calloc(nobsijz,sizeof(double)); + if(tmp_data_out == NULL || data_out == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_bint: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + +/* + * Create dimension sizes for output array. + */ + dsizes_data_out = (ng_size_t*)calloc(ndims_data_in,sizeof(ng_size_t)); + if( dsizes_data_out == NULL ) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_bint: Unable to allocate memory for holding dimension sizes"); + return(NhlFATAL); + } + for(i = 1; i < ndims_data_in-2; i++) dsizes_data_out[i] = dsizes_data_in[i]; + dsizes_data_out[ndims_data_in-2] = nobsjcrs; + dsizes_data_out[ndims_data_in-1] = nobsicrs; +/* + * Loop across leftmost dimensions and call the Fortran routine for each + * one-dimensional subsection. + */ + index_data_in = index_data_out = index_nobsij = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of data_in (tmp_data_in) to double if necessary. + */ + if(type_data_in != NCL_double) { + coerce_subset_input_double(data_in,tmp_data_in,index_data_in, + type_data_in,nxyz,0,NULL,NULL); + } + else { + tmp_data_in = &((double*)data_in)[index_data_in]; + } +/* + * Coerce subsection of obsii (tmp_obsii) to double if ncessary. + */ + if(type_obsii != NCL_double) { + coerce_subset_input_double(obsii,tmp_obsii,index_nobsij,type_obsii, + nobsij,0,NULL,NULL); + } + else { + tmp_obsii = &((double*)obsii)[index_nobsij]; + } + +/* + * Coerce subsection of obsjj (tmp_obsjj) to double if ncessary. + */ + if(type_obsjj != NCL_double) { + coerce_subset_input_double(obsjj,tmp_obsjj,index_nobsij,type_obsjj, + nobsij,0,NULL,NULL); + } + else { + tmp_obsjj = &((double*)obsjj)[index_nobsij]; + } + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_data_out == NCL_double) { + tmp_data_out = &((double*)data_out)[index_data_out]; + } +/* + * Call Fortran routine. + */ + NGCALLF(dbint3d,DBINT3D)(tmp_data_out,tmp_obsii,tmp_obsjj,tmp_data_in, + &inx,&iny,&inz,&inobsicrs,&inobsjcrs,icrs,jcrs); +/* + * Coerce output back to float if necessary. + */ + if(type_data_out == NCL_float) { + coerce_output_float_only(data_out,tmp_data_out,nobsijz,index_data_out); + } + +/* + * Increment indices. + */ + index_data_in += nxyz; + index_data_out += nobsijz; + index_nobsij += nobsij; + } +/* + * Free up memory. + */ + if(type_data_in != NCL_double) NclFree(tmp_data_in); + if(type_obsii != NCL_double) NclFree(tmp_obsii); + if(type_obsjj != NCL_double) NclFree(tmp_obsjj); + if(type_data_out != NCL_double) NclFree(tmp_data_out); + + ret = NclReturnValue(data_out,ndims_data_in,dsizes_data_out,NULL, + type_data_out,0); + NclFree(dsizes_data_out); + return(ret); +} + + +NhlErrorTypes wrf_iclw_W( void ) +{ + +/* + * Input variables + */ +/* + * Argument # 0 + */ + void *p; + double *tmp_p = NULL; + int ndims_p; + ng_size_t dsizes_p[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_p; + +/* + * Argument # 1 + */ + void *qc; + double *tmp_qc = NULL; + int ndims_qc; + ng_size_t dsizes_qc[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_qc; + +/* + * Return variable + */ + void *iclw; + NclQuark *description, *units; + char *cdescription, *cunits; + double *tmp_iclw = NULL; + int ndims_iclw; + ng_size_t *dsizes_iclw; + NclBasicDataTypes type_iclw; + NclObjClass type_obj_iclw; +/* + * Variables for returning the output array with attributes attached. + */ + int att_id; + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Various + */ + ng_size_t nz, ny, nx, nznynx, nynx; + ng_size_t index_p, index_iclw; + ng_size_t i, ndims_leftmost, size_leftmost, size_output; + int inx, iny, inz; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ +/* + * Get argument # 0 + */ + p = (void*)NclGetArgValue( + 0, + 2, + &ndims_p, + dsizes_p, + NULL, + NULL, + &type_p, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_p < 3) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_iclw: The p array must have at least 3 dimensions"); + return(NhlFATAL); + } + nz = dsizes_p[ndims_p-3]; + ny = dsizes_p[ndims_p-2]; + nx = dsizes_p[ndims_p-1]; + nynx = ny * nx; + nznynx = nz * nynx; + +/* + * Test dimension sizes. + */ + if((nx > INT_MAX) || (ny > INT_MAX) || (nz > INT_MAX)) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_iclw: nx, ny and/or is greater than INT_MAX"); + return(NhlFATAL); + } + inx = (int) nx; + iny = (int) ny; + inz = (int) nz; + +/* + * Get argument # 1 + */ + qc = (void*)NclGetArgValue( + 1, + 2, + &ndims_qc, + dsizes_qc, + NULL, + NULL, + &type_qc, + DONT_CARE); + +/* + * Check dimension sizes. + */ + if(ndims_qc < 3) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_iclw: The qc array must have at least 3 dimensions"); + return(NhlFATAL); + } + + if(dsizes_qc[ndims_qc-3] != nz || + dsizes_qc[ndims_qc-2] != ny || + dsizes_qc[ndims_qc-1] != nx) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_iclw: The rightmost dimensions of qc must be nz x ny x nx"); + return(NhlFATAL); + } + +/* + * Calculate size of leftmost dimensions. + */ + size_leftmost = 1; + ndims_leftmost = ndims_p-3; + for(i = 0; i < ndims_leftmost; i++) { + if(dsizes_qc[i] != dsizes_p[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_iclw: The leftmost dimensions of p and qc must be the same"); + return(NhlFATAL); + } + size_leftmost *= dsizes_p[i]; + } + +/* + * The output type defaults to float, unless either input array is double. + */ + type_iclw = NCL_float; + type_obj_iclw = nclTypefloatClass; + +/* + * Allocate space for coercing input arrays. If any of the input + * is already double, then we don't need to allocate space for + * temporary arrays, because we'll just change the pointer into + * the void array appropriately. + */ +/* + * Allocate space for tmp_p. + */ + if(type_p != NCL_double) { + tmp_p = (double *)calloc(nznynx,sizeof(double)); + if(tmp_p == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_iclw: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_iclw = NCL_double; + type_obj_iclw = nclTypedoubleClass; + } +/* + * Allocate space for tmp_qc. + */ + if(type_qc != NCL_double) { + tmp_qc = (double *)calloc(nznynx,sizeof(double)); + if(tmp_qc == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_iclw: Unable to allocate memory for coercing input array to double"); + return(NhlFATAL); + } + } + else { + type_iclw = NCL_double; + type_obj_iclw = nclTypedoubleClass; + } + +/* + * Calculate size of output array. + */ + size_output = size_leftmost * nynx; + +/* + * Allocate space for output array. + */ + if(type_iclw != NCL_double) { + iclw = (void *)calloc(size_output, sizeof(float)); + tmp_iclw = (double *)calloc(nynx,sizeof(double)); + if(tmp_iclw == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_iclw: Unable to allocate memory for temporary output array"); + return(NhlFATAL); + } + } + else { + iclw = (void *)calloc(size_output, sizeof(double)); + } + if(iclw == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_iclw: Unable to allocate memory for output array"); + return(NhlFATAL); + } + +/* + * Allocate space for output dimension sizes and set them. + */ + ndims_iclw = ndims_leftmost + 2; + dsizes_iclw = (ng_size_t*)calloc(ndims_iclw,sizeof(ng_size_t)); + if( dsizes_iclw == NULL ) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_iclw: Unable to allocate memory for holding dimension sizes"); + return(NhlFATAL); + } + for(i = 0; i < ndims_iclw-2; i++) dsizes_iclw[i] = dsizes_p[i]; + dsizes_iclw[ndims_iclw-2] = ny; + dsizes_iclw[ndims_iclw-1] = nx; + +/* + * Loop across leftmost dimensions and call the Fortran routine for each + * subsection of the input arrays.. + */ + index_p = index_iclw = 0; + + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of p (tmp_p) to double if necessary. + */ + if(type_p != NCL_double) { + coerce_subset_input_double(p,tmp_p,index_p,type_p,nznynx,0,NULL,NULL); + } + else { + tmp_p = &((double*)p)[index_p]; + } + +/* + * Coerce subsection of qc (tmp_qc) to double if necessary. + */ + if(type_qc != NCL_double) { + coerce_subset_input_double(qc,tmp_qc,index_p,type_qc,nznynx,0,NULL,NULL); + } + else { + tmp_qc = &((double*)qc)[index_p]; + } +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_iclw == NCL_double) tmp_iclw = &((double*)iclw)[index_iclw]; + +/* + * Call the Fortran routine. + */ + NGCALLF(dcomputeiclw,DCOMPUTEICLW)(tmp_iclw, tmp_p, tmp_qc, &inx, &iny, &inz); +/* + * Coerce output back to float if necessary. + */ + if(type_iclw == NCL_float) { + coerce_output_float_only(iclw,tmp_iclw,nynx,index_iclw); + } + index_p += nznynx; + index_iclw += nynx; + } + +/* + * Free unneeded memory. + */ + if(type_p != NCL_double) NclFree(tmp_p); + if(type_qc != NCL_double) NclFree(tmp_qc); + if(type_iclw != NCL_double) NclFree(tmp_iclw); + +/* + * Set up some attributes ("description" and "units") to return. + */ + cdescription = (char *)calloc(16,sizeof(char)); + cunits = (char *)calloc(3,sizeof(char)); + strcpy(cdescription,"Int Cloud Water"); + strcpy(cunits,"mm"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + *units = NrmStringToQuark(cunits); + free(cdescription); + free(cunits); + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)iclw, + NULL, + ndims_iclw, + dsizes_iclw, + TEMPORARY, + NULL, + type_obj_iclw + ); + +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + NULL, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + NclFree(dsizes_iclw); +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); + +} + +NhlErrorTypes wrf_wetbulb_W( void ) +{ +/* + * Input array variables + */ + void *prs, *tmk, *qvp; + double *tmp_prs = NULL; + double *tmp_tmk = NULL; + double *tmp_qvp = NULL; + int ndims_prs, ndims_tmk, ndims_qvp; + ng_size_t dsizes_prs[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_tmk[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_qvp[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_prs, type_tmk, type_qvp; +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info; + +/* + * Output variable and attributes. + */ + void *twb; + NclQuark *description, *units; + char *cdescription, *cunits; + double *tmp_twb = NULL; + NclBasicDataTypes type_twb; + NclObjClass type_obj_twb; +/* + * Various + */ + ng_size_t i, nx, ny, nz, nxyz, size_leftmost, index_prs, size_twb; + int inx, iny, inz; + char *psa_file; + +/* + * Variables for returning the output array with attributes attached. + */ + int att_id; + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ + prs = (void*)NclGetArgValue( + 0, + 3, + &ndims_prs, + dsizes_prs, + NULL, + NULL, + &type_prs, + DONT_CARE); + + tmk = (void*)NclGetArgValue( + 1, + 3, + &ndims_tmk, + dsizes_tmk, + NULL, + NULL, + &type_tmk, + DONT_CARE); + + qvp = (void*)NclGetArgValue( + 2, + 3, + &ndims_qvp, + dsizes_qvp, + NULL, + NULL, + &type_qvp, + DONT_CARE); +/* + * Error checking. Input variables must be same size. + */ + if(ndims_prs < 3 || ndims_prs != ndims_tmk || ndims_prs != ndims_qvp ) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wetbulb: The prs, tmk, and qvp arrays must have at least 3 dimensions and have the same number of dimensions as each other"); + return(NhlFATAL); + } + for(i = 0; i < ndims_prs; i++) { + if(dsizes_prs[i] != dsizes_tmk[i] || dsizes_prs[i] != dsizes_qvp[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wetbulb: prs, tmk, and qvp must be the same dimensionality"); + return(NhlFATAL); + } + } + +/* + * Test dimension sizes. + */ + nz = dsizes_prs[ndims_prs-1]; + ny = dsizes_prs[ndims_prs-2]; + nx = dsizes_prs[ndims_prs-3]; + + if(nx > INT_MAX) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wetbulb: nx = %ld is greater than INT_MAX", nx); + return(NhlFATAL); + } + if(ny > INT_MAX) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wetbulb: ny = %ld is greater than INT_MAX", ny); + return(NhlFATAL); + } + if(nz > INT_MAX) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wetbulb: nz = %ld is greater than INT_MAX", nz); + return(NhlFATAL); + } + inx = (int) nx; + iny = (int) ny; + inz = (int) nz; + +/* + * Retrieve dimension names from the "tmk" variable, if any. + * These dimension names will later be attached to the output variable. + */ + dim_info = get_wrf_dim_info(1,3,ndims_tmk,dsizes_tmk); + +/* + * Calculate size of leftmost dimensions. + */ + size_leftmost = 1; + for(i = 0; i < ndims_prs-3; i++) size_leftmost *= dsizes_prs[i]; + nxyz = nx * ny * nz; + size_twb = size_leftmost * nxyz; + +/* + * Allocate space for coercing input arrays. If the input prs, tmk, + * or qvp are already double, then we don't need to allocate space + * for temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * The output type defaults to float, unless any of the input arrays + * are double. + */ + type_twb = NCL_float; + type_obj_twb = nclTypefloatClass; + if(type_prs != NCL_double) { + tmp_prs = (double *)calloc(nxyz,sizeof(double)); + if(tmp_prs == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wetbulb: Unable to allocate memory for coercing 'prs' array to double"); + return(NhlFATAL); + } + } + else { + type_twb = NCL_double; + type_obj_twb = nclTypedoubleClass; + } + + if(type_tmk != NCL_double) { + tmp_tmk = (double *)calloc(nxyz,sizeof(double)); + if(tmp_tmk == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wetbulb: Unable to allocate memory for coercing 'tmk' to double"); + return(NhlFATAL); + } + } + else { + type_twb = NCL_double; + type_obj_twb = nclTypedoubleClass; + } + + if(type_qvp != NCL_double) { + tmp_qvp = (double *)calloc(nxyz,sizeof(double)); + if(tmp_qvp == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wetbulb: Unable to allocate memory for coercing 'qvp' to double"); + return(NhlFATAL); + } + } + else { + type_twb = NCL_double; + type_obj_twb = nclTypedoubleClass; + } + +/* + * Allocate space for output array. + */ + if(type_twb == NCL_double) { + twb = (double *)calloc(size_twb,sizeof(double)); + if(twb == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wetbulb: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + else { + twb = (float *)calloc(size_twb,sizeof(float)); + tmp_twb = (double *)calloc(nxyz,sizeof(double)); + if(tmp_twb == NULL || twb == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_wetbulb: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } +/* + * Get path to psadilookup.dat file required by this routine. + */ + psa_file = get_psa_file(); + +/* + * Loop across leftmost dimensions and call the Fortran routine for each + * three-dimensional subsection. + */ + index_prs = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of p (tmp_prs) to double if necessary. + */ + if(type_prs != NCL_double) { + coerce_subset_input_double(prs,tmp_prs,index_prs,type_prs, + nxyz,0,NULL,NULL); + } + else { + tmp_prs = &((double*)prs)[index_prs]; + } +/* + * Coerce subsection of tmk (tmp_tmk) to double if ncessary. + */ + if(type_tmk != NCL_double) { + coerce_subset_input_double(tmk,tmp_tmk,index_prs,type_tmk, + nxyz,0,NULL,NULL); + } + else { + tmp_tmk = &((double*)tmk)[index_prs]; + } + +/* + * Coerce subsection of qvp (tmp_qvp) to double if ncessary. + */ + if(type_qvp != NCL_double) { + coerce_subset_input_double(qvp,tmp_qvp,index_prs,type_qvp, + nxyz,0,NULL,NULL); + } + else { + tmp_qvp = &((double*)qvp)[index_prs]; + } + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_twb == NCL_double) tmp_twb = &((double*)twb)[index_prs]; +/* + * Call Fortran routine. + */ + NGCALLF(wetbulbcalc,WETBULBCALC)(tmp_prs,tmp_tmk,tmp_qvp,tmp_twb, + &inx,&iny,&inz,psa_file, + strlen(psa_file)); + +/* + * Coerce output back to float if necessary. + */ + if(type_twb == NCL_float) { + coerce_output_float_only(twb,tmp_twb,nxyz,index_prs); + } + + index_prs += nxyz; /* Increment index */ + } +/* + * Free up memory. + */ + if(type_prs != NCL_double) NclFree(tmp_prs); + if(type_tmk != NCL_double) NclFree(tmp_tmk); + if(type_qvp != NCL_double) NclFree(tmp_qvp); + if(type_twb != NCL_double) NclFree(tmp_twb); + NclFree(psa_file); + +/* + * Set up some attributes ("description" and "units") to return. + */ + cdescription = (char *)calloc(21,sizeof(char)); + strcpy(cdescription,"Wet Bulb Temperature"); + cunits = (char *)calloc(2,sizeof(char)); + strcpy(cunits,"C"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + *units = NrmStringToQuark(cunits); + free(cunits); + free(cdescription); +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)twb, + NULL, + ndims_prs, + dsizes_prs, + TEMPORARY, + NULL, + type_obj_twb + ); +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + + NclFree(dim_info); +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); +} + + +NhlErrorTypes wrf_omega_W( void ) +{ +/* + * Input array variables + */ + void *qvp, *tmk, *www, *prs; + double *tmp_qvp = NULL; + double *tmp_tmk = NULL; + double *tmp_www = NULL; + double *tmp_prs = NULL; + int ndims_qvp, ndims_tmk, ndims_www, ndims_prs; + ng_size_t dsizes_qvp[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_tmk[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_www[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_prs[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_qvp, type_tmk, type_www, type_prs; +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info; + +/* + * Output variable and attributes. + */ + void *omg; + NclQuark *description, *units; + char *cdescription, *cunits; + double *tmp_omg = NULL; + NclBasicDataTypes type_omg; + NclObjClass type_obj_omg; +/* + * Various + */ + ng_size_t i, nx, ny, nz, nxyz, size_leftmost, index_qvp, size_omg; + int inx, iny, inz; + +/* + * Variables for returning the output array with attributes attached. + */ + int att_id; + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ + qvp = (void*)NclGetArgValue( + 0, + 4, + &ndims_qvp, + dsizes_qvp, + NULL, + NULL, + &type_qvp, + DONT_CARE); + + tmk = (void*)NclGetArgValue( + 1, + 4, + &ndims_tmk, + dsizes_tmk, + NULL, + NULL, + &type_tmk, + DONT_CARE); + + www = (void*)NclGetArgValue( + 2, + 4, + &ndims_www, + dsizes_www, + NULL, + NULL, + &type_www, + DONT_CARE); + + prs = (void*)NclGetArgValue( + 3, + 4, + &ndims_prs, + dsizes_prs, + NULL, + NULL, + &type_prs, + DONT_CARE); + +/* + * Error checking. Input variables must be same size. + */ + if(ndims_qvp < 3 || ndims_qvp != ndims_tmk || ndims_qvp != ndims_www || + ndims_qvp != ndims_prs) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_omega: qvp, tmk, www, and prs must have at least 3 dimensions and have the same number of dimensions as each other"); + return(NhlFATAL); + } + for(i = 0; i < ndims_qvp; i++) { + if(dsizes_qvp[i] != dsizes_tmk[i] || dsizes_qvp[i] != dsizes_prs[i] || dsizes_qvp[i] != dsizes_www[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_omega: qvp, tmk, www, and prs must be the same dimensionality"); + return(NhlFATAL); + } + } + +/* + * Test dimension sizes. + */ + nz = dsizes_qvp[ndims_qvp-1]; + ny = dsizes_qvp[ndims_qvp-2]; + nx = dsizes_qvp[ndims_qvp-3]; + + if(nx > INT_MAX) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_omega: nx = %ld is greater than INT_MAX", nx); + return(NhlFATAL); + } + if(ny > INT_MAX) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_omega: ny = %ld is greater than INT_MAX", ny); + return(NhlFATAL); + } + if(nz > INT_MAX) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_omega: nz = %ld is greater than INT_MAX", nz); + return(NhlFATAL); + } + inx = (int) nx; + iny = (int) ny; + inz = (int) nz; + +/* + * Retrieve dimension names from the "tmk" variable, if any. + * These dimension names will later be attached to the output variable. + */ + dim_info = get_wrf_dim_info(1,3,ndims_tmk,dsizes_tmk); + +/* + * Calculate size of leftmost dimensions. + */ + size_leftmost = 1; + for(i = 0; i < ndims_qvp-3; i++) size_leftmost *= dsizes_qvp[i]; + nz = dsizes_qvp[ndims_qvp-1]; + ny = dsizes_qvp[ndims_qvp-2]; + nx = dsizes_qvp[ndims_qvp-3]; + nxyz = nx * ny * nz; + size_omg = size_leftmost * nxyz; + +/* + * Allocate space for coercing input arrays. If the input qvp, tmk, + * www, prs are already double, then we don't need to allocate space + * for temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * The output type defaults to float, unless any of the input arrays + * are double. + */ + type_omg = NCL_float; + type_obj_omg = nclTypefloatClass; + + if(type_qvp != NCL_double) { + tmp_qvp = (double *)calloc(nxyz,sizeof(double)); + if(tmp_qvp == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_omega: Unable to allocate memory for coercing 'qvp' to double"); + return(NhlFATAL); + } + } + else { + type_omg = NCL_double; + type_obj_omg = nclTypedoubleClass; + } + + if(type_tmk != NCL_double) { + tmp_tmk = (double *)calloc(nxyz,sizeof(double)); + if(tmp_tmk == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_omega: Unable to allocate memory for coercing 'tmk' to double"); + return(NhlFATAL); + } + } + else { + type_omg = NCL_double; + type_obj_omg = nclTypedoubleClass; + } + + if(type_www != NCL_double) { + tmp_www = (double *)calloc(nxyz,sizeof(double)); + if(tmp_www == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_omega: Unable to allocate memory for coercing 'www' to double"); + return(NhlFATAL); + } + } + else { + type_omg = NCL_double; + type_obj_omg = nclTypedoubleClass; + } + + if(type_prs != NCL_double) { + tmp_prs = (double *)calloc(nxyz,sizeof(double)); + if(tmp_prs == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_omega: Unable to allocate memory for coercing 'prs' array to double"); + return(NhlFATAL); + } + } + else { + type_omg = NCL_double; + type_obj_omg = nclTypedoubleClass; + } +/* + * Allocate space for output array. + */ + if(type_omg == NCL_double) { + omg = (double *)calloc(size_omg,sizeof(double)); + if(omg == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_omega: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + else { + omg = (float *)calloc(size_omg,sizeof(float)); + tmp_omg = (double *)calloc(nxyz,sizeof(double)); + if(tmp_omg == NULL || omg == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_omega: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + +/* + * Loop across leftmost dimensions and call the Fortran routine for each + * three-dimensional subsection. + */ + index_qvp = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of qvp (tmp_qvp) to double if ncessary. + */ + if(type_qvp != NCL_double) { + coerce_subset_input_double(qvp,tmp_qvp,index_qvp,type_qvp, + nxyz,0,NULL,NULL); + } + else { + tmp_qvp = &((double*)qvp)[index_qvp]; + } + +/* + * Coerce subsection of tmk (tmp_tmk) to double if ncessary. + */ + if(type_tmk != NCL_double) { + coerce_subset_input_double(tmk,tmp_tmk,index_qvp,type_tmk, + nxyz,0,NULL,NULL); + } + else { + tmp_tmk = &((double*)tmk)[index_qvp]; + } + +/* + * Coerce subsection of www (tmp_www) to double if ncessary. + */ + if(type_www != NCL_double) { + coerce_subset_input_double(www,tmp_www,index_qvp,type_www, + nxyz,0,NULL,NULL); + } + else { + tmp_www = &((double*)www)[index_qvp]; + } + +/* + * Coerce subsection of p (tmp_prs) to double if necessary. + */ + if(type_prs != NCL_double) { + coerce_subset_input_double(prs,tmp_prs,index_qvp,type_prs, + nxyz,0,NULL,NULL); + } + else { + tmp_prs = &((double*)prs)[index_qvp]; + } +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_omg == NCL_double) tmp_omg = &((double*)omg)[index_qvp]; +/* + * Call Fortran routine. + */ + NGCALLF(omgcalc,OMGCALC)(tmp_qvp,tmp_tmk,tmp_www,tmp_prs,tmp_omg, + &inx,&iny,&inz); + +/* + * Coerce output back to float if necessary. + */ + if(type_omg == NCL_float) { + coerce_output_float_only(omg,tmp_omg,nxyz,index_qvp); + } + + index_qvp += nxyz; /* Increment index */ + } + +/* + * Free up memory. + */ + if(type_qvp != NCL_double) NclFree(tmp_qvp); + if(type_tmk != NCL_double) NclFree(tmp_tmk); + if(type_www != NCL_double) NclFree(tmp_www); + if(type_prs != NCL_double) NclFree(tmp_prs); + if(type_omg != NCL_double) NclFree(tmp_omg); + +/* + * Set up some attributes ("description" and "units") to return. + */ + cdescription = (char *)calloc(6,sizeof(char)); + strcpy(cdescription,"Omega"); + cunits = (char *)calloc(5,sizeof(char)); + strcpy(cunits,"Pa/s"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + *units = NrmStringToQuark(cunits); + free(cunits); + free(cdescription); + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)omg, + NULL, + ndims_qvp, + dsizes_qvp, + TEMPORARY, + NULL, + type_obj_omg + ); +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + + NclFree(dim_info); +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); + } + + +NhlErrorTypes wrf_virtual_temp_W( void ) +{ +/* + * Input array variables + */ + void *temp, *ratmx; + double *tmp_temp = NULL; + double *tmp_ratmx = NULL; + int ndims_temp, ndims_ratmx; + ng_size_t dsizes_temp[NCL_MAX_DIMENSIONS]; + ng_size_t dsizes_ratmx[NCL_MAX_DIMENSIONS]; + NclBasicDataTypes type_temp, type_ratmx; +/* + * Variable for getting/setting dimension name info. + */ + NclDimRec *dim_info; + +/* + * Output variable and attributes. + */ + void *tv; + NclQuark *description, *units; + char *cdescription, *cunits; + double *tmp_tv = NULL; + NclBasicDataTypes type_tv; + NclObjClass type_obj_tv; +/* + * Various + */ + ng_size_t i, nx, ny, nz, nxyz, size_leftmost, index_temp, size_tv; + int inx, iny, inz; + +/* + * Variables for returning the output array with attributes attached. + */ + int att_id; + ng_size_t dsizes[1]; + NclMultiDValData att_md, return_md; + NclVar tmp_var; + NclStackEntry return_data; + +/* + * Retrieve parameters. + * + * Note any of the pointer parameters can be set to NULL, which + * implies you don't care about its value. + */ + temp = (void*)NclGetArgValue( + 0, + 2, + &ndims_temp, + dsizes_temp, + NULL, + NULL, + &type_temp, + DONT_CARE); + + ratmx = (void*)NclGetArgValue( + 1, + 2, + &ndims_ratmx, + dsizes_ratmx, + NULL, + NULL, + &type_ratmx, + DONT_CARE); +/* + * Error checking. Input variables must be same size. + */ + if(ndims_temp < 3 || ndims_temp != ndims_ratmx) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_virtual_temp: The temp and ratmx arrays must have at least 3 dimensions and have the same number of dimensions as each other"); + return(NhlFATAL); + } + for(i = 0; i < ndims_temp; i++) { + if(dsizes_temp[i] != dsizes_ratmx[i]) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_virtual_temp: temp and ratmx must be the same dimensionality"); + return(NhlFATAL); + } + } + +/* + * Test dimension sizes. + */ + nx = dsizes_temp[ndims_temp-1]; + ny = dsizes_temp[ndims_temp-2]; + nz = dsizes_temp[ndims_temp-3]; + + if(nx > INT_MAX) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_virtual_temp: nx = %ld is greater than INT_MAX", nx); + return(NhlFATAL); + } + if(ny > INT_MAX) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_virtual_temp: ny = %ld is greater than INT_MAX", ny); + return(NhlFATAL); + } + if(nz > INT_MAX) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_virtual_temp: nz = %ld is greater than INT_MAX", nz); + return(NhlFATAL); + } + inx = (int) nx; + iny = (int) ny; + inz = (int) nz; + +/* + * Retrieve dimension names from the "temp" variable, if any. + * These dimension names will later be attached to the output variable. + */ + dim_info = get_wrf_dim_info(1,3,ndims_temp,dsizes_temp); + +/* + * Calculate size of leftmost dimensions. + */ + size_leftmost = 1; + for(i = 0; i < ndims_temp-3; i++) size_leftmost *= dsizes_temp[i]; + nxyz = nx * ny * nz; + size_tv = size_leftmost * nxyz; + +/* + * Allocate space for coercing input arrays. If the input temp + * or ratmx are already double, then we don't need to allocate space + * for temporary arrays, because we'll just change the pointer into + * the void array appropriately. + * + * The output type defaults to float, unless any of the input arrays + * are double. + */ + type_tv = NCL_float; + type_obj_tv = nclTypefloatClass; + + if(type_temp != NCL_double) { + tmp_temp = (double *)calloc(nxyz,sizeof(double)); + if(tmp_temp == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_virtual_temp: Unable to allocate memory for coercing 'temp' to double"); + return(NhlFATAL); + } + } + else { + type_tv = NCL_double; + type_obj_tv = nclTypedoubleClass; + } + + if(type_ratmx != NCL_double) { + tmp_ratmx = (double *)calloc(nxyz,sizeof(double)); + if(tmp_ratmx == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_virtual_temp: Unable to allocate memory for coercing 'ratmx' to double"); + return(NhlFATAL); + } + } + else { + type_tv = NCL_double; + type_obj_tv = nclTypedoubleClass; + } + +/* + * Allocate space for output array. + */ + if(type_tv == NCL_double) { + tv = (double *)calloc(size_tv,sizeof(double)); + if(tv == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_virtual_temp: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } + else { + tv = (float *)calloc(size_tv,sizeof(float)); + tmp_tv = (double *)calloc(nxyz,sizeof(double)); + if(tmp_tv == NULL || tv == NULL) { + NhlPError(NhlFATAL,NhlEUNKNOWN,"wrf_virtual_temp: Unable to allocate memory for output array"); + return(NhlFATAL); + } + } +/* + * Loop across leftmost dimensions and call the Fortran routine for each + * three-dimensional subsection. + */ + index_temp = 0; + for(i = 0; i < size_leftmost; i++) { +/* + * Coerce subsection of temp (tmp_temp) to double if ncessary. + */ + if(type_temp != NCL_double) { + coerce_subset_input_double(temp,tmp_temp,index_temp,type_temp, + nxyz,0,NULL,NULL); + } + else { + tmp_temp = &((double*)temp)[index_temp]; + } + +/* + * Coerce subsection of ratmx (tmp_ratmx) to double if ncessary. + */ + if(type_ratmx != NCL_double) { + coerce_subset_input_double(ratmx,tmp_ratmx,index_temp,type_ratmx, + nxyz,0,NULL,NULL); + } + else { + tmp_ratmx = &((double*)ratmx)[index_temp]; + } + +/* + * Point temporary output array to void output array if appropriate. + */ + if(type_tv == NCL_double) tmp_tv = &((double*)tv)[index_temp]; +/* + * Call Fortran routine. + */ + NGCALLF(virtual_temp,VIRTUAL_TEMP)(tmp_temp,tmp_ratmx,tmp_tv, + &inx,&iny,&inz); + +/* + * Coerce output back to float if necessary. + */ + if(type_tv == NCL_float) { + coerce_output_float_only(tv,tmp_tv,nxyz,index_temp); + } + + index_temp += nxyz; /* Increment index */ + } +/* + * Free up memory. + */ + if(type_temp != NCL_double) NclFree(tmp_temp); + if(type_ratmx != NCL_double) NclFree(tmp_ratmx); + if(type_tv != NCL_double) NclFree(tmp_tv); + +/* + * Set up some attributes ("description" and "units") to return. + */ + cdescription = (char *)calloc(20,sizeof(char)); + strcpy(cdescription,"Virtual Temperature"); + cunits = (char *)calloc(2,sizeof(char)); + strcpy(cunits,"K"); + description = (NclQuark*)NclMalloc(sizeof(NclQuark)); + units = (NclQuark*)NclMalloc(sizeof(NclQuark)); + *description = NrmStringToQuark(cdescription); + *units = NrmStringToQuark(cunits); + free(cunits); + free(cdescription); + +/* + * Set up return value. + */ + return_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)tv, + NULL, + ndims_temp, + dsizes_temp, + TEMPORARY, + NULL, + type_obj_tv + ); +/* + * Set up attributes to return. + */ + att_id = _NclAttCreate(NULL,NULL,Ncl_Att,0,NULL); + + dsizes[0] = 1; + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)description, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "description", + att_md, + NULL + ); + + att_md = _NclCreateVal( + NULL, + NULL, + Ncl_MultiDValData, + 0, + (void*)units, + NULL, + 1, + dsizes, + TEMPORARY, + NULL, + (NclObjClass)nclTypestringClass + ); + _NclAddAtt( + att_id, + "units", + att_md, + NULL + ); + + tmp_var = _NclVarCreate( + NULL, + NULL, + Ncl_Var, + 0, + NULL, + return_md, + dim_info, + att_id, + NULL, + RETURNVAR, + NULL, + TEMPORARY + ); + + NclFree(dim_info); +/* + * Return output grid and attributes to NCL. + */ + return_data.kind = NclStk_VAR; + return_data.u.data_var = tmp_var; + _NclPlaceReturn(return_data); + return(NhlNOERROR); +} + + + +/* + * This routine gets the path to the psadilookup.dat file + * required by some WRF routines. + * + * The default is to use $NCARG_ROOT/lib/ncarg/data/asc/psadilookup.dat + * for the input data file, unless PSADILOOKUP_PATH is set by the + * user, then it will try to use this path. + */ +char *get_psa_file() +{ + const char *path = NULL; + char *psa_file; + int path_len; + + path = getenv("PSADILOOKUP_PATH"); + if ((void *)path == (void *)NULL) { + path = _NGGetNCARGEnv("data"); + if ((void *)path != (void *)NULL) { + path_len = strlen(path) + 21; /* 21 = "/asc/psadilookup.dat\0" */ + psa_file = malloc(path_len*sizeof(char)); + strcpy(psa_file,path); + strcat(psa_file,_NhlPATHDELIMITER); + strcat(psa_file,"asc"); + } + } + else { + strcpy(psa_file,path); + path_len = strlen(path) + 17; /* 17 = "/psadilookup.dat\0" */ + psa_file = malloc(path_len*sizeof(char)); + } + strcat(psa_file,_NhlPATHDELIMITER); + strcat(psa_file,"psadilookup.dat"); + strcat(psa_file,"\0"); + return(psa_file); +} + +/* + * This routine sets all values of var < 0 to 0.0. This is + * so you don't have to do this in the NCL script. It's the + * equivalent of: + * + * tmp_var = tmp_var > 0.0 + * + */ +void var_zero(double *tmp_var, ng_size_t n) +{ + ng_size_t i; + + for(i = 0; i < n; i++) { + if(tmp_var[i] < 0.0) tmp_var[i] = 0.0; + } +} + + +/* Converts from hPa to Pa. */ + +void convert_to_hPa(double *pp, ng_size_t np) +{ + ng_size_t i; + for(i = 0; i < np; i++) pp[i] *= 0.01; +} + + +/* + * This procedure flips the given double array in the + * leftmost dimension, given the size of the leftmost + * dimension, and the product of the rightmost two dimensions. + */ +void flip_it(double *tmp_from, double *tmp_to, ng_size_t nz, ng_size_t nynx) +{ + ng_size_t i, index_from, index_to, size_copy; + + size_copy = nynx*sizeof(double); + for(i = 0; i < nz; i++) { + index_from = (i * nynx) * sizeof(double); + index_to = ((nz-1-i) * nynx) * sizeof(double); + (void *)memcpy((void*)((char*)tmp_to) + index_to, + (void*)((char*)tmp_from) + index_from,size_copy); + } +} diff --git a/fortran/wrf_fctt.f90 b/fortran/wrf_fctt.f90 new file mode 100644 index 0000000..ebcb07f --- /dev/null +++ b/fortran/wrf_fctt.f90 @@ -0,0 +1,125 @@ +!NCLFORTSTART +SUBROUTINE wrfcttcalc(prs, tk, qci, qcw, qvp, ght, ter, ctt, haveqci, ew, ns, nz) + USE constants, ONLY : EPS, USSALR, RD, G, ABSCOEFI, ABSCOEF, CELKEL + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: ctt + + INTEGER, INTENT(IN) :: nz, ns, ew, haveqci + REAL(KIND=8), DIMENSION(ew,ns,nz), INTENT(IN) :: ght, prs, tk, qci, qcw, qvp + REAL(KIND=8), DIMENSION(ew,ns), INTENT(IN) :: ter + REAL(KIND=8), DIMENSION(ew,ns), INTENT(OUT) :: ctt + +!NCLEND + + ! REAL(KIND=8) :: znfac(nz) + + ! LOCAL VARIABLES + INTEGER i,j,k,ripk + !INTEGER :: mjx,miy,mkzh + REAL(KIND=8) :: vt,opdepthu,opdepthd,dp + REAL(KIND=8) :: ratmix,arg1,arg2,agl_hgt + REAL(KIND=8) :: fac,prsctt + !REAL(KIND=8) :: eps,ussalr,rgas,grav,abscoefi,abscoef,celkel,wrfout + !REAL(KIND=8) :: ght(ew,ns,nz),stuff(ew,ns) + !REAL(KIND=8), DIMENSION(ew,ns,nz) :: pf(ns,ew,nz),p1,p2 + REAL(KIND=8), DIMENSION(ew,ns,nz) :: pf + REAL(KIND=8) :: p1, p2 + + !mjx = ew + !miy = ns + !mkzh = nz + + prsctt = 0 ! removes the warning + +! Calculate the surface pressure + DO j=1,ns + DO i=1,ew + ratmix = .001d0*qvp(i,j,1) + arg1 = EPS + ratmix + arg2 = EPS * (1. + ratmix) + vt = tk(i,j,1) * arg1/arg2 !Virtual temperature + agl_hgt = ght(i,j,nz) - ter(i,j) + arg1 = -G / (RD * USSALR) + pf(i,j,nz) = prs(i,j,1) * (vt / (vt + USSALR*(agl_hgt)))**(arg1) + END DO + END DO + + DO k=1,nz-1 + DO j=1,ns + DO i=1,ew + ripk = nz-k+1 + pf(i,j,k) = .5d0 * (prs(i,j,ripk) + prs(i,j,ripk-1)) + END DO + END DO + END DO + + DO j=1,ns + DO i=1,ew + opdepthd = 0.d0 + k = 0 + +! Integrate downward from model top, calculating path at full +! model vertical levels. + +!20 opdepthu=opdepthd + + DO k=1, nz + opdepthu = opdepthd + !k=k+1 + ripk = nz - k + 1 + + IF (k .EQ. 1) THEN + dp = 200.d0 * (pf(i,j,1) - prs(i,j,nz)) ! should be in Pa + ELSE + dp = 100.d0 * (pf(i,j,k) - pf(i,j,k-1)) ! should be in Pa + END IF + + IF (haveqci .EQ. 0) then + IF (tk(i,j,k) .LT. CELKEL) then + ! Note: abscoefi is m**2/g, qcw is g/kg, so no convrsion needed + opdepthd = opdepthu + ABSCOEFI*qcw(i,j,k) * dp/G + ELSE + opdepthd = opdepthu + ABSCOEF*qcw(i,j,k) * dp/G + END IF + ELSE + opdepthd = opdepthd + (ABSCOEF*qcw(i,j,ripk) + ABSCOEFI*qci(i,j,ripk)) * dp/G + END IF + + IF (opdepthd .LT. 1. .AND. k .LT. nz) THEN + !GOTO 20 + CYCLE + + ELSE IF (opdepthd .LT. 1. .AND. k .EQ. nz) THEN + prsctt = prs(i,j,1) + EXIT + ELSE + fac = (1. - opdepthu) / (opdepthd - opdepthu) + prsctt = pf(i,j,k-1) + fac*(pf(i,j,k) - pf(i,j,k-1)) + prsctt = MIN(prs(i,j,1), MAX(prs(i,j,nz), prsctt)) + EXIT + END IF + END DO + + DO k=2,nz + ripk = nz-k+1 + p1 = prs(i,j,ripk+1) + p2 = prs(i,j,ripk) + IF (prsctt .GE. p1 .AND. prsctt .LE. p2) THEN + fac = (prsctt - p1) / (p2 - p1) + arg1 = fac * (tk(i,j,ripk) - tk(i,j,ripk+1)) - CELKEL + ctt(i,j) = tk(i,j,ripk+1) + arg1 + !GOTO 40 + EXIT + END IF + END DO + END DO + END DO +! 30 CONTINUE +! 40 CONTINUE +! 190 CONTINUE + RETURN + +END SUBROUTINE wrfcttcalc diff --git a/fortran/wrf_pvo.f90 b/fortran/wrf_pvo.f90 new file mode 100644 index 0000000..a810edc --- /dev/null +++ b/fortran/wrf_pvo.f90 @@ -0,0 +1,122 @@ +!NCLFORTSTART +SUBROUTINE DCOMPUTEABSVORT(av, u, v, msfu, msfv, msft, cor, dx, dy, nx, ny, nz,& + nxp1, nyp1) + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: av + + INTEGER, INTENT(IN) :: nx, ny, nz, nxp1, nyp1 + REAL(KIND=8), DIMENSION(nxp1,ny,nz), INTENT(IN) :: u + REAL(KIND=8), DIMENSION(nx,nyp1,nz), INTENT(IN) :: v + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(OUT) :: av + REAL(KIND=8), DIMENSION(nxp1,ny), INTENT(IN):: msfu + REAL(KIND=8), DIMENSION(nx,nyp1), INTENT(IN) :: msfv + REAL(KIND=8), DIMENSION(nx,ny), INTENT(IN) :: msft + REAL(KIND=8), DIMENSION(nx,ny), INTENT(IN) :: cor + REAL(KIND=8) :: dx, dy + +!NCLEND + + INTEGER :: jp1, jm1, ip1, im1, i, j, k + REAL(KIND=8) :: dsy, dsx, dudy, dvdx, avort + REAL(KIND=8) :: mm + + ! PRINT*,'nx,ny,nz,nxp1,nyp1' + ! PRINT*,nx,ny,nz,nxp1,nyp1 + DO k = 1,nz + DO j = 1,ny + jp1 = MIN(j+1, ny) + jm1 = MAX(j-1, 1) + DO i = 1,nx + ip1 = MIN(i+1, nx) + im1 = MAX(i-1, 1) + ! PRINT *,jp1,jm1,ip1,im1 + dsx = (ip1 - im1) * dx + dsy = (jp1 - jm1) * dy + mm = msft(i,j)*msft(i,j) + ! PRINT *,j,i,u(i,jp1,k),msfu(i,jp1),u(i,jp1,k)/msfu(i,jp1) + dudy = 0.5D0 * (u(i,jp1,k)/msfu(i,jp1) + u(i+1,jp1,k)/msfu(i+1,jp1) - & + u(i,jm1,k)/msfu(i,jm1) - u(i+1,jm1,k)/msfu(i+1,jm1))/dsy*mm + dvdx = 0.5D0 * (v(ip1,j,k)/msfv(ip1,j) + v(ip1,j+1,k)/msfv(ip1,j+1) - & + v(im1,j,k)/msfv(im1,j) - v(im1,j+1,k)/msfv(im1,j+1))/dsx*mm + avort = dvdx - dudy + cor(i,j) + av(i,j,k) = avort*1.D5 + END DO + END DO + END DO + + RETURN + +END SUBROUTINE DCOMPUTEABSVORT + + +!NCLFORTSTART +SUBROUTINE DCOMPUTEPV(pv, u, v, theta, prs, msfu, msfv, msft, cor, dx, dy, nx, & + ny, nz, nxp1, nyp1) + USE constants, ONLY : G + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: pv + + INTEGER,INTENT(IN) :: nx, ny, nz, nxp1, nyp1 + REAL(KIND=8), DIMENSION(nxp1,ny,nz), INTENT(IN) :: u + REAL(KIND=8), DIMENSION(nx,nyp1,nz), INTENT(IN) :: v + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: prs + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: theta + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(OUT) :: pv + REAL(KIND=8), DIMENSION(nxp1,ny), INTENT(IN) :: msfu + REAL(KIND=8), DIMENSION(nx,nyp1), INTENT(IN) :: msfv + REAL(KIND=8), DIMENSION(nx,ny), INTENT(IN) :: msft + REAL(KIND=8), DIMENSION(nx,ny), INTENT(IN) :: cor + REAL(KIND=8) :: dx,dy + +!NCLEND + + INTEGER :: kp1, km1, jp1, jm1, ip1, im1, i, j, k + REAL(KIND=8) :: dsy, dsx, dp, dudy, dvdx, dudp, dvdp, dthdp, avort + REAL(KIND=8) :: dthdx, dthdy, mm + + ! PRINT*,'nx,ny,nz,nxp1,nyp1' + ! PRINT*,nx,ny,nz,nxp1,nyp1 + DO k = 1,nz + kp1 = MIN(k+1, nz) + km1 = MAX(k-1, 1) + DO J = 1,ny + jp1 = MIN(j+1, ny) + jm1 = MAX(j-1, 1) + DO i = 1,nx + ip1 = MIN(i+1, nx) + im1 = MAX(i-1, 1) + ! PRINT *,jp1,jm1,ip1,im1 + dsx = (ip1 - im1) * dx + dsy = (jp1 - jm1) * dy + mm = msft(i,j)*msft(i,j) + ! PRINT *,j,i,u(i,jp1,k),msfu(i,jp1),u(i,jp1,k)/msfu(i,jp1) + dudy = 0.5D0 * (u(i,jp1,k)/msfu(i,jp1) + u(i+1,jp1,k)/msfu(i+1,jp1) - & + u(i,jm1,k)/msfu(i,jm1) - u(i+1,jm1,k)/msfu(i+1,jm1))/dsy*mm + dvdx = 0.5D0 * (v(ip1,j,k)/msfv(ip1,j) + v(ip1,j+1,k)/msfv(ip1,j+1) - & + v(im1,j,k)/msfv(im1,j) - v(im1,j+1,k)/msfv(im1,j+1))/dsx*mm + avort = dvdx - dudy + cor(i,j) + dp = prs(i,j,kp1) - prs(i,j,km1) + dudp = 0.5D0 * (u(i,j,kp1) + u(i+1,j,kp1) - u(i,j,km1) - u(i+1,j,km1))/dp + dvdp = 0.5D0 * (v(i,j,kp1) + v(i,j+1,kp1) - v(i,j,km1) - v(i,J+1,km1))/dp + dthdp = (theta(i,j,kp1) - theta(i,j,km1))/dp + dthdx = (theta(ip1,j,k) - theta(im1,j,k))/dsx * msft(i,j) + dthdy = (theta(i,jp1,k) - theta(i,jm1,k))/dsy * msft(i,j) + pv(i,j,k) = -G * (dthdp*avort - dvdp*dthdx + dudp*dthdy)*10000.D0 + ! if(i.eq.300 .and. j.eq.300) then + ! PRINT*,'avort,dudp,dvdp,dthdp,dthdx,dthdy,pv' + ! PRINT*,avort,dudp,dvdp,dthdp,dthdx,dthdy,pv(i,j,k) + ! endif + pv(i,j,k) = pv(i,j,k)*1.D2 + END DO + END DO + END DO + + RETURN + +END SUBROUTINE DCOMPUTEPV diff --git a/fortran/wrf_pw.f90 b/fortran/wrf_pw.f90 new file mode 100644 index 0000000..6a7e8d3 --- /dev/null +++ b/fortran/wrf_pw.f90 @@ -0,0 +1,31 @@ +!NCLFORTSTART +SUBROUTINE DCOMPUTEPW(p, tv, qv, ht, pw, nx, ny, nz, nzh) + USE constants, ONLY : RD + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: pw + + INTEGER, INTENT(IN) :: nx, ny, nz, nzh + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: p, tv, qv + REAL(KIND=8), DIMENSION(nx,ny,nzh), INTENT(IN) :: ht + REAL(KIND=8), DIMENSION(nx,ny), INTENT(OUT) :: pw + +!NCLEND + + INTEGER :: i, j, k + !REAL(KIND=8),PARAMETER :: R=287.06 + + pw = 0 + DO k=1,nz + DO j=1,ny + DO i=1,nx + pw(i,j) = pw(i,j) + ((p(i,j,k)/(RD*tv(i,j,k))) * qv(i,j,k) * (ht(i,j,k+1) - ht(i,j,k))) + END DO + END DO + END DO + + RETURN + +END SUBROUTINE DCOMPUTEPW diff --git a/fortran/wrf_relhl.f90 b/fortran/wrf_relhl.f90 new file mode 100644 index 0000000..b72acab --- /dev/null +++ b/fortran/wrf_relhl.f90 @@ -0,0 +1,84 @@ +! NCLFORTSTART +SUBROUTINE DCALRELHL(u, v, ght, ter, top, sreh, miy, mjx, mkzh) + USE constants, ONLY : PI, RAD_PER_DEG, DEG_PER_RAD + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: sreh + + INTEGER, INTENT(IN) :: miy, mjx, mkzh + REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(IN) :: u, v, ght + REAL(KIND=8), INTENT(IN) :: top + REAL(KIND=8), DIMENSION(miy,mjx), INTENT(IN) :: ter + REAL(KIND=8), DIMENSION(miy,mjx), INTENT(OUT) :: sreh + +! NCLEND + + ! This helicity code was provided by Dr. Craig Mattocks, and + ! verified by Cindy Bruyere to produce results equivalent to + ! those generated by RIP4. (The code came from RIP4?) + + REAL(KIND=8) :: dh, sdh, su, sv, ua, va, asp, adr, bsp, bdr + REAL(KIND=8) :: cu, cv, x, sum + INTEGER :: i, j, k, k10, k3, ktop + !REAL(KIND=8), PARAMETER :: DTR=PI/180.d0, DPR=180.d0/PI + + DO j = 1, mjx-1 + DO i = 1, miy-1 + sdh = 0.d0 + su = 0.d0 + sv = 0.d0 + k3 = 0 + k10 = 0 + ktop = 0 + DO k = mkzh, 2, -1 + IF (((ght(i,j,k) - ter(i,j)) .GT. 10000.D0) .AND. (k10 .EQ. 0)) THEN + k10 = k + EXIT + ENDIF + IF (((ght(i,j,k) - ter(i,j)) .GT. top) .AND. (ktop .EQ. 0)) THEN + ktop = k + ENDIF + IF (((ght(i,j,k) - ter(i,j)) .GT. 3000.D0) .AND. (k3 .EQ. 0)) THEN + k3 = k + ENDIF + END DO + + IF (k10 .EQ. 0) THEN + k10 = 2 + ENDIF + DO k = k3, k10, -1 + dh = ght(i,j,k-1) - ght(i,j,k) + sdh = sdh + dh + su = su + 0.5D0*dh*(u(i,j,k-1) + u(i,j,k)) + sv = sv + 0.5D0*dh*(v(i,j,k-1) + v(i,j,k)) + END DO + ua = su / sdh + va = sv / sdh + asp = SQRT(ua*ua + va*va) + IF (ua .EQ. 0.D0 .AND. va .EQ. 0.D0) THEN + adr = 0.D0 + ELSE + adr = DEG_PER_RAD * (PI + ATAN2(ua,va)) + ENDIF + bsp = 0.75D0 * asp + bdr = adr + 30.D0 + IF (bdr .GT. 360.D0) THEN + bdr = bdr - 360.D0 + ENDIF + cu = -bsp * SIN(bdr * RAD_PER_DEG) + cv = -bsp * COS(bdr * RAD_PER_DEG) + sum = 0.D0 + DO k = mkzh-1, ktop, -1 + x = ((u(i,j,k) - cu) * (v(i,j,k) - v(i,j,k+1))) - & + ((v(i,j,k) - cv) * (u(i,j,k) - u(i,j,k+1))) + sum = sum + x + END DO + sreh(i,j) = -sum + END DO + END DO + + RETURN + +END SUBROUTINE DCALRELHL diff --git a/fortran/wrf_rip_phys_routines.f90 b/fortran/wrf_rip_phys_routines.f90 new file mode 100644 index 0000000..3476fbd --- /dev/null +++ b/fortran/wrf_rip_phys_routines.f90 @@ -0,0 +1,269 @@ +!====================================================================== +! +! !IROUTINE: WETBULBCALC -- Calculate wet bulb temperature (C) +! +! !DESCRIPTION: +! +! Calculates wet bulb temperature in C, given pressure in +! temperature in K and mixing ratio in kg/kg. +! +! !INPUT: +! nx - index for x dimension +! ny - index for y dimension +! nz - index for z dimension +! prs - pressure (mb) +! tmk - temperature (K) +! qvp - water vapor mixing ratio (kg/kg) +! +! !OUTPUT: +! twb - Wet bulb temperature (C) +! +! !ASSUMPTIONS: +! +! !REVISION HISTORY: +! 2009-March - Mark T. Stoelinga - from RIP4.5 +! 2010-August - J. Schramm +! 2014-March - A. Jaye - modified to run with NCL and ARW wrf output +! +! !INTERFACE: +! ------------------------------------------------------------------ + +! NCLFORTSTART +SUBROUTINE WETBULBCALC(prs, tmk, qvp, twb, nx, ny, nz, psafile, errstat, errmsg) + USE constants, ONLY : ALGERR, GAMMA, GAMMAMD, TLCLC1, TLCLC2, TLCLC3, & + EPS, TLCLC4, THTECON1, THTECON2, THTECON3 + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: twb + + INTEGER, INTENT(IN) :: nx, ny, nz + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: prs + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: tmk + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: qvp + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(OUT) :: twb + CHARACTER(LEN=*), INTENT(IN) :: psafile + INTEGER, INTENT(INOUT) :: errstat + CHARACTER(LEN=*), INTENT(INOUT) :: errmsg + +!NCLEND + + INTEGER :: i, j, k + INTEGER :: jtch, jt, ipch, ip + REAL(KIND=8) :: q, t, p, e, tlcl, eth + REAL(KIND=8) :: fracip, fracip2, fracjt, fracjt2 + REAL(KIND=8), DIMENSION(150) :: PSADITHTE, PSADIPRS + REAL(KIND=8), DIMENSION(150,150) :: PSADITMK + REAL(KIND=8) :: tonpsadiabat + + + ! Before looping, set lookup table for getting temperature on + ! a pseudoadiabat. + + CALL DLOOKUP_TABLE(PSADITHTE, PSADIPRS, PSADITMK, psafile, errstat, errmsg) + + IF (errstat .NE. 0) THEN + RETURN + END IF + + DO k=1,nz + DO j=1,ny + DO i=1,nx + q = DMAX1(qvp(i,j,k), 1.D-15) + t = tmk(i,j,k) + p = prs(i,j,k)/100. + e = q*p/(EPS + q) + tlcl = TLCLC1/(DLOG(t**TLCLC2/e) - TLCLC3) + TLCLC4 + eth = t*(1000./p)**(GAMMA*(1. + GAMMAMD*q))*& + EXP((THTECON1/tlcl - THTECON2)*q*(1. + THTECON3*q)) + + ! Now we need to find the temperature (in K) on a moist adiabat + ! (specified by eth in K) given pressure in hPa. It uses a + ! lookup table, with data that was generated by the Bolton (1980) + ! formula for theta_e. + + ! First check if pressure is less than min pressure in lookup table. + ! If it is, assume parcel is so dry that the given theta-e value can + ! be interpretted as theta, and get temperature from the simple dry + ! theta formula. + + IF (p .LE. PSADIPRS(150)) THEN + tonpsadiabat = eth*(p/1000.)**GAMMA + ELSE + ! Otherwise, look for the given thte/prs point in the lookup table. + jt=-1 + DO jtch=1,150-1 + IF (eth .GE. PSADITHTE(jtch) .AND. eth .LT. PSADITHTE(jtch+1)) THEN + jt = jtch + EXIT + ENDIF + END DO + + ip=-1 + DO ipch=1,150-1 + IF (p .LE. PSADIPRS(ipch) .AND. p .GT. PSADIPRS(ipch+1)) THEN + ip = ipch + EXIT + ENDIF + END DO + + IF (jt .EQ. -1 .OR. ip .EQ. -1) THEN + errstat = ALGERR + WRITE(errmsg, *) "Outside of lookup table bounds. prs,thte=", p, eth + RETURN + ENDIF + + fracjt = (eth - PSADITHTE(jt))/(PSADITHTE(jt+1) - PSADITHTE(jt)) + fracjt2 = 1. - fracjt + fracip = (PSADIPRS(ip) - p)/(PSADIPRS(ip) - PSADIPRS(ip+1)) + fracip2 = 1. - fracip + + IF (PSADITMK(ip,jt) .GT. 1e9 .OR. PSADITMK(ip+1,jt) .GT. 1e9 .OR. & + PSADITMK(ip,jt+1) .GT. 1e9 .OR. PSADITMK(ip+1,jt+1) .GT. 1e9) THEN + !PRINT*,'Tried to access missing tmperature in lookup table.' + errstat = ALGERR + WRITE(errmsg, *) "Prs and Thte probably unreasonable. prs, thte=", p, eth + RETURN + ENDIF + + tonpsadiabat = fracip2*fracjt2*PSADITMK(ip,jt) + & + fracip*fracjt2*PSADITMK(ip+1,jt) + & + fracip2*fracjt*PSADITMK(ip,jt+1) + & + fracip*fracjt*PSADITMK(ip+1,jt+1) + ENDIF + + twb(i,j,k) = tonpsadiabat + + END DO + END DO + END DO + + RETURN + +END SUBROUTINE WETBULBCALC + + +! !IROUTINE: omgcalc -- Calculate omega (dp/dt) +! +! !DESCRIPTION: +! +! Calculate approximate omega, based on vertical velocity w (dz/dt). +! It is approximate because it cannot take into account the vertical +! motion of pressure surfaces. +! +! !INPUT: +! mx - index for x dimension +! my - index for y dimension +! mx - index for vertical dimension +! qvp - water vapor mixing ratio (kg/kg) +! tmk - temperature (K) +! www - vertical velocity (m/s) +! prs - pressure (Pa) +! +! !OUTPUT: +! omg - omega (Pa/sec) +! +! !ASSUMPTIONS: +! +! !REVISION HISTORY: +! 2009-March - Mark T. Stoelinga - from RIP4.5 +! 2010-August - J. Schramm +! 2014-March - A. Jaye - modified to run with NCL and ARW wrf output +! +! ------------------------------------------------------------------ + +!NCLFORTSTART +SUBROUTINE OMGCALC(qvp, tmk, www, prs, omg, mx, my, mz) + USE constants, ONLY : G, RD, EPS + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: omg + + INTEGER,INTENT(IN) :: mx, my, mz + REAL(KIND=8), INTENT(IN), DIMENSION(mx,my,mz) :: qvp + REAL(KIND=8), INTENT(IN), DIMENSION(mx,my,mz) :: tmk + REAL(KIND=8), INTENT(IN), DIMENSION(mx,my,mz) :: www + REAL(KIND=8), INTENT(IN), DIMENSION(mx,my,mz) :: prs + REAL(KIND=8), INTENT(OUT), DIMENSION(mx,my,mz) :: omg + +!NCLEND + + ! Local variables + INTEGER :: i, j, k + !REAL(KIND=8), PARAMETER :: GRAV=9.81, RGAS=287.04, EPS=0.622 + + DO k=1,mz + DO j=1,my + DO i=1,mx + omg(i,j,k) = -G*prs(i,j,k)/& + (RD*((tmk(i,j,k)*(EPS + qvp(i,j,k)))/& + (EPS*(1. + qvp(i,j,k)))))*www(i,j,k) + END DO + END DO + END DO + + RETURN + +END SUBROUTINE OMGCALC + +!====================================================================== +! +! !IROUTINE: VIRTUAL_TEMP -- Calculate virtual temperature (K) +! +! !DESCRIPTION: +! +! Calculates virtual temperature in K, given temperature +! in K and mixing ratio in kg/kg. +! +! !INPUT: +! NX - index for x dimension +! NY - index for y dimension +! NZ - index for z dimension +! RATMIX - water vapor mixing ratio (kg/kg) +! TEMP - temperature (K) +! +! !OUTPUT: +! TV - Virtual temperature (K) +! +! !ASSUMPTIONS: +! +! !REVISION HISTORY: +! 2009-March - Mark T. Stoelinga - from RIP4.5 +! 2010-August - J. Schramm +! 2014-March - A. Jaye - modified to run with NCL and ARW wrf output +! +! ------------------------------------------------------------------ +!NCLFORTSTART +SUBROUTINE VIRTUAL_TEMP(temp, ratmix, tv, nx, ny, nz) + USE constants, ONLY : EPS + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: tv + + INTEGER, INTENT(IN) :: nx, ny, nz + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: temp + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: ratmix + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(OUT) :: tv + +!NCLEND + + INTEGER :: i,j,k + !REAL(KIND=8),PARAMETER :: EPS = 0.622D0 + + DO k=1,nz + DO j=1,ny + DO i=1,nx + tv(i,j,k) = temp(i,j,k)*(EPS + ratmix(i,j,k))/(EPS*(1.D0 + ratmix(i,j,k))) + END DO + END DO + END DO + + RETURN + +END SUBROUTINE VIRTUAL_TEMP + diff --git a/fortran/wrf_user.f90 b/fortran/wrf_user.f90 index 0b8c475..b3081d7 100644 --- a/fortran/wrf_user.f90 +++ b/fortran/wrf_user.f90 @@ -1,6 +1,6 @@ ! NCLFORTSTART SUBROUTINE DCOMPUTEPI(pi, pressure, nx, ny, nz) - USE constants, ONLY : P1000MB, R_D, CP + USE constants, ONLY : P1000MB, RD, CP IMPLICIT NONE @@ -19,7 +19,7 @@ SUBROUTINE DCOMPUTEPI(pi, pressure, nx, ny, nz) DO k = 1,nz DO j = 1,ny DO i = 1,nx - pi(i,j,k) = (pressure(i,j,k)/P1000MB)**(R_D/CP) + pi(i,j,k) = (pressure(i,j,k)/P1000MB)**(RD/CP) END DO END DO END DO @@ -29,7 +29,7 @@ END SUBROUTINE DCOMPUTEPI ! Temperature from potential temperature in kelvin. !NCLFORTSTART SUBROUTINE DCOMPUTETK(tk, pressure, theta, nx) - USE constants, ONLY : P1000MB, R_D, CP + USE constants, ONLY : P1000MB, RD, CP IMPLICIT NONE @@ -46,10 +46,10 @@ SUBROUTINE DCOMPUTETK(tk, pressure, theta, nx) INTEGER :: i - !REAL(KIND=8), PARAMETER :: P1000MB=100000.D0, R_D=287.D0, CP=7.D0*R_D/2.D0 + !REAL(KIND=8), PARAMETER :: P1000MB=100000.D0, RD=287.D0, CP=7.D0*RD/2.D0 DO i = 1,nx - pi = (pressure(i)/P1000MB)**(R_D/CP) + pi = (pressure(i)/P1000MB)**(RD/CP) tk(i) = pi*theta(i) END DO @@ -282,7 +282,7 @@ END SUBROUTINE DINTERP1D ! NCLFORTSTART SUBROUTINE DCOMPUTESEAPRS(nx, ny, nz, z, t, p, q, sea_level_pressure, & t_sea_level, t_surf, level, errstat, errmsg) - USE constants, ONLY : ERRLEN, R, G, GAMMA + USE constants, ONLY : ALGERR, RD, G, USSALR IMPLICIT NONE @@ -297,11 +297,10 @@ SUBROUTINE DCOMPUTESEAPRS(nx, ny, nz, z, t, p, q, sea_level_pressure, & REAL(KIND=8), DIMENSION(nx,ny), INTENT(OUT) :: sea_level_pressure INTEGER, DIMENSION(nx,ny), INTENT(INOUT) :: level REAL(KIND=8), DIMENSION(nx,ny), INTENT(INOUT) :: t_surf, t_sea_level -! NCLFORTEND - + INTEGER, INTENT(INOUT) :: errstat + CHARACTER(LEN=*), INTENT(INOUT) :: errmsg - INTEGER, OPTIONAL, INTENT(INOUT) :: errstat - CHARACTER(LEN=ERRLEN), OPTIONAL, INTENT(INOUT) :: errmsg +! NCLFORTEND ! Some required physical constants: @@ -329,9 +328,7 @@ SUBROUTINE DCOMPUTESEAPRS(nx, ny, nz, z, t, p, q, sea_level_pressure, & ! temperature, which is supposed to reduce the effect of the diurnal ! heating cycle in the pressure field. - IF (PRESENT(errstat)) THEN - errstat = 0 - END IF + errstat = 0 DO j = 1,ny DO i = 1,nx @@ -348,16 +345,14 @@ SUBROUTINE DCOMPUTESEAPRS(nx, ny, nz, z, t, p, q, sea_level_pressure, & END DO IF (level(i,j) == -1) THEN - IF (PRESENT(errstat)) THEN - errstat = 1 - errmsg = 'Error in finding 100 hPa up' - RETURN - ELSE - PRINT '(A,I4,A)','Troubles finding level ', NINT(PCONST)/100,' above ground.' - PRINT '(A,I4,A,I4,A)','Problems first occur at (',I,',',J,')' - PRINT '(A,F6.1,A)','Surface pressure = ',p(i,j,1)/100,' hPa.' - STOP 'Error in finding 100 hPa up' - END IF + errstat = ALGERR + errmsg = "Error in finding 100 hPa up" + RETURN + + !PRINT '(A,I4,A)','Troubles finding level ', NINT(PCONST)/100,' above ground.' + !PRINT '(A,I4,A,I4,A)','Problems first occur at (',I,',',J,')' + !PRINT '(A,F6.1,A)','Surface pressure = ',p(i,j,1)/100,' hPa.' + !STOP 'Error in finding 100 hPa up' END IF END DO @@ -366,28 +361,26 @@ SUBROUTINE DCOMPUTESEAPRS(nx, ny, nz, z, t, p, q, sea_level_pressure, & ! Get temperature PCONST Pa above surface. Use this to extrapolate ! the temperature at the surface and down to sea level. - DO J = 1,ny - DO I = 1,nx + DO j = 1,ny + DO i = 1,nx klo = MAX(level(i,j)-1,1) khi = MIN(klo+1,nz-1) IF (klo == khi) THEN - IF (PRESENT(errstat)) THEN - errstat = 1 - errmsg = 'Error trapping levels' - RETURN - ELSE - PRINT '(A)','Trapping levels are weird.' - PRINT '(A,I3,A,I3,A)','klo = ',klo,', khi = ',khi,': and they should not be equal.' - STOP 'Error trapping levels' - END IF + errstat = ALGERR + errmsg = "Error trapping levels" + RETURN + + !PRINT '(A)','Trapping levels are weird.' + !PRINT '(A,I3,A,I3,A)','klo = ',klo,', khi = ',khi,': and they should not be equal.' + !STOP 'Error trapping levels' END IF plo = p(i,j,klo) phi = p(i,j,khi) - tlo = t(i,j,klo)* (1.D0+0.608D0*q(i,j,klo)) - thi = t(i,j,khi)* (1.D0+0.608D0*q(i,j,khi)) + tlo = t(i,j,klo) * (1.D0+0.608D0*q(i,j,klo)) + thi = t(i,j,khi) * (1.D0+0.608D0*q(i,j,khi)) ! zlo = zetahalf(klo)/ztop*(ztop-terrain(i,j))+terrain(i,j) ! zhi = zetahalf(khi)/ztop*(ztop-terrain(i,j))+terrain(i,j) zlo = z(i,j,klo) @@ -397,8 +390,8 @@ SUBROUTINE DCOMPUTESEAPRS(nx, ny, nz, z, t, p, q, sea_level_pressure, & t_at_pconst = thi - (thi-tlo)*LOG(p_at_pconst/phi)*LOG(plo/phi) z_at_pconst = zhi - (zhi-zlo)*LOG(p_at_pconst/phi)*LOG(plo/phi) - t_surf(i,j) = t_at_pconst * (p(i,j,1)/p_at_pconst)**(GAMMA*R/G) - t_sea_level(i,j) = t_at_pconst + GAMMA*z_at_pconst + t_surf(i,j) = t_at_pconst * (p(i,j,1)/p_at_pconst)**(USSALR*RD/G) + t_sea_level(i,j) = t_at_pconst + USSALR*z_at_pconst END DO END DO @@ -408,8 +401,8 @@ SUBROUTINE DCOMPUTESEAPRS(nx, ny, nz, z, t, p, q, sea_level_pressure, & ! temperatures are *too* hot. IF (ridiculous_mm5_test) THEN - DO J = 1,ny - DO I = 1,nx + DO j = 1,ny + DO i = 1,nx l1 = t_sea_level(i,j) < TC l2 = t_surf(i,j) <= TC l3 = .NOT. l1 @@ -423,8 +416,8 @@ SUBROUTINE DCOMPUTESEAPRS(nx, ny, nz, z, t, p, q, sea_level_pressure, & END IF ! The grand finale: ta da! - DO J = 1,ny - DO I = 1,nx + DO j = 1,ny + DO i = 1,nx ! z_half_lowest=zetahalf(1)/ztop*(ztop-terrain(i,j))+terrain(i,j) z_half_lowest = z(i,j,1) @@ -432,7 +425,7 @@ SUBROUTINE DCOMPUTESEAPRS(nx, ny, nz, z, t, p, q, sea_level_pressure, & ! Fortran routine didn't do this, but the NCL script that called it ! did, so we moved it here. sea_level_pressure(i,j) = 0.01 * (p(i,j,1)*EXP((2.D0*G*z_half_lowest)/& - (R*(t_sea_level(i,j)+t_surf(i,j))))) + (RD*(t_sea_level(i,j)+t_surf(i,j))))) END DO END DO @@ -592,6 +585,7 @@ END SUBROUTINE FILTER2D ! NCLFORTSTART SUBROUTINE DCOMPUTERH(qv, p, t, rh, nx) + USE constants, ONLY : EZERO, ESLCON1, ESLCON2, CELKEL, RD, RV, EPS IMPLICIT NONE @@ -604,23 +598,19 @@ SUBROUTINE DCOMPUTERH(qv, p, t, rh, nx) ! NCLEND - REAL(KIND=8), PARAMETER :: SVP1=0.6112D0,SVP2=17.67D0,SVP3=29.65D0,SVPT0=273.15D0 - INTEGER :: i REAL(KIND=8) :: qvs,es,pressure,temperature - REAL(KIND=8), PARAMETER :: R_D=287.D0,R_V=461.6D0,EP_2=R_D/R_V - REAL(KIND=8), PARAMETER :: EP_3=0.622D0 DO i = 1,nx pressure = p(i) temperature = t(i) ! es = 1000.*svp1* - es = 10.D0*SVP1*EXP(SVP2* (temperature-SVPT0)/(temperature-SVP3)) + es = EZERO * EXP(ESLCON1 * (temperature-CELKEL) / (temperature-ESLCON2)) ! qvs = ep_2*es/(pressure-es) - qvs = EP_3*es/ (0.01D0*pressure- (1.D0-EP_3)*es) + qvs = EPS * es / (0.01D0 * pressure - (1.D0 - EPS) * es) ! rh = 100*amax1(1., qv(i)/qvs) ! rh(i) = 100.*qv(i)/qvs - rh(i) = 100.D0*DMAX1(DMIN1(qv(i)/qvs,1.0D0),0.0D0) + rh(i) = 100.D0 * DMAX1(DMIN1(qv(i) / qvs, 1.0D0), 0.0D0) END DO RETURN @@ -744,7 +734,7 @@ SUBROUTINE DCOMPUTEUVMET(u, v, uvmet, longca,longcb,flong,flat, & END DO END DO - ! WRITE (6,FMT=*) ' computing velocities ' + ! WRITE (6,FMT=*) " computing velocities " DO j = 1,ny DO i = 1,nx IF (istag.EQ.1) THEN @@ -859,27 +849,24 @@ SUBROUTINE DCOMPUTEICLW(iclw, pressure, qc_in, nx, ny, nz) END SUBROUTINE DCOMPUTEICLW -SUBROUTINE testfunc(a, b, nx, ny, nz, errstat, errstr) +SUBROUTINE testfunc(a, b, c, nx, ny, nz, errstat, errmsg) + USE constants, ONLY : ALGERR IMPLICIT NONE - !f2py threadsafe + !threadsafe !f2py intent(in,out) :: b INTEGER, INTENT(IN) :: nx, ny, nz REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: a REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(OUT) :: b - INTEGER, INTENT(INOUT), OPTIONAL :: errstat - CHARACTER(LEN=512), INTENT(INOUT), OPTIONAL :: errstr + CHARACTER(LEN=*), INTENT(IN) :: c + INTEGER, INTENT(INOUT) :: errstat + REAL(KIND=8), PARAMETER :: blah=123.45 + CHARACTER(LEN=*), INTENT(INOUT) :: errmsg INTEGER :: i,j,k - IF (PRESENT(errstat)) THEN - errstat = 0 - errstr = 'test string worked' - END IF - - DO k=1,nz DO j=1,ny DO i=1,nx @@ -888,9 +875,8 @@ SUBROUTINE testfunc(a, b, nx, ny, nz, errstat, errstr) END DO END DO - IF (PRESENT(errstat)) THEN - errstat = 1 - END IF + errstat = ALGERR + WRITE(errmsg, *) c(1:20), blah RETURN diff --git a/fortran/wrf_user_dbz.f90 b/fortran/wrf_user_dbz.f90 new file mode 100644 index 0000000..93ad9af --- /dev/null +++ b/fortran/wrf_user_dbz.f90 @@ -0,0 +1,147 @@ +!NCLFORTSTART +SUBROUTINE CALCDBZ(prs, tmk, qvp, qra, qsn, qgr, sn0, ivarint, iliqskin, dbz, nx, ny, nz) + USE constants, ONLY : GAMMA_SEVEN, RHOWAT, RHO_R, RHO_S, RHO_G, ALPHA, & + CELKEL, PI, RD + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: dbz + + ! Arguments + INTEGER, INTENT(IN) :: nx, ny, nz + INTEGER, INTENT(IN) :: sn0, ivarint, iliqskin + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(OUT) :: dbz + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: prs + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: tmk + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(INOUT) :: qvp + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(INOUT) :: qra + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(INOUT) :: qsn + REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(INOUT) :: qgr + +!NCLEND + + ! Local Variables + INTEGER :: i, j, k + REAL(KIND=8) :: temp_c, virtual_t + REAL(KIND=8) :: gonv, ronv, sonv + REAL(KIND=8) :: factor_g, factor_r, factor_s + REAL(KIND=8) :: factorb_g, factorb_s + REAL(KIND=8) :: rhoair, z_e + + ! Constants used to calculate variable intercepts + REAL(KIND=8), PARAMETER :: R1 = 1.D-15 + REAL(KIND=8), PARAMETER :: RON = 8.D6 + REAL(KIND=8), PARAMETER :: RON2 = 1.D10 + REAL(KIND=8), PARAMETER :: SON = 2.D7 + REAL(KIND=8), PARAMETER :: GON = 5.D7 + REAL(KIND=8), PARAMETER :: RON_MIN = 8.D6 + REAL(KIND=8), PARAMETER :: RON_QR0 = 0.00010D0 + REAL(KIND=8), PARAMETER :: RON_DELQR0 = 0.25D0*RON_QR0 + REAL(KIND=8), PARAMETER :: RON_CONST1R = (RON2-RON_MIN)*0.5D0 + REAL(KIND=8), PARAMETER :: RON_CONST2R = (RON2+RON_MIN)*0.5D0 + + ! Constant intercepts + REAL(KIND=8), PARAMETER :: RN0_R = 8.D6 + REAL(KIND=8), PARAMETER :: RN0_S = 2.D7 + REAL(KIND=8), PARAMETER :: RN0_G = 4.D6 + + ! Force all Q arrays to be 0.0 or greater. + DO k = 1,nz + DO j = 1,ny + DO i = 1,nx + IF (qvp(i,j,k).LT.0.0) THEN + qvp(i,j,k) = 0.0 + END IF + IF (qra(i,j,k).LT.0.0) THEN + qra(i,j,k) = 0.0 + END IF + IF (qsn(i,j,k).LT.0.0) THEN + qsn(i,j,k) = 0.0 + END IF + IF (qgr(i,j,k).LT.0.0) THEN + qgr(i,j,k) = 0.0 + END IF + END DO + END DO + END DO + + ! Input pressure is Pa, but we need hPa in calculations + + IF (sn0 .EQ. 0) THEN + DO k = 1,nz + DO j = 1,ny + DO i = 1,nx + IF (tmk(i,j,k) .LT. CELKEL) THEN + qsn(i,j,k) = qra(i,j,k) + qra(i,j,k) = 0.D0 + END IF + END DO + END DO + END DO + END IF + + factor_r = GAMMA_SEVEN*1.D18*(1.D0/(PI*RHO_R))**1.75D0 + factor_s = GAMMA_SEVEN*1.D18*(1.D0/(PI*RHO_S))**1.75D0*(RHO_S/RHOWAT)**2*ALPHA + factor_g = GAMMA_SEVEN*1.D18*(1.D0/(PI*RHO_G))**1.75D0*(RHO_G/RHOWAT)**2*ALPHA + + DO k = 1,nz + DO j = 1,ny + DO i = 1,nx + virtual_t = tmk(i,j,k)*(0.622D0 + qvp(i,j,k))/(0.622D0*(1.D0 + qvp(i,j,k))) + rhoair = prs(i,j,k) / (RD*virtual_t) + + ! Adjust factor for brightband, where snow or graupel particle + ! scatters like liquid water (alpha=1.0) because it is assumed to + ! have a liquid skin. + IF (iliqskin .EQ. 1 .AND. tmk(i,j,k) .GT. CELKEL) THEN + factorb_s = factor_s/ALPHA + factorb_g = factor_g/ALPHA + ELSE + factorb_s = factor_s + factorb_g = factor_g + END IF + + ! Calculate variable intercept parameters + IF (ivarint .EQ. 1) THEN + + temp_c = DMIN1(-0.001D0, tmk(i,j,k)-CELKEL) + sonv = DMIN1(2.0D8, 2.0D6*EXP(-0.12D0*temp_c)) + + gonv = gon + IF (qgr(i,j,k) .GT. R1) THEN + gonv = 2.38D0 * (PI*RHO_G/(rhoair*qgr(i,j,k)))**0.92D0 + gonv = MAX(1.D4, MIN(gonv,GON)) + END IF + + ronv = RON2 + IF (qra(i,j,k) .GT. R1) THEN + ronv = RON_CONST1R*TANH((RON_QR0-qra(i,j,k))/RON_DELQR0) + RON_CONST2R + END IF + + ELSE + ronv = RN0_R + sonv = RN0_S + gonv = RN0_G + END IF + + ! Total equivalent reflectivity factor (z_e, in mm^6 m^-3) is + ! the sum of z_e for each hydrometeor species: + + z_e = factor_r*(rhoair*qra(i,j,k))**1.75D0/ronv**.75D0 + & + factorb_s*(rhoair*qsn(i,j,k))**1.75D0/sonv**.75D0 + & + factorb_g* (rhoair*qgr(i,j,k))**1.75D0/gonv**.75D0 + + ! Adjust small values of Z_e so that dBZ is no lower than -30 + z_e = MAX(z_e, .001D0) + + ! Convert to dBZ + dbz(i,j,k) = 10.D0*LOG10(z_e) + END DO + END DO + END DO + + RETURN + +END SUBROUTINE CALCDBZ + diff --git a/fortran/wrf_user_latlon_routines.f90 b/fortran/wrf_user_latlon_routines.f90 new file mode 100644 index 0000000..86e638f --- /dev/null +++ b/fortran/wrf_user_latlon_routines.f90 @@ -0,0 +1,524 @@ +!NCLFORTSTART +SUBROUTINE ROTATECOORDS(ilat, ilon, olat, olon, lat_np, lon_np, lon_0, direction) + USE constants, ONLY : PI, RAD_PER_DEG, DEG_PER_RAD + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: olat, olon + + REAL(KIND=8), INTENT(IN) :: ilat, ilon + REAL(KIND=8), INTENT(OUT) :: olat, olon + REAL(KIND=8), INTENT(IN) :: lat_np, lon_np, lon_0 + INTEGER, INTENT(IN) :: direction + +! NCLFORTEND + + ! >=0, default : computational -> geographical + ! < 0 : geographical -> computational + + REAL(KIND=8) :: rlat, rlon + REAL(KIND=8) :: phi_np, lam_np, lam_0, dlam + REAL(KIND=8) :: sinphi, cosphi, coslam, sinlam + !REAL(KIND=8), PARAMETER :: PI=3.141592653589793D0 + !REAL(KIND=8), PARAMETER :: RAD_PER_DEG=PI/180.D0 + !REAL(KIND=8), PARAMETER :: DEG_PER_RAD=180.D0/PI + + !convert all angles to radians + phi_np = lat_np*RAD_PER_DEG + lam_np = lon_np*RAD_PER_DEG + lam_0 = lon_0*RAD_PER_DEG + rlat = ilat*RAD_PER_DEG + rlon = ilon*RAD_PER_DEG + + IF (direction .LT. 0) THEN + ! the equations are exactly the same except for one + ! small difference with respect to longitude ... + dlam = pi - lam_0 + ELSE + dlam = lam_np + END IF + + sinphi = COS(phi_np)*COS(rlat)*COS(rlon - dlam) + SIN(phi_np)*SIN(rlat) + cosphi = SQRT(1.D0 - sinphi*sinphi) + coslam = SIN(phi_np)*COS(rlat)*COS(rlon - dlam) - COS(phi_np)*SIN(rlat) + sinlam = COS(rlat)*SIN(rlon - dlam) + + IF (cosphi.NE.0.D0) THEN + coslam = coslam/cosphi + sinlam = sinlam/cosphi + END IF + + olat = DEG_PER_RAD*ASIN(sinphi) + olon = DEG_PER_RAD*(ATAN2(sinlam,coslam) - dlam - lam_0 + lam_np) + + RETURN + +END SUBROUTINE ROTATECOORDS + + +!NCLFORTSTART +SUBROUTINE DLLTOIJ(map_proj, truelat1, truelat2, stdlon, lat1, lon1,& + pole_lat, pole_lon, knowni, knownj, dx, dy, latinc,& + loninc, lat, lon, loc, errstat, errmsg) + USE constants, ONLY : ALGERR, PI, RAD_PER_DEG, DEG_PER_RAD, WRF_EARTH_RADIUS + + ! Converts input lat/lon values to the cartesian (i,j) value + ! for the given projection. + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: loc + + + INTEGER, INTENT(IN) :: map_proj + REAL(KIND=8), INTENT(IN) :: stdlon + REAL(KIND=8), INTENT(IN) ::lat1, lon1, pole_lat, pole_lon, knowni, knownj + REAL(KIND=8), INTENT(IN) ::dx, dy, latinc, loninc + REAL(KIND=8), INTENT(INOUT) :: lat, lon, truelat1, truelat2 ! these might get modified + REAL(KIND=8), DIMENSION(2), INTENT(OUT) :: loc + INTEGER, INTENT(INOUT) :: errstat + CHARACTER(LEN=*), INTENT(INOUT) :: errmsg + +!NCLEND + + REAL(KIND=8) :: deltalon1 + REAL(KIND=8) :: tl1r + REAL(KIND=8) :: clain, dlon, rsw, deltalon, deltalat + REAL(KIND=8) :: reflon, scale_top, ala1, alo1, ala, alo, rm, polei, polej + ! earth radius divided by dx + REAL(KIND=8) :: rebydx + REAL(KIND=8) :: ctl1r, arg, cone, hemi + REAL(KIND=8) :: i, j + REAL(KIND=8) :: lat1n, lon1n, olat, olon + + ! Contants + !REAL(KIND=8),PARAMETER :: PI=3.141592653589793D0 + !REAL(KIND=8),PARAMETER :: RAD_PER_DEG=PI/180.D0 + !REAL(KIND=8),PARAMETER :: DEG_PER_RAD=180.D0/PI + !REAL(KIND=8),PARAMETER :: RE_M=6370000.D0 ! radius of earth in meters + + ! lat1 ! sw latitude (1,1) in degrees (-90->90n) + ! lon1 ! sw longitude (1,1) in degrees (-180->180e) + ! dx ! grid spacing in meters at truelats + ! dlat ! lat increment for lat/lon grids + ! dlon ! lon increment for lat/lon grids + ! stdlon ! longitude parallel to y-axis (-180->180e) + ! truelat1 ! first true latitude (all projections) + ! truelat2 ! second true lat (lc only) + ! hemi ! 1 for nh, -1 for sh + ! cone ! cone factor for lc projections + ! polei ! computed i-location of pole point + ! polej ! computed j-location of pole point + ! rsw ! computed radius to sw corner + ! knowni ! x-location of known lat/lon + ! knownj ! y-location of known lat/lon + ! re_m ! radius of spherical earth, meters + ! rebydx ! earth radius divided by dx + + errstat = INT(dy) ! remove compiler warning since dy not used + errstat = 0 + + rebydx = WRF_EARTH_RADIUS/dx + + ! Get rid of compiler warnings + i=0 + j=0 + + hemi = 1.0D0 + IF (truelat1 .LT. 0.0D0) THEN + hemi = -1.0D0 + END IF + + ! mercator + IF (map_proj.EQ.3) THEN + + ! preliminary variables + clain = COS(RAD_PER_DEG*truelat1) + dlon = dx/(WRF_EARTH_RADIUS*clain) + + ! compute distance from equator to origin, and store in + ! the rsw tag. + rsw = 0.D0 + IF (lat1 .NE. 0.D0) THEN + rsw = (DLOG(TAN(0.5D0*((lat1 + 90.D0)*RAD_PER_DEG))))/dlon + END IF + + deltalon = lon - lon1 + IF (deltalon .LT. -180.D0) deltalon = deltalon + 360.D0 + IF (deltalon .GT. 180.D0) deltalon = deltalon - 360.D0 + i = knowni + (deltalon/(dlon*DEG_PER_RAD)) + j = knownj + (DLOG(TAN(0.5D0*((lat + 90.D0)*RAD_PER_DEG))))/dlon - rsw + + ! ps + ELSE IF (map_proj .EQ. 2) THEN + + reflon = stdlon + 90.D0 + + ! compute numerator term of map scale factor + scale_top = 1.D0 + hemi*SIN(truelat1*RAD_PER_DEG) + + ! compute radius to lower-left (sw) corner + ala1 = lat1*RAD_PER_DEG + rsw = rebydx*COS(ala1)*scale_top/(1.D0 + hemi*SIN(ala1)) + + ! find the pole point + alo1 = (lon1 - reflon)*RAD_PER_DEG + polei = knowni - rsw*COS(alo1) + polej = knownj - hemi*rsw*SIN(alo1) + + ! find radius to desired point + ala = lat*RAD_PER_DEG + rm = rebydx*COS(ala)*scale_top/(1.D0 + hemi*SIN(ala)) + alo = (lon - reflon)*RAD_PER_DEG + i = polei + rm*COS(alo) + j = polej + hemi*rm*SIN(alo) + + ! lambert + ELSE IF (map_proj .EQ. 1) THEN + + IF (ABS(truelat2) .GT. 90.D0) THEN + truelat2 = truelat1 + END IF + + IF (ABS(truelat1 - truelat2) .GT. 0.1D0) THEN + cone = (DLOG(COS(truelat1*RAD_PER_DEG))-DLOG(COS(truelat2*RAD_PER_DEG)))/& + (DLOG(TAN((90.D0 - ABS(truelat1))*RAD_PER_DEG*0.5D0))-& + DLOG(TAN((90.D0 - ABS(truelat2))*RAD_PER_DEG*0.5D0))) + ELSE + cone = SIN(ABS(truelat1)*RAD_PER_DEG) + END IF + + ! compute longitude differences and ensure we stay + ! out of the forbidden "cut zone" + deltalon1 = lon1 - stdlon + IF (deltalon1 .GT. +180.D0) deltalon1 = deltalon1 - 360.D0 + IF (deltalon1 .LT. -180.D0) deltalon1 = deltalon1 + 360.D0 + + ! convert truelat1 to radian and compute cos for later use + tl1r = truelat1*RAD_PER_DEG + ctl1r = COS(tl1r) + + ! compute the radius to our known lower-left (sw) corner + rsw = rebydx*ctl1r/cone*(TAN((90.D0*hemi - lat1)*RAD_PER_DEG/2.D0)/& + TAN((90.D0*hemi - truelat1)*RAD_PER_DEG/2.D0))**cone + + ! find pole point + arg = cone*(deltalon1*RAD_PER_DEG) + polei = hemi*knowni - hemi*rsw*SIN(arg) + polej = hemi*knownj + rsw*COS(arg) + + ! compute deltalon between known longitude and standard + ! lon and ensure it is not in the cut zone + deltalon = lon - stdlon + IF (deltalon .GT. +180.D0) deltalon = deltalon - 360.D0 + IF (deltalon .LT. -180.D0) deltalon = deltalon + 360.D0 + + ! radius to desired point + rm = rebydx*ctl1r/cone*(TAN((90.D0*hemi - lat)*RAD_PER_DEG/2.D0)/& + TAN((90.D0*hemi - truelat1)*RAD_PER_DEG/2.D0))**cone + + arg = cone*(deltalon*RAD_PER_DEG) + i = polei + hemi*rm*SIN(arg) + j = polej - rm*COS(arg) + + ! finally, if we are in the southern hemisphere, flip the + ! i/j values to a coordinate system where (1,1) is the sw + ! corner (what we assume) which is different than the + ! original ncep algorithms which used the ne corner as + ! the origin in the southern hemisphere (left-hand vs. + ! right-hand coordinate?) + i = hemi*i + j = hemi*j + + ! lat-lon + ELSE IF (map_proj .EQ. 6) THEN + + IF (pole_lat .NE. 90.D0) THEN + CALL ROTATECOORDS(lat, lon, olat, olon, pole_lat, pole_lon, stdlon, -1) + lat = olat + lon = olon + stdlon + END IF + + ! make sure center lat/lon is good + IF (pole_lat .NE. 90.D0) THEN + CALL ROTATECOORDS(lat1, lon1, olat, olon, pole_lat, pole_lon, stdlon, -1) + lat1n = olat + lon1n = olon + stdlon + deltalat = lat - lat1n + deltalon = lon - lon1n + ELSE + deltalat = lat - lat1 + deltalon = lon - lon1 + END IF + + ! compute i/j + i = deltalon/loninc + j = deltalat/latinc + + i = i + knowni + j = j + knownj + + ELSE + errstat = ALGERR + WRITE(errmsg, *) "Do not know map projection ", map_proj + RETURN + END IF + + loc(1) = j + loc(2) = i + + RETURN + +END SUBROUTINE DLLTOIJ + + +!NCLFORTSTART +SUBROUTINE DIJTOLL(map_proj, truelat1, truelat2, stdlon, lat1, lon1,& + pole_lat, pole_lon, knowni, knownj, dx, dy, latinc,& + loninc, ai, aj, loc, errstat, errmsg) + USE constants, ONLY : ALGERR, PI, RAD_PER_DEG, DEG_PER_RAD, WRF_EARTH_RADIUS + + ! converts input lat/lon values to the cartesian (i,j) value + ! for the given projection. + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: loc + + INTEGER, INTENT(IN) :: map_proj + REAL(KIND=8), INTENT(IN) :: stdlon + REAL(KIND=8), INTENT(IN) :: lat1, lon1, pole_lat, pole_lon, knowni, knownj + REAL(KIND=8), INTENT(IN) :: dx, dy, latinc, loninc, ai, aj + REAL(KIND=8), INTENT(INOUT) :: truelat1, truelat2 + REAL(KIND=8), DIMENSION(2), INTENT(OUT) :: loc + INTEGER, INTENT(INOUT) :: errstat + CHARACTER(LEN=*), INTENT(INOUT) :: errmsg + +!NCLEND + + REAL(KIND=8) :: gi2 + REAL(KIND=8) :: arccos + REAL(KIND=8) :: deltalon1 + REAL(KIND=8) :: tl1r + REAL(KIND=8) :: clain, dlon, rsw, deltalon, deltalat + REAL(KIND=8) :: reflon, scale_top, ala1, alo1, polei, polej + ! earth radius divided by dx + REAL(KIND=8) :: rebydx + REAL(KIND=8) :: ctl1r, cone, hemi + + !REAL(KIND=8),PARAMETER :: PI = 3.141592653589793D0 + !REAL(KIND=8),PARAMETER :: RAD_PER_DEG = PI/180.D0 + !REAL(KIND=8),PARAMETER :: DEG_PER_RAD = 180.D0/PI + !REAL(KIND=8),PARAMETER :: RE_M = 6370000.D0 ! radius of sperical earth + + REAL(KIND=8) :: inew, jnew, r, r2 + REAL(KIND=8) :: chi, chi1, chi2 + REAL(KIND=8) :: xx, yy, lat, lon + + REAL(KIND=8) :: olat, olon, lat1n, lon1n + + + ! lat1 ! sw latitude (1,1) in degrees (-90->90n) + ! lon1 ! sw longitude (1,1) in degrees (-180->180e) + ! dx ! grid spacing in meters at truelats + ! dlat ! lat increment for lat/lon grids + ! dlon ! lon increment for lat/lon grids + ! stdlon ! longitude parallel to y-axis (-180->180e) + ! truelat1 ! first true latitude (all projections) + ! truelat2 ! second true lat (lc only) + ! hemi ! 1 for nh, -1 for sh + ! cone ! cone factor for lc projections + ! polei ! computed i-location of pole point + ! polej ! computed j-location of pole point + ! rsw ! computed radius to sw corner + ! knowni ! x-location of known lat/lon + ! knownj ! y-location of known lat/lon + ! re_m ! radius of spherical earth, meters + ! rebydx ! earth radius divided by dx + + errstat = INT(dy) ! Remove compiler warning since dy not used + errstat = 0 + + rebydx = WRF_EARTH_RADIUS/dx + + hemi = 1.0D0 + IF (truelat1 .LT. 0.0D0) THEN + hemi = -1.0D0 + END IF + + ! mercator + IF (map_proj .EQ. 3) THEN + ! preliminary variables + clain = COS(RAD_PER_DEG*truelat1) + dlon = dx/(WRF_EARTH_RADIUS*clain) + + ! compute distance from equator to origin, and store in + ! the rsw tag. + rsw = 0.D0 + IF (lat1 .NE. 0.D0) THEN + rsw = (DLOG(TAN(0.5D0*((lat1 + 90.D0)*RAD_PER_DEG))))/dlon + END IF + + lat = 2.0D0*ATAN(EXP(dlon*(rsw + aj - knownj)))*DEG_PER_RAD - 90.D0 + lon = (ai - knowni)*dlon*DEG_PER_RAD + lon1 + IF (lon .GT. 180.D0) lon = lon - 360.D0 + IF (lon .LT. -180.D0) lon = lon + 360.D0 + + ! ps + ELSE IF (map_proj .EQ. 2) THEN + + ! compute the reference longitude by rotating 90 degrees to + ! the east to find the longitude line parallel to the + ! positive x-axis. + reflon = stdlon + 90.D0 + + ! compute numerator term of map scale factor + scale_top = 1.D0 + hemi*SIN(truelat1*RAD_PER_DEG) + + ! compute radius to known point + ala1 = lat1*RAD_PER_DEG + rsw = rebydx*COS(ala1)*scale_top/(1.D0 + hemi*SIN(ala1)) + + ! find the pole point + alo1 = (lon1 - reflon)*RAD_PER_DEG + polei = knowni - rsw*COS(alo1) + polej = knownj - hemi*rsw*SIN(alo1) + + ! compute radius to point of interest + xx = ai - polei + yy = (aj - polej)*hemi + r2 = xx**2 + yy**2 + + ! now the magic code + IF (r2 .EQ. 0.D0) THEN + lat = hemi*90.D0 + lon = reflon + ELSE + gi2 = (rebydx*scale_top)**2.D0 + lat = DEG_PER_RAD*hemi*ASIN((gi2 - r2)/(gi2 + r2)) + arccos = ACOS(xx/SQRT(r2)) + IF (yy .GT. 0) THEN + lon = reflon + DEG_PER_RAD*arccos + ELSE + lon = reflon - DEG_PER_RAD*arccos + END IF + END IF + + ! convert to a -180 -> 180 east convention + IF (lon .GT. 180.D0) lon = lon - 360.D0 + IF (lon .LT. -180.D0) lon = lon + 360.D0 + + ! !lambert + ELSE IF (map_proj .EQ. 1) THEN + + IF (ABS(truelat2) .GT. 90.D0) THEN + truelat2 = truelat1 + END IF + + IF (ABS(truelat1 - truelat2) .GT. 0.1D0) THEN + cone = (DLOG(COS(truelat1*RAD_PER_DEG)) - DLOG(COS(truelat2*RAD_PER_DEG)))/& + (DLOG(TAN((90.D0 - ABS(truelat1))*RAD_PER_DEG*0.5D0)) - & + DLOG(TAN((90.D0 - ABS(truelat2))*RAD_PER_DEG*0.5D0))) + ELSE + cone = SIN(ABS(truelat1)*RAD_PER_DEG) + END IF + + ! compute longitude differences and ensure we stay out of the + ! forbidden "cut zone" + deltalon1 = lon1 - stdlon + IF (deltalon1 .GT. +180.D0) deltalon1 = deltalon1 - 360.D0 + IF (deltalon1 .LT. -180.D0) deltalon1 = deltalon1 + 360.D0 + + ! convert truelat1 to radian and compute cos for later use + tl1r = truelat1*RAD_PER_DEG + ctl1r = COS(tl1r) + + ! compute the radius to our known point + rsw = rebydx*ctl1r/cone*(TAN((90.D0*hemi - lat1)*RAD_PER_DEG/2.D0)/& + TAN((90.D0*hemi - truelat1)*RAD_PER_DEG/2.D0))**cone + + ! find pole point + alo1 = cone*(deltalon1*RAD_PER_DEG) + polei = hemi*knowni - hemi*rsw*SIN(alo1) + polej = hemi*knownj + rsw*COS(alo1) + + chi1 = (90.D0 - hemi*truelat1)*RAD_PER_DEG + chi2 = (90.D0 - hemi*truelat2)*RAD_PER_DEG + + ! see if we are in the southern hemispere and flip the + ! indices if we are. + inew = hemi*ai + jnew = hemi*aj + + ! compute radius**2 to i/j location + reflon = stdlon + 90.D0 + xx = inew - polei + yy = polej - jnew + r2 = (xx*xx + yy*yy) + r = sqrt(r2)/rebydx + + ! convert to lat/lon + IF (r2 .EQ. 0.D0) THEN + lat = hemi*90.D0 + lon = stdlon + ELSE + lon = stdlon + DEG_PER_RAD*ATAN2(hemi*xx,yy)/cone + lon = dmod(lon + 360.D0, 360.D0) + IF (chi1 .EQ. chi2) THEN + chi = 2.0D0*ATAN((r/TAN(chi1))**(1.D0/cone)*TAN(chi1*0.5D0)) + ELSE + chi = 2.0D0*ATAN((r*cone/SIN(chi1))**(1.D0/cone)*TAN(chi1*0.5D0)) + END IF + lat = (90.0D0 - chi*DEG_PER_RAD)*hemi + END IF + + IF (lon .GT. +180.D0) lon = lon - 360.D0 + IF (lon .LT. -180.D0) lon = lon + 360.D0 + + ! !lat-lon + ELSE IF (map_proj .EQ. 6) THEN + inew = ai - knowni + jnew = aj - knownj + + IF (inew .LT. 0.D0) inew = inew + 360.D0/loninc + IF (inew .GE. 360.D0/dx) inew = inew - 360.D0/loninc + + ! compute deltalat and deltalon + deltalat = jnew*latinc + deltalon = inew*loninc + + IF (pole_lat .NE. 90.D0) THEN + CALL ROTATECOORDS(lat1, lon1, olat, olon, pole_lat, pole_lon, stdlon, -1) + lat1n = olat + lon1n = olon + stdlon + lat = deltalat + lat1n + lon = deltalon + lon1n + ELSE + lat = deltalat + lat1 + lon = deltalon + lon1 + END IF + + IF (pole_lat .NE. 90.D0) THEN + lon = lon - stdlon + CALL ROTATECOORDS(lat, lon, olat, olon, pole_lat, pole_lon, stdlon, 1) + lat = olat + lon = olon + END IF + + IF (lon .LT. -180.D0) lon = lon + 360.D0 + IF (lon .GT. 180.D0) lon = lon - 360.D0 + + ELSE + errstat = ALGERR + WRITE(errmsg, *) "Do not know map projection ", map_proj + RETURN + END IF + + loc(1) = lat + loc(2) = lon + + RETURN + +END SUBROUTINE DIJTOLL diff --git a/fortran/wrf_vinterp.f90 b/fortran/wrf_vinterp.f90 new file mode 100644 index 0000000..6fb2328 --- /dev/null +++ b/fortran/wrf_vinterp.f90 @@ -0,0 +1,445 @@ +!NCLFORTSTART +SUBROUTINE wrf_monotonic(out, in, lvprs, cor, idir, delta, ew, ns, nz, icorsw) + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: out + + INTEGER, INTENT(IN) :: idir, ew, ns, nz, icorsw + REAL(KIND=8), INTENT(IN) :: delta + REAL(KIND=8), DIMENSION(ew,ns,nz), INTENT(INOUT) :: in + REAL(KIND=8), DIMENSION(ew,ns,nz), INTENT(OUT) :: out + REAL(KIND=8), DIMENSION(ew,ns,nz) :: lvprs + REAL(KIND=8), DIMENSION(ew,ns) :: cor + +!NCLEND + + INTEGER :: i, j, k, ripk, k300 + + k300 = 0 ! removes the warning + + DO j=1,ns + DO i=1,ew + IF (icorsw .EQ. 1 .AND. cor(i,j) .LT. 0.) THEN + DO k=1,nz + in(i,j,k) = -in(i,j,k) + END DO + END IF + + ! First find k index that is at or below (height-wise) + ! the 300 hPa level. + DO k = 1,nz + ripk = nz-k+1 + IF (lvprs(i,j,k) .LE. 300.D0) THEN + k300 = k + EXIT + END IF + END DO + + DO k = k300,1,-1 + IF (idir .EQ. 1) THEN + out(i,j,k) = MIN(in(i,j,k), in(i,j,k+1) + delta) + ELSE IF (idir .EQ. -1) THEN + out(i,j,k) = MAX(in(i,j,k), in(i,j,k+1) - delta) + END IF + END DO + + DO k = k300+1, nz + IF (idir .EQ. 1) THEN + out(i,j,k) = MAX(in(i,j,k), in(i,j,k-1) - delta) + ELSE IF (idir .EQ. -1) THEN + out(i,j,k) = MIN(in(i,j,k), in(i,j,k-1) + delta) + END IF + END DO + END DO + END DO + + RETURN + +END SUBROUTINE wrf_monotonic + + +!NCLFORTSTART +FUNCTION wrf_intrp_value(wvalp0, wvalp1, vlev, vcp0, vcp1, icase, errstat, errmsg) + USE constants, ONLY : ALGERR, SCLHT + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER, INTENT(IN) :: icase + REAL(KIND=8), INTENT(IN) :: wvalp0, wvalp1, vlev, vcp0, vcp1 + INTEGER, INTENT(INOUT) :: errstat + CHARACTER(LEN=*), INTENT(INOUT) :: errmsg + REAL(KIND=8) :: wrf_intrp_value + +!NCLEND + + REAL(KIND=8) :: valp0, valp1, rvalue + REAL(KIND=8) :: chkdiff + + !REAL(KIND=8), PARAMETER :: RGAS=287.04d0 + !REAL(KIND=8), PARAMETER :: USSALR=0.0065d0 + !REAL(KIND=8), PARAMETER :: SCLHT=RGAS*256.d0/9.81d0 + + errstat = 0 + + valp0 = wvalp0 + valp1 = wvalp1 + IF ( icase .EQ. 2) THEN !GHT + valp0=EXP(-wvalp0/SCLHT) + valp1=EXP(-wvalp1/SCLHT) + END IF + + chkdiff = vcp1 - vcp0 + IF(chkdiff .EQ. 0) THEN + errstat = ALGERR + errmsg = "bad difference in vcp's" + wrf_intrp_value = 0 + RETURN + !PRINT *,"bad difference in vcp's" + !STOP + END IF + + rvalue = (vlev - vcp0)*(valp1 - valp0)/(vcp1 - vcp0) + valp0 + IF (icase .EQ. 2) THEN !GHT + wrf_intrp_value = -SCLHT*LOG(rvalue) + ELSE + wrf_intrp_value = rvalue + END IF + + RETURN + +END FUNCTION wrf_intrp_value + +! NOTES: +! vcarray is the array holding the values for the vertical coordinate. +! It will always come in with the dimensions of the staggered U and V grid. + +!NCLFORTSTART +SUBROUTINE wrf_vintrp(datain, dataout, pres, tk, qvp, ght, terrain,& + sfp, smsfp, vcarray, interp_levels, numlevels,& + icase, ew, ns, nz, extrap, vcor, logp, rmsg,& + errstat, errmsg) + USE constants, ONLY : ALGERR, SCLHT, EXPON, EXPONI, GAMMA, GAMMAMD, TLCLC1, & + TLCLC2, TLCLC3, TLCLC4, THTECON1, THTECON2, THTECON3, & + CELKEL, EPS, USSALR + + IMPLICIT NONE + + !f2py threadsafe + !f2py intent(in,out) :: dataout + + INTEGER, INTENT(IN) :: ew, ns, nz, icase, extrap + INTEGER, INTENT(IN) :: vcor, numlevels, logp + REAL(KIND=8), DIMENSION(ew,ns,nz), INTENT(IN) :: datain, pres, tk, qvp + REAL(KIND=8), DIMENSION(ew,ns,nz), INTENT(IN) :: ght + REAL(KIND=8), DIMENSION(ew,ns), INTENT(IN) :: terrain, sfp, smsfp + REAL(KIND=8), DIMENSION(ew,ns,numlevels), INTENT(OUT) :: dataout + REAL(KIND=8), DIMENSION(ew,ns,nz), INTENT(IN) :: vcarray + REAL(KIND=8), DIMENSION(numlevels), INTENT(IN) :: interp_levels + REAL(KIND=8), INTENT(IN) :: rmsg + INTEGER, INTENT(INOUT) :: errstat + CHARACTER(LEN=*), INTENT(INOUT) :: errmsg + +!NCLEND + + INTEGER :: nreqlvs, ripk !njx,niy + INTEGER :: i, j, k, kupper !itriv + INTEGER :: ifound, isign !miy,mjx + REAL(KIND=8), DIMENSION(ew,ns) :: tempout + REAL(KIND=8) :: rlevel, vlev, diff + REAL(KIND=8) :: tmpvlev + REAL(KIND=8) :: vcp1, vcp0, valp0, valp1 +! REAL(KIND=8) :: cvc + REAL(KIND=8) :: vclhsl, vctophsl !qvlhsl,ttlhsl + REAL(KIND=8) :: wrf_intrp_value + REAL(KIND=8) :: plhsl, zlhsl, ezlhsl, tlhsl, psurf, pratio, tlev + REAL(KIND=8) :: ezsurf, psurfsm, zsurf, qvapor, vt + REAL(KIND=8) :: ezlev, plev, zlev, ptarget, dpmin, dp + REAL(KIND=8) :: pbot, zbot, tbotextrap, e + REAL(KIND=8) :: tlcl, gammam + CHARACTER(LEN=1) :: cvcord + + !REAL(KIND=8), PARAMETER :: RGAS = 287.04d0 !J/K/kg + !REAL(KIND=8), PARAMETER :: RGASMD = .608d0 + !REAL(KIND=8), PARAMETER :: USSALR = .0065d0 ! deg C per m + !REAL(KIND=8), PARAMETER :: SCLHT = RGAS*256.d0/9.81d0 + !REAL(KIND=8), PARAMETER :: EPS = 0.622d0 + !REAL(KIND=8), PARAMETER :: RCONST = -9.81d0/(RGAS * USSALR) + !REAL(KIND=8), PARAMETER :: EXPON = RGAS*USSALR/9.81d0 + !REAL(KIND=8), PARAMETER :: EXPONI = 1./EXPON + !REAL(KIND=8), PARAMETER :: TLCLC1 = 2840.d0 + !REAL(KIND=8), PARAMETER :: TLCLC2 = 3.5d0 + !REAL(KIND=8), PARAMETER :: TLCLC3 = 4.805d0 + !REAL(KIND=8), PARAMETER :: TLCLC4 = 55.d0 + !REAL(KIND=8), PARAMETER :: THTECON1 = 3376.d0 ! K + !REAL(KIND=8), PARAMETER :: THTECON2 = 2.54d0 + !REAL(KIND=8), PARAMETER :: THTECON3 = 0.81d0 + !REAL(KIND=8), PARAMETER :: CP = 1004.d0 + !REAL(KIND=8), PARAMETER :: CPMD = 0.887d0 + !REAL(KIND=8), PARAMETER :: GAMMA = RGAS/CP + !REAL(KIND=8), PARAMETER :: GAMMAMD = RGASMD-CPMD + !REAL(KIND=8), PARAMETER :: CELKEL = 273.16d0 + + ! Removes the warnings for uninitialized variables + cvcord = '' + plev = 0 + zlev = 0 + vlev = 0 + errstat = 0 + + IF (vcor .EQ. 1) THEN + cvcord = 'p' + ELSE IF ((vcor .EQ. 2) .OR. (vcor .EQ. 3)) THEN + cvcord = 'z' + ELSE IF ((vcor .EQ. 4) .OR. (vcor .EQ. 5)) THEN + cvcord = 't' + END IF + + !miy = ns + !mjx = ew + !njx = ew + !niy = ns + + DO j = 1,ns + DO i = 1,ew + tempout(i,j) = rmsg + END DO + END DO + + DO nreqlvs = 1,numlevels + IF (cvcord .EQ. 'z') THEN + ! Convert rlevel to meters from km + rlevel = interp_levels(nreqlvs) * 1000.D0 + vlev = EXP(-rlevel/SCLHT) + ELSE IF (cvcord .EQ. 'p') THEN + vlev = interp_levels(nreqlvs) + ELSE IF (cvcord .EQ. 't') THEN + vlev = interp_levels(nreqlvs) + END IF + + DO j=1,ns + DO i=1,ew + ! Get the interpolated value that is within the model domain + ifound = 0 + DO k = 1,nz-1 + ripk = nz-k+1 + vcp1 = vcarray(i,j,ripk-1) + vcp0 = vcarray(i,j,ripk) + valp0 = datain(i,j,ripk) + valp1 = datain(i,j,ripk-1) + + IF ((vlev .GE. vcp0 .AND. vlev .LE. vcp1) .OR. & + (vlev .LE. vcp0 .AND. vlev .GE. vcp1)) THEN + ! print *,i,j,valp0,valp1 + IF ((valp0 .EQ. rmsg) .OR. (valp1 .EQ. rmsg)) THEN + tempout(i,j) = rmsg + ifound = 1 + ELSE + IF (logp .EQ. 1) THEN + vcp1 = LOG(vcp1) + vcp0 = LOG(vcp0) + IF (vlev .EQ. 0.0D0) THEN + errstat = ALGERR + WRITE(errmsg, *) "Pres=0. Unable to take log of 0." + RETURN + !PRINT *,"Pressure value = 0" + !PRINT *,"Unable to take log of 0" + !STOP + END IF + tmpvlev = LOG(vlev) + ELSE + tmpvlev = vlev + END IF + tempout(i,j) = wrf_intrp_value(valp0, valp1, tmpvlev, vcp0, & + vcp1, icase, errstat, errmsg) + IF (errstat .NE. 0) THEN + RETURN + END IF + + ! print *,"one ",i,j,tempout(i,j) + ifound = 1 + END IF + !GOTO 115 ! EXIT + EXIT + END IF + END DO !end for the k loop + !115 CONTINUE + + IF (ifound .EQ. 1) THEN !Grid point is in the model domain + !GOTO 333 ! CYCLE + CYCLE + END IF + + !If the user has requested no extrapolatin then just assign + !all values above or below the model level to rmsg. + IF (extrap .EQ. 0) THEN + tempout(i,j) = rmsg + !GOTO 333 ! CYCLE + CYCLE + END IF + + ! The grid point is either above or below the model domain + ! First we will check to see if the grid point is above the + ! model domain. + vclhsl = vcarray(i,j,1) !lowest model level + vctophsl = vcarray(i,j,nz) !highest model level + diff = vctophsl - vclhsl + isign = NINT(diff/ABS(diff)) + + IF (isign*vlev .GE. isign*vctophsl) THEN + ! Assign the highest model level to the out array + tempout(i,j) = datain(i,j,nz) + ! print *,"at warn",i,j,tempout(i,j) + !GOTO 333 ! CYCLE + CYCLE + END IF + + ! Only remaining possibility is that the specified level is below + ! lowest model level. If lowest model level value is missing, + ! set interpolated value to missing. + + IF (datain(i,j,1) .EQ. rmsg) THEN + tempout(i,j) = rmsg + !GOTO 333 ! CYCLE + CYCLE + END IF + + ! If the field comming in is not a pressure,temperature or height + ! field we can set the output array to the value at the lowest + ! model level. + + tempout(i,j) = datain(i,j,1) + + ! For the special cases of pressure on height levels or height on + ! pressure levels, or temperature-related variables on pressure or + ! height levels, perform a special extrapolation based on + ! US Standard Atmosphere. Here we calcualate the surface pressure + ! with the altimeter equation. This is how RIP calculates the + ! surface pressure. + IF (icase .GT. 0) THEN + plhsl = pres(i,j,1) * 0.01D0 !pressure at lowest model level + zlhsl = ght(i,j,1) !grid point height a lowest model level + ezlhsl = EXP(-zlhsl/SCLHT) + tlhsl = tk(i,j,1) !temperature in K at lowest model level + zsurf = terrain(i,j) + qvapor = MAX((qvp(i,j,1)*.001D0),1.e-15) + ! virtual temperature + ! vt = tlhsl * (eps + qvapor)/(eps*(1.0 + qvapor)) + ! psurf = plhsl * (vt/(vt+USSALR * (zlhsl-zsurf)))**rconst + psurf = sfp(i,j) + psurfsm = smsfp(i,j) + ezsurf = EXP(-zsurf/SCLHT) + + ! The if for checking above ground + IF ((cvcord .EQ. 'z' .AND. vlev .LT. ezsurf) .OR. & + (cvcord .EQ. 'p' .AND. vlev .LT. psurf)) THEN + + ! We are below the lowest data level but above the ground. + ! Use linear interpolation (linear in prs and exp-height). + + IF (cvcord .EQ. 'p') THEN + plev = vlev + ezlev = ((plev - plhsl)*& + ezsurf + (psurf - plev)*ezlhsl)/(psurf - plhsl) + zlev = -SCLHT*LOG(ezlev) + IF (icase .EQ. 2) THEN + tempout(i,j) = zlev + !GOTO 333 ! CYCLE + CYCLE + END IF + + ELSE IF (cvcord .EQ. 'z') THEN + ezlev = vlev + zlev = -SCLHT*LOG(ezlev) + plev = ((ezlev - ezlhsl)*& + psurf + (ezsurf - ezlev)*plhsl)/(ezsurf - ezlhsl) + IF (icase .EQ. 1) THEN + tempout(i,j) = plev + !GOTO 333 ! CYCLE + CYCLE + END IF + END IF + + ELSE !else for checking above ground + ptarget = psurfsm - 150.D0 + dpmin = 1.e4 + DO k=1,nz + ripk = nz-k+1 + dp = ABS((pres(i,j,ripk) * 0.01D0) - ptarget) + IF (dp .GT. dpmin) THEN + !GOTO 334 ! EXIT + EXIT + END IF + dpmin = MIN(dpmin, dp) + END DO + !334 + kupper = k-1 + + ripk = nz - kupper + 1 + pbot = MAX(plhsl,psurf) + zbot = MIN(zlhsl,zsurf) + pratio = pbot/(pres(i,j,ripk) * 0.01D0) + tbotextrap = tk(i,j,ripk)*(pratio)**EXPON + ! virtual temperature + vt = tbotextrap * (EPS + qvapor)/(EPS*(1.0D0 + qvapor)) + IF (cvcord .EQ. 'p') THEN + plev = vlev + zlev = zbot + vt/USSALR*(1. - (vlev/pbot)**EXPON) + IF (icase .EQ. 2) THEN + tempout(i,j) = zlev + !GOTO 333 ! CYCLE + CYCLE + END IF + ELSE IF (cvcord .EQ. 'z') THEN + zlev = -sclht*LOG(vlev) + plev = pbot*(1. + USSALR/vt*(zbot - zlev))**EXPONI + IF (icase .EQ. 1) THEN + tempout(i,j) = plev + !GOTO 333 ! CYCLE + CYCLE + END IF + END IF + END IF !end if for checking above ground + END IF !for icase gt 0 + + IF (icase .GT. 2) THEN !extrapolation for temperature + tlev = tlhsl + (zlhsl - zlev)*USSALR + qvapor = MAX(qvp(i,j,1), 1.e-15) + gammam = GAMMA*(1. + GAMMAMD*qvapor) + IF (icase .EQ. 3) THEN + tempout(i,j) = tlev - CELKEL + ELSE IF (icase .EQ. 4) THEN + tempout(i,j) = tlev + ! Potential temperature - theta + ELSE IF (icase .EQ. 5) THEN + tempout(i,j) = tlev*(1000.D0/plev)**gammam + ! extraolation for equivalent potential temperature + ELSE IF (icase .EQ. 6) THEN + e = qvapor*plev/(EPS + qvapor) + tlcl = TLCLC1/(LOG(tlev**TLCLC2/e) - TLCLC3) + TLCLC4 + tempout(i,j)=tlev*(1000.D0/plev)**(gammam)*& + EXP((THTECON1/tlcl - THTECON2)*& + qvapor*(1. + THTECON3*qvapor)) + END IF + END IF + + !333 CONTINUE + + END DO + END DO + + ! print *,"----done----",interp_levels(nreqlvs) + DO j = 1,ns + DO i = 1,ew + dataout(i,j,nreqlvs) = tempout(i,j) + END DO + END DO + + END DO !end for the nreqlvs + + RETURN + +END SUBROUTINE wrf_vintrp diff --git a/fortran/wrffortran.pyf b/fortran/wrffortran.pyf index d2a2698..fe3f9ad 100644 --- a/fortran/wrffortran.pyf +++ b/fortran/wrffortran.pyf @@ -3,18 +3,269 @@ python module _wrffortran ! in interface ! in :_wrffortran + subroutine dcalcuh(nx,ny,nz,nzp1,zp,mapfct,dx,dy,uhmnhgt,uhmxhgt,us,vs,w,uh,tem1,tem2) ! in :_wrffortran:calc_uh.f90 + threadsafe + integer, optional,intent(in),check(shape(zp,0)==nx),depend(zp) :: nx=shape(zp,0) + integer, optional,intent(in),check(shape(zp,1)==ny),depend(zp) :: ny=shape(zp,1) + integer, optional,intent(in),check(shape(us,2)==nz),depend(us) :: nz=shape(us,2) + integer, optional,intent(in),check(shape(zp,2)==nzp1),depend(zp) :: nzp1=shape(zp,2) + real(kind=8) dimension(nx,ny,nzp1),intent(in) :: zp + real(kind=8) dimension(nx,ny),intent(in),depend(nx,ny) :: mapfct + real(kind=8) intent(in) :: dx + real(kind=8) intent(in) :: dy + real(kind=8) intent(in) :: uhmnhgt + real(kind=8) intent(in) :: uhmxhgt + real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny) :: us + real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: vs + real(kind=8) dimension(nx,ny,nzp1),intent(in),depend(nx,ny,nzp1) :: w + real(kind=8) dimension(nx,ny),intent(out,in),depend(nx,ny) :: uh + real(kind=8) dimension(nx,ny,nz),intent(inout),depend(nx,ny,nz) :: tem1 + real(kind=8) dimension(nx,ny,nz),intent(inout),depend(nx,ny,nz) :: tem2 + end subroutine dcalcuh + subroutine dcloudfrac(pres,rh,lowc,midc,highc,nz,ns,ew) ! in :_wrffortran:cloud_fracf.f90 + threadsafe + real(kind=8) dimension(ew,ns,nz),intent(in) :: pres + real(kind=8) dimension(ew,ns,nz),intent(in),depend(ew,ns,nz) :: rh + real(kind=8) dimension(ew,ns),intent(out,in),depend(ew,ns) :: lowc + real(kind=8) dimension(ew,ns),intent(out,in),depend(ew,ns) :: midc + real(kind=8) dimension(ew,ns),intent(out,in),depend(ew,ns) :: highc + integer, optional,check(shape(pres,2)==nz),depend(pres) :: nz=shape(pres,2) + integer, optional,check(shape(pres,1)==ns),depend(pres) :: ns=shape(pres,1) + integer, optional,check(shape(pres,0)==ew),depend(pres) :: ew=shape(pres,0) + end subroutine dcloudfrac module constants ! in :_wrffortran:constants.f90 + real(kind=8), parameter,optional :: wrf_earth_radius=6370000.d0 + real(kind=8), parameter,optional :: rhowat=1000.d0 + real(kind=8), parameter,optional :: t_base=300.0 + real(kind=8), parameter,optional :: cp=1004.d0 + real(kind=8), parameter,optional :: thtecon1=3376.d0 + real(kind=8), parameter,optional :: thtecon3=.81d0 + real(kind=8), parameter,optional :: thtecon2=2.54d0 real(kind=8), parameter,optional :: p1000mb=100000.d0 - real(kind=8), parameter,optional :: r=287.04d0 + real(kind=8), parameter,optional :: rv=461.5d0 + real(kind=8), parameter,optional,depend(pi) :: rad_per_deg=pi/180.d0 + real(kind=8), parameter,optional :: rd=287.04d0 + real(kind=8), parameter,optional :: abscoef=.145d0 + real(kind=8), parameter,optional :: celkel=273.15d0 + real(kind=8), parameter,optional :: abscoefi=.272d0 + real(kind=8), parameter,optional :: eslcon2=29.65d0 + real(kind=8), parameter,optional :: eslcon1=17.67d0 + real(kind=8), parameter,optional :: pi=3.141592653589793d0 + real(kind=8), parameter,optional :: tlclc2=3.5d0 + real(kind=8), parameter,optional :: tlclc3=4.805d0 + real(kind=8), parameter,optional :: rho_g=400.d0 + real(kind=8), parameter,optional :: tlclc1=2840.d0 + real(kind=8), parameter,optional :: tlclc4=55.d0 + real(kind=8), parameter,optional,depend(pi) :: deg_per_rad=180.d0/pi + real(kind=8), parameter,optional :: cpmd=.887d0 + real(kind=8), parameter,optional,depend(rd,g) :: sclht=rd*256.d0/g + real(kind=8), parameter,optional :: ussalr=0.0065d0 + real(kind=8), parameter,optional :: default_fill=9.9692099683868690d36 + real(kind=8), parameter,optional :: rho_s=100.d0 + real(kind=8), parameter,optional,depend(rhowat) :: rho_r=1000.0 + real(kind=8), parameter,optional :: alpha=0.224d0 + real(kind=8), parameter,optional :: celkel_triple=273.16d0 + real(kind=8), parameter,optional :: ezero=6.112d0 + real(kind=8), parameter,optional,depend(rd,ussalr,g) :: expon=0.190189602446 + real(kind=8), parameter,optional :: rgasmd=.608d0 real(kind=8), parameter,optional :: g=9.81d0 - real(kind=8), parameter,optional :: r_d=287.d0 - real(kind=8), parameter,optional,depend(r_d) :: cp=7.d0*r_d/2.d0 integer, optional :: errlen=512 - real(kind=8), parameter,optional :: gamma=0.0065d0 + real(kind=8), parameter,optional :: eps=0.622d0 + real(kind=8), parameter,optional :: gamma_seven=720.d0 + real(kind=8), parameter,optional,depend(cpmd,rgasmd) :: gammamd=-0.279 + integer, optional :: algerr=64 + real(kind=8), parameter,optional,depend(cp,rd) :: gamma=0.285896414343 + real(kind=8), parameter,optional,depend(expon,rd,ussalr,g) :: exponi=5.25791098534 end module constants + subroutine deqthecalc(qvp,tmk,prs,eth,miy,mjx,mkzh) ! in :_wrffortran:eqthecalc.f90 + threadsafe + use constants, only: tlclc2,tlclc3,tlclc1,tlclc4,eps,thtecon3,gammamd,thtecon1,gamma,thtecon2 + real(kind=8) dimension(miy,mjx,mkzh),intent(in) :: qvp + real(kind=8) dimension(miy,mjx,mkzh),intent(in),depend(miy,mjx,mkzh) :: tmk + real(kind=8) dimension(miy,mjx,mkzh),intent(in),depend(miy,mjx,mkzh) :: prs + real(kind=8) dimension(miy,mjx,mkzh),intent(out,in),depend(miy,mjx,mkzh) :: eth + integer, optional,intent(in),check(shape(qvp,0)==miy),depend(qvp) :: miy=shape(qvp,0) + integer, optional,intent(in),check(shape(qvp,1)==mjx),depend(qvp) :: mjx=shape(qvp,1) + integer, optional,intent(in),check(shape(qvp,2)==mkzh),depend(qvp) :: mkzh=shape(qvp,2) + end subroutine deqthecalc + function tvirtual(temp,ratmix) ! in :_wrffortran:rip_cape.f90 + threadsafe + use constants, only: eps + real(kind=8) intent(in) :: temp + real(kind=8) intent(in) :: ratmix + real(kind=8) :: tvirtual + end function tvirtual + function tonpsadiabat(thte,prs,psadithte,psadiprs,psaditmk,gamma,errstat,errmsg) ! in :_wrffortran:rip_cape.f90 + threadsafe + use constants, only: algerr + real(kind=8) intent(in) :: thte + real(kind=8) intent(in) :: prs + real(kind=8) dimension(150),intent(in) :: psadithte + real(kind=8) dimension(150),intent(in) :: psadiprs + real(kind=8) dimension(150,150),intent(in) :: psaditmk + real(kind=8) intent(in) :: gamma + integer intent(inout) :: errstat + character*(*) intent(inout) :: errmsg + real(kind=8) :: tonpsadiabat + end function tonpsadiabat + subroutine dlookup_table(psadithte,psadiprs,psaditmk,fname,errstat,errmsg) ! in :_wrffortran:rip_cape.f90 + threadsafe + use constants, only: algerr + real(kind=8) dimension(150),intent(inout) :: psadithte + real(kind=8) dimension(150),intent(inout) :: psadiprs + real(kind=8) dimension(150,150),intent(inout) :: psaditmk + character*(*) intent(in) :: fname + integer intent(inout) :: errstat + character*(*) intent(inout) :: errmsg + end subroutine dlookup_table + subroutine dpfcalc(prs,sfp,pf,miy,mjx,mkzh,ter_follow) ! in :_wrffortran:rip_cape.f90 + real(kind=8) dimension(miy,mjx,mkzh),intent(in) :: prs + real(kind=8) dimension(miy,mjx),intent(in),depend(miy,mjx) :: sfp + real(kind=8) dimension(miy,mjx,mkzh),intent(out),depend(miy,mjx,mkzh) :: pf + integer, optional,intent(in),check(shape(prs,0)==miy),depend(prs) :: miy=shape(prs,0) + integer, optional,intent(in),check(shape(prs,1)==mjx),depend(prs) :: mjx=shape(prs,1) + integer, optional,intent(in),check(shape(prs,2)==mkzh),depend(prs) :: mkzh=shape(prs,2) + integer intent(in) :: ter_follow + end subroutine dpfcalc + subroutine dcapecalc3d(prs,tmk,qvp,ght,ter,sfp,cape,cin,cmsg,miy,mjx,mkzh,i3dflag,ter_follow,psafile,errstat,errmsg) ! in :_wrffortran:rip_cape.f90 + threadsafe + use constants, only: tlclc2,gamma,tlclc1,rgasmd,tlclc4,g,tlclc3,thtecon3,eps,rd,cpmd,celkel,gammamd,eslcon2,eslcon1,cp,thtecon1,algerr,ezero,thtecon2 + real(kind=8) dimension(miy,mjx,mkzh),intent(in) :: prs + real(kind=8) dimension(miy,mjx,mkzh),intent(in),depend(miy,mjx,mkzh) :: tmk + real(kind=8) dimension(miy,mjx,mkzh),intent(in),depend(miy,mjx,mkzh) :: qvp + real(kind=8) dimension(miy,mjx,mkzh),intent(in),depend(miy,mjx,mkzh) :: ght + real(kind=8) dimension(miy,mjx),intent(in),depend(miy,mjx) :: ter + real(kind=8) dimension(miy,mjx),intent(in),depend(miy,mjx) :: sfp + real(kind=8) dimension(miy,mjx,mkzh),intent(out,in),depend(miy,mjx,mkzh) :: cape + real(kind=8) dimension(miy,mjx,mkzh),intent(out,in),depend(miy,mjx,mkzh) :: cin + real(kind=8) intent(in) :: cmsg + integer, optional,intent(in),check(shape(prs,0)==miy),depend(prs) :: miy=shape(prs,0) + integer, optional,intent(in),check(shape(prs,1)==mjx),depend(prs) :: mjx=shape(prs,1) + integer, optional,intent(in),check(shape(prs,2)==mkzh),depend(prs) :: mkzh=shape(prs,2) + integer intent(in) :: i3dflag + integer intent(in) :: ter_follow + character*(*) intent(in) :: psafile + integer intent(inout) :: errstat + character*(*) intent(inout) :: errmsg + end subroutine dcapecalc3d + subroutine wrfcttcalc(prs,tk,qci,qcw,qvp,ght,ter,ctt,haveqci,ew,ns,nz) ! in :_wrffortran:wrf_fctt.f90 + threadsafe + use constants, only: g,eps,rd,ussalr,abscoefi,abscoef,celkel + real(kind=8) dimension(ew,ns,nz),intent(in) :: prs + real(kind=8) dimension(ew,ns,nz),intent(in),depend(ew,ns,nz) :: tk + real(kind=8) dimension(ew,ns,nz),intent(in),depend(ew,ns,nz) :: qci + real(kind=8) dimension(ew,ns,nz),intent(in),depend(ew,ns,nz) :: qcw + real(kind=8) dimension(ew,ns,nz),intent(in),depend(ew,ns,nz) :: qvp + real(kind=8) dimension(ew,ns,nz),intent(in),depend(ew,ns,nz) :: ght + real(kind=8) dimension(ew,ns),intent(in),depend(ew,ns) :: ter + real(kind=8) dimension(ew,ns),intent(out,in),depend(ew,ns) :: ctt + integer intent(in) :: haveqci + integer, optional,intent(in),check(shape(prs,0)==ew),depend(prs) :: ew=shape(prs,0) + integer, optional,intent(in),check(shape(prs,1)==ns),depend(prs) :: ns=shape(prs,1) + integer, optional,intent(in),check(shape(prs,2)==nz),depend(prs) :: nz=shape(prs,2) + end subroutine wrfcttcalc + subroutine dcomputeabsvort(av,u,v,msfu,msfv,msft,cor,dx,dy,nx,ny,nz,nxp1,nyp1) ! in :_wrffortran:wrf_pvo.f90 + threadsafe + real(kind=8) dimension(nx,ny,nz),intent(out,in) :: av + real(kind=8) dimension(nxp1,ny,nz),intent(in),depend(ny,nz) :: u + real(kind=8) dimension(nx,nyp1,nz),intent(in),depend(nx,nz) :: v + real(kind=8) dimension(nxp1,ny),intent(in),depend(nxp1,ny) :: msfu + real(kind=8) dimension(nx,nyp1),intent(in),depend(nx,nyp1) :: msfv + real(kind=8) dimension(nx,ny),intent(in),depend(nx,ny) :: msft + real(kind=8) dimension(nx,ny),intent(in),depend(nx,ny) :: cor + real(kind=8) :: dx + real(kind=8) :: dy + integer, optional,intent(in),check(shape(av,0)==nx),depend(av) :: nx=shape(av,0) + integer, optional,intent(in),check(shape(av,1)==ny),depend(av) :: ny=shape(av,1) + integer, optional,intent(in),check(shape(av,2)==nz),depend(av) :: nz=shape(av,2) + integer, optional,intent(in),check(shape(u,0)==nxp1),depend(u) :: nxp1=shape(u,0) + integer, optional,intent(in),check(shape(v,1)==nyp1),depend(v) :: nyp1=shape(v,1) + end subroutine dcomputeabsvort + subroutine dcomputepv(pv,u,v,theta,prs,msfu,msfv,msft,cor,dx,dy,nx,ny,nz,nxp1,nyp1) ! in :_wrffortran:wrf_pvo.f90 + threadsafe + use constants, only: g + real(kind=8) dimension(nx,ny,nz),intent(out,in) :: pv + real(kind=8) dimension(nxp1,ny,nz),intent(in),depend(ny,nz) :: u + real(kind=8) dimension(nx,nyp1,nz),intent(in),depend(nx,nz) :: v + real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: theta + real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: prs + real(kind=8) dimension(nxp1,ny),intent(in),depend(nxp1,ny) :: msfu + real(kind=8) dimension(nx,nyp1),intent(in),depend(nx,nyp1) :: msfv + real(kind=8) dimension(nx,ny),intent(in),depend(nx,ny) :: msft + real(kind=8) dimension(nx,ny),intent(in),depend(nx,ny) :: cor + real(kind=8) :: dx + real(kind=8) :: dy + integer, optional,intent(in),check(shape(pv,0)==nx),depend(pv) :: nx=shape(pv,0) + integer, optional,intent(in),check(shape(pv,1)==ny),depend(pv) :: ny=shape(pv,1) + integer, optional,intent(in),check(shape(pv,2)==nz),depend(pv) :: nz=shape(pv,2) + integer, optional,intent(in),check(shape(u,0)==nxp1),depend(u) :: nxp1=shape(u,0) + integer, optional,intent(in),check(shape(v,1)==nyp1),depend(v) :: nyp1=shape(v,1) + end subroutine dcomputepv + subroutine dcomputepw(p,tv,qv,ht,pw,nx,ny,nz,nzh) ! in :_wrffortran:wrf_pw.f90 + threadsafe + use constants, only: rd + real(kind=8) dimension(nx,ny,nz),intent(in) :: p + real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: tv + real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: qv + real(kind=8) dimension(nx,ny,nzh),intent(in),depend(nx,ny) :: ht + real(kind=8) dimension(nx,ny),intent(out,in),depend(nx,ny) :: pw + integer, optional,intent(in),check(shape(p,0)==nx),depend(p) :: nx=shape(p,0) + integer, optional,intent(in),check(shape(p,1)==ny),depend(p) :: ny=shape(p,1) + integer, optional,intent(in),check(shape(p,2)==nz),depend(p) :: nz=shape(p,2) + integer, optional,intent(in),check(shape(ht,2)==nzh),depend(ht) :: nzh=shape(ht,2) + end subroutine dcomputepw + subroutine dcalrelhl(u,v,ght,ter,top,sreh,miy,mjx,mkzh) ! in :_wrffortran:wrf_relhl.f90 + threadsafe + use constants, only: rad_per_deg,deg_per_rad,pi + real(kind=8) dimension(miy,mjx,mkzh),intent(in) :: u + real(kind=8) dimension(miy,mjx,mkzh),intent(in),depend(miy,mjx,mkzh) :: v + real(kind=8) dimension(miy,mjx,mkzh),intent(in),depend(miy,mjx,mkzh) :: ght + real(kind=8) dimension(miy,mjx),intent(in),depend(miy,mjx) :: ter + real(kind=8) intent(in) :: top + real(kind=8) dimension(miy,mjx),intent(out,in),depend(miy,mjx) :: sreh + integer, optional,intent(in),check(shape(u,0)==miy),depend(u) :: miy=shape(u,0) + integer, optional,intent(in),check(shape(u,1)==mjx),depend(u) :: mjx=shape(u,1) + integer, optional,intent(in),check(shape(u,2)==mkzh),depend(u) :: mkzh=shape(u,2) + end subroutine dcalrelhl + subroutine wetbulbcalc(prs,tmk,qvp,twb,nx,ny,nz,psafile,errstat,errmsg) ! in :_wrffortran:wrf_rip_phys_routines.f90 + threadsafe + use constants, only: tlclc2,tlclc3,tlclc1,tlclc4,eps,thtecon3,gammamd,thtecon1,algerr,gamma,thtecon2 + real(kind=8) dimension(nx,ny,nz),intent(in) :: prs + real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: tmk + real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: qvp + real(kind=8) dimension(nx,ny,nz),intent(out,in),depend(nx,ny,nz) :: twb + integer, optional,intent(in),check(shape(prs,0)==nx),depend(prs) :: nx=shape(prs,0) + integer, optional,intent(in),check(shape(prs,1)==ny),depend(prs) :: ny=shape(prs,1) + integer, optional,intent(in),check(shape(prs,2)==nz),depend(prs) :: nz=shape(prs,2) + character*(*) intent(in) :: psafile + integer intent(inout) :: errstat + character*(*) intent(inout) :: errmsg + end subroutine wetbulbcalc + subroutine omgcalc(qvp,tmk,www,prs,omg,mx,my,mz) ! in :_wrffortran:wrf_rip_phys_routines.f90 + threadsafe + use constants, only: rd,eps,g + real(kind=8) dimension(mx,my,mz),intent(in) :: qvp + real(kind=8) dimension(mx,my,mz),intent(in),depend(mx,my,mz) :: tmk + real(kind=8) dimension(mx,my,mz),intent(in),depend(mx,my,mz) :: www + real(kind=8) dimension(mx,my,mz),intent(in),depend(mx,my,mz) :: prs + real(kind=8) dimension(mx,my,mz),intent(out,in),depend(mx,my,mz) :: omg + integer, optional,intent(in),check(shape(qvp,0)==mx),depend(qvp) :: mx=shape(qvp,0) + integer, optional,intent(in),check(shape(qvp,1)==my),depend(qvp) :: my=shape(qvp,1) + integer, optional,intent(in),check(shape(qvp,2)==mz),depend(qvp) :: mz=shape(qvp,2) + end subroutine omgcalc + subroutine virtual_temp(temp,ratmix,tv,nx,ny,nz) ! in :_wrffortran:wrf_rip_phys_routines.f90 + threadsafe + use constants, only: eps + real(kind=8) dimension(nx,ny,nz),intent(in) :: temp + real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: ratmix + real(kind=8) dimension(nx,ny,nz),intent(out,in),depend(nx,ny,nz) :: tv + integer, optional,intent(in),check(shape(temp,0)==nx),depend(temp) :: nx=shape(temp,0) + integer, optional,intent(in),check(shape(temp,1)==ny),depend(temp) :: ny=shape(temp,1) + integer, optional,intent(in),check(shape(temp,2)==nz),depend(temp) :: nz=shape(temp,2) + end subroutine virtual_temp subroutine dcomputepi(pi,pressure,nx,ny,nz) ! in :_wrffortran:wrf_user.f90 threadsafe - use constants, only: p1000mb,cp,r_d + use constants, only: rd,p1000mb,cp real(kind=8) dimension(nx,ny,nz),intent(out,in) :: pi real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: pressure integer, optional,intent(in),check(shape(pi,0)==nx),depend(pi) :: nx=shape(pi,0) @@ -23,7 +274,7 @@ python module _wrffortran ! in end subroutine dcomputepi subroutine dcomputetk(tk,pressure,theta,nx) ! in :_wrffortran:wrf_user.f90 threadsafe - use constants, only: p1000mb,cp,r_d + use constants, only: rd,p1000mb,cp real(kind=8) dimension(nx),intent(out,in) :: tk real(kind=8) dimension(nx),intent(in),depend(nx) :: pressure real(kind=8) dimension(nx),intent(in),depend(nx) :: theta @@ -74,7 +325,7 @@ python module _wrffortran ! in end subroutine dinterp1d subroutine dcomputeseaprs(nx,ny,nz,z,t,p,q,sea_level_pressure,t_sea_level,t_surf,level,errstat,errmsg) ! in :_wrffortran:wrf_user.f90 threadsafe - use constants, only: r,errlen,gamma,g + use constants, only: rd,ussalr,algerr,g integer, optional,intent(in),check(shape(z,0)==nx),depend(z) :: nx=shape(z,0) integer, optional,intent(in),check(shape(z,1)==ny),depend(z) :: ny=shape(z,1) integer, optional,intent(in),check(shape(z,2)==nz),depend(z) :: nz=shape(z,2) @@ -86,8 +337,8 @@ python module _wrffortran ! in real(kind=8) dimension(nx,ny),intent(inout),depend(nx,ny) :: t_sea_level real(kind=8) dimension(nx,ny),intent(inout),depend(nx,ny) :: t_surf integer dimension(nx,ny),intent(inout),depend(nx,ny) :: level - integer, optional,intent(inout) :: errstat - character*errlen, optional,intent(inout) :: errmsg + integer intent(inout) :: errstat + character*(*) intent(inout) :: errmsg end subroutine dcomputeseaprs subroutine dfilter2d(a,b,nx,ny,it,missing) ! in :_wrffortran:wrf_user.f90 threadsafe @@ -109,6 +360,7 @@ python module _wrffortran ! in end subroutine filter2d subroutine dcomputerh(qv,p,t,rh,nx) ! in :_wrffortran:wrf_user.f90 threadsafe + use constants, only: rv,eps,rd,ezero,eslcon2,eslcon1,celkel real(kind=8) dimension(nx),intent(in) :: qv real(kind=8) dimension(nx),intent(in),depend(nx) :: p real(kind=8) dimension(nx),intent(in),depend(nx) :: t @@ -165,16 +417,144 @@ python module _wrffortran ! in integer, optional,intent(in),check(shape(iclw,1)==ny),depend(iclw) :: ny=shape(iclw,1) integer, optional,intent(in),check(shape(pressure,2)==nz),depend(pressure) :: nz=shape(pressure,2) end subroutine dcomputeiclw - subroutine testfunc(a,b,nx,ny,nz,errstat,errstr) ! in :_wrffortran:wrf_user.f90 - threadsafe + subroutine testfunc(a,b,c,nx,ny,nz,errstat,errmsg) ! in :_wrffortran:wrf_user.f90 + use constants, only: algerr real(kind=8) dimension(nx,ny,nz),intent(in) :: a real(kind=8) dimension(nx,ny,nz),intent(out,in),depend(nx,ny,nz) :: b + character*(*) intent(in) :: c integer, optional,intent(in),check(shape(a,0)==nx),depend(a) :: nx=shape(a,0) integer, optional,intent(in),check(shape(a,1)==ny),depend(a) :: ny=shape(a,1) integer, optional,intent(in),check(shape(a,2)==nz),depend(a) :: nz=shape(a,2) - integer, optional,intent(inout) :: errstat - character*512, optional,intent(inout) :: errstr + integer intent(inout) :: errstat + character*(*) intent(inout) :: errmsg end subroutine testfunc + subroutine calcdbz(prs,tmk,qvp,qra,qsn,qgr,sn0,ivarint,iliqskin,dbz,nx,ny,nz) ! in :_wrffortran:wrf_user_dbz.f90 + threadsafe + use constants, only: rho_g,gamma_seven,rho_r,rd,rho_s,alpha,rhowat,pi,celkel + real(kind=8) dimension(nx,ny,nz),intent(in) :: prs + real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: tmk + real(kind=8) dimension(nx,ny,nz),intent(inout),depend(nx,ny,nz) :: qvp + real(kind=8) dimension(nx,ny,nz),intent(inout),depend(nx,ny,nz) :: qra + real(kind=8) dimension(nx,ny,nz),intent(inout),depend(nx,ny,nz) :: qsn + real(kind=8) dimension(nx,ny,nz),intent(inout),depend(nx,ny,nz) :: qgr + integer intent(in) :: sn0 + integer intent(in) :: ivarint + integer intent(in) :: iliqskin + real(kind=8) dimension(nx,ny,nz),intent(out,in),depend(nx,ny,nz) :: dbz + integer, optional,intent(in),check(shape(prs,0)==nx),depend(prs) :: nx=shape(prs,0) + integer, optional,intent(in),check(shape(prs,1)==ny),depend(prs) :: ny=shape(prs,1) + integer, optional,intent(in),check(shape(prs,2)==nz),depend(prs) :: nz=shape(prs,2) + end subroutine calcdbz + subroutine rotatecoords(ilat,ilon,olat,olon,lat_np,lon_np,lon_0,direction) ! in :_wrffortran:wrf_user_latlon_routines.f90 + threadsafe + use constants, only: rad_per_deg,deg_per_rad,pi + real(kind=8) intent(in) :: ilat + real(kind=8) intent(in) :: ilon + real(kind=8) intent(out,in) :: olat + real(kind=8) intent(out,in) :: olon + real(kind=8) intent(in) :: lat_np + real(kind=8) intent(in) :: lon_np + real(kind=8) intent(in) :: lon_0 + integer intent(in) :: direction + end subroutine rotatecoords + subroutine dlltoij(map_proj,truelat1,truelat2,stdlon,lat1,lon1,pole_lat,pole_lon,knowni,knownj,dx,dy,latinc,loninc,lat,lon,loc,errstat,errmsg) ! in :_wrffortran:wrf_user_latlon_routines.f90 + threadsafe + use constants, only: rad_per_deg,deg_per_rad,pi,algerr,wrf_earth_radius + integer intent(in) :: map_proj + real(kind=8) intent(inout) :: truelat1 + real(kind=8) intent(inout) :: truelat2 + real(kind=8) intent(in) :: stdlon + real(kind=8) intent(in) :: lat1 + real(kind=8) intent(in) :: lon1 + real(kind=8) intent(in) :: pole_lat + real(kind=8) intent(in) :: pole_lon + real(kind=8) intent(in) :: knowni + real(kind=8) intent(in) :: knownj + real(kind=8) intent(in) :: dx + real(kind=8) intent(in) :: dy + real(kind=8) intent(in) :: latinc + real(kind=8) intent(in) :: loninc + real(kind=8) intent(inout) :: lat + real(kind=8) intent(inout) :: lon + real(kind=8) dimension(2),intent(out,in) :: loc + integer intent(inout) :: errstat + character*(*) intent(inout) :: errmsg + end subroutine dlltoij + subroutine dijtoll(map_proj,truelat1,truelat2,stdlon,lat1,lon1,pole_lat,pole_lon,knowni,knownj,dx,dy,latinc,loninc,ai,aj,loc,errstat,errmsg) ! in :_wrffortran:wrf_user_latlon_routines.f90 + threadsafe + use constants, only: rad_per_deg,deg_per_rad,pi,algerr,wrf_earth_radius + integer intent(in) :: map_proj + real(kind=8) intent(inout) :: truelat1 + real(kind=8) intent(inout) :: truelat2 + real(kind=8) intent(in) :: stdlon + real(kind=8) intent(in) :: lat1 + real(kind=8) intent(in) :: lon1 + real(kind=8) intent(in) :: pole_lat + real(kind=8) intent(in) :: pole_lon + real(kind=8) intent(in) :: knowni + real(kind=8) intent(in) :: knownj + real(kind=8) intent(in) :: dx + real(kind=8) intent(in) :: dy + real(kind=8) intent(in) :: latinc + real(kind=8) intent(in) :: loninc + real(kind=8) intent(in) :: ai + real(kind=8) intent(in) :: aj + real(kind=8) dimension(2),intent(out,in) :: loc + integer intent(inout) :: errstat + character*(*) intent(inout) :: errmsg + end subroutine dijtoll + subroutine wrf_monotonic(out,in,lvprs,cor,idir,delta,ew,ns,nz,icorsw) ! in :_wrffortran:wrf_vinterp.f90 + threadsafe + real(kind=8) dimension(ew,ns,nz),intent(out,in) :: out + real(kind=8) dimension(ew,ns,nz),intent(inout),depend(ew,ns,nz) :: in + real(kind=8) dimension(ew,ns,nz),depend(ew,ns,nz) :: lvprs + real(kind=8) dimension(ew,ns),depend(ew,ns) :: cor + integer intent(in) :: idir + real(kind=8) intent(in) :: delta + integer, optional,intent(in),check(shape(out,0)==ew),depend(out) :: ew=shape(out,0) + integer, optional,intent(in),check(shape(out,1)==ns),depend(out) :: ns=shape(out,1) + integer, optional,intent(in),check(shape(out,2)==nz),depend(out) :: nz=shape(out,2) + integer intent(in) :: icorsw + end subroutine wrf_monotonic + function wrf_intrp_value(wvalp0,wvalp1,vlev,vcp0,vcp1,icase,errstat,errmsg) ! in :_wrffortran:wrf_vinterp.f90 + threadsafe + use constants, only: sclht,algerr + real(kind=8) intent(in) :: wvalp0 + real(kind=8) intent(in) :: wvalp1 + real(kind=8) intent(in) :: vlev + real(kind=8) intent(in) :: vcp0 + real(kind=8) intent(in) :: vcp1 + integer intent(in) :: icase + integer intent(inout) :: errstat + character*(*) intent(inout) :: errmsg + real(kind=8) :: wrf_intrp_value + end function wrf_intrp_value + subroutine wrf_vintrp(datain,dataout,pres,tk,qvp,ght,terrain,sfp,smsfp,vcarray,interp_levels,numlevels,icase,ew,ns,nz,extrap,vcor,logp,rmsg,errstat,errmsg) ! in :_wrffortran:wrf_vinterp.f90 + threadsafe + use constants, only: tlclc2,tlclc3,sclht,tlclc4,thtecon3,eps,tlclc1,celkel,exponi,gammamd,ussalr,expon,thtecon1,algerr,gamma,thtecon2 + real(kind=8) dimension(ew,ns,nz),intent(in) :: datain + real(kind=8) dimension(ew,ns,numlevels),intent(out,in),depend(ew,ns) :: dataout + real(kind=8) dimension(ew,ns,nz),intent(in),depend(ew,ns,nz) :: pres + real(kind=8) dimension(ew,ns,nz),intent(in),depend(ew,ns,nz) :: tk + real(kind=8) dimension(ew,ns,nz),intent(in),depend(ew,ns,nz) :: qvp + real(kind=8) dimension(ew,ns,nz),intent(in),depend(ew,ns,nz) :: ght + real(kind=8) dimension(ew,ns),intent(in),depend(ew,ns) :: terrain + real(kind=8) dimension(ew,ns),intent(in),depend(ew,ns) :: sfp + real(kind=8) dimension(ew,ns),intent(in),depend(ew,ns) :: smsfp + real(kind=8) dimension(ew,ns,nz),intent(in),depend(ew,ns,nz) :: vcarray + real(kind=8) dimension(numlevels),intent(in),depend(numlevels) :: interp_levels + integer, optional,intent(in),check(shape(dataout,2)==numlevels),depend(dataout) :: numlevels=shape(dataout,2) + integer intent(in) :: icase + integer, optional,intent(in),check(shape(datain,0)==ew),depend(datain) :: ew=shape(datain,0) + integer, optional,intent(in),check(shape(datain,1)==ns),depend(datain) :: ns=shape(datain,1) + integer, optional,intent(in),check(shape(datain,2)==nz),depend(datain) :: nz=shape(datain,2) + integer intent(in) :: extrap + integer intent(in) :: vcor + integer intent(in) :: logp + real(kind=8) intent(in) :: rmsg + integer intent(inout) :: errstat + character*(*) intent(inout) :: errmsg + end subroutine wrf_vintrp end interface end python module _wrffortran diff --git a/ncl_reference/WRFUsersherrie.ncl b/ncl_reference/WRFUsersherrie.ncl new file mode 100644 index 0000000..df8a8be --- /dev/null +++ b/ncl_reference/WRFUsersherrie.ncl @@ -0,0 +1,5541 @@ +;-------------------------------------------------------------------------------- +; function wrf_user_set_xy( var:numeric, xp:numeric, yp:numeric, x1:numeric, \ +; y1:numeric,angle:numeric ,opts ) +; function wrf_user_intrp3d( var3d:numeric, z:numeric, plot_type:string, \ +; loc_param:numeric, angle:numeric, opts:logical ) +; function wrf_user_intrp2d( var2d:numeric, \ +; loc_param:numeric, angle:numeric, opts:logical ) +; function wrf_user_vert_interp(file_handle,field:float,\ +; vert_coordinate[1]:string, \ + ; interp_levels[*]:numeric,opts[1]:logical) +; function wrf_user_getvar( file_handle, variable:string, time:integer ) +; function wrf_user_list_times( file_handle ) +; function wrf_user_ll_to_ij( nc_file:file, longitude:numeric, latitude:numeric, \ +; opts:logical ) +; function wrf_user_ij_to_ll( nc_file:file, i:numeric, j:numeric \ +; opts:logical ) +; function wrf_contour(nc_file:file,wks[1]: graphic, data[*][*]:numeric, \ +; opt_args[1]:logical) +; function wrf_vector(nc_file:file,wks[1]: graphic, data_u[*][*]:numeric, \ +; data_v[*][*]:numeric, opt_args[1]:logical) +; function wrf_map_resources(in_file[1]:file,opt_args[1]:logical) +; function wrf_map(wks[1]:graphic,in_file[1]:file,opt_args[1]:logical) +; function wrf_map_overlays(in_file[1]:file,wks:graphic,base[1]:graphic, \ +; plots[*]:graphic,opt_arg[1]:logical,mp_arg[1]:logical) +; function wrf_overlays(in_file[1]:file,wks:graphic, plots[*]:graphic, \ +; opt_arg[1]:logical) +; function wrf_user_unstagger( varin:numeric, unstagDim:string ) +; +; function wrf_cloud_fraction(file_handle,out_arrays[*][*][*]:numeric,time:integer) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Thse functions are still experimental +; function wrf_wps_dom(wks[1]:graphic,mpres[1]:logical,lnres[1]:logical,txres[1]:logical) +; function wrf_contour_ps(nc_file:file,wks[1]: graphic, data[*][*]:numeric, \ +; opt_args[1]:logical) +; function wrf_vector_ps(nc_file:file,wks[1]: graphic, \ +; data_u[*][*]:numeric, data_v[*][*]:numeric, \ +; opt_args[1]:logical) +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; These functions/procedures are obsolete as of version 5.0.1 of NCL. +; Do not use them. +; Use wrf_overlays instead of wrf_overlay +; Use wrf_map_overlays instead of wrf_map_overlay +; Use wrf_user_ll_to_ij instead of wrf_user_latlon_to_ij +; +; function wrf_map_zoom(wks[1]:graphic,in_file[1]:file,opt_args[1]:logical, \ +; y1:integer,y2:integer,x1:integer,x2:integer) +; procedure wrf_map_overlay(wks:graphic,base[1]:graphic, \ +; plots[*]:graphic, \ +; opt_arg[1]:logical) +; procedure wrf_overlay(wks:graphic, plots[*]:graphic, \ +; opt_arg[1]:logical) +; function wrf_user_latlon_to_ij( nc_file:file, latitude:numeric, +; longitude:numeric ) +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; function add_white_space(str:string,maxlen:integer) +; procedure print_opts(opts_name,opts,debug) +; procedure print_header(icount:integer,debug) +; +;-------------------------------------------------------------------------------- + external fortran_clouds "./cloudsf.so" +;-------------------------------------------------------------------------------- +undef("wrf_user_set_xy") +function wrf_user_set_xy( var:numeric, xp:numeric, yp:numeric, x1:numeric, \ + y1:numeric, angle:numeric, opts ) + +; mass coordinate version of ncl user routines + +local dims,x,y,slope,intercept,distance,dx,dy,dxy,npts,xy + +begin + +; find intersection of line and domain boundaries + + dims = dimsizes(var) + + if (.not. opts) then ; We have a pivot point and location and + ; need to calculate the start and end points of + ; the cross section + + if ((angle .gt. 315.) .or. (angle .lt. 45.) .or. \ + ((angle .gt. 135.) .and. (angle .lt. 225.)) ) then + +; x = y*slope + intercept + + slope = -(360.-angle)/45. + if( angle .lt. 45. ) then + slope = angle/45. + end if + if( angle .gt. 135.) then + slope = (angle-180.)/45. + end if + intercept = xp - yp*slope + +; find intersections with domain boundaries + + y0 = 0. + x0 = y0*slope + intercept + + if( x0 .lt. 0.) then ; intersect outside of left boundary + x0 = 0. + y0 = (x0 - intercept)/slope + end if + if( x0 .gt. dims(2)-1) then ; intersect outside of right boundary + x0 = dims(2)-1 + y0 = (x0 - intercept)/slope + end if + + y1 = dims(1)-1. ; need to make sure this will be a float? + x1 = y1*slope + intercept + + if( x1 .lt. 0.) then ; intersect outside of left boundary + x1 = 0. + y1 = (x1 - intercept)/slope + end if + if( x1 .gt. dims(2)-1) then ; intersect outside of right boundary + x1 = dims(2)-1 + y1 = (x1 - intercept)/slope + end if + + else + +; y = x*slope + intercept + + slope = (90.-angle)/45. + if( angle .gt. 225. ) then + slope = (270.-angle)/45. + end if + intercept = yp - xp*slope + +; find intersections with domain boundaries + + x0 = 0. + y0 = x0*slope + intercept + + if( y0 .lt. 0.) then ; intersect outside of bottom boundary + y0 = 0. + x0 = (y0 - intercept)/slope + end if + if( y0 .gt. dims(1)-1) then ; intersect outside of top boundary + y0 = dims(1)-1 + x0 = (y0 - intercept)/slope + end if + + x1 = dims(2)-1. ; need to make sure this will be a float? + y1 = x1*slope + intercept + + if( y1 .lt. 0.) then ; intersect outside of bottom boundary + y1 = 0. + x1 = (y1 - intercept)/slope + end if + if( y1 .gt. dims(1)-1) then ; intersect outside of top boundary + y1 = dims(1)-1 + x1 = (y1 - intercept)/slope + end if + + end if ; we have beginning and ending points + + end if + + + if (opts) then ; We have a specified start and end point + x0 = xp + y0 = yp + if ( x1 .gt. dims(2)-1 ) then + x1 = dims(2) + end if + if ( y1 .gt. dims(1)-1 ) then + y1 = dims(1) + end if + end if + + dx = x1 - x0 + dy = y1 - y0 + distance = (dx*dx + dy*dy)^0.5 + npts = tointeger(distance) + dxy = new(1,typeof(distance)) + dxy = distance/npts + + xy = new((/ npts, 2 /),typeof(x1)) + + dx = dx/npts + dy = dy/npts + + do i=0,npts-1 + xy(i,0) = x0 + i*dx + xy(i,1) = y0 + i*dy + end do + +; print(xy) + return(xy) + +end + +;-------------------------------------------------------------------------------- + +undef("wrf_user_intrp3d") +function wrf_user_intrp3d( var3d:numeric, z_in:numeric, \ + plot_type:string, \ + loc_param:numeric, angle:numeric, opts:logical ) + +; var3d - 3d field to interpolate (all input fields must be unstaggered) +; z_in - interpolate to this field (either p/z) +; plot_type - interpolate horizontally "h", or vertically "v" +; loc_param - level(s) for horizontal plots (eg. 500hPa ; 3000m - scalar), +; plane for vertical plots (2 values representing an xy point +; on the model domain through which the vertical plane will pass +; OR 4 values specifying start and end values +; angle - 0.0 for horizontal plots, and +; an angle for vertical plots - 90 represent a WE cross section +; opts Used IF opts is TRUE, else use loc_param and angle to determine crosssection + +begin + + if(plot_type .eq. "h" ) then ; horizontal cross section needed + + dimL = dimsizes(loc_param) + + dims = dimsizes(var3d) + nd = dimsizes(dims) + + dimX = dims(nd-1) + dimY = dims(nd-2) + dimZ = dims(nd-3) + dim4 = 1 + dim5 = 1 + if ( nd .eq. 4 ) then + dim4 = dims(nd-4) + end if + if ( nd .eq. 5 ) then + dim4 = dims(nd-4) + dim5 = dims(nd-5) + end if + + var3 = new ( (/ dim5, dim4, dimZ, dimY, dimX /) , typeof(var3d) ) + z = new ( (/ dim5, dim4, dimZ, dimY, dimX /) , typeof(var3d) ) + var2d = new ( (/ dim5, dim4, dimL, dimY, dimX /) , typeof(var3d) ) + + if ( nd .eq. 5 ) then + var3 = var3d + z = z_in + end if + if ( nd .eq. 4 ) then + var3(0,:,:,:,:) = var3d(:,:,:,:) + z(0,:,:,:,:) = z_in(:,:,:,:) + end if + if ( nd .eq. 3 ) then + var3(0,0,:,:,:) = var3d(:,:,:) + z(0,0,:,:,:) = z_in(:,:,:) + end if + + + if ( z(0,0,dimZ-1,0,0) .lt. z(0,0,dimZ-2,0,0) ) then + ; We must be interpolating to pressure + ; This routine needs input field and level in hPa - lets make sure of this + if ( max(z) .gt. 2000. ) then + ; looks like we have Pa as input - make this hPa + z = z * 0.01 + end if + if ( loc_param(0) .gt. 2000. ) then + ; looks like the input was specified in Pa - change this + loc_param = loc_param * 0.01 + end if + end if + + do il = 0,dimL-1 + var = wrf_interp_3d_z(var3,z,loc_param(il)) + var2d(:,:,il,:,:) = var(:,:,:,:) + end do + + copy_VarAtts(var3d,var3) + if(isatt(var3,"description")) then + delete_VarAtts(var3,(/"description"/)) + end if + if(isatt(var3,"units")) then + delete_VarAtts(var3,(/"units"/)) + end if + if(isatt(var3,"MemoryOrder")) then + delete_VarAtts(var3,(/"MemoryOrder"/)) + end if + if(isatt(var3,"_FillValue")) then + delete_VarAtts(var3,(/"_FillValue"/)) + end if + copy_VarAtts(var3,var2d) + + nn = nd-2 + var2d!nn = "plevs" + + if ( dimL .gt. 1 ) then + if ( nd .eq. 5 ) then + return( var2d ) + end if + if ( nd .eq. 4 ) then + return( var2d(0,:,:,:,:) ) + end if + if ( nd .eq. 3 ) then + return( var2d(0,0,:,:,:) ) + end if + else + if ( z(0,0,dimZ-1,0,0) .lt. z(0,0,dimZ-2,0,0) ) then + var2d@PlotLevelID = loc_param + " hPa" + else + var2d@PlotLevelID = .001*loc_param + " km" + end if + if ( nd .eq. 5 ) then + return( var2d(:,:,0,:,:) ) + end if + if ( nd .eq. 4 ) then + return( var2d(0,:,0,:,:) ) + end if + if ( nd .eq. 3 ) then + return( var2d(0,0,0,:,:) ) + end if + end if + + + end if + + + + + if(plot_type .eq. "v" ) then ; vertical cross section needed + + dims = dimsizes(var3d) + nd = dimsizes(dims) + + dimX = dims(nd-1) + dimY = dims(nd-2) + dimZ = dims(nd-3) + + if ( nd .eq. 4 ) then + if ( z_in(0,dimZ-1,0,0) .lt. z_in(0,dimZ-2,0,0) ) then + ; We must be interpolating to pressure + ; This routine needs input field and level in hPa - lets make sure of this + if ( max(z_in) .gt. 2000. ) then + ; looks like we have Pa as input - make this hPa + z_in = z_in * 0.01 + end if + end if + z = z_in(0,:,:,:) + else + if ( z_in(dimZ-1,0,0) .lt. z_in(dimZ-2,0,0) ) then + ; We must be interpolating to pressure + ; This routine needs input field and level in hPa - lets make sure of this + if ( z_in(0,0,0) .gt. 2000. ) then + ; looks like we have Pa as input - make this hPa + z_in = z_in * 0.01 + end if + end if + z = z_in + end if + + +; set vertical cross section + if (opts) then + xy = wrf_user_set_xy( z, loc_param(0)-1, loc_param(1)-1, \ ; the -1 is for NCL dimensions + loc_param(2)-1, loc_param(3)-1, \ + angle, opts ) + else + xy = wrf_user_set_xy( z, loc_param(0), loc_param(1), \ + 0.0, 0.0, angle, opts ) + end if + xp = dimsizes(xy) + + +; first we interp z + var2dz = wrf_interp_2d_xy( z, xy) + +; interp to constant z grid + if(var2dz(0,0) .gt. var2dz(1,0) ) then ; monotonically decreasing coordinate + z_max = floor(max(z)/10)*10 ; bottom value + z_min = ceil(min(z)/10)*10 ; top value + dz = 10 + nlevels = tointeger( (z_max-z_min)/dz) + z_var2d = new( (/nlevels/), typeof(z)) + z_var2d(0) = z_max + dz = -dz + else + z_max = max(z) + z_min = 0. + dz = 0.01 * z_max + nlevels = tointeger( z_max/dz ) + z_var2d = new( (/nlevels/), typeof(z)) + z_var2d(0) = z_min + end if + + do i=1, nlevels-1 + z_var2d(i) = z_var2d(0)+i*dz + end do + + +; interp the variable + if ( dimsizes(dims) .eq. 4 ) then + var2d = new( (/dims(0), nlevels, xp(0)/), typeof(var2dz)) + do it = 0,dims(0)-1 + var2dtmp = wrf_interp_2d_xy( var3d(it,:,:,:), xy) + do i=0,xp(0)-1 + var2d(it,:,i) = wrf_interp_1d( var2dtmp(:,i), var2dz(:,i), z_var2d) + end do + end do + var2d!0 = var3d!0 + var2d!1 = "Vertical" + var2d!2 = "Horizontal" + else + var2d = new( (/nlevels, xp(0)/), typeof(var2dz)) + var2dtmp = wrf_interp_2d_xy( var3d, xy) + do i=0,xp(0)-1 + var2d(:,i) = wrf_interp_1d( var2dtmp(:,i), var2dz(:,i), z_var2d) + end do + var2d!0 = "Vertical" + var2d!1 = "Horizontal" + end if + + + + st_x = tointeger(xy(0,0)) + 1 + st_y = tointeger(xy(0,1)) + 1 + ed_x = tointeger(xy(xp(0)-1,0)) + 1 + ed_y = tointeger(xy(xp(0)-1,1)) + 1 + if (opts) then + var2d@Orientation = "Cross-Section: (" + \ + st_x + "," + st_y + ") to (" + \ + ed_x + "," + ed_y + ")" + else + var2d@Orientation = "Cross-Section: (" + \ + st_x + "," + st_y + ") to (" + \ + ed_x + "," + ed_y + ") ; center=(" + \ + loc_param(0) + "," + loc_param(1) + \ + ") ; angle=" + angle + end if + + return(var2d) + end if + + + +end + +;-------------------------------------------------------------------------------- + +undef("wrf_user_intrp2d") +function wrf_user_intrp2d( var2d:numeric, \ + loc_param:numeric, angle:numeric, opts:logical ) + +; var2d - 2d field to interpolate +; loc_param - plane for vertical plots (2 values representing an xy point +; on the model domain through which the vertical plane will pass +; OR 4 values specifying start and end values +; angle - 0.0 for horizontal plots, and +; an angle for vertical plots - 90 represent a WE cross section +; opts Used IF opts is TRUE, else use loc_param and angle to determine crosssection + +begin + + dims = dimsizes(var2d) + nd = dimsizes(dims) + dimX = dims(nd-1) + dimY = dims(nd-2) + dimT = 1 + if ( nd .eq. 3 ) then + dimT = dims(nd-3) + end if + var2dtmp = new( (/ 1, dimY, dimX /), typeof(var2d) ) + + +; set vertical cross section + if ( nd .eq. 3 ) then + var2dtmp(0,:,:) = var2d(0,:,:) + else + var2dtmp(0,:,:) = var2d(:,:) + end if + if (opts) then + xy = wrf_user_set_xy( var2dtmp, \ + loc_param(0)-1, loc_param(1)-1, \ ; the -1 is for NCL dimensions + loc_param(2)-1, loc_param(3)-1, \ + angle, opts ) + else + xy = wrf_user_set_xy( var2dtmp, \ + loc_param(0), loc_param(1), \ + 0.0, 0.0, angle, opts ) + end if + xp = dimsizes(xy) + + var2dout = new( (/ dimT, xp(0) /), typeof(var2d) ) + + var1dtmp = wrf_interp_2d_xy( var2dtmp, xy ) + var2dout(0,:) = var1dtmp(0,:) + if ( dimT .eq. 1 ) then + var2dout!1 = "Horizontal" + return ( var2dout(0,:) ) + end if + + do it = 1,dimT-1 + var2dtmp(0,:,:) = var2d(it,:,:) + var1dtmp = wrf_interp_2d_xy( var2dtmp, xy ) + var2dout(it,:) = var1dtmp(0,:) + end do + var2dout!0 = "Time" + var2dout!1 = "Horizontal" + return(var2dout) + +end + +;-------------------------------------------------------------------------------- + +undef("wrf_user_unstagger") +function wrf_user_unstagger( varin:numeric, unstagDim:string ) + +begin + + dims = dimsizes(varin) + nd = dimsizes(dims) + + if ( unstagDim .eq. "X" .or. unstagDim .eq. "U" ) then + dimU = dims(nd-1) + if ( nd .eq. 5 ) then + varout = 0.5*(varin(:,:,:,:,:dimU-2) + varin(:,:,:,:,1:dimU-1)) + end if + if ( nd .eq. 4 ) then + varout = 0.5*(varin(:,:,:,:dimU-2) + varin(:,:,:,1:dimU-1)) + end if + if ( nd .eq. 3 ) then + varout = 0.5*(varin(:,:,:dimU-2) + varin(:,:,1:dimU-1)) + end if + if ( nd .eq. 2 ) then + varout = 0.5*(varin(:,:dimU-2) + varin(:,1:dimU-1)) + end if + do i = 0,nd-2 + varout!i = varin!i + end do + i = nd-1 + varout!i = "west_east" + copy_VarAtts(varin,varout) + varout@coordinates = "XLONG XLAT" + varout@stagger = " " + end if + + if ( unstagDim .eq. "Y" .or. unstagDim .eq. "V" ) then + dimV = dims(nd-2) + if ( nd .eq. 5 ) then + varout = 0.5*(varin(:,:,:,:dimV-2,:)+varin(:,:,:,1:dimV-1,:)) + end if + if ( nd .eq. 4 ) then + varout = 0.5*(varin(:,:,:dimV-2,:)+varin(:,:,1:dimV-1,:)) + end if + if ( nd .eq. 3 ) then + varout = 0.5*(varin(:,:dimV-2,:)+varin(:,1:dimV-1,:)) + end if + if ( nd .eq. 2 ) then + varout = 0.5*(varin(:dimV-2,:)+varin(1:dimV-1,:)) + end if + do i = 0,nd-1 + varout!i = varin!i + end do + i = nd-2 + varout!i = "south_north" + copy_VarAtts(varin,varout) + varout@coordinates = "XLONG XLAT" + varout@stagger = " " + end if + + if ( unstagDim .eq. "Z" ) then + dimW = dims(nd-3) + if ( nd .eq. 5 ) then + varout = 0.5*(varin(:,:,0:dimW-2,:,:)+varin(:,:,1:dimW-1,:,:)) + end if + if ( nd .eq. 4 ) then + varout = 0.5*(varin(:,0:dimW-2,:,:)+varin(:,1:dimW-1,:,:)) + end if + if ( nd .eq. 3 ) then + varout = 0.5*(varin(0:dimW-2,:,:)+varin(1:dimW-1,:,:)) + end if + do i = 0,nd-1 + varout!i = varin!i + end do + i = nd-3 + varout!i = "bottom_top" + copy_VarAtts(varin,varout) + varout@coordinates = "XLONG XLAT" + varout@stagger = " " + end if + + if( any( unstagDim .eq. (/"X","U","Y","V","Z"/) ) ) then + return(varout) + else + print("NOTE: No unstaggering required, as the input field is already on mass points.") + return(varin) + end if + +end + +;-------------------------------------------------------------------------------- +; This function was modified in May 2011 to allow a list of files. +; +undef("wrf_user_getvar") +function wrf_user_getvar( file_handle, varin[*]:string, time_in:integer ) +local variable, time, var, u, v, u_in, v_in, pii, radians_per_degree, \ +dims, nd, latitude, longitude, rank +begin + +;---As of NCL V6.0.0, wrf_user_getvar can now handle a file or a list of files. + if(typeof(file_handle).eq."file") then + ISFILE = True + nc_file = file_handle + else if(typeof(file_handle).eq."list") then + ISFILE = False + nc_file = file_handle[0] + else + print("wrf_user_getvar: error: the first argument must be a file or a list of files opened with addfile or addfiles") + return + end if + end if + + variable = varin(0) + time = time_in(0) + + if( (variable .eq. "uvmet") .or. (variable .eq. "uvmet10") ) then + ;; Calculate winds rotated to earth coord. + + pii = 3.14159265 + radians_per_degree = pii/180. + + if( (variable .eq. "uvmet") ) then + getU = "U" + getV = "V" + if(.not. isfilevar(nc_file,"U")) then + if(isfilevar(nc_file,"UU")) then + getU = "UU" + getV = "VV" + end if + end if + if ( time .eq. -1 ) then + if(ISFILE) then + u_in = nc_file->$getU$ + v_in = nc_file->$getV$ + else + u_in = file_handle[:]->$getU$ + v_in = file_handle[:]->$getV$ + end if + u = wrf_user_unstagger(u_in,u_in@stagger) + v = wrf_user_unstagger(v_in,v_in@stagger) + else + if(ISFILE) then + u_in = nc_file->$getU$(time_in,:,:,:) + v_in = nc_file->$getV$(time_in,:,:,:) + else + u_in = file_handle[:]->$getU$(time_in,:,:,:) + v_in = file_handle[:]->$getV$(time_in,:,:,:) + end if + u = wrf_user_unstagger(u_in,u_in@stagger) + v = wrf_user_unstagger(v_in,v_in@stagger) + end if + end if + + if( (variable .eq. "uvmet10") ) then + if(isfilevar(nc_file,"U10")) then + if ( time .eq. -1 ) then + if(ISFILE) then + u_in = nc_file->U10 + v_in = nc_file->V10 + else + u_in = file_handle[:]->U10 + v_in = file_handle[:]->V10 + end if + u = wrf_user_unstagger(u_in,u_in@stagger) + v = wrf_user_unstagger(v_in,v_in@stagger) + else + if(ISFILE) then + u_in = nc_file->U10(time_in,:,:) + v_in = nc_file->V10(time_in,:,:) + else + u_in = file_handle[:]->U10(time_in,:,:) + v_in = file_handle[:]->V10(time_in,:,:) + end if + u = wrf_user_unstagger(u_in,u_in@stagger) + v = wrf_user_unstagger(v_in,v_in@stagger) + end if + else ; may be a met file, so get lowest level of UU and VV + if(isfilevar(nc_file,"UU")) then + print("wrf_user_getvar: Assume this is a met_em file - getting lowest level from UU and VV fields") + if ( time .eq. -1 ) then + if(ISFILE) then + u_in = nc_file->UU(:,0,:,:) + v_in = nc_file->VV(:,0,:,:) + else + u_in = file_handle[:]->UU(:,0,:,:) + v_in = file_handle[:]->VV(:,0,:,:) + end if + u = wrf_user_unstagger(u_in,u_in@stagger) + v = wrf_user_unstagger(v_in,v_in@stagger) + else + if(ISFILE) then + u_in = nc_file->UU(time_in,0,:,:) + v_in = nc_file->VV(time_in,0,:,:) + else + u_in = file_handle[:]->UU(time_in,0,:,:) + v_in = file_handle[:]->VV(time_in,0,:,:) + end if + u = wrf_user_unstagger(u_in,u_in@stagger) + v = wrf_user_unstagger(v_in,v_in@stagger) + end if + end if + end if + end if + + + map_projection = nc_file@MAP_PROJ + + + if( any(map_projection.eq.(/0,3,6/)) ) then ; no rotation needed + dims = dimsizes(u) + nd = dimsizes(dims) + if ( nd .eq. 5 ) then + uvmet = new( (/ 2, dims(0), dims(1), dims(2), dims(3), dims(4) /), typeof(u)) + uvmet(0,:,:,:,:,:) = u(:,:,:,:,:) + uvmet(1,:,:,:,:,:) = v(:,:,:,:,:) + end if + if ( nd .eq. 4 ) then + uvmet = new( (/ 2, dims(0), dims(1), dims(2), dims(3) /), typeof(u)) + uvmet(0,:,:,:,:) = u(:,:,:,:) + uvmet(1,:,:,:,:) = v(:,:,:,:) + end if + if ( nd .eq. 3 ) then + uvmet = new( (/ 2, dims(0), dims(1), dims(2) /), typeof(u)) + uvmet(0,:,:,:) = u(:,:,:) + uvmet(1,:,:,:) = v(:,:,:) + end if + if ( nd .eq. 2 ) then + uvmet = new( (/ 2, dims(0), dims(1) /), typeof(u)) + uvmet(0,:,:) = u(:,:) + uvmet(1,:,:) = v(:,:) + end if + delete_VarAtts(u,(/"description","units"/)) + copy_VarAtts(u,uvmet) + uvmet@description = " u,v met velocity" + uvmet!0 = "u_v" + end if + + + if( any(map_projection.eq.(/1,2/)) ) then ; no rotation needed + cen_lat = nc_file@CEN_LAT + if(isatt(nc_file,"STAND_LON")) then + cen_long = nc_file@STAND_LON + else + cen_long = nc_file@CEN_LON + end if + true_lat1 = nc_file@TRUELAT1 + true_lat2 = nc_file@TRUELAT2 + + getLAT = "XLAT" + getLON = "XLONG" + if(.not. isfilevar(nc_file,"XLAT")) then + if(isfilevar(nc_file,"XLAT_M")) then + getLAT = "XLAT_M" + getLON = "XLONG_M" + end if + end if + if ( time .eq. -1 ) then + if(ISFILE) then + latitude = nc_file->$getLAT$ + longitude = nc_file->$getLON$ + else + latitude = file_handle[:]->$getLAT$ + longitude = file_handle[:]->$getLON$ + end if + else + if(ISFILE) then + latitude = nc_file->$getLAT$(time_in,:,:) + longitude = nc_file->$getLON$(time_in,:,:) + else + latitude = file_handle[:]->$getLAT$(time_in,:,:) + longitude = file_handle[:]->$getLON$(time_in,:,:) + end if + end if + + cone = 1. + if( map_projection .eq. 1) then ; Lambert Conformal mapping + if( (fabs(true_lat1 - true_lat2) .gt. 0.1) .and. \ + (fabs(true_lat2 - 90. ) .gt. 0.1) ) then + cone = log(cos(true_lat1*radians_per_degree)) \ + -log(cos(true_lat2*radians_per_degree)) + cone = cone/( log(tan(( 45. -fabs(true_lat1/2.))*radians_per_degree)) - \ + log(tan((45. -fabs(true_lat2/2.))*radians_per_degree)) ) + else + cone = sin(fabs(true_lat1)*radians_per_degree) + end if + end if + if(map_projection .eq. 2) then ; polar stereographic + cone = 1. + end if + if(map_projection .eq. 3) then ; Mercator + cone = 0. + end if + + uvmet = wrf_uvmet( u, v, latitude, longitude, cen_long, cone ) + delete_VarAtts(u,(/"description","units"/)) + copy_VarAtts(u,uvmet) + + end if + + if( (variable .eq. "uvmet10") ) then + uvmet@description = " u10,v10 met velocity" + end if + return(uvmet) + + end if + + + + if( variable .eq. "ua" ) then + ; U interpolated to mass points + getTHIS = "U" + if(.not. isfilevar(nc_file,"U")) then + if(isfilevar(nc_file,"UU")) then + getTHIS = "UU" + end if + end if + if ( time .eq. -1 ) then + if(ISFILE) then + var = nc_file->$getTHIS$ + else + var = file_handle[:]->$getTHIS$ + end if + else + if(ISFILE) then + var = nc_file->$getTHIS$(time_in,:,:,:) + else + var = file_handle[:]->$getTHIS$(time_in,:,:,:) + end if + end if + + ua = wrf_user_unstagger(var,var@stagger) + + return(ua) + end if + + + + if( variable .eq. "va" ) then + ; V interpolated to mass points + getTHIS = "V" + if(.not. isfilevar(nc_file,"V")) then + if(isfilevar(nc_file,"VV")) then + getTHIS = "VV" + end if + end if + if ( time .eq. -1 ) then + if(ISFILE) then + var = nc_file->$getTHIS$ + else + var = file_handle[:]->$getTHIS$ + end if + else + if(ISFILE) then + var = nc_file->$getTHIS$(time_in,:,:,:) + else + var = file_handle[:]->$getTHIS$(time_in,:,:,:) + end if + end if + + va = wrf_user_unstagger(var,var@stagger) + + return(va) + end if + + + + if( variable .eq. "wa" ) then + ; W interpolated to mass points + if ( time .eq. -1 ) then + if(ISFILE) then + var = nc_file->W + else + var = file_handle[:]->W + end if + else + if(ISFILE) then + var = nc_file->W(time_in,:,:,:) + else + var = file_handle[:]->W(time_in,:,:,:) + end if + end if + + wa = wrf_user_unstagger(var,var@stagger) + + return(wa) + end if + + + + if( any( variable .eq. (/"p","pres","pressure"/) ) ) then + ; Full model pressure [=base pressure (PB) + pertubation pressure (P)] + if(isfilevar(nc_file,"P")) then + if ( time .eq. -1 ) then + if(ISFILE) then + var = nc_file->P + PB = nc_file->PB + else + var = file_handle[:]->P + PB = file_handle[:]->PB + end if + else + if(ISFILE) then + var = nc_file->P(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + else + var = file_handle[:]->P(time_in,:,:,:) + PB = file_handle[:]->PB(time_in,:,:,:) + end if + end if + var = var + PB + else + ;; may be a met_em file - see if we can get PRES + if(isfilevar(nc_file,"PRES")) then + if ( time .eq. -1 ) then + if(ISFILE) then + var = nc_file->PRES + else + var = file_handle[:]->PRES + end if + else + if(ISFILE) then + var = nc_file->PRES(time_in,:,:,:) + else + var = file_handle[:]->PRES(time_in,:,:,:) + end if + end if + end if + end if + var@description = "Pressure" + if( variable .eq. "pressure" ) then + var = var * 0.01 + var@units = "hPa" + end if + return(var) + end if + + + if( any( variable .eq. (/"geopt","geopotential","z","height"/) ) ) then + ; Height [=full geopotentail height / 9.81] + if(isfilevar(nc_file,"PH")) then + if ( time .eq. -1 ) then + if(ISFILE) then + var = nc_file->PH + PHB = nc_file->PHB + else + var = file_handle[:]->PH + PHB = file_handle[:]->PHB + end if + else + if(ISFILE) then + var = nc_file->PH(time,:,:,:) + PHB = nc_file->PHB(time,:,:,:) + else + var = file_handle[:]->PH(time,:,:,:) + PHB = file_handle[:]->PHB(time,:,:,:) + end if + end if + + var = var + PHB + z = wrf_user_unstagger(var,var@stagger) + z@description = "Geopotential" + + else + ;; may be a met_em file - see if we can get GHT - data in met_em file is Height in M + if(isfilevar(nc_file,"GHT")) then + if ( time .eq. -1 ) then + if(ISFILE) then + z = nc_file->GHT + else + z = file_handle[:]->GHT + end if + else + if(ISFILE) then + z = nc_file->GHT(time,:,:,:) + else + z = file_handle[:]->GHT(time,:,:,:) + end if + end if + z = z * 9.81 + z@description = "Geopotential" + z@units = "m2 s-2" + end if + end if + + if( any( variable .eq. (/"z","height"/) ) ) then + z = z / 9.81 + z@description = "Height" + z@units = "m" + end if + return(z) + end if + + + + if( any( variable .eq. (/"th","theta"/) ) ) then + ; Potentail Temperature is model output T + 300K + if ( time .eq. -1 ) then + if(ISFILE) then + var = nc_file->T + else + var = file_handle[:]->T + end if + else + if(ISFILE) then + var = nc_file->T(time_in,:,:,:) + else + var = file_handle[:]->T(time_in,:,:,:) + end if + end if + var = var + 300. + var@description = "Potential Temperature (theta) " + return(var) + end if + + + + if( any( variable .eq. (/"tk","tc"/) ) ) then + ;; function wrf_tk needs theta and pressure (Pa) on input and returns temperature in K on return + if(isfilevar(nc_file,"T")) then + if ( time .eq. -1 ) then + if(ISFILE) then + T = nc_file->T + P = nc_file->P + PB = nc_file->PB + else + T = file_handle[:]->T + P = file_handle[:]->P + PB = file_handle[:]->PB + end if + else + if(ISFILE) then + T = nc_file->T(time_in,:,:,:) + P = nc_file->P(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + else + T = file_handle[:]->T(time_in,:,:,:) + P = file_handle[:]->P(time_in,:,:,:) + PB = file_handle[:]->PB(time_in,:,:,:) + end if + end if + T = T + 300. + P = P + PB + t = wrf_tk( P , T ) + delete_VarAtts(T,(/"description"/)) + copy_VarAtts(T,t) + else + ;; may be a met_em file - see if we can get TT + if(isfilevar(nc_file,"TT")) then + if ( time .eq. -1 ) then + if(ISFILE) then + t = nc_file->TT + else + t = file_handle[:]->TT + end if + else + if(ISFILE) then + t = nc_file->TT(time_in,:,:,:) + else + t = file_handle[:]->TT(time_in,:,:,:) + end if + end if + end if + end if + if( variable .eq. "tc" ) then + t = t - 273.16 + t@units = "C" ; Overwrite return units + end if + return(t) + end if + + + + if( variable .eq. "eth" ) then + ;Equivalent Potential Temperature in degrees K + if(isfilevar(nc_file,"T")) then + if ( time .eq. -1 ) then + if(ISFILE) then + T = nc_file->T + P = nc_file->P + PB = nc_file->PB + QV = nc_file->QVAPOR + else + T = file_handle[:]->T + P = file_handle[:]->P + PB = file_handle[:]->PB + QV = file_handle[:]->QVAPOR + end if + else + if(ISFILE) then + T = nc_file->T(time_in,:,:,:) + P = nc_file->P(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + QV = nc_file->QVAPOR(time_in,:,:,:) + else + T = file_handle[:]->T(time_in,:,:,:) + P = file_handle[:]->P(time_in,:,:,:) + PB = file_handle[:]->PB(time_in,:,:,:) + QV = file_handle[:]->QVAPOR(time_in,:,:,:) + end if + end if + T = T + 300. ; potential temperature in K. + P = P + PB ; full pressure in Pa. + tk = wrf_tk( P , T ) ; temperature in K. + eth = wrf_eth ( QV, tk, P ) + delete_VarAtts(T,(/"description"/)) + copy_VarAtts(T,eth) + return(eth) + else + print("This diagnostic only for with WRF data file and not for WPS files") + exit + end if + + end if + + + + if( variable .eq. "td" ) then + ;; function wrf_td needs qv and pressure (Pa) on input and returns dewpoint temperature on return + if ( time .eq. -1 ) then + if(ISFILE) then + P = nc_file->P + PB = nc_file->PB + QVAPOR = nc_file->QVAPOR + else + P = file_handle[:]->P + PB = file_handle[:]->PB + QVAPOR = file_handle[:]->QVAPOR + end if + else + if(ISFILE) then + P = nc_file->P(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + QVAPOR = nc_file->QVAPOR(time_in,:,:,:) + else + P = file_handle[:]->P(time_in,:,:,:) + PB = file_handle[:]->PB(time_in,:,:,:) + QVAPOR = file_handle[:]->QVAPOR(time_in,:,:,:) + end if + end if + P = P + PB + td = wrf_td( P , QVAPOR ) + delete_VarAtts(QVAPOR,(/"description","units"/)) + copy_VarAtts(QVAPOR,td) + return(td) + end if + + + + if( variable .eq. "td2" ) then + ;; function wrf_td needs qv and pressure (Pa) on input and returns dewpoint temperature on return + if ( time .eq. -1 ) then + if(ISFILE) then + PSFC = nc_file->PSFC + Q2 = nc_file->Q2 + else + PSFC = file_handle[:]->PSFC + Q2 = file_handle[:]->Q2 + end if + else + if(ISFILE) then + PSFC = nc_file->PSFC(time_in,:,:) + Q2 = nc_file->Q2(time_in,:,:) + else + PSFC = file_handle[:]->PSFC(time_in,:,:) + Q2 = file_handle[:]->Q2(time_in,:,:) + end if + end if + td = wrf_td( PSFC , Q2 ) + delete_VarAtts(Q2,(/"description","units"/)) + copy_VarAtts(Q2,td) + td@description = "2m Dewpoint Temperature" ; Overwrite return description + return(td) + end if + + + + if( variable .eq. "slp" ) then + if(isfilevar(nc_file,"T")) then + ;; first compute theta - function wrf_tk needs theta and pressure (Pa) on input + ;; THEN compute sea level pressure, from qv, p (Pa), tk, z + if ( time .eq. -1 ) then + if(ISFILE) then + T = nc_file->T + P = nc_file->P + PB = nc_file->PB + QVAPOR = nc_file->QVAPOR + PH = nc_file->PH + PHB = nc_file->PHB + else + T = file_handle[:]->T + P = file_handle[:]->P + PB = file_handle[:]->PB + QVAPOR = file_handle[:]->QVAPOR + PH = file_handle[:]->PH + PHB = file_handle[:]->PHB + end if + else + if(ISFILE) then + T = nc_file->T(time_in,:,:,:) + P = nc_file->P(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + QVAPOR = nc_file->QVAPOR(time_in,:,:,:) + PH = nc_file->PH(time_in,:,:,:) + PHB = nc_file->PHB(time_in,:,:,:) + else + T = file_handle[:]->T(time_in,:,:,:) + P = file_handle[:]->P(time_in,:,:,:) + PB = file_handle[:]->PB(time_in,:,:,:) + QVAPOR = file_handle[:]->QVAPOR(time_in,:,:,:) + PH = file_handle[:]->PH(time_in,:,:,:) + PHB = file_handle[:]->PHB(time_in,:,:,:) + end if + end if + T = T + 300. + P = P + PB + QVAPOR = QVAPOR > 0.000 + PH = ( PH + PHB ) / 9.81 + z = wrf_user_unstagger(PH,PH@stagger) + + tk = wrf_tk( P , T ) ; calculate TK + slp = wrf_slp( z, tk, P, QVAPOR ) ; calculate slp + delete_VarAtts(T,(/"description","units"/)) + copy_VarAtts(T,slp) + else + ;; may be a met_em file - see if we can get PMSL + if(isfilevar(nc_file,"PMSL")) then + if ( time .eq. -1 ) then + if(ISFILE) then + slp = nc_file->PMSL + else + slp = file_handle[:]->PMSL + end if + else + if(ISFILE) then + slp = nc_file->PMSL(time_in,:,:) + else + slp = file_handle[:]->PMSL(time_in,:,:) + end if + end if + end if + end if + + return(slp) + end if + + + + if( variable .eq. "rh" ) then + if(isfilevar(nc_file,"T")) then + ;; first compute theta - function wrf_tk needs theta and pressure (Pa) on input + ;; THEN compute rh, using tk, p (Pa), QVAPOR + if ( time .eq. -1 ) then + if(ISFILE) then + T = nc_file->T + P = nc_file->P + PB = nc_file->PB + QVAPOR = nc_file->QVAPOR + else + T = file_handle[:]->T + P = file_handle[:]->P + PB = file_handle[:]->PB + QVAPOR = file_handle[:]->QVAPOR + end if + else + if(ISFILE) then + T = nc_file->T(time_in,:,:,:) + P = nc_file->P(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + QVAPOR = nc_file->QVAPOR(time_in,:,:,:) + else + T = file_handle[:]->T(time_in,:,:,:) + P = file_handle[:]->P(time_in,:,:,:) + PB = file_handle[:]->PB(time_in,:,:,:) + QVAPOR = file_handle[:]->QVAPOR(time_in,:,:,:) + end if + end if + T = T + 300. + P = P + PB + Pdims = dimsizes(P) + QVAPOR = QVAPOR > 0.000 + tk = wrf_tk( P , T ) + rh = wrf_rh( QVAPOR, P, tk ) + delete_VarAtts(T,(/"description","units"/)) + copy_VarAtts(T,rh) + else + ;; may be a met_em file - see if we can get RH + if(isfilevar(nc_file,"RH")) then + if ( time .eq. -1 ) then + if(ISFILE) then + rh = nc_file->RH + else + rh = file_handle[:]->RH + end if + else + if(ISFILE) then + rh = nc_file->RH(time_in,:,:,:) + else + rh = file_handle[:]->RH(time_in,:,:,:) + end if + end if + end if + end if + return(rh) + end if + + + + if( variable .eq. "rh2" ) then + if(isfilevar(nc_file,"T2")) then + ;; Compute rh2, using T2, PSFC, Q2 + if ( time .eq. -1 ) then + if(ISFILE) then + T2 = nc_file->T2 + PSFC = nc_file->PSFC + Q2 = nc_file->Q2 + else + T2 = file_handle[:]->T2 + PSFC = file_handle[:]->PSFC + Q2 = file_handle[:]->Q2 + end if + else + if(ISFILE) then + T2 = nc_file->T2(time_in,:,:) + PSFC = nc_file->PSFC(time_in,:,:) + Q2 = nc_file->Q2(time_in,:,:) + else + T2 = file_handle[:]->T2(time_in,:,:) + PSFC = file_handle[:]->PSFC(time_in,:,:) + Q2 = file_handle[:]->Q2(time_in,:,:) + end if + end if + Q2 = Q2 > 0.000 + rh = wrf_rh( Q2, PSFC, T2 ) + delete_VarAtts(T2,(/"description","units"/)) + copy_VarAtts(T2,rh) + rh@description = "2m Relative Humidity" + else + ;; may be a met_em file - see if we can get RH + if(isfilevar(nc_file,"RH")) then + print("Probably a met_em file - get lowerst level from RH field") + if ( time .eq. -1 ) then + if(ISFILE) then + rh2 = nc_file->RH(:,0,:,:) + else + rh2 = file_handle[:]->RH(:,0,:,:) + end if + else + if(ISFILE) then + rh2 = nc_file->RH(time_in,0,:,:) + else + rh2 = file_handle[:]->RH(time_in,0,:,:) + end if + end if + end if + end if + return(rh) + end if + + + + if( variable .eq. "pvo" ) then + if ( time .eq. -1 ) then + if(ISFILE) then + U = nc_file->U + V = nc_file->V + T = nc_file->T + P = nc_file->P + PB = nc_file->PB + MSFU = nc_file->MAPFAC_U + MSFV = nc_file->MAPFAC_V + MSFM = nc_file->MAPFAC_M + COR = nc_file->F + else + U = file_handle[:]->U + V = file_handle[:]->V + T = file_handle[:]->T + P = file_handle[:]->P + PB = file_handle[:]->PB + MSFU = file_handle[:]->MAPFAC_U + MSFV = file_handle[:]->MAPFAC_V + MSFM = file_handle[:]->MAPFAC_M + COR = file_handle[:]->F + end if + else + if(ISFILE) then + U = nc_file->U(time_in,:,:,:) + V = nc_file->V(time_in,:,:,:) + T = nc_file->T(time_in,:,:,:) + P = nc_file->P(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + MSFU = nc_file->MAPFAC_U(time_in,:,:) + MSFV = nc_file->MAPFAC_V(time_in,:,:) + MSFM = nc_file->MAPFAC_M(time_in,:,:) + COR = nc_file->F(time_in,:,:) + else + U = file_handle[:]->U(time_in,:,:,:) + V = file_handle[:]->V(time_in,:,:,:) + T = file_handle[:]->T(time_in,:,:,:) + P = file_handle[:]->P(time_in,:,:,:) + PB = file_handle[:]->PB(time_in,:,:,:) + MSFU = file_handle[:]->MAPFAC_U(time_in,:,:) + MSFV = file_handle[:]->MAPFAC_V(time_in,:,:) + MSFM = file_handle[:]->MAPFAC_M(time_in,:,:) + COR = file_handle[:]->F(time_in,:,:) + end if + end if + T = T + 300. + P = P + PB + DX = nc_file@DX + DY = nc_file@DY + + pvo = wrf_pvo( U, V, T, P, MSFU, MSFV, MSFM, COR, DX, DY, 0) + + delete_VarAtts(T,(/"description","units"/)) + copy_VarAtts(T,pvo) + return(pvo) + end if + + + + if( variable .eq. "avo" ) then + if ( time .eq. -1 ) then + if(ISFILE) then + U = nc_file->U + V = nc_file->V + MSFU = nc_file->MAPFAC_U + MSFV = nc_file->MAPFAC_V + MSFM = nc_file->MAPFAC_M + COR = nc_file->F + else + U = file_handle[:]->U + V = file_handle[:]->V + MSFU = file_handle[:]->MAPFAC_U + MSFV = file_handle[:]->MAPFAC_V + MSFM = file_handle[:]->MAPFAC_M + COR = file_handle[:]->F + end if + else + if(ISFILE) then + U = nc_file->U(time_in,:,:,:) + V = nc_file->V(time_in,:,:,:) + MSFU = nc_file->MAPFAC_U(time_in,:,:) + MSFV = nc_file->MAPFAC_V(time_in,:,:) + MSFM = nc_file->MAPFAC_M(time_in,:,:) + COR = nc_file->F(time_in,:,:) + else + U = file_handle[:]->U(time_in,:,:,:) + V = file_handle[:]->V(time_in,:,:,:) + MSFU = file_handle[:]->MAPFAC_U(time_in,:,:) + MSFV = file_handle[:]->MAPFAC_V(time_in,:,:) + MSFM = file_handle[:]->MAPFAC_M(time_in,:,:) + COR = file_handle[:]->F(time_in,:,:) + end if + end if + DX = nc_file@DX + DY = nc_file@DY + + avo = wrf_avo( U, V, MSFU, MSFV, MSFM, COR, DX, DY, 0) + + delete_VarAtts(COR,(/"description","units"/)) + copy_VarAtts(COR,avo) + return(avo) + end if + + + + if( variable .eq. "dbz" .or. variable .eq. "mdbz" ) then + ; calculate dbz + ivarint = 0 + iliqskin = 0 + dim_vars = dimsizes(varin) + do idims = 1,dim_vars-1 + if ( idims .eq. 1 ) then + if ( varin(idims) .eq. "1" ) then + ivarint = 1 + end if + end if + if ( idims .eq. 2 ) then + if ( varin(idims) .eq. "1" ) then + iliqskin = 1 + end if + end if + end do + + if ( time .eq. -1 ) then + if(ISFILE) then + T = nc_file->T + P = nc_file->P + PB = nc_file->PB + qv = nc_file->QVAPOR + qr = nc_file->QRAIN + else + T = file_handle[:]->T + P = file_handle[:]->P + PB = file_handle[:]->PB + qv = file_handle[:]->QVAPOR + qr = file_handle[:]->QRAIN + end if + if(isfilevar(nc_file,"QSNOW")) + if(ISFILE) then + qs = nc_file->QSNOW + else + qs = file_handle[:]->QSNOW + end if + end if + if(isfilevar(nc_file,"QGRAUP")) + if(ISFILE) then + qg = nc_file->QGRAUP + else + qg = file_handle[:]->QGRAUP + end if + end if + else + if(ISFILE) then + T = nc_file->T(time_in,:,:,:) + P = nc_file->P(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + qv = nc_file->QVAPOR(time_in,:,:,:) + qr = nc_file->QRAIN(time_in,:,:,:) + else + T = file_handle[:]->T(time_in,:,:,:) + P = file_handle[:]->P(time_in,:,:,:) + PB = file_handle[:]->PB(time_in,:,:,:) + qv = file_handle[:]->QVAPOR(time_in,:,:,:) + qr = file_handle[:]->QRAIN(time_in,:,:,:) + end if + if(isfilevar(nc_file,"QSNOW")) + if(ISFILE) then + qs = nc_file->QSNOW(time_in,:,:,:) + else + qs = file_handle[:]->QSNOW(time_in,:,:,:) + end if + end if + if(isfilevar(nc_file,"QGRAUP")) + if(ISFILE) then + qg = nc_file->QGRAUP(time_in,:,:,:) + else + qg = file_handle[:]->QGRAUP(time_in,:,:,:) + end if + end if + end if + T = T + 300. + P = P + PB + tk = wrf_tk( P , T ) + + if ( .not. isvar("qs") ) then + qs = qv + qs = 0.0 + end if + if ( .not. isvar("qg") ) then + qg = qv + qg = 0.0 + end if + + dbz = wrf_dbz ( P, tk, qv, qr, qs, qg, ivarint, iliqskin) + delete(qs) + delete(qg) + + delete_VarAtts(T,(/"description","units"/)) + copy_VarAtts(T,dbz) + + + if ( variable .eq. "mdbz") then + dims = getvardims(dbz) + rank = dimsizes(dims) + if ( rank .eq. 5 ) then + mdbz = dim_max ( dbz($dims(0)$|:,$dims(1)$|:,$dims(3)$|:,$dims(4)$|:,$dims(2)$|:) ) + mdbz!0 = dbz!0 + mdbz!1 = dbz!1 + end if + if ( rank .eq. 4 ) then + mdbz = dim_max ( dbz($dims(0)$|:,$dims(2)$|:,$dims(3)$|:,$dims(1)$|:) ) + mdbz!0 = dbz!0 + end if + if ( rank .eq. 3 ) then + mdbz = dim_max ( dbz($dims(1)$|:,$dims(2)$|:,$dims(0)$|:) ) + end if + nn = rank-1 + nm = rank-2 + mdbz!nm = dbz!nn + nn = rank-2 + nm = rank-3 + mdbz!nm = dbz!nn + copy_VarAtts(dbz,mdbz) + mdbz@description = "Max Reflectivity" + return(mdbz) + else + return(dbz) + end if + + end if + + + + if( any( variable .eq. (/"cape_3d","cape_2d"/) ) ) then + if ( time .eq. -1 ) then + if(ISFILE) then + T = nc_file->T + P = nc_file->P + PB = nc_file->PB + QV = nc_file->QVAPOR + PH = nc_file->PH + PHB = nc_file->PHB + HGT = nc_file->HGT + PSFC = nc_file->PSFC + else + T = file_handle[:]->T + P = file_handle[:]->P + PB = file_handle[:]->PB + QV = file_handle[:]->QVAPOR + PH = file_handle[:]->PH + PHB = file_handle[:]->PHB + HGT = file_handle[:]->HGT + PSFC = file_handle[:]->PSFC + end if + else + if(ISFILE) then + T = nc_file->T(time_in,:,:,:) + P = nc_file->P(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + QV = nc_file->QVAPOR(time_in,:,:,:) + PH = nc_file->PH(time_in,:,:,:) + PHB = nc_file->PHB(time_in,:,:,:) + HGT = nc_file->HGT(time_in,:,:) + PSFC = nc_file->PSFC(time_in,:,:) + else + T = file_handle[:]->T(time_in,:,:,:) + P = file_handle[:]->P(time_in,:,:,:) + PB = file_handle[:]->PB(time_in,:,:,:) + QV = file_handle[:]->QVAPOR(time_in,:,:,:) + PH = file_handle[:]->PH(time_in,:,:,:) + PHB = file_handle[:]->PHB(time_in,:,:,:) + HGT = file_handle[:]->HGT(time_in,:,:) + PSFC = file_handle[:]->PSFC(time_in,:,:) + end if + end if + T = T + 300. + P = P + PB + tk = wrf_tk( P , T ) + PH = PH + PHB + z = wrf_user_unstagger(PH,PH@stagger) + z = z/9.81 + + if( variable .eq. "cape_3d" ) then + cape = wrf_cape_3d( P, tk, QV, z, HGT, PSFC, True ) + cape@description = "cape ; cin" + end if + if( variable .eq. "cape_2d" ) then + cape = wrf_cape_2d( P, tk, QV, z, HGT, PSFC, True ) + delete_VarAtts(T,(/"MemoryOrder"/)) + cape@MemoryOrder = "XY" + cape@description = "mcape ; mcin ; lcl ; lfc" + end if + delete_VarAtts(T,(/"description","units"/)) + copy_VarAtts(T,cape) + + return(cape) + end if + + + + if( any( variable .eq. (/"pw"/) ) ) then + ;Precipitable Water + print("calculating precipitable water") + gas_const = 287. ; J/K/kg + Cp = 1004. ; J/K/kg + if ( time .eq. -1 ) then + if(ISFILE) then + T = nc_file->T + P = nc_file->P + PB = nc_file->PB + PH = nc_file->PH + PHB = nc_file->PHB + QV = nc_file->QVAPOR + else + T = file_handle[:]->T + P = file_handle[:]->P + PB = file_handle[:]->PB + PH = file_handle[:]->PH + PHB = file_handle[:]->PHB + QV = file_handle[:]->QVAPOR + end if + else + if(ISFILE) then + T = nc_file->T(time_in,:,:,:) + P = nc_file->P(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + PH = nc_file->PH(time_in,:,:,:) + PHB = nc_file->PHB(time_in,:,:,:) + QV = nc_file->QVAPOR(time_in,:,:,:) + else + T = file_handle[:]->T(time_in,:,:,:) + P = file_handle[:]->P(time_in,:,:,:) + PB = file_handle[:]->PB(time_in,:,:,:) + PH = file_handle[:]->PH(time_in,:,:,:) + PHB = file_handle[:]->PHB(time_in,:,:,:) + QV = file_handle[:]->QVAPOR(time_in,:,:,:) + end if + end if + + pres = P + PB + height = (PH + PHB)/9.8 ; height at full levels + theta = T + 300. + temp = theta * (pres/100000) ^ (gas_const/Cp) + vtemp = (1 + 0.61*QV) * temp ; virtual temp + + dims = dimsizes(T) + nd = dimsizes(dims) + + if ( nd .eq. 4 ) then + zdiff = height(:,0,:,:) + zdiff = 0. + pw_sfc_ptop = height(:,0,:,:) + pw_sfc_ptop = 0. + do k = 0,dims(1)-1 + zdiff(:,:,:) = (height(:,k+1,:,:) - height(:,k,:,:)) + pw_sfc_ptop(:,:,:) = pw_sfc_ptop(:,:,:) + ((pres(:,k,:,:)/(gas_const * vtemp(:,k,:,:))) * QV(:,k,:,:) * zdiff(:,:,:)) + end do + end if + if ( nd .eq. 3 ) then + zdiff = height(0,:,:) + zdiff = 0. + pw_sfc_ptop = height(0,:,:) + pw_sfc_ptop = 0. + do k = 0,dims(0)-1 + zdiff(:,:) = (height(k+1,:,:) - height(k,:,:)) + pw_sfc_ptop(:,:) = pw_sfc_ptop(:,:) + ((pres(k,:,:)/(gas_const * vtemp(k,:,:))) * QV(k,:,:) * zdiff(:,:)) + end do + end if + + pw_sfc_ptop@description = "Precipitable Water" + return(pw_sfc_ptop) + end if + + + + if( any( variable .eq. (/"helicity"/) ) ) then + getU = "U" + getV = "V" + if(.not. isfilevar(nc_file,"U")) then + if(isfilevar(nc_file,"UU")) then + getU = "UU" + getV = "VV" + end if + end if + if ( time .eq. -1 ) then + if(ISFILE) then + u_in = nc_file->$getU$ + v_in = nc_file->$getV$ + PH = nc_file->PH + geopt = nc_file->PHB + ter = nc_file->HGT + else + u_in = file_handle[:]->$getU$ + v_in = file_handle[:]->$getV$ + PH = file_handle[:]->PH + geopt = file_handle[:]->PHB + ter = file_handle[:]->HGT + end if + else + if(ISFILE) then + u_in = nc_file->$getU$(time_in,:,:,:) + v_in = nc_file->$getV$(time_in,:,:,:) + PH = nc_file->PH(time_in,:,:,:) + geopt = nc_file->PHB(time_in,:,:,:) + ter = nc_file->HGT(time_in,:,:) + else + u_in = file_handle[:]->$getU$(time_in,:,:,:) + v_in = file_handle[:]->$getV$(time_in,:,:,:) + PH = file_handle[:]->PH(time_in,:,:,:) + geopt = file_handle[:]->PHB(time_in,:,:,:) + ter = file_handle[:]->HGT(time_in,:,:) + end if + end if + + ua = wrf_user_unstagger(u_in,u_in@stagger) + va = wrf_user_unstagger(v_in,v_in@stagger) + geopt = geopt + PH + za = wrf_user_unstagger(geopt,geopt@stagger) + za = za / 9.81 ; change to height + + ua1 = ua(::-1,:,:) + va1 = va(::-1,:,:) + za1 = za(::-1,:,:) + + top_ok = 0 + top = 3000. + + dim_vars = dimsizes(varin) + if(dim_vars .eq. 2) then + if( varin(1) .eq. "3000" ) then + top = 3000. + top_ok = 1 + end if + + if( varin(1) .eq. "1000" ) then + top = 1000. + top_ok = 1 + end if + + if(top_ok .eq. 0) then + print("Top values of 1000 or 3000 are accepted.") + top = 3000. + end if + end if + + print("Calculations are done with a top of " + top) + sreh = wrf_helicity(ua1, va1, za1, ter, top) + return(sreh) + end if + + + + if( any(variable .eq. (/"updraft_helicity"/) ) )then + getU = "U" + getV = "V" + if(.not. isfilevar(nc_file,"U")) then + if(isfilevar(nc_file,"UU")) then + getU = "UU" + getV = "VV" + end if + end if + if ( time .eq. -1 ) then + if(ISFILE) then + u_in = nc_file->$getU$ + v_in = nc_file->$getV$ + w = nc_file->W + ph = nc_file->PH + phb = nc_file->PHB + else + u_in = file_handle[:]->$getU$ + v_in = file_handle[:]->$getV$ + w = file_handle[:]->W + ph = file_handle[:]->PH + phb = file_handle[:]->PHB + end if + else + if(ISFILE) then + u_in = nc_file->$getU$(time_in,:,:,:) + v_in = nc_file->$getV$(time_in,:,:,:) + w = nc_file->W(time_in,:,:,:) + ph = nc_file->PH(time_in,:,:,:) + phb = nc_file->PHB(time_in,:,:,:) + else + u_in = file_handle[:]->$getU$(time_in,:,:,:) + v_in = file_handle[:]->$getV$(time_in,:,:,:) + w = file_handle[:]->W(time_in,:,:,:) + ph = file_handle[:]->PH(time_in,:,:,:) + phb = file_handle[:]->PHB(time_in,:,:,:) + end if + end if + ua = wrf_user_unstagger(u_in,u_in@stagger) + va = wrf_user_unstagger(v_in,v_in@stagger) + mapfct = nc_file->MAPFAC_M(0,:,:) + zp = ph + phb + dx = nc_file@DX + dy = nc_file@DY + + uh_opt = True + uh_opt@uhmnhgt = 2000. + uh_opt@uhmxhgt = 5000. + dim_vars = dimsizes(varin) + + print("Calculating updraft helicity") + if(dim_vars .eq. 1) then + print(" Using defaults for the integration limits") + end if + + if(dim_vars .eq. 2) then + print(" Please enter both the minimum and maximum integration limits") + print(" Going to use defaults for the integration limits") + end if + + if(dim_vars .eq. 3) then + if ( stringtofloat(varin(1)) .lt. 1000. ) then + print(" Integration limits needs to be greater than 1000 meter") + print(" Going to use defaults for the integration limits") + else + uh_opt@uhmnhgt = stringtofloat(varin(1)) + uh_opt@uhmxhgt = stringtofloat(varin(2)) + print(" Setting custom integration limits") + end if + end if + + print(" min = "+uh_opt@uhmnhgt+" max = "+uh_opt@uhmxhgt) + uh = wrf_updraft_helicity(zp, mapfct, ua, va, w, dx, dy, uh_opt) + delete(uh_opt) + + return(uh) + end if + + + if( variable .eq. "twb" ) then + ; Wet bulb temperature + if ( time .eq. -1 ) then + if(ISFILE) then + T = nc_file->T + P = nc_file->P + PB = nc_file->PB + QV = nc_file->QVAPOR + else + T = file_handle[:]->T + P = file_handle[:]->P + PB = file_handle[:]->PB + QV = file_handle[:]->QVAPOR + end if + else + if(ISFILE) then + T = nc_file->T(time_in,:,:,:) + P = nc_file->P(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + QV = nc_file->QVAPOR(time_in,:,:,:) + else + T = file_handle[:]->T(time_in,:,:,:) + P = file_handle[:]->P(time_in,:,:,:) + PB = file_handle[:]->PB(time_in,:,:,:) + QV = file_handle[:]->QVAPOR(time_in,:,:,:) + end if + end if + T = T + 300. + P = P + PB + t = wrf_tk(P,T) + + twb = wrf_wetbulb(P,t,QV) + + delete_VarAtts(T,(/"description"/)) + copy_VarAtts(T,twb) + return(twb) + end if + + + if( variable .eq. "omg" ) then + ; Omega + if ( time .eq. -1 ) then + if(ISFILE) then + T = nc_file->T + P = nc_file->P + W = nc_file->W + PB = nc_file->PB + QV = nc_file->QVAPOR + else + T = file_handle[:]->T + P = file_handle[:]->P + W = file_handle[:]->W + PB = file_handle[:]->PB + QV = file_handle[:]->QVAPOR + end if + else + if(ISFILE) then + T = nc_file->T(time_in,:,:,:) + P = nc_file->P(time_in,:,:,:) + W = nc_file->W(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + QV = nc_file->QVAPOR(time_in,:,:,:) + else + T = file_handle[:]->T(time_in,:,:,:) + P = file_handle[:]->P(time_in,:,:,:) + W = file_handle[:]->W(time_in,:,:,:) + PB = file_handle[:]->PB(time_in,:,:,:) + QV = file_handle[:]->QVAPOR(time_in,:,:,:) + end if + end if + T = T + 300. + P = P + PB + t = wrf_tk(P,T) + wa = wrf_user_unstagger(W,W@stagger) + + omg = wrf_omega(QV,t,wa,P) + + delete_VarAtts(T,(/"description","units"/)) + copy_VarAtts(T,omg) + return(omg) + end if + + + if( variable .eq. "tv" ) then + ; Virtual temperature + if ( time .eq. -1 ) then + if(ISFILE) then + T = nc_file->T + P = nc_file->P + PB = nc_file->PB + QV = nc_file->QVAPOR + else + T = file_handle[:]->T + P = file_handle[:]->P + PB = file_handle[:]->PB + QV = file_handle[:]->QVAPOR + end if + else + if(ISFILE) then + T = nc_file->T(time_in,:,:,:) + P = nc_file->P(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + QV = nc_file->QVAPOR(time_in,:,:,:) + else + T = file_handle[:]->T(time_in,:,:,:) + P = file_handle[:]->P(time_in,:,:,:) + PB = file_handle[:]->PB(time_in,:,:,:) + QV = file_handle[:]->QVAPOR(time_in,:,:,:) + end if + end if + T = T + 300. + P = P + PB + t = wrf_tk(P,T) + + tv = wrf_virtual_temp(t,QV) + + delete_VarAtts(T,(/"description"/)) + copy_VarAtts(T,tv) + return(tv) + end if + + if( variable .eq. "ctt") then + if ( time .eq. -1 ) then + explicit_time = 0 + if(ISFILE) then + P = nc_file->P + PB = nc_file->PB + T = nc_file->T + +;geopotential height + PHB = nc_file->PHB + PH = nc_file->PH + + if(isfilevar(nc_file,"QVAPOR")) then + qvp = nc_file->QVAPOR * 1000. ; kg/kg -> g/kg + else + print("wrf_user_getvar: QVAPOR is needed to calculate the cloud top temperature.") + print("It has not been found in the data set.") + exit + end if + + + haveqci = 1 + if(isfilevar(nc_file,"QICE")) then + qci = nc_file->QICE * 1000. ; kg/kg -> g/kg + else + qci = new( (/Pdims(0),Pdims(1),Pdims(2),Pdims(3)/),float) + haveqci = 0 + end if + + + if(isfilevar(nc_file,"QCLOUD")) then + qcw = nc_file->QCLOUD * 1000. ; kg/kg -> g/kg + else + print("wrf_user_getvar: QCLOUD is needed to calculate the cloud top temperature.") + print("It has not been found in the data set.") + exit + end if + + ter = nc_file->HGT(0,:,:) + + else ; the else for ISFILE + P = file_handle[:]->P + PB = file_handle[:]->PB + T = file_handle[:]->T + PHB = file_handle[:]->PHB + PH = file_handle[:]->PH + nc_file = file_handle[0] + ter = nc_file->HGT(0,:,:) + if(isfilevar(nc_file,"QVAPOR")) then + qvp = file_handle[:]->QVAPOR * 1000. ; kg/kg -> g/kg + else + print("wrf_user_getvar: QVAPOR is needed to calculate the cloud top temperature.") + print("It has not been found in the data set.") + exit + end if + + haveqci = 1 + if(isfilevar(nc_file,"QICE")) then + qci = file_handle[:]->QICE * 1000. ; kg/kg -> g/kg + else + qci = new( (/Pdims(0),Pdims(1),Pdims(2),Pdims(3)/),float) + haveqci = 0 + end if + + + if(isfilevar(nc_file,"QCLOUD")) then + qcw = file_handle[:]->QCLOUD * 1000. ; kg/kg -> g/kg + else + print("wrf_user_getvar: QCLOUD is needed to calculate the cloud top temperature.") + print("It has not been found in the data set.") + exit + end if + + end if ;if ISFILE + else ;the else for time = -1 + if(ISFILE) then + explicit_time = 1 + P = nc_file->P(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + T = nc_file->T(time_in,:,:,:) + +;geopotential height + PHB = nc_file->PHB(time_in,:,:,:) + PH = nc_file->PH(time_in,:,:,:) + + if(isfilevar(nc_file,"QVAPOR")) then + qvp = nc_file->QVAPOR(time_in,:,:,:) * 1000. ; kg/kg -> g/kg + else + print("wrf_user_getvar: QVAPOR is needed to calculate the cloud top temperature.") + print("It has not been found in the data set") + exit + end if + + + haveqci = 1 + if(isfilevar(nc_file,"QICE")) then + qci = nc_file->QICE(time_in,:,:,:) * 1000. ; kg/kg -> g/kg + else + qci = new( (/Pdims(0),Pdims(1),Pdims(2),Pdims(3)/),float) + haveqci = 0 + end if + + + if(isfilevar(nc_file,"QCLOUD")) then + qcw = nc_file->QCLOUD(time_in,:,:,:) * 1000. ; kg/kg -> g/kg + else + print("wrf_user_getvar: QCLOUD is needed to calculate the cloud top temperature.") + print("It has not been found in the data set.") + exit + end if + + ter = nc_file->HGT(0,:,:) + end if ;end if for ISFILE + end if ;time = -1 + + +;Get total pressure + Pdims = dimsizes(P) + pres = P + PB + pres = pres * 0.01 + +;Get temperature in degrees K + T = T +300. + tk = wrf_tk( pres , T ) + +;Get geopotential height on mass points + stag_ght = PH + stag_ght = (PHB + PH)/9.81 + ght = wrf_user_unstagger(stag_ght,PHB@stagger) + + fctt = wrf_ctt(pres,tk,qci,qcw,qvp,ght,ter,haveqci) +; fctt will have description, units, and dimension names attached + delete_VarAtts(T,(/"description","units"/)) + copy_VarAtts(T,fctt) + return(fctt) + end if ;variable is ctt + + + if( any( variable .eq. (/"ter","HGT","HGT_M"/) ) ) then + variable = "HGT" + if(.not. isfilevar(nc_file,"HGT")) then + variable = "HGT_M" + end if + end if + + + if( any( variable .eq. (/"lat","XLAT","XLAT_M"/) ) ) then + variable = "XLAT" + if(.not. isfilevar(nc_file,"XLAT")) then + variable = "XLAT_M" + end if + end if + + + if( any( variable .eq. (/"lon","long","XLONG","XLONG_M"/) ) ) then + variable = "XLONG" + if(.not. isfilevar(nc_file,"XLONG")) then + variable = "XLONG_M" + end if + end if + + + if( any( variable .eq. (/"times"/) ) ) then + if ( time .eq. -1 ) then + if(ISFILE) then + var = nc_file->Times + else + var = file_handle[:]->Times + end if + else + if(ISFILE) then + var = nc_file->Times(time_in,:) + else + var = file_handle[:]->Times(time_in,:) + end if + end if + dims = dimsizes(var) + times = new(dims(0),string) + do i=0,dims(0)-1 + times(i) = chartostring(var(i,:)) + end do + times@description = "times in file" + return (times) + end if + + + +; end of diagnostic variable list - we must want a variable already in the file. + + if ( time .eq. -1 ) then + if(ISFILE) then + var = nc_file->$variable$ + else + var = file_handle[:]->$variable$ + end if + else + ; check variable dimensionality and pull proper time out of file + ndims = dimsizes(filevardimsizes(nc_file,variable)) + if( ndims .eq. 4) then + if(ISFILE) then + var = nc_file->$variable$(time_in,:,:,:) + else + var = file_handle[:]->$variable$(time_in,:,:,:) + end if + end if + if( ndims .eq. 3) then + if(ISFILE) then + var = nc_file->$variable$(time_in,:,:) + else + var = file_handle[:]->$variable$(time_in,:,:) + end if + end if + if( ndims .eq. 2) then + if(ISFILE) then + var = nc_file->$variable$(time_in,:) + else + var = file_handle[:]->$variable$(time_in,:) + end if + end if + if( ndims .eq. 1) then + if(ISFILE) then + var = nc_file->$variable$(time_in) + else + var = file_handle[:]->$variable$(time_in) + end if + end if + end if + + return(var) + +end + + +;-------------------------------------------------------------------------------- +undef("wrf_user_getvar_from_files") +function wrf_user_getvar_from_files( nc_files:string, varin[*]:string, time[*]:integer, opts_args:logical ) + +begin + + numFiles = dimsizes(nc_files) + f = addfiles(nc_files,"r") + + var_tmp = wrf_user_getvar(f[0],varin,-1) + varDims = dimsizes(var_tmp) + varRank = dimsizes(varDims) + time_req = 0 + time_inc = 1 + time_end = varDims(0)*numFiles + if ( dimsizes(time) .eq. 1 ) then + if ( time(0) .ge. 0 ) then + numTimes = 1 + time_req = time(0) + time_end = time(0) + time_inc = 1 + else + numTimes = varDims(0)*numFiles + end if + end if + if ( dimsizes(time) .eq. 2 ) then + if ( time(0) .ge. 0 ) then + numTimes = (time(1)-time(0))+1 + time_req = time(0) + time_end = time(1) + time_inc = 1 + else + numTimes = varDims(0)*numFiles + end if + end if + if ( dimsizes(time) .eq. 3 ) then + if ( time(0) .ge. 0 ) then + numTimes = ((time(1)-time(0))+1)/time(2) + time_req = time(0) + time_end = time(1) + time_inc = time(2) + else + numTimes = varDims(0)*numFiles + end if + end if + outtime = 0 + outtime_avail = 0 + + + if ( varRank .eq. 4 ) + varout = new ( (/numTimes,varDims(1),varDims(2),varDims(3)/), typeof(var_tmp) ) + varout = 0 + do it = 0,varDims(0)-1 + if ( (outtime_avail.eq.time_req) .and. (time_req.le.time_end) ) then + varout(outtime,:,:,:) = var_tmp(it,:,:,:) + outtime = outtime + 1 + time_req = time_req + time_inc + end if + outtime_avail = outtime_avail + 1 + end do + delete(var_tmp) + do ifil = 1,numFiles-1 + var_tmp = wrf_user_getvar(f[ifil],varin,-1) + dimLoop = dimsizes(var_tmp) + do it = 0,dimLoop(0)-1 + if ( (outtime_avail.eq.time_req) .and. (time_req.le.time_end) ) then + varout(outtime,:,:,:) = var_tmp(it,:,:,:) + outtime = outtime + 1 + time_req = time_req + time_inc + end if + outtime_avail = outtime_avail + 1 + end do + delete(var_tmp) + end do + end if + if ( varRank .eq. 3 ) + varout = new ( (/numTimes,varDims(1),varDims(2)/), typeof(var_tmp) ) + varout = 0 + do it = 0,varDims(0)-1 + if ( (outtime_avail.eq.time_req) .and. (time_req.le.time_end) ) then + varout(outtime,:,:) = var_tmp(it,:,:) + outtime = outtime + 1 + time_req = time_req + time_inc + end if + outtime_avail = outtime_avail + 1 + end do + delete(var_tmp) + do ifil = 1,numFiles-1 + var_tmp = wrf_user_getvar(f[ifil],varin,-1) + dimLoop = dimsizes(var_tmp) + do it = 0,dimLoop(0)-1 + if ( (outtime_avail.eq.time_req) .and. (time_req.le.time_end) ) then + varout(outtime,:,:) = var_tmp(it,:,:) + outtime = outtime + 1 + time_req = time_req + time_inc + end if + outtime_avail = outtime_avail + 1 + end do + delete(var_tmp) + end do + end if + if ( varRank .eq. 2 ) + varout = new ( (/numTimes,varDims(1)/), typeof(var_tmp) ) + if ( typeof(var_tmp) .eq. "float" .or. typeof(var_tmp) .eq. "integer" ) then + varout = 0 + end if + do it = 0,varDims(0)-1 + if ( (outtime_avail.eq.time_req) .and. (time_req.le.time_end) ) then + varout(outtime,:) = var_tmp(it,:) + outtime = outtime + 1 + time_req = time_req + time_inc + end if + outtime_avail = outtime_avail + 1 + end do + delete(var_tmp) + do ifil = 1,numFiles-1 + var_tmp = wrf_user_getvar(f[ifil],varin,-1) + dimLoop = dimsizes(var_tmp) + do it = 0,dimLoop(0)-1 + if ( (outtime_avail.eq.time_req) .and. (time_req.le.time_end) ) then + varout(outtime,:) = var_tmp(it,:) + outtime = outtime + 1 + time_req = time_req + time_inc + end if + outtime_avail = outtime_avail + 1 + end do + delete(var_tmp) + end do + end if + if ( varRank .eq. 1 ) + varout = new ( (/numTimes/), typeof(var_tmp) ) + if ( typeof(var_tmp) .eq. "float" .or. typeof(var_tmp) .eq. "integer" ) then + varout = 0 + end if + do it = 0,varDims(0)-1 + if ( (outtime_avail.eq.time_req) .and. (time_req.le.time_end) ) then + varout(outtime) = var_tmp(it) + outtime = outtime + 1 + time_req = time_req + time_inc + end if + outtime_avail = outtime_avail + 1 + end do + delete(var_tmp) + do ifil = 1,numFiles-1 + var_tmp = wrf_user_getvar(f[ifil],varin,-1) + dimLoop = dimsizes(var_tmp) + do it = 0,dimLoop(0)-1 + if ( (outtime_avail.eq.time_req) .and. (time_req.le.time_end) ) then + varout(outtime) = var_tmp(it) + outtime = outtime + 1 + time_req = time_req + time_inc + end if + outtime_avail = outtime_avail + 1 + end do + delete(var_tmp) + end do + end if + + return(varout) +end + + + + +;-------------------------------------------------------------------------------- +; This function was modified in May 2011 to allow a list of files. +; +undef("wrf_user_list_times") +function wrf_user_list_times( nc_file ) + +local times, times_in_file, dims, i +begin + +;---As of NCL V6.0.0, wrf_user_getvar can now handle a file or a list of files. + if(all(typeof(nc_file).ne.(/"file","list"/))) then + print("wrf_user_list_times: error: the input argument must be a file or a list of files opened with addfile or addfiles") + return + end if + + if(typeof(nc_file).eq."file") then + times_in_file = nc_file->Times + else + times_in_file = nc_file[:]->Times + end if + dims = dimsizes(times_in_file) + times = new(dims(0),string) + do i=0,dims(0)-1 + times(i) = chartostring(times_in_file(i,:)) + end do + times@description = "times in file" + print(times) + return(times) + +end + +;-------------------------------------------------------------------------------- + +undef("wrf_user_latlon_to_ij") +function wrf_user_latlon_to_ij( nc_file:file, latitude:numeric, \ + longitude:numeric ) + +begin + WE = "WEST-EAST_GRID_DIMENSION" + SN = "SOUTH-NORTH_GRID_DIMENSION" + wedim = nc_file@$WE$ + sndim = nc_file@$SN$ + + if(isfilevar(nc_file,"XLAT")) + XLAT = nc_file->XLAT(0,:,:) + XLONG = nc_file->XLONG(0,:,:) + else + XLAT = nc_file->XLAT_M(0,:,:) + XLONG = nc_file->XLONG_M(0,:,:) + end if + + loc = wrf_latlon_to_ij( XLAT, XLONG, latitude, longitude ) + + loc!0 = "j & i locations" + return(loc) + +end + +;-------------------------------------------------------------------------------- + +undef("wrf_user_ll_to_ij") +function wrf_user_ll_to_ij( file_handle, longitude:numeric, latitude:numeric, \ + opts_args:logical ) + +begin +; +; As of NCL V6.0.0, wrf_user_ll_to_ij can now handle a file +; or a list of files. +; + if(typeof(file_handle).eq."file") then + ISFILE = True + nc_file = file_handle + else if(typeof(file_handle).eq."list") then + ISFILE = False + nc_file = file_handle[0] + else + print("wrf_user_ll_to_ij: error: the first argument must be a file or a list of files opened with addfile or addfiles") + return + end if + end if + + opts = opts_args + useT = get_res_value(opts,"useTime",0) + returnI= get_res_value(opts,"returnInt",True) + + res = True + res@MAP_PROJ = nc_file@MAP_PROJ + res@TRUELAT1 = nc_file@TRUELAT1 + res@TRUELAT2 = nc_file@TRUELAT2 + res@STAND_LON = nc_file@STAND_LON + res@DX = nc_file@DX + res@DY = nc_file@DY + + if (res@MAP_PROJ .eq. 6) then + res@POLE_LAT = nc_file@POLE_LAT + res@POLE_LON = nc_file@POLE_LON + res@LATINC = (res@DY*360.)/2.0/3.141592653589793/6370000. + res@LONINC = (res@DX*360.)/2.0/3.141592653589793/6370000. + else + res@POLE_LAT = 90.0 + res@POLE_LON = 0.0 + res@LATINC = 0.0 + res@LONINC = 0.0 + end if + + if(isfilevar(nc_file,"XLAT")) + if(ISFILE) then + XLAT = nc_file->XLAT(useT,:,:) + XLONG = nc_file->XLONG(useT,:,:) + else + XLAT = file_handle[useT]->XLAT + XLONG = file_handle[useT]->XLONG + end if + else + if(ISFILE) then + XLAT = nc_file->XLAT_M(useT,:,:) + XLONG = nc_file->XLONG_M(useT,:,:) + else + XLAT = file_handle[useT]->XLAT_M + XLONG = file_handle[useT]->XLONG_M + end if + end if + + + if(dimsizes(dimsizes(XLAT)).eq.2) then +; Rank 2 + res@REF_LAT = XLAT(0,0) + res@REF_LON = XLONG(0,0) + else +; Rank 3 + res@REF_LAT = XLAT(0,0,0) + res@REF_LON = XLONG(0,0,0) + end if + res@KNOWNI = 1.0 + res@KNOWNJ = 1.0 + + loc = wrf_ll_to_ij (longitude, latitude, res) + + if ( returnI ) then + loci = new(dimsizes(loc),integer) + ;loci@_FillValue = default_fillvalue("integer") ; was -999 + loci = tointeger(loc + .5) + loci!0 = loc!0 + return(loci) + else + return(loc) + end if + + +end + +;-------------------------------------------------------------------------------- + +undef("wrf_user_ij_to_ll") +function wrf_user_ij_to_ll( file_handle, i:numeric, j:numeric, \ + opts_args:logical ) + +begin +; +; As of NCL V6.0.0, wrf_user_ll_to_ij can now handle a file +; or a list of files. +; + if(typeof(file_handle).eq."file") then + ISFILE = True + nc_file = file_handle + else if(typeof(file_handle).eq."list") then + ISFILE = False + nc_file = file_handle[0] + else + print("wrf_user_ij_to_ll: error: the first argument must be a file or a list of files opened with addfile or addfiles") + return + end if + end if + + opts = opts_args + useT = get_res_value(opts,"useTime",0) + + res = True + res@MAP_PROJ = nc_file@MAP_PROJ + res@TRUELAT1 = nc_file@TRUELAT1 + res@TRUELAT2 = nc_file@TRUELAT2 + res@STAND_LON = nc_file@STAND_LON + res@DX = nc_file@DX + res@DY = nc_file@DY + + if (res@MAP_PROJ .eq. 6) then + res@POLE_LAT = nc_file@POLE_LAT + res@POLE_LON = nc_file@POLE_LON + res@LATINC = (res@DY*360.)/2.0/3.141592653589793/6370000. + res@LONINC = (res@DX*360.)/2.0/3.141592653589793/6370000. + else + res@POLE_LAT = 90.0 + res@POLE_LON = 0.0 + res@LATINC = 0.0 + res@LONINC = 0.0 + end if + + + if(isfilevar(nc_file,"XLAT")) then + if(ISFILE) then + XLAT = nc_file->XLAT(useT,:,:) + XLONG = nc_file->XLONG(useT,:,:) + else + XLAT = file_handle[useT]->XLAT + XLONG = file_handle[useT]->XLONG + end if + else + if(ISFILE) then + XLAT = nc_file->XLAT_M(useT,:,:) + XLONG = nc_file->XLONG_M(useT,:,:) + else + XLAT = file_handle[useT]->XLAT_M + XLONG = file_handle[useT]->XLONG_M + end if + end if + + if(dimsizes(dimsizes(XLAT)).eq.2) then +; Rank 2 + res@REF_LAT = XLAT(0,0) + res@REF_LON = XLONG(0,0) + else +; Rank 3 + res@REF_LAT = XLAT(0,0,0) + res@REF_LON = XLONG(0,0,0) + end if + res@KNOWNI = 1.0 + res@KNOWNJ = 1.0 + + loc = wrf_ij_to_ll (i,j,res) + + return(loc) + + +end + +;-------------------------------------------------------------------------------- +undef("wrf_user_vert_interp") +function wrf_user_vert_interp(file_handle,field:numeric, \ + vert_coordinate[1]:string, \ + interp_levels[*]:numeric,opts[1]:logical) +local valid_vert_coords, nc_file, valid_field_types +begin + + valid_vert_coords = (/"pressure","pres","ght_msl","ght_agl","theta","theta-e"/) + if(.not.any(vert_coordinate.eq.valid_vert_coords)) then + print("wrf_user_vert_interp: Unrecognized vertical coordinate.") + print(" Accepted vertical coordinates are:") + print( "pressure, pres hPa") + print( "ght_msl km") + print( "ght_agl km") + print( "theta K") + print( "theta-e K") + exit + end if + + if(typeof(file_handle).eq."file") then + ISFILE = True + nc_file = file_handle + else if(typeof(file_handle).eq."list") then + ISFILE = False + nc_file = file_handle[0] + else + print("wrf_user_vert_interp: error: the first argument must be a file or a list of files opened with addfile or addfiles") + return + end if + end if + + rgas = 287.04 ;J/K/kg + ussalr = .0065 ; deg C per m + sclht = rgas*256./9.81 + +;read grid sizes from the nc_file. Check to make +;sure that we don't have a staggered field. + dNames = getvardims(nc_file) + dSizes = getfiledimsizes(nc_file) + thedims = dimsizes(dSizes) + number_dims = thedims(0) + + ew = dSizes(ind(dNames .eq. "west_east")) + ns = dSizes(ind(dNames .eq. "south_north")) + nz = dSizes(ind(dNames .eq. "bottom_top")) + + field_dims = dimsizes(field) + num_field_dims = dimsizes(field_dims) + + if(num_field_dims .lt. 3 .or. num_field_dims .gt. 4) then + print("wrf_user_vert_interp: We can only interpolate a 3D or 4D field") + exit + end if + +; Check to see if the field comes in unstaggered. + if(field_dims(num_field_dims-3) .ne. nz) then + print("wrf_user_vert_interp: Please unstagger the field in the vertical") + exit + end if + + if(field_dims(num_field_dims-2) .ne. ns .or. \ + field_dims(num_field_dims-1) .ne. ew) then + print("wrf_user_vert_interp: Please unstagger the field") + exit + end if + +; See what options we have + extrap_field = get_res_value_keep(opts,"extrapolate",False) + field_type = str_lower(get_res_value_keep(opts,"field_type","none")) + log_of_Pressure = get_res_value_keep(opts,"logP",False) + debug = get_res_value_keep(opts,"debug",False) + + valid_field_types = (/"none","pressure","pres","p","z","t","ght"/) + if(.not.any(field_type.eq.valid_field_types)) then + print("wrf_user_vert_interp: Unrecognized field type.") + print("Valid field types are: " + str_join(valid_field_types,", ")) + exit + end if + + if(log_of_Pressure) then + logP = 1 ; this is for passing into Fortran + else + logP = 0 + end if + + icase = 0 + extrap = 0 ; This is for passing into Fortran + if(extrap_field) then + extrap = 1 + if(any(field_type .eq. (/"p","pres","pressure"/))) then + icase = 1 + end if + + if(field_type .eq. "z") then + icase = 2 + end if + + if(field_type .eq. "ght") then + icase = 2 + end if +; +; For temperature we may have just temperature, potential temperature +; or equivalent potential temperature. Check the field description attribute +; to see which one we have. +; + if(field_type .eq. "t") then + if(isatt(field,"description")) then + + if(field@description .eq. "Temperature") then + if(field@units .eq. "C") then + icase = 3 + else + icase = 4 + end if + end if + + if(field@description .eq. "Potential Temperature (theta) ") then + icase = 5 + end if + + if(field@description .eq. "Equivalent Potential Temperature") then + icase = 6 + end if + end if ;the endif for checking for the field description attribute + + end if;end if for the field_type being T or t + + + end if; the endif for extrap_field .eq. True + + + numlevels = dimsizes(interp_levels) + +;We will need some basic fields for the interpolation +;regardless of the field requested. Get all time periods +;of the fields. + if(ISFILE) then + P = nc_file->P + nc_file->PB + Pdims = dimsizes(P) + ght = wrf_user_getvar(nc_file,"height",-1) + tk = wrf_user_getvar(nc_file,"tk",-1) + qvp = nc_file->QVAPOR + terht = nc_file->HGT + sfp = nc_file->PSFC * 0.01 + else + P = file_handle[:]->P + file_handle[:]->PB + Pdims = dimsizes(P) + tmpz = file_handle[:]->PH + PHB = file_handle[:]->PHB + tmpz = (tmpz + PHB)/9.81 + ght = wrf_user_unstagger(tmpz,"Z") + T = file_handle[:]->T + T = T + 300. + tk = wrf_tk( P , T ) + qvp = file_handle[:]->QVAPOR + terht = file_handle[:] ->HGT + sfp = file_handle[:] ->PSFC * 0.01 + end if + smsfp = sfp + wrf_smooth_2d(smsfp,3) + + +;Initialize an array for the vertical coordinate + ntimes = Pdims(0) + +;Get the vertical coordinate type + vcor = 0 + logp = 0 + if(any(vert_coordinate .eq. (/"pressure","pres"/))) then + vcor = 1 + vcord_array = P * 0.01 + end if + + if(vert_coordinate .eq. "ght_msl") then + vcor = 2 + vcord_array = exp(-ght/sclht) + end if + + if(vert_coordinate .eq. "ght_agl") then + vcor = 3 + rtemp = new( (/nz,ns,ew/),float) + vcord_array = new((/ntimes,nz,ns,ew/),float) + do it = 0, ntimes - 1 + do ilev = 0,nz-1 + rtemp(ilev,:,:) = ght(it,ilev,:,:) - terht(0,:,:) + end do + vcord_array(it,:,:,:) = exp(-rtemp/sclht) + end do + delete(rtemp) + end if + + if(vert_coordinate .eq. "theta") then + vcor = 4 + idir = 1 + icorsw = 0 + delta = 0.01 + if(ISFILE) then + coriolis = nc_file->F(0,:,:) + theta = wrf_user_getvar(nc_file,"theta",-1) + else + coriolis = file_handle[0]->F(0,:,:) + theta = T + end if + preshPa = P * 0.01 + vcord_array = wrf_monotonic(theta,preshPa,coriolis,idir,delta,icorsw) +; +; We only extrapolate temperature fields below ground if we are interpolating +; to pressure or height vertical surfaces. +; + icase = 0 + end if + + if(vert_coordinate .eq. "theta-e") then + vcor = 5 + icorsw = 0 + idir = 1 + delta = 0.01 + if(ISFILE) then + coriolis = nc_file->F(0,:,:) + eqpot = wrf_user_getvar(nc_file,"eth",-1) + else + coriolis = file_handle[0]->F(0,:,:) + eqpot = wrf_eth ( qvp, tk, P ) + end if + preshPa = P * 0.01 + + vcord_array = wrf_monotonic(eqpot,preshPa,coriolis,idir,delta,icorsw) +; We only extrapolate temperature fields below ground if we are interpolating +; to pressure or height vertical surfaces. + icase = 0 + end if + + if(debug) then + print("icase = " + icase + " extrap = " + extrap + " vcor = " + vcor + " logP = " + logP) + end if + + field_out = wrf_vintrp(field,P,tk,qvp,ght,terht(0,:,:),sfp,smsfp,\ + vcord_array,interp_levels,icase,extrap,vcor,logP) + +; Add metadata to return array + copy_VarMeta(field,field_out) + +; Add new levels as a coordinate array + lev_field = num_field_dims-3 + field_out!lev_field = "interp_levels" + field_out&$field_out!lev_field$ = interp_levels(::-1) + field_out@vert_interp_type = vert_coordinate + + return(field_out) +end + +;-------------------------------------------------------------------------------- +;-------------------------------------------------------------------------------- +;-------------------------------------------------------------------------------- +undef("write_wrf_debug_info") +procedure write_wrf_debug_info(wks[1]:graphic,data1,data2, \ + debug_file[1]:string, \ + wrf_opts,wrf_func_name[1]:string) +; +; This procedure writes resources and data variables used to +; create a WRF plot to a NetCDF file. This file can be read +; in later to recreate the NCL script that created that plot, +; using gsn_xxx functions. This is for debug purposes. You can't +; tell what resources a WRF script is using, so this is a way +; of seeing them all in a NetCDF file. +; +begin + if(.not.isatt(wks,"WRFDebug")) then + first_time = True + wks@WRFDebug = True + else + first_time = False + end if +; +; The default will be "wrfdebug.ncl" and "wrfdebug.nc" +; unless otherwise specified. +; + cdf_debug_file = debug_file + ".nc" + ncl_debug_file = debug_file + ".ncl" + res_debug_file = debug_file + ".res" + +; +; If this is the first time writing debug information to the file, +; then create the file and add the first set of information. +; +; Make sure the files don't already exist. +; + if(first_time) then + if(fileexists(cdf_debug_file).or.fileexists(ncl_debug_file).or.\ + fileexists(res_debug_file)) then + print("write_wrf_debug_info: error: debug files '" + cdf_debug_file + "',") + print("'" + ncl_debug_file + "' and/or " + res_debug_file + " exist.") + print("Please remove file(s) and start script again.") + exit + end if + dbgfile = addfile(cdf_debug_file,"c") + else +; +; If this is not the first time, open the file as read/write. +; + dbgfile = addfile(cdf_debug_file,"w") + end if + +; +; If this is not the first time, then we need to append the information. +; + if(.not.first_time) then +; +; The variables should be wrf_var_1, wrf_var_2, etc. We need to get the +; highest one already in use, so we can create the next highest one. +; + wrf_debug_vars = getfilevarnames(dbgfile) + max_num = max(stringtointeger(str_get_field(wrf_debug_vars,3,"_"))) + 1 + else + max_num = 1 + end if + +; This will be name of the logical variable to hold all the resources +; for this dataset. + wrf_res_name = "wrf_res_" + max_num + +; +; Write the plot data to the netCDF file. If the data contains the +; special 2D lat2d/lon2d arrays, we have to write these as 1D arrays +; and reconstruct them as 2D later. +; + if(typeof(data1).ne."logical".and.typeof(data2).eq."logical") then +; For non u,v data + wrf_data_name = "wrf_data_" + max_num + add_latlon2d_debug_info(data1) + dbgfile->$wrf_data_name$ = (/data1/) ; Write the data + end if + if(typeof(data1).ne."logical".and.typeof(data2).ne."logical") then +; For u,v data + add_latlon2d_debug_info(data1) + add_latlon2d_debug_info(data2) + wrf_data_name = "wrf_udata_" + max_num + dbgfile->$wrf_data_name$ = (/data1/) ; Write the U data + wrf_data_name = "wrf_vdata_" + max_num + dbgfile->$wrf_data_name$ = (/data2/) ; Write the V data + end if + +; Retain the name of the wrf function that called this routine. + tmp = "wrf_func_name_" + max_num + dbgfile@$tmp$ = wrf_func_name + +; +; Get plot resources, if any. +; + wattnames = getvaratts(wrf_opts) + if(.not.any(ismissing(wattnames))) then + natt = dimsizes(wattnames) + else + natt = 0 + end if + +; +; Check if any of the plot attributes are ones that can contain +; big data arrays, like sfXArray, vfYArray, etc. +; +; If so, then write these to the netCDF file. Otherwise, write them +; to the file as attributes. +; + array_resources = (/"sfXArray","sfYArray","vfXArray","vfYArray"/) + + if(natt.gt.0) then + tmp_opts = 1 + do i=0,natt-1 + if(any(wattnames(i).eq.array_resources)) then + tmp = "wrf_data_coord_name_" + wattnames(i) + "_" + max_num + dbgfile->$tmp$ = wrf_opts@$wattnames(i)$ + else +; Can't write "logical" to a NetCDF file. + if(typeof(wrf_opts@$wattnames(i)$).eq."logical") then + if(wrf_opts@$wattnames(i)$) then + tmp_opts@$wattnames(i)$ = 1 + else + tmp_opts@$wattnames(i)$ = 0 + end if + else +; Just write the resource. + tmp_opts@$wattnames(i)$ = wrf_opts@$wattnames(i)$ + end if + end if + end do + dbgfile->$wrf_res_name$ = tmp_opts + end if + +; Close the NetCDF file + delete(dbgfile) +end + +undef("write_wrf_debug_script") +procedure write_wrf_debug_script(wks,debug_file,wrf_func_name) +begin + dbgfile = addfile(debug_file+".nc","r") + print(getvaratts(dbgfile)) +end + +undef("delete_attrs") +procedure delete_attrs(opts:logical) + +; This procedure does some cleanup by removing unneeded attributes +; so they don't get passed to other routines by accident. + +begin + list_attrs = (/"MainTitle","MainTitlePos","MainTitlePosF", \ + "InitTime","ValidTime","TimePos","TimePosF", \ + "NoHeaderFooter","TimeLabel","LevelLabel", \ + "FieldTitle","UnitLabel","NumVectors","AspectRatio", \ + "SubFieldTitle","PlotOrientation","PlotLevelID", \ + "mpNestTime","ContourParameters","FontHeightF","Footer", \ + "start_lat","start_lon","end_lat","end_lon", \ + "proj","map_proj","stand_lon","truelat1","truelat2","cenlat", \ + "pole_lat","pole_lon","ref_lat","ref_lon","ref_x","ref_y", \ + "e_we","e_sn","parent_id","parent_grid_ratio", \ + "i_parent_start","j_parent_start", \ + "dx","dy","max_dom" \ + /) + + do i=0,dimsizes(list_attrs)-1 + if(isatt(opts,list_attrs(i))) then + delete(opts@$list_attrs(i)$) + end if + end do +end + +;-------------------------------------------------------------------------------- +;-------------------------------------------------------------------------------- +undef("set_cn_resources") +function set_cn_resources (data[*][*]:numeric, res:logical) + +begin + + opts = res + +; The ContourParameters resource can either be a scalar that +; represents the contour level spacing, or it can be an array +; of three elements that represent the minimum level, the maximum +; level, and the level spacing. +; + mx = max(data) + mn = min(data) + + if(mn.ne.mx.and.opts.and.isatt(opts,"ContourParameters")) then + if(dimsizes(opts@ContourParameters) .eq. 1) then + +; Only the contour interval is specified. + nlev = tointeger((mx-mn)/opts@ContourParameters)+1 + levels = nice_mnmxintvl(mn,mx,nlev,True) + if(levels(0) .lt. 0.) then + ; Set a zero contour. + nlev = tointeger(levels(0)/opts@ContourParameters) - 1 + levels(0) = nlev*opts@ContourParameters + end if + nlev = tointeger((levels(1)-levels(0))/opts@ContourParameters)+1 + levels(1) = levels(0) + nlev*opts@ContourParameters + levels(2) = opts@ContourParameters + +; Min level, max level, and level spacing are specified by user. + else + if(dimsizes(opts@ContourParameters) .eq. 3) then + levels = opts@ContourParameters + else + print("wrf_contour: Warning: illegal setting for ContourParameters attribute") + end if + end if + + end if + +; Contour levels + if(isvar("levels")) then + opts@cnLevelSelectionMode = get_res_value_keep(opts, "cnLevelSelectionMode", "ManualLevels") + opts@cnMinLevelValF = get_res_value_keep(opts, "cnMinLevelValF", levels(0)) + opts@cnMaxLevelValF = get_res_value_keep(opts, "cnMaxLevelValF", levels(1)) + opts@cnLevelSpacingF = get_res_value_keep(opts, "cnLevelSpacingF",levels(2)) + delete(levels) + end if + + +; Set the default zero line thickness to 2, and the negative contour +; line dash pattern to 1 (0 is solid). + opts@gsnContourZeroLineThicknessF = get_res_value_keep(opts, "gsnContourZeroLineThicknessF",2.0) + opts@gsnContourNegLineDashPattern = get_res_value_keep(opts, "gsnContourNegLineDashPattern",1) + + +; Set resources that apply for both filled and line contour plots. + opts@cnFillDrawOrder = get_res_value_keep(opts,"cnFillDrawOrder", "PreDraw") + + + opts@cnLineLabelAngleF = get_res_value_keep(opts,"cnLineLabelAngleF", 0.0) + opts@cnLineLabelFontHeightF = get_res_value_keep(opts,"cnLineLabelFontHeightF", 0.015) + opts@cnInfoLabelFontHeightF = get_res_value_keep(opts,"cnInfoLabelFontHeightF", 0.015) + opts@cnLineLabelPerimOn = get_res_value_keep(opts,"cnLineLabelPerimOn", True) + opts@cnInfoLabelPerimOn = get_res_value_keep(opts,"cnInfoLabelPerimOn", False) + opts@cnLineLabelBackgroundColor = get_res_value_keep(opts,"cnLineLabelBackgroundColor", -1) + opts@cnHighLabelBackgroundColor = get_res_value_keep(opts,"cnHighLabelBackgroundColor", -1) + opts@cnLowLabelBackgroundColor = get_res_value_keep(opts,"cnLowLabelBackgroundColor", -1) + opts@cnLineColor = get_res_value_keep(opts,"cnLineColor", "Black") + opts@cnLineLabelFontColor = opts@cnLineColor + opts@cnLineLabelPerimColor = opts@cnLineColor + opts@cnInfoLabelFontColor = opts@cnLineColor + opts@cnHighLabelFontColor = opts@cnLineColor + opts@cnLowLabelFontColor = opts@cnLineColor + + +; Set field Title and levels if available + if(.not.isatt(opts,"cnInfoLabelString")) then + info_string = " Contours: $CMN$ to $CMX$ by $CIU$" + if(isatt(opts,"FieldTitle")) then + opts@cnInfoLabelString = opts@FieldTitle + info_string + else if(isatt(data,"description")) then + opts@cnInfoLabelString = data@description + info_string + else + opts@cnInfoLabelString = info_string + end if + end if + end if + + + return(opts) +end +;-------------------------------------------------------------------------------- +;-------------------------------------------------------------------------------- +undef("set_lb_resources") +function set_lb_resources (data[*][*]:numeric, res:logical) + +begin + + opts = res + + +; Somewhat convoluted way to see if a labelbar is not desired. + if(check_attr(opts,"pmTickMarkDisplayMode","Never",True).or.\ + check_attr(opts,"pmTickMarkDisplayMode",-1,False).or.\ + check_attr(opts,"pmTickMarkDisplayMode",0,False).or. \ + check_attr(opts,"lbLabelBarOn",False,False).or.\ + check_attr(opts,"lbLabelBarOn",0,False)) then + lbar_on = False + else + lbar_on = True + end if + atmp = get_res_value(opts,"lbLabelBarOn",True) ; Remove this resource + delete(atmp) ; just in case. + + +; Possible title for the labelbar + if(isatt(opts,"FieldTitle")) then + lb_desc = opts@FieldTitle + else + if(isatt(data,"description")) then + lb_desc = data@description + else + lb_desc = "" + end if + end if + + if(isatt(opts,"UnitLabel") ) then + lb_desc = lb_desc + " (" + opts@UnitLabel + ")" + else + if(isatt(data,"units") .and. .not.(data@units.eq."")) then + lb_desc = lb_desc + " (" + data@units + ")" + end if + end if + + + if(.not.isatt(opts,"cnFillColors")) then + opts@gsnSpreadColors = get_res_value_keep(opts, "gsnSpreadColors", True) + end if + opts@cnInfoLabelOn = get_res_value_keep(opts,"cnInfoLabelOn", False) + opts@cnLinesOn = get_res_value_keep(opts,"cnLinesOn", False) + opts@cnLineLabelsOn = get_res_value_keep(opts,"cnLineLabelsOn", False) + +; Labelbar resources + if(lbar_on) then + opts@pmLabelBarDisplayMode = get_res_value_keep(opts,"pmLabelBarDisplayMode", "Always") + opts@pmLabelBarSide = get_res_value_keep(opts,"pmLabelBarSide", "Bottom") + opts@lbAutoManage = get_res_value_keep(opts,"lbAutoManage",False) + opts@lbOrientation = get_res_value_keep(opts,"lbOrientation", "Horizontal") + opts@lbPerimOn = get_res_value_keep(opts,"lbPerimOn", False) + opts@lbLabelJust = get_res_value_keep(opts,"lbLabelJust", "BottomCenter") + opts@lbLabelAutoStride = get_res_value_keep(opts,"lbLabelAutoStride",True) + opts@lbBoxMinorExtentF = get_res_value_keep(opts,"lbBoxMinorExtentF", 0.13) + opts@lbTitleFontHeightF = get_res_value_keep(opts,"lbTitleFontHeightF", 0.015) + opts@lbLabelFontHeightF = get_res_value_keep(opts,"lbLabelFontHeightF", 0.015) + opts@pmLabelBarOrthogonalPosF = get_res_value_keep(opts,"pmLabelBarOrthogonalPosF", -0.1) + + opts@lbTitleOn = get_res_value_keep(opts,"lbTitleOn", True) + if(lb_desc.ne."" .and. opts@lbTitleOn) then + opts@lbTitleOn = get_res_value_keep(opts,"lbTitleOn", True) + opts@lbTitleString = get_res_value_keep(opts,"lbTitleString", lb_desc) + opts@lbTitleJust = get_res_value_keep(opts,"lbTitleJust", "BottomCenter") + opts@lbTitleOffsetF = get_res_value_keep(opts,"lbTitleOffsetF", -0.5) + else + opts@lbTitleOn = False + end if + end if + + + return(opts) +end +;-------------------------------------------------------------------------------- +;-------------------------------------------------------------------------------- +undef("set_title_resources") +function set_title_resources (data[*][*]:numeric, res:logical) + +begin + + opts = res + +; Set field Title and levels if available + if(isatt(opts,"FieldTitle")) then + SubTitles = opts@FieldTitle + else + if(isatt(data,"description")) then + SubTitles = data@description + else + SubTitles = "UnKnown" + end if + end if + + if(isatt(opts,"SubFieldTitle")) then + SubTitles = SubTitles + " " + opts@SubFieldTitle + end if + if(isatt(opts,"UnitLabel")) then + SubTitles = SubTitles + " (" + opts@UnitLabel + ")" + else + if(isatt(data,"units") .and. .not.(data@units.eq."")) then + SubTitles = SubTitles + " (" + data@units + ")" + end if + end if + if (isatt(opts,"PlotLevelID")) then + SubTitles = SubTitles + " at " + opts@PlotLevelID + else + if (isatt(data,"PlotLevelID")) then + SubTitles = SubTitles + " at " + data@PlotLevelID + end if + end if + opts@tiMainString = SubTitles + + return(opts) +end +;-------------------------------------------------------------------------------- +;-------------------------------------------------------------------------------- +undef("set_vc_resources") +function set_vc_resources (res:logical) + +begin + + opts = res + + if ( isatt(opts,"vpWidthF") ) then + ; num_vectors is used for vcMinDistanceF and vcRefLengthF + width = opts@vpWidthF + num_vectors = get_res_value(opts,"NumVectors",25.0) + opts@vcMinDistanceF = get_res_value_keep(opts,"vcMinDistanceF", width/num_vectors) + opts@vcRefLengthF = get_res_value_keep(opts,"vcRefLengthF", width/num_vectors) + else + opts@vcMinDistanceF = get_res_value_keep(opts,"vcMinDistanceF", 0.02) + opts@vcRefLengthF = get_res_value_keep(opts,"vcRefLengthF", 0.02) + end if + + + opts@vcGlyphStyle = get_res_value_keep(opts,"vcGlyphStyle", "WindBarb") + opts@vcWindBarbColor = get_res_value_keep(opts,"vcWindBarbColor", "Black") + opts@vcRefAnnoOn = get_res_value_keep(opts,"vcRefAnnoOn", False) + opts@vcMinFracLengthF = get_res_value_keep(opts,"vcMinFracLengthF", .2) + + return(opts) +end +;-------------------------------------------------------------------------------- +;-------------------------------------------------------------------------------- +undef("set_mp_resources") +function set_mp_resources (res:logical) + +begin + + opts = res + +; "LowRes" is the default that NCL uses, so you don't need to +; set it here. However, if you want a higher resolution, use +; "MediumRes". If you want higher resolution for the coastlines, +; then set it to "HighRes", but then you also need to download +; the RANGS-GSHHS database. Higher resolutions take longer to +; draw. + + opts@mpDataBaseVersion = get_res_value_keep(opts, "mpDataBaseVersion","MediumRes") + ;opts@mpOutlineBoundarySets = get_res_value_keep(opts, "mpOutlineBoundarySets", "AllBoundaries") + opts@mpOutlineBoundarySets = get_res_value_keep(opts, "mpOutlineBoundarySets", "GeophysicalAndUSStates") + opts@mpPerimLineThicknessF = get_res_value_keep(opts, "mpPerimLineThicknessF", 1.0) + opts@tmXBLabelFontHeightF = get_res_value_keep(opts, "tmXBLabelFontHeightF", 0.01) + opts@tmYLLabelFontHeightF = get_res_value_keep(opts, "tmYLLabelFontHeightF", 0.01) + +; Select portion of the map to view. + opts@mpLimitMode = get_res_value_keep(opts, "mpLimitMode","Corners") + opts@mpLeftCornerLatF = get_res_value_keep(opts, "mpLeftCornerLatF", opts@start_lat) + opts@mpLeftCornerLonF = get_res_value_keep(opts, "mpLeftCornerLonF", opts@start_lon) + opts@mpRightCornerLatF = get_res_value_keep(opts, "mpRightCornerLatF",opts@end_lat) + opts@mpRightCornerLonF = get_res_value_keep(opts, "mpRightCornerLonF",opts@end_lon) + + if ( opts@mpRightCornerLonF .lt. 0.0 ) then + opts@mpRightCornerLonF = opts@mpRightCornerLonF + 360.0 + end if + +; Set some other resources for line colors and grid spacing. + + opts@mpGeophysicalLineColor = get_res_value_keep(opts, "mpGeophysicalLineColor","Gray") + opts@mpGeophysicalLineThicknessF = get_res_value_keep(opts, "mpGeophysicalLineThicknessF",0.5) + opts@mpGridLineColor = get_res_value_keep(opts, "mpGridLineColor","Gray") + opts@mpGridLineThicknessF = get_res_value_keep(opts, "mpGridLineThicknessF",0.5) + ;opts@mpGridMaskMode = get_res_value_keep(opts, "mpGridMaskMode",3) + opts@mpGridSpacingF = get_res_value_keep(opts, "mpGridSpacingF",5) + opts@mpLimbLineColor = get_res_value_keep(opts, "mpLimbLineColor","Gray") + opts@mpLimbLineThicknessF = get_res_value_keep(opts, "mpLimbLineThicknessF",0.5) + opts@mpNationalLineColor = get_res_value_keep(opts, "mpNationalLineColor","Gray") + opts@mpNationalLineThicknessF = get_res_value_keep(opts, "mpNationalLineThicknessF",0.5) + opts@mpPerimLineColor = get_res_value_keep(opts, "mpPerimLineColor","Gray") + opts@mpPerimOn = get_res_value_keep(opts, "mpPerimOn",True) + opts@mpUSStateLineColor = get_res_value_keep(opts, "mpUSStateLineColor","Gray") + opts@mpUSStateLineThicknessF = get_res_value_keep(opts, "mpUSStateLineThicknessF",0.5) + opts@pmTickMarkDisplayMode = get_res_value_keep(opts, "pmTickMarkDisplayMode","Always") + +; Tick mark resources + + ;opts@tmXBMajorLengthF = get_res_value(opts, "tmXBMajorLengthF",-0.03) + ;opts@tmYLMajorLengthF = get_res_value(opts, "tmYLMajorLengthF",-0.03) + opts@tmXTOn = get_res_value(opts,"tmXTOn",False) + opts@tmYROn = get_res_value(opts,"tmYROn",False) + opts@tmYRLabelsOn = get_res_value(opts,"tmYRLabelsOn",True) + opts@tmXBBorderOn = get_res_value(opts,"tmXBBorderOn",True) + opts@tmXTBorderOn = get_res_value(opts,"tmXTBorderOn",True) + opts@tmYLBorderOn = get_res_value(opts,"tmYLBorderOn",True) + opts@tmYRBorderOn = get_res_value(opts,"tmYRBorderOn",True) + + return(opts) +end +;-------------------------------------------------------------------------------- +;-------------------------------------------------------------------------------- + +undef("_SetMainTitle") +procedure _SetMainTitle(nc_file:file,wks[1]:graphic,cn[1]:graphic,opts) + +; This procedure checks the input data for certain attributes, and +; based on those, sets MainTitle, InitTime and ValidTime +; +; Attributes recognized by this procedure: +; MainTitle (main title - top left) +; (with Init time top right) +; TimeLabel (valid time - right under init time) +; NoHeaderFooter (switch all headers and footers off - mainly for panels) +; +; If the "NoHeaderFooter" attribute exists and is set True, then +; don't create any titles. + +begin +; + if(opts.and.isatt(opts,"NoHeaderFooter").and.opts@NoHeaderFooter) then + return + end if + +; +; Set basic plot font +; + font_height = get_res_value_keep(opts,"FontHeightF",0.01) +; +; +; If a MainTitle attribute hasn't been set, then set to "WRF" +; Also set an Initial time +; +; MAIN Header of plot + opts@MainTitle = get_res_value_keep(opts,"MainTitle", " ") + opts@MainTitlePos = get_res_value_keep(opts,"MainTitlePos", "Left") + opts@InitTime = get_res_value_keep(opts,"InitTime", True) + opts@ValidTime = get_res_value_keep(opts,"ValidTime", True) + opts@TimePos = get_res_value_keep(opts,"TimePos", "Right") + opts@Footer = get_res_value_keep(opts,"Footer", True) + + + if (opts@MainTitlePos .eq. "Left") + opts@MainTitlePos = "CenterLeft" + opts@MainTitlePosF = 0.0 + end if + if (opts@MainTitlePos .eq. "Center") + opts@MainTitlePos = "CenterCenter" + opts@MainTitlePosF = 0.5 + end if + if (opts@MainTitlePos .eq. "Right") + opts@MainTitlePos = "CenterRight" + opts@MainTitlePosF = 1.0 + end if + + if (opts@TimePos .eq. "Left") + MTOPosF = 0.30 + else + MTOPosF = 0.20 + end if + + txt0 = create "MainPlotTitle" textItemClass wks + "txString" : opts@MainTitle + "txFontHeightF" : font_height*1.5 + end create + anno = NhlAddAnnotation(cn,txt0) + setvalues anno + "amZone" : 3 + "amSide" : "Top" + "amJust" : opts@MainTitlePos + "amParallelPosF" : opts@MainTitlePosF + "amOrthogonalPosF" : MTOPosF + "amResizeNotify" : False + end setvalues + +; Time information on plot + if (opts@TimePos .eq. "Left") + opts@TimePos = "CenterLeft" + opts@TimePosF = 0.0 + if (opts@MainTitlePos .eq. "CenterLeft") + MTOPosF = MTOPosF - 0.05 + end if + end if + if (opts@TimePos .eq. "Right") + opts@TimePos = "CenterRight" + opts@TimePosF = 1.0 + if (opts@MainTitlePos .eq. "CenterRight") + MTOPosF = MTOPosF - 0.05 + end if + end if + + if( isatt(nc_file,"START_DATE") ) then + model_start_time = nc_file@START_DATE + else + if( isatt(nc_file,"SIMULATION_START_DATE") ) then + model_start_time = nc_file@SIMULATION_START_DATE + else + opts@InitTime = False + end if + end if + if( opts@InitTime ) then + InitTime = "Init: " + model_start_time + txt1 = create "InitTime" textItemClass wks + "txString" : InitTime + "txFontHeightF" : font_height + end create + anno = NhlAddAnnotation(cn,txt1) + setvalues anno + "amZone" : 3 + "amSide" : "Top" + "amJust" : opts@TimePos + "amParallelPosF" : opts@TimePosF + "amOrthogonalPosF" : MTOPosF + "amResizeNotify" : False + end setvalues + end if + + plot_narrow = False + if((opts).and.(isatt(opts,"vpWidthF")).and.(isatt(opts,"vpHeightF"))) then + ph = opts@vpHeightF + pw = opts@vpWidthF + phw = ph/pw + if ( phw .gt. 1.8 ) then + plot_narrow = True + end if + end if + + if( opts@ValidTime .and. isatt(opts,"TimeLabel") ) then + + ValidTime = "Valid: " + opts@TimeLabel + + MTOPosF = MTOPosF - 0.03 + txt2 = create "ValidTime" textItemClass wks + "txString" : ValidTime + "txFontHeightF" : font_height + end create + anno = NhlAddAnnotation(cn,txt2) + setvalues anno + "amZone" : 3 + "amSide" : "Top" + "amJust" : opts@TimePos + "amParallelPosF" : opts@TimePosF + "amOrthogonalPosF" : MTOPosF + "amResizeNotify" : False + end setvalues + end if + + +; Add Footer if called for + if( opts@Footer ) then + footer1 = nc_file@TITLE + dis = nc_file@DX / 1000.0 + WE = "WEST-EAST_GRID_DIMENSION" + SN = "SOUTH-NORTH_GRID_DIMENSION" + BT = "BOTTOM-TOP_GRID_DIMENSION" + footer2 = " WE = " + nc_file@$WE$ + \ + " ; SN = " + nc_file@$SN$ + \ + " ; Levels = " + nc_file@$BT$ + \ + " ; Dis = " + dis + "km" + if ( isatt(nc_file,"MP_PHYSICS")) then + footer2 = footer2 + " ; Phys Opt = " + nc_file@MP_PHYSICS + end if + if ( isatt(nc_file,"BL_PBL_PHYSICS")) then + footer2 = footer2 + " ; PBL Opt = " + nc_file@BL_PBL_PHYSICS + end if + if ( isatt(nc_file,"CU_PHYSICS")) then + footer2 = footer2 + " ; Cu Opt = " + nc_file@CU_PHYSICS + end if + Footer = footer1 + "~C~" + footer2 + else + Footer = " " + end if + txt3 = create "Footer" textItemClass wks + "txString" : Footer + "txFontHeightF" : font_height*.9 + end create + anno = NhlAddAnnotation(cn,txt3) + setvalues anno + "amZone" : 1 +; "amZone" : 7 + "amJust" : "TopLeft" + "amSide" : "Bottom" + "amParallelPosF" : 0.0 + "amOrthogonalPosF" : -0.55 + "amResizeNotify" : False + end setvalues + + +; Add X-setion information if needed + if(opts.and.isatt(opts,"PlotOrientation")) then + ;Xsection = "Cross-Section Orientation : " + opts@PlotOrientation + Xsection = opts@PlotOrientation + txt4 = create "Xsection" textItemClass wks + "txString" : Xsection + "txFontHeightF" : font_height*.9 + end create + anno = NhlAddAnnotation(cn,txt4) + setvalues anno + "amZone" : 3 + "amSide" : "Top" + "amJust" : "CenterRight" + "amParallelPosF" : 1.0 + "amOrthogonalPosF" : 0.005 + "amResizeNotify" : False + end setvalues + end if + +end + +;-------------------------------------------------------------------------------- +;-------------------------------------------------------------------------------- +;-------------------------------------------------------------------------------- +undef("set_mp_wrf_map_resources") +function set_mp_wrf_map_resources(in_file[1]:file,opt_args[1]:logical) + +begin +; + opts = opt_args ; Make a copy of the resource list + +; Set some resources depending on what kind of map projection is +; chosen. +; +; MAP_PROJ = 0 : "CylindricalEquidistant" +; MAP_PROJ = 1 : "LambertConformal" +; MAP_PROJ = 2 : "Stereographic" +; MAP_PROJ = 3 : "Mercator" +; MAP_PROJ = 6 : "Lat/Lon" + + if(isatt(in_file,"MAP_PROJ")) + +; CylindricalEquidistant + if(in_file@MAP_PROJ .eq. 0) + projection = "CylindricalEquidistant" + opts@mpProjection = projection + opts@mpGridSpacingF = 45 + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF", 0.0) + if(isatt(in_file,"STAND_LON")) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; LambertConformal projection + if(in_file@MAP_PROJ .eq. 1) + projection = "LambertConformal" + opts@mpProjection = projection + opts@mpLambertParallel1F = get_res_value_keep(opts, "mpLambertParallel1F",in_file@TRUELAT1) + opts@mpLambertParallel2F = get_res_value_keep(opts, "mpLambertParallel2F",in_file@TRUELAT2) + if(isatt(in_file,"STAND_LON")) + opts@mpLambertMeridianF = get_res_value_keep(opts, "mpLambertMeridianF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + opts@mpLambertMeridianF = get_res_value_keep(opts, "mpLambertMeridianF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; Stereographic projection + if(in_file@MAP_PROJ .eq. 2) + projection = "Stereographic" + opts@mpProjection = projection + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF", in_file@CEN_LAT) + if(isatt(in_file,"STAND_LON")) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; Mercator projection + if(in_file@MAP_PROJ .eq. 3) + projection = "Mercator" + opts@mpProjection = projection + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF", 0.0) + if(isatt(in_file,"STAND_LON")) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; global WRF CylindricalEquidistant + if(in_file@MAP_PROJ .eq. 6) + projection = "CylindricalEquidistant" + opts@mpProjection = projection + opts@mpGridSpacingF = 45 + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",in_file@CEN_LON) + if( isatt(in_file,"POLE_LAT") ) then + opts@mpCenterRotF = get_res_value_keep(opts, "mpCenterRotF", 90.0 - in_file@POLE_LAT) + delete(opts@mpCenterLonF) + calcen = -190. + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF", calcen ) + end if + end if + + end if + + return(opts) ; Return. + +end +;-------------------------------------------------------------------------------- + +undef("wrf_contour_ps") +function wrf_contour_ps(nc_file:file,wks[1]: graphic, data[*][*]:numeric, \ + opt_args[1]:logical) + +begin + + callFrame = True + if ( isatt(opt_args,"FrameIT") ) then + if ( .not.opt_args@FrameIT ) then + callFrame = False + end if + delete (opt_args@FrameIT) + end if + + lat2U = nc_file->XLAT_U(0,:,:) + lon2U = nc_file->XLONG_U(0,:,:) + + opts = opt_args + opts@sfXArray = lon2U + opts@sfYArray = lat2U + opts@sfDataArray = data + opts@mpProjection = "Stereographic" + opts@mpEllipticalBoundary = True + opts@mpFillOn = False + + opts@mpGeophysicalLineColor = get_res_value_keep(opts, "mpGeophysicalLineColor","Gray") + opts@mpGeophysicalLineThicknessF = get_res_value_keep(opts, "mpGeophysicalLineThicknessF",2.0) + + + ; Set the contour resources + opts = set_cn_resources(data,opts) + opts@cnInfoLabelFontHeightF = 0.012 + opts@cnLineLabelPerimOn = False + opts@cnInfoLabelPerimOn = True + + + ; Find out if we are working with a contour or a shaded plot + ; fill_on = False : line contour plot + ; fill_on = True : filled contour plot + fill_on = get_res_value_keep(opts,"cnFillOn",False) + if(fill_on) then ; set lb resources if needed + opts@pmLabelBarDisplayMode = get_res_value_keep(opts,"pmLabelBarDisplayMode", "Never") + opts = set_lb_resources(data,opts) + opts@pmLabelBarOrthogonalPosF = 0.0 + opts@lbTitleJust = "BottomLeft" + end if + + + + opts@gsnDraw = False + opts@gsnFrame = False + opts@gsnMaximize = False + delete_attrs(opts) + cn = gsn_csm_contour_map_polar(wks,data,opts) ; Create the plot. + + draw(cn) + + + if ( callFrame ) then + frame(wks) + end if + +return (cn) +end +;-------------------------------------------------------------------------------- +undef("wrf_vector_ps") +function wrf_vector_ps(nc_file:file,wks[1]: graphic, \ + data_u[*][*]:numeric, data_v[*][*]:numeric, \ + opt_args[1]:logical) + +begin + + callFrame = True + if ( isatt(opt_args,"FrameIT") ) then + if ( .not.opt_args@FrameIT ) then + callFrame = False + end if + delete (opt_args@FrameIT) + end if + + if(isfilevar(nc_file,"XLAT")) + lat2T = nc_file->XLAT(0,:,:) + lon2T = nc_file->XLONG(0,:,:) + else + lat2T = nc_file->XLAT_M(0,:,:) + lon2T = nc_file->XLONG_M(0,:,:) + end if + + opts = opt_args + opts@vfXArray = lon2T + opts@vfYArray = lat2T + opts@vfUDataArray = data_u + opts@vfVDataArray = data_v + opts@mpProjection = "Stereographic" + opts@mpEllipticalBoundary = True + opts@mpFillOn = False + + opts@mpGeophysicalLineColor = get_res_value_keep(opts, "mpGeophysicalLineColor","Gray") + opts@mpGeophysicalLineThicknessF = get_res_value_keep(opts, "mpGeophysicalLineThicknessF",2.0) + + +; Set vector resources + opts = set_vc_resources(opts) + + + opts@gsnDraw = False + opts@gsnFrame = False + opts@gsnMaximize = False + delete_attrs(opts) + cn = gsn_csm_vector_map_polar(wks,data_u,data_v,opts) ; Create the plot. + + draw(cn) + + + if ( callFrame ) then + frame(wks) + end if + +return (cn) +end +;-------------------------------------------------------------------------------- + +undef("wrf_contour") +function wrf_contour(nc_file:file,wks[1]: graphic, data[*][*]:numeric, \ + opt_args[1]:logical) + +; This function creates a contour plot and adds some titles to it. +; +; 1. Determine width to height ratio of plot. +; +; 2. First determine if this is to be a filled or line +; contour plot (fill_on) +; +; 3. If the ContourParameters attribute is set, then calculate +; the contour levels. +; +; 4. Set two resources for setting the zero contour line to +; a larger thickness, and for changing the negative contour +; lines to a dashed pattern. +; +; 5. If doing a filled contour plot, set a title for the labelbar +; based on whether a units attribute is set. +; +; 6. Make a copy of the resource list, and set some additional +; resources for filled contour plots. +; +; 7. Create the contour plot, attach the titles, and draw +; and advance the frame (if requested). + +local dims +begin + opts = opt_args ; Make a copy of the resource list. + + if(opts.and.isatt(opts,"gsnDebugWriteFileName")) then + wrf_debug_file = get_res_value(opts,"gsnDebugWriteFileName", "") + end if + + if(opts.and.isatt(opts,"mpOutlineBoundarySets")) then + delete(opts@mpOutlineBoundarySets) + end if + + +; Calculate ratio of plot width and height. Note that this doesn't +; affect the setting of gsnMaximize to True, because gsnMaximize will +; retain the aspect ratio of the plot. + + if(opts.and.isatt(opts,"AspectRatio")) then + ratio = opts@AspectRatio + else + dims = dimsizes(data) + ratio = 1.*dims(0)/dims(1) + if(ratio .gt. 1.2) then + ratio = 1.2 + end if + if(ratio .lt. 0.6667) then + ratio = 0.6667 + end if + end if + + if(ratio .gt. 1) + width = 0.65 * 1.0/ratio + height = 0.65 + else + width = 0.85 + height = 0.85 * ratio + end if + + opts@vpWidthF = get_res_value_keep(opts,"vpWidthF", width) + opts@vpHeightF = get_res_value_keep(opts,"vpHeightF", height) + + +; Set some basic contour resources + opts = set_cn_resources(data,opts) + + +; Find out if we are working with a contour or a shaded plot +; fill_on = False : line contour plot +; fill_on = True : filled contour plot + fill_on = get_res_value_keep(opts,"cnFillOn",False) + if(fill_on) then ; set lb resources if needed + opts = set_lb_resources(data,opts) + atmp = get_res_value(opts,"lbLabelBarOn",True) ; Remove this resource + delete(atmp) ; just in case. + end if + + +; Set Title resources + opts = set_title_resources(data,opts) + + +; Setting gsnScale to True ensures that the tickmark lengths and labels +; will be the same size on both axes. + opts@gsnScale = get_res_value_keep(opts,"gsnScale", True) + + +; The default is not to draw the plot or advance the frame, and +; to maximize the plot in the frame. + opts@gsnDraw = False ; Make sure don't draw or frame or, + opts@gsnFrame = False ; maximize, b/c we'll do this later. + opts@gsnMaximize = False + + + opts2 = opts + delete_attrs(opts2) ; Clean up. + cn = gsn_contour(wks,data,opts2) ; Create the plot. + _SetMainTitle(nc_file,wks,cn,opts) ; Set some titles + + if(isvar("wrf_debug_file")) then + write_wrf_debug_info(wks,data,False,wrf_debug_file,opts2,"wrf_contour") + end if + + opts2@gsnDraw = get_res_value_keep(opts2,"gsnDraw", False) + opts2@gsnFrame = get_res_value_keep(opts2,"gsnFrame", False) + opts2@gsnMaximize = get_res_value_keep(opts2,"gsnMaximize", True) + draw_and_frame(wks,cn,opts2@gsnDraw,opts2@gsnFrame,False,opts2@gsnMaximize) + + return(cn) ; Return + +end + +;-------------------------------------------------------------------------------- + +undef("wrf_vector") +function wrf_vector(nc_file:file,wks[1]: graphic, data_u[*][*]:numeric, \ + data_v[*][*]:numeric, opt_args[1]:logical) +; +; This function creates a vector plot and adds some titles to it. +; +; 1. Determine width to height ratio of plot. Will also be use +; to calculate values for vector resources later. +; +; 2. Make a copy of the resource list, and set some additional +; resources. +; +; 3. Create the vector plot, attach the titles, and draw +; and advance the frame (if requested). + +local dims +begin + opts = opt_args ; Make a copy of the resource list. + + if(opts.and.isatt(opts,"gsnDebugWriteFileName")) then + wrf_debug_file = get_res_value(opts,"gsnDebugWriteFileName", "") + end if + + if(opts.and.isatt(opts,"mpOutlineBoundarySets")) then + delete(opts@mpOutlineBoundarySets) + end if +; +; The ratio is used to determine the width and height of the +; plot, and also to determine the value for the vcMinDistanceF +; resource. +; + if(opts.and.isatt(opts,"AspectRatio")) then + ratio = get_res_value(opts,"AspectRatio",0.) + else + dims = dimsizes(data_u) + ratio = 1.*dims(0)/dims(1) + if(ratio .gt. 1.2) then + ratio = 1.2 + end if + if(ratio .lt. 0.6667) then + ratio = 0.6667 + end if + end if + + if(ratio .gt. 1) + width = 0.65/ratio + height = 0.65 + else + width = 0.95 + height = 0.95 * ratio + end if + + opts@vpWidthF = get_res_value_keep(opts,"vpWidthF", width) + opts@vpHeightF = get_res_value_keep(opts,"vpHeightF", height) + + +; Set Title resources + opts = set_title_resources(data_u,opts) + + +; Set vector resources + opts = set_vc_resources(opts) + + +; Setting gsnScale to True ensures that the tickmark lengths and labels +; will be the same size on both axes. + opts@gsnScale = get_res_value_keep(opts,"gsnScale", True) + + +; The default is not to draw the plot or advance the frame, and +; to maximize the plot in the frame. + opts@gsnDraw = False ; Make sure don't draw or frame or, + opts@gsnFrame = False ; maximize, b/c we'll do this later. + opts@gsnMaximize = False + + opts2 = opts + delete_attrs(opts2) ; Clean up. + vct = gsn_vector(wks,data_u,data_v,opts2) ; Create vector plot. + _SetMainTitle(nc_file,wks,vct,opts) + + if(isvar("wrf_debug_file")) then + write_wrf_debug_info(wks,data_u,data_v,wrf_debug_file,opts2,"wrf_vector") + end if + + opts2@gsnDraw = get_res_value_keep(opts2,"gsnDraw", False) + opts2@gsnFrame = get_res_value_keep(opts2,"gsnFrame", False) + opts2@gsnMaximize = get_res_value_keep(opts2,"gsnMaximize", True) + draw_and_frame(wks,vct,opts2@gsnDraw,opts2@gsnFrame,False, \ + opts2@gsnMaximize) + + return(vct) ; Return. +end + +;-------------------------------------------------------------------------------- +undef("wrf_wps_map") +function wrf_wps_map(wks[1]:graphic,opt_args[1]:logical) + +begin +; +; 1. Make a copy of the resource list, and set some resources +; common to all map projections. +; +; 2. Determine the projection being used, and set resources based +; on that projection. +; +; 3. Create the map plot, and draw and advance the frame +; (if requested). + + opts = opt_args ; Make a copy of the resource list + opts = True + +; Set some resources depending on what kind of map projection is +; chosen. +; +; MAP_PROJ = 0 : "CylindricalEquidistant" +; MAP_PROJ = 1 : "LambertConformal" +; MAP_PROJ = 2 : "Stereographic" +; MAP_PROJ = 3 : "Mercator" +; MAP_PROJ = 6 : "Lat/Lon" + +; CylindricalEquidistant + if(opts@map_proj .eq. 0) + projection = "CylindricalEquidistant" + opts@mpGridSpacingF = 45 + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF", 0.0) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",opts@stand_lon) + end if + +; LambertConformal projection + if(opts@map_proj .eq. 1) + projection = "LambertConformal" + opts@mpLambertParallel1F = get_res_value_keep(opts, "mpLambertParallel1F",opts@truelat1) + opts@mpLambertParallel2F = get_res_value_keep(opts, "mpLambertParallel2F",opts@truelat2) + opts@mpLambertMeridianF = get_res_value_keep(opts, "mpLambertMeridianF",opts@stand_lon) + end if + +; Stereographic projection + if(opts@map_proj .eq. 2) + projection = "Stereographic" + if( isatt(opts,"cenlat") ) then + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF",opts@cenlat) + else + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF",opts@ref_lat) + end if + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",opts@stand_lon) + end if + +; Mercator projection + if(opts@map_proj .eq. 3) + projection = "Mercator" + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF", 0.0) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",opts@stand_lon) + end if + +; global WRF CylindricalEquidistant + if(opts@map_proj .eq. 6) + projection = "CylindricalEquidistant" + opts@mpGridSpacingF = 45 + if( isatt(opts,"cenlon") ) then + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",opts@cenlon) + else + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",opts@ref_lon) + end if + if( isatt(opts,"pole_lat") ) then + delete(opts@mpCenterLonF) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF", - 190. ) + opts@mpCenterRotF = get_res_value_keep(opts, "mpCenterRotF", 90.0 - opts@pole_lat) + else + opts@mpCenterRotF = get_res_value_keep(opts, "mpCenterRotF", 0.0) + end if + end if + +; Set some resources common to all map projections. + opts = set_mp_resources(opts) + +; The default is not to draw the plot or advance the frame, and +; to maximize the plot in the frame. + + opts@gsnDraw = get_res_value_keep(opts,"gsnDraw", False) + opts@gsnFrame = get_res_value_keep(opts,"gsnFrame", False) + opts@gsnMaximize = get_res_value_keep(opts,"gsnMaximize", True) + + delete_attrs(opts) ; Clean up. + mp = gsn_map(wks,projection,opts) ; Create map plot. + return(mp) ; Return. + +end + +;-------------------------------------------------------------------------------- +undef("wrf_wps_dom") +function wrf_wps_dom(wks[1]:graphic,opt_args[1]:logical,lnres[1]:logical,txres[1]:logical) + +begin + + mpres = opt_args + ;BPR BEGIN + ;grid_to_plot = 0 => plot using the corner mass grid points + ;grid_to_plot = 1 => plot using the edges of the corner grid cells + ; This uses the locations of the corner mass grid points +/- 0.5 grid cells + ; to get from the mass grid point to the edge of the grid cell + grid_to_plot = 1 + ;grid_to_plot = mpres@grid_to_plot + if(grid_to_plot.eq.0) then + ; print("Plotting using corner mass grid points") + else if(grid_to_plot.eq.1) then + ; print("Plotting using edges of the corner grid cells") + else + print("ERROR: Invalid value for grid_to_plot = "+grid_to_plot) + end if + end if + ;BPR END + + res = True + res@DX = mpres@dx + res@DY = mpres@dy + res@LATINC = 0.0 + res@LONINC = 0.0 + if ( mpres@map_proj .eq. "lambert") then + mpres@map_proj = 1 + res@MAP_PROJ = 1 + end if + if ( mpres@map_proj .eq. "polar") then + mpres@map_proj = 2 + res@MAP_PROJ = 2 + end if + if ( mpres@map_proj .eq. "mercator") then + mpres@map_proj = 3 + res@MAP_PROJ = 3 + end if + if ( mpres@map_proj .eq. "lat-lon") then + mpres@map_proj = 6 + res@MAP_PROJ = 6 + res@LATINC = mpres@dy + res@LONINC = mpres@dx + end if + res@TRUELAT1 = mpres@truelat1 + res@TRUELAT2 = mpres@truelat2 + res@STAND_LON = mpres@stand_lon + + res@REF_LAT = mpres@ref_lat + res@REF_LON = mpres@ref_lon + if ( isatt(mpres,"ref_x") ) then + res@KNOWNI = mpres@ref_x + else + res@KNOWNI = int2flt(mpres@e_we(0))/2. + end if + if ( isatt(mpres,"ref_y") ) then + res@KNOWNJ = mpres@ref_y + else + res@KNOWNJ = int2flt(mpres@e_sn(0))/2. + end if + + if ( isatt(mpres,"pole_lat") ) then + res@POLE_LAT = mpres@pole_lat + else + res@POLE_LAT = 90.0 + end if + if ( isatt(mpres,"pole_lon") ) then + res@POLE_LON = mpres@pole_lon + else + res@POLE_LON = 0.0 + end if + + ;BPR BEGIN + ;Determine adjustment needed to convert from mass grid to chosen grid + if(grid_to_plot.eq.0) then + adjust_grid = 0.0 + else if(grid_to_plot.eq.1) then + adjust_grid = 0.5 + else + print("ERROR: Invalid value for grid_to_plot = "+grid_to_plot) + adjust_grid = 0.0 + end if + end if + + xx = 1.0 - adjust_grid + yy = 1.0 - adjust_grid + ;xx = 1.0 + ;yy = 1.0 + ;BPR END + loc = wrf_ij_to_ll (xx,yy,res) + start_lon = loc(0) + start_lat = loc(1) + ;BPR BEGIN + ;e_we is the largest U grid point and e_sn the largest V gridpoint + ;xx = int2flt(mpres@e_we(0)) + ;yy = int2flt(mpres@e_sn(0)) + ;Change it so it is in terms of mass grid points since wrf_ij_to_ll is + ;in terms of mass grid points + xx = int2flt(mpres@e_we(0)-1) + adjust_grid + yy = int2flt(mpres@e_sn(0)-1) + adjust_grid + ;BPR END + loc = wrf_ij_to_ll (xx,yy,res) + end_lon = loc(0) + end_lat = loc(1) + + mpres@start_lat = start_lat + mpres@start_lon = start_lon + mpres@end_lat = end_lat + mpres@end_lon = end_lon + + + mp = wrf_wps_map(wks,mpres) + draw(mp) + + + if ( mpres@max_dom .gt. 1 ) then + + numLineColors = 0 + if ( isatt(lnres,"domLineColors") ) then + numLineColors = dimsizes(lnres@domLineColors) + end if + + do idom = 1,mpres@max_dom-1 + + if ( numLineColors .gt. 0 ) then + if ( numLineColors .ge. idom ) then + lnres@gsLineColor = lnres@domLineColors(idom-1) + txres@txFontColor = lnres@domLineColors(idom-1) + else + lnres@gsLineColor = lnres@domLineColors(numLineColors-1) + txres@txFontColor = lnres@domLineColors(numLineColors-1) + end if + end if + + + ; nest start and end points in large domain space + if ( mpres@parent_id(idom) .eq. 1) then + ; corner value + ;BPR BEGIN + ;Due to the alignment of nests we need goffset in order to + ;find the location of (1,1) in the fine domain in coarse domain + ;coordinates + ;i_start = mpres@i_parent_start(idom) + ;j_start = mpres@j_parent_start(idom) + goffset = 0.5*(1-(1.0/mpres@parent_grid_ratio(idom))) + i_start = mpres@i_parent_start(idom)-goffset + j_start = mpres@j_parent_start(idom)-goffset + ; end point + ;Change to mass point + ;i_end = (mpres@e_we(idom)-1)/mpres@parent_grid_ratio(idom) + i_start + ;j_end = (mpres@e_sn(idom)-1)/mpres@parent_grid_ratio(idom) + j_start + i_end = (mpres@e_we(idom)-2)/(1.0*mpres@parent_grid_ratio(idom)) + i_start + j_end = (mpres@e_sn(idom)-2)/(1.0*mpres@parent_grid_ratio(idom)) + j_start + + if(grid_to_plot.eq.0) then + adjust_grid = 0.0 + else if(grid_to_plot.eq.1) then + adjust_grid = 0.5/(1.0*mpres@parent_grid_ratio(idom)) + else + print("ERROR: Invalid value for grid_to_plot = "+grid_to_plot) + adjust_grid = 0.0 + end if + end if + + ;BPR END + end if + if ( mpres@parent_id(idom) .ge. 2) then + ; corner value + nd = mpres@parent_id(idom) + ;BPR BEGIN + ;i_points = ((mpres@e_we(idom)-1)/mpres@parent_grid_ratio(idom)) + ;j_points = ((mpres@e_sn(idom)-1)/mpres@parent_grid_ratio(idom)) + i_points = ((mpres@e_we(idom)-2)/(1.0*mpres@parent_grid_ratio(idom))) + j_points = ((mpres@e_sn(idom)-2)/(1.0*mpres@parent_grid_ratio(idom))) + goffset = 0.5*(1-(1.0/(1.0*mpres@parent_grid_ratio(idom)))) + ai_start = mpres@i_parent_start(idom)*1.0-goffset + aj_start = mpres@j_parent_start(idom)*1.0-goffset + ;ai_start = mpres@i_parent_start(idom)*1.0 + ;aj_start = mpres@j_parent_start(idom)*1.0 + + if(grid_to_plot.eq.0) then + adjust_grid = 0.0 + else if(grid_to_plot.eq.1) then + adjust_grid = 0.5/(1.0*mpres@parent_grid_ratio(idom)) + else + print("ERROR: Invalid value for grid_to_plot = "+grid_to_plot) + adjust_grid = 0.0 + end if + end if + + do while ( nd .gt. 1) + ;Note that nd-1 is used in the following because the WPS namelist is + ;one-based but arrays in NCL are zero-based + goffset = 0.5*(1-(1.0/(1.0*mpres@parent_grid_ratio(nd-1)))) + ;ai_start = ai_start/mpres@parent_grid_ratio(nd-1) + mpres@i_parent_start(nd-1) + ;aj_start = aj_start/mpres@parent_grid_ratio(nd-1) + mpres@j_parent_start(nd-1) + ai_start = (ai_start-1)/(1.0*mpres@parent_grid_ratio(nd-1)) + mpres@i_parent_start(nd-1)-goffset + aj_start = (aj_start-1)/(1.0*mpres@parent_grid_ratio(nd-1)) + mpres@j_parent_start(nd-1)-goffset + ;i_points = (i_points/mpres@parent_grid_ratio(nd-1)) + ;j_points = (j_points/mpres@parent_grid_ratio(nd-1)) + i_points = (i_points/(1.0*mpres@parent_grid_ratio(nd-1))) + j_points = (j_points/(1.0*mpres@parent_grid_ratio(nd-1))) + if(grid_to_plot.eq.0) then + adjust_grid = 0.0 + else if(grid_to_plot.eq.1) then + adjust_grid = adjust_grid/(1.0*mpres@parent_grid_ratio(nd-1)) + else + print("ERROR: Invalid value for grid_to_plot = "+grid_to_plot) + adjust_grid = 0.0 + end if + end if + + ;nd = nd - 1 + nd = mpres@parent_id(nd-1) + end do + ;i_start = tointeger(ai_start + .5 ) + ;j_start = tointeger(aj_start + .5 ) + i_start = ai_start + j_start = aj_start + ; end point + ;i_end = i_points + i_start + 1 + ;j_end = j_points + j_start + 1 + i_end = i_points + i_start + j_end = j_points + j_start + ;BPR END + end if + + ; get the four corners + + xx = i_start - adjust_grid + yy = j_start - adjust_grid + ;xx = int2flt(i_start) + ;yy = int2flt(j_start) + loc = wrf_ij_to_ll (xx,yy,res) + lon_SW = loc(0) + lat_SW = loc(1) + + xx = i_end + adjust_grid + yy = j_start - adjust_grid + ;xx = int2flt(i_end) + ;yy = int2flt(j_start) + loc = wrf_ij_to_ll (xx,yy,res) + lon_SE = loc(0) + lat_SE = loc(1) + + xx = i_start - adjust_grid + yy = j_end + adjust_grid + ;xx = int2flt(i_start) + ;yy = int2flt(j_end) + loc = wrf_ij_to_ll (xx,yy,res) + lon_NW = loc(0) + lat_NW = loc(1) + + ;xx = int2flt(i_end) + ;yy = int2flt(j_end) + xx = i_end + adjust_grid + yy = j_end + adjust_grid + ;BPR END + loc = wrf_ij_to_ll (xx,yy,res) + lon_NE = loc(0) + lat_NE = loc(1) + + xbox = (/lon_SW, lon_SE, lon_NE, lon_NW, lon_SW /) + ybox = (/lat_SW, lat_SE, lat_NE, lat_NW, lat_SW /) + x_out = new(dimsizes(xbox),typeof(xbox)) + y_out = new(dimsizes(ybox),typeof(ybox)) + datatondc(mp, xbox, ybox, x_out, y_out) + gsn_polyline_ndc(wks, x_out, y_out, lnres) + + idd = idom + 1 + dom_text = "d0"+idd + if ( txres@txJust .eq. "BottomLeft" ) then + gsn_text(wks,mp,dom_text,lon_NW,lat_NW,txres) + else + gsn_text_ndc(wks,dom_text,x_out(3)+0.01,y_out(3)-0.01,txres) + end if + + end do + + end if + + return(mp) + +end + +;-------------------------------------------------------------------------------- +undef("wrf_map_resources") +function wrf_map_resources(in_file[1]:file,map_args[1]:logical) +local lat, lon, x1, x2, y1, y2, dims, ii, jj +begin +; +; This function sets resources for a WRF map plot, basing the projection on +; the MAP_PROJ attribute in the given file. It's intended to be callable +; by users who need to set mpXXXX resources for other plotting scripts. +; + +; Set some resources depending on what kind of map projection is +; chosen. +; +; MAP_PROJ = 0 : "CylindricalEquidistant" +; MAP_PROJ = 1 : "LambertConformal" +; MAP_PROJ = 2 : "Stereographic" +; MAP_PROJ = 3 : "Mercator" +; MAP_PROJ = 6 : "Lat/Lon" + + if(isatt(in_file,"MAP_PROJ")) + +; CylindricalEquidistant + if(in_file@MAP_PROJ .eq. 0) + map_args@mpProjection = "CylindricalEquidistant" + map_args@mpGridSpacingF = 45 + map_args@mpCenterLatF = get_res_value_keep(map_args, "mpCenterLatF", 0.0) + if(isatt(in_file,"STAND_LON")) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; LambertConformal projection + if(in_file@MAP_PROJ .eq. 1) + map_args@mpProjection = "LambertConformal" + map_args@mpLambertParallel1F = get_res_value_keep(map_args, "mpLambertParallel1F",in_file@TRUELAT1) + map_args@mpLambertParallel2F = get_res_value_keep(map_args, "mpLambertParallel2F",in_file@TRUELAT2) + if(isatt(in_file,"STAND_LON")) + map_args@mpLambertMeridianF = get_res_value_keep(map_args, "mpLambertMeridianF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + map_args@mpLambertMeridianF = get_res_value_keep(map_args, "mpLambertMeridianF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; Stereographic projection + if(in_file@MAP_PROJ .eq. 2) + map_args@mpProjection = "Stereographic" + map_args@mpCenterLatF = get_res_value_keep(map_args, "mpCenterLatF", in_file@CEN_LAT) + if(isatt(in_file,"STAND_LON")) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; Mercator projection + if(in_file@MAP_PROJ .eq. 3) + map_args@mpProjection = "Mercator" + map_args@mpCenterLatF = get_res_value_keep(map_args, "mpCenterLatF", 0.0) + if(isatt(in_file,"STAND_LON")) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; global WRF CylindricalEquidistant + if(in_file@MAP_PROJ .eq. 6) + map_args@mpProjection = "CylindricalEquidistant" + map_args@mpGridSpacingF = 45 + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",in_file@CEN_LON) + if( isatt(in_file,"POLE_LAT") ) then + map_args@mpCenterRotF = get_res_value_keep(map_args, "mpCenterRotF", 90.0 - in_file@POLE_LAT) + delete(map_args@mpCenterLonF) + calcen = -190. + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF", calcen ) + end if + end if + + else + + return(map_args) + + end if + + map_args@mpNestTime = get_res_value_keep(map_args, "mpNestTime",0) + + if(isfilevar(in_file,"XLAT")) + lat = in_file->XLAT(map_args@mpNestTime,:,:) + lon = in_file->XLONG(map_args@mpNestTime,:,:) + else + lat = in_file->XLAT_M(map_args@mpNestTime,:,:) + lon = in_file->XLONG_M(map_args@mpNestTime,:,:) + end if + dims = dimsizes(lat) + + do ii = 0, dims(0)-1 + do jj = 0, dims(1)-1 + if ( lon(ii,jj) .lt. 0.0) then + lon(ii,jj) = lon(ii,jj) + 360. + end if + end do + end do + + map_args@start_lat = lat(0,0) + map_args@start_lon = lon(0,0) + map_args@end_lat = lat(dims(0)-1,dims(1)-1) + map_args@end_lon = lon(dims(0)-1,dims(1)-1) + + +; Set some resources common to all map projections. + map_args = set_mp_resources(map_args) + + if ( isatt(map_args,"ZoomIn") .and. map_args@ZoomIn ) then + y1 = 0 + x1 = 0 + y2 = dims(0)-1 + x2 = dims(1)-1 + if ( isatt(map_args,"Ystart") ) then + y1 = map_args@Ystart + delete(map_args@Ystart) + end if + if ( isatt(map_args,"Xstart") ) then + x1 = map_args@Xstart + delete(map_args@Xstart) + end if + if ( isatt(map_args,"Yend") ) then + if ( map_args@Yend .le. y2 ) then + y2 = map_args@Yend + end if + delete(map_args@Yend) + end if + if ( isatt(map_args,"Xend") ) then + if ( map_args@Xend .le. x2 ) then + x2 = map_args@Xend + end if + delete(map_args@Xend) + end if + + map_args@mpLeftCornerLatF = lat(y1,x1) + map_args@mpLeftCornerLonF = lon(y1,x1) + map_args@mpRightCornerLatF = lat(y2,x2) + map_args@mpRightCornerLonF = lon(y2,x2) + + if ( map_args@mpRightCornerLonF .lt. 0.0 ) then + map_args@mpRightCornerLonF = map_args@mpRightCornerLonF + 360.0 + end if + + delete(map_args@ZoomIn) + end if + + return(map_args) +end + +;-------------------------------------------------------------------------------- +undef("wrf_map") +function wrf_map(wks[1]:graphic,in_file[1]:file,opt_args[1]:logical) + +begin +; +; This function creates a map plot, and bases the projection on +; the MAP_PROJ attribute in the given file. +; +; 1. Make a copy of the resource list, and call a function to set +; some resources common to all map projections. +; +; 2. Determine the projection being used, and set resources based +; on that projection. +; +; 3. Create the map plot, and draw and advance the frame +; (if requested). + + if(opt_args.and.isatt(opt_args,"gsnDebugWriteFileName")) then + wrf_debug_file = get_res_value(opt_args,"gsnDebugWriteFileName", "") + end if + + opts = opt_args ; Make a copy of the resource list + opts = True + +;---Set some map resources based on parameters and variables in input file. + opts = wrf_map_resources(in_file,opts) + + if(.not.isatt(opts,"mpProjection")) then + print("wrf_map: Error: no MAP_PROJ attribute in input file") + return(new(1,graphic)) + else + projection = opts@mpProjection + end if + +; The default is not to draw the plot or advance the frame, and +; to maximize the plot in the frame. + + opts@gsnDraw = get_res_value_keep(opts,"gsnDraw", False) + opts@gsnFrame = get_res_value_keep(opts,"gsnFrame", False) + opts@gsnMaximize = get_res_value_keep(opts,"gsnMaximize", True) + + delete_attrs(opts) ; Clean up. + mp = gsn_map(wks,projection,opts) ; Create map plot. + + if(isvar("wrf_debug_file")) then + opts@mpProjection = projection + write_wrf_debug_info(wks,False,False,wrf_debug_file,opts,"wrf_map") + end if + + return(mp) ; Return. + +end + +;-------------------------------------------------------------------------------- + +undef("wrf_map_overlays") +function wrf_map_overlays(in_file[1]:file, \ + wks:graphic, \ + plots[*]:graphic, \ + opt_arg[1]:logical, \ + opt_mp[1]:logical) + +; This procedure takes an array of plots and overlays them on a +; base plot - map background. +; +; It will advance the plot and cleanup, unless you set the +; PanelPlot resource to True. +; +; Attributes recognized by this procedure: +; FramePlot +; PanelPlot +; NoTitles (don't do any titles) +; CommonTitle & PlotTitle is used to overwrite field titles +; CommonTitle will supercede NoTitles +; LatLonOverlay +; +; If FramePlot False, then Draw the plot but do not Frame. +; In this case a user want to add to the drawing, and will +; have to advance the Frame manually in the script. +; +; If the "NoTitles" attribute exists and is set True, then +; don't create the top-left titles, and leave the main titles alone. +; This resource can be useful if you are planning to panel +; the plots. +; +; If PanelPlot is set to True, then this flags to wrf_map_overlays +; that these plots are going to be eventually paneled (likely +; by gsn_panel), and hence 1) draw and frame should not be called +; (unless gsnDraw and/or gsnFrame are explicitly set to True), +; and 2) the overlays and titles should not be removed with +; NhlRemoveOverlay and NhlRemoveAnnotation. +; +; If LatLonOverlay is set to True, then this means the user is +; using the 2D lat/lon coordinates to do the overlay, and hence +; tfDoNDCOverlay should not be set to True. (The default is False.) +; +begin + + opts = opt_arg ; Make a copy of the resource lists + opt_mp_2 = opt_mp + + if(opts.and.isatt(opts,"gsnDebugWriteFileName")) then + opt_mp_2@gsnDebugWriteFileName = get_res_value(opts, \ + "gsnDebugWriteFileName", "") + wrf_debug_file = opt_mp_2@gsnDebugWriteFileName + end if + + ; Let's make the map first + base = wrf_map(wks,in_file,opt_mp_2) + + no_titles = get_res_value(opts,"NoTitles",False) ; Do we want field titles? + com_title = get_res_value(opts,"CommonTitle",False) ; Do we have a common title? + if ( com_title ) then + plot_title = get_res_value(opts,"PlotTitle"," ") + no_titles = True + end if + + call_draw = True + call_frame = get_res_value(opts,"FramePlot",True) ; Do we want to frame the plot? + panel_plot = get_res_value(opts,"PanelPlot",False) ; Are we paneling? + latlon_overlay = get_res_value(opts,"LatLonOverlay",False) ; Lat/lon Overlay? + opts@gsnMaximize = get_res_value_keep(opts,"gsnMaximize", True) + + nplots = dimsizes(plots) +; font_color = "Black" + + do i=0,nplots-1 + if(.not.ismissing(plots(i))) then +; class_name = NhlClassName(plots(i)) +; print(class_name) +; if(class_name.eq."contourPlotClass") then +; getvalues plots(i) +; "cnFillOn" : fill_on +; "cnLineColor" : line_color +; end getvalues +; if (.not.fill_on) then +; font_color = line_color +; end if +; end if + if(.not.no_titles) then + getvalues plots(i) + "tiMainString" : SubTitle + end getvalues + if(i.eq.0) then + SubTitles = SubTitle + else + SubTitles = SubTitles + "~C~" + SubTitle + end if + end if + if(com_title .and. i .eq. nplots-1) then + getvalues plots(i) + "tiMainString" : SubTitle + end getvalues + SubTitles = plot_title + end if + if(.not.latlon_overlay) then + setvalues plots(i) + "tfDoNDCOverlay" : True + "tiMainOn" : False + end setvalues + else + setvalues plots(i) + "tiMainOn" : False + end setvalues + end if + overlay(base,plots(i)) + else + print("wrf_map_overlays: Warning: overlay plot #" + i + " is not valid.") + end if + end do + + if(.not.no_titles .or. com_title) then + font_height = get_res_value_keep(opts,"FontHeightF",0.01) + txt = create "map_titles" textItemClass wks + "txString" : SubTitles + "txFontHeightF" : font_height + ;"txFontColor" : font_color + end create + anno = NhlAddAnnotation(base,txt) + setvalues anno + "amZone" : 3 + "amJust" : "BottomLeft" + "amSide" : "Top" + "amParallelPosF" : 0.005 + "amOrthogonalPosF" : 0.03 + "amResizeNotify" : False + end setvalues + base@map_titles = anno + end if +; +; gsnDraw and gsnFrame default to False if panel plot. +; + if(panel_plot) then + call_draw = False + call_frame= False + end if + + + opts@gsnDraw = get_res_value_keep(opts,"gsnDraw", call_draw) + opts@gsnFrame = get_res_value_keep(opts,"gsnFrame", call_frame) + + draw_and_frame(wks,base,opts@gsnDraw,opts@gsnFrame,False, \ + opts@gsnMaximize) + + if(.not.panel_plot) then + do i=0,nplots-1 + if(.not.ismissing(plots(i))) then + NhlRemoveOverlay(base,plots(i),False) + else + print("wrf_remove_map_overlays: Warning: overlay plot #" + i + " is not valid.") + print(" Nothing to remove.") + end if + end do + end if + + if(isvar("wrf_debug_file")) then + write_wrf_debug_script(wks,wrf_debug_file,"wrf_map_overlays") + end if + + if(.not.no_titles.and..not.panel_plot) then + if(isatt(base,"map_titles")) then + NhlRemoveAnnotation(base,base@map_titles) + delete(base@map_titles) + end if + end if + +return(base) +end + +;-------------------------------------------------------------------------------- + +undef("wrf_overlays") +function wrf_overlays(in_file[1]:file, \ + wks:graphic, plots[*]:graphic, \ + opt_arg[1]:logical) + +; This procedure takes an array of plots and overlays them. +; +; It will advance the plot and cleanup, unless you set the +; PanelPlot resource to True. +; +; Attributes recognized by this procedure: +; FramePlot +; PanelPlot +; NoTitles (don't do any titles) +; CommonTitle & PlotTile is used to overwrite field titles +; CommonTitle will super-seed NoTitles +; +; If FramePlot False, then Draw the plot but do not Frame. +; In this case a user want to add to the drawing, and will +; have to advance the Frame manually in the script. +; +; If the "NoTitles" attribute exists and is set True, then +; don't create the top-left titles, and leave the main titles alone. +; This resource can be useful if you are planning to panel +; the plots. +; +; If PanelPlot is set to True, then this flags to wrf_overlays +; that these plots are going to be eventually paneled (likely +; by gsn_panel), and hence 1) draw and frame should not be called +; (unless gsnDraw and/or gsnFrame are explicitly set to True), +; and 2) the overlays and titles should not be removed with +; NhlRemoveOverlay and NhlRemoveAnnotation. +; +; If LatLonOverlay is set to True, then this means the user is +; using the 2D lat/lon coordinates to do the overlay, and hence +; tfDoNDCOverlay should not be set to True. (The default is False.) +; +begin + opts = opt_arg ; Make a copy of the resource list. + + no_titles = get_res_value(opts,"NoTitles",False) ; Do we want field titles? + com_title = get_res_value(opts,"CommonTitle",False) ; Do we have a common title? + latlon_overlay = get_res_value(opts,"LatLonOverlay",False) ; Lat/lon Overlay? + if ( com_title ) then + plot_title = get_res_value(opts,"PlotTitle"," ") + no_titles = True + end if + + call_draw = True + call_frame = get_res_value(opts,"FramePlot",True) ; Do we want to frame the plot? + panel_plot = get_res_value(opts,"PanelPlot",False) ; Are we paneling? + opts@gsnMaximize = get_res_value_keep(opts,"gsnMaximize", True) + + nplots = dimsizes(plots) + + base = plots(0) + if(.not.no_titles) then + getvalues plots(0) + "tiMainString" : SubTitle + end getvalues + SubTitles = SubTitle + if(.not.latlon_overlay) then + setvalues plots(0) + "tfDoNDCOverlay" : True + "tiMainOn" : False + end setvalues + else + setvalues plots(0) + "tiMainOn" : False + end setvalues + end if + else + if(.not.latlon_overlay) then + setvalues plots(0) + "tfDoNDCOverlay" : True + end setvalues + end if + end if + + if (nplots.eq.1) then + blank = create "BlankPlot" logLinPlotClass wks + ;"cnConstFLabelOn" : False + end create + overlay(base,blank) + end if + + do i=1,nplots-1 + if(.not.ismissing(plots(i))) then + if(.not.no_titles) then + getvalues plots(i) + "tiMainString" : SubTitle + end getvalues + if(i.eq.0) then + SubTitles = SubTitle + else + SubTitles = SubTitles + "~C~" + SubTitle + end if + end if + if(com_title .and. i .eq. nplots-1) then + getvalues plots(i) + "tiMainString" : SubTitle + end getvalues + SubTitles = plot_title + end if + if(.not.latlon_overlay) then + setvalues plots(i) + "tfDoNDCOverlay" : True + "tiMainOn" : False + end setvalues + else + setvalues plots(i) + "tiMainOn" : False + end setvalues + end if + overlay(base,plots(i)) + else + print("wrf_overlays: Warning: overlay plot #" + i + " is not valid.") + end if + end do + + if(.not.no_titles .or. com_title) then + font_height = get_res_value_keep(opts,"FontHeightF",0.01) + + txt = create "map_titles" textItemClass wks + "txString" : SubTitles + "txFontHeightF" : font_height + end create + anno = NhlAddAnnotation(base,txt) + setvalues anno + "amZone" : 3 + "amJust" : "BottomLeft" + "amSide" : "Top" + "amParallelPosF" : 0.005 + "amOrthogonalPosF" : 0.03 + "amResizeNotify" : False + end setvalues + base@map_titles = anno + end if + +; +; gsnDraw and gsnFrame should default to True if not a panel plot. +; + if(panel_plot) then + call_draw = False + call_frame= False + end if + + opts@gsnDraw = get_res_value_keep(opts,"gsnDraw", call_draw) + opts@gsnFrame = get_res_value_keep(opts,"gsnFrame", call_frame) + opts@gsnMaximize = get_res_value_keep(opts,"gsnMaximize", True) + + draw_and_frame(wks,base,opts@gsnDraw,opts@gsnFrame,False, \ + opts@gsnMaximize) + + if(.not.no_titles.and..not.panel_plot) then + NhlRemoveAnnotation(base,base@map_titles) + delete(base@map_titles) + end if + + if(.not.panel_plot) then + if ( nplots .ge. 2 ) then + do i=1,nplots-1 + if(.not.ismissing(plots(i))) then + NhlRemoveOverlay(base,plots(i),False) + else + print("wrf_remove_overlays: Warning: overlay plot #" + i + " is not valid.") + print(" Nothing to remove.") + end if + end do + end if + end if + +return(base) +end + +;-------------------------------------------------------------------------------- + +undef("wrf_map_zoom") +function wrf_map_zoom(wks[1]:graphic,in_file[1]:file,opt_args[1]:logical, \ + y1:integer,y2:integer,x1:integer,x2:integer) + +; As of version 5.0.1, this routine is redundant. Use the special "ZoomIn" +; resource in wrf_map to accomplish the same thing. This function is +; being kept for backwards capability. There should be no need for it +; except to run old WRF-NCL codes. Do not make any changes to it except +; possibly to fix bugs. +; +begin + print("wrf_map_zoom: Warning: This function is obsolete. Consider using") + print(" the 'ZoomIn' resource in wrf_map instead.") + if(isfilevar(in_file,"XLAT")) + lat = in_file->XLAT(0,:,:) + lon = in_file->XLONG(0,:,:) + else + lat = in_file->XLAT_M(0,:,:) + lon = in_file->XLONG_M(0,:,:) + end if + opts = opt_args ; Make a copy of the resource list + opts = True + opts@mpLeftCornerLatF = lat(y1,x1) + opts@mpLeftCornerLonF = lon(y1,x1) + opts@mpRightCornerLatF = lat(y2,x2) + opts@mpRightCornerLonF = lon(y2,x2) + mz = wrf_map(wks,in_file,opts) + return(mz) +end + +;-------------------------------------------------------------------------------- + +undef("wrf_map_overlay") +procedure wrf_map_overlay(wks:graphic,base[1]:graphic, \ + plots[*]:graphic, \ + opt_arg[1]:logical) + +; As of version 5.0.1, this procedure is obsolete. Use wrf_map_overlays +; instead. It is being kept for backwards capability. Do not make any +; changes to it except possibly to fix bugs. +; +; This procedure takes an array of plots and overlays them on a +; base plot - map background. +; +; It will advance the plot and cleanup, unless you set the +; PanelPlot resource to True. +; +; Attributes recognized by this procedure: +; NoTitles (don't do any titles) +; PanelPlot +; +; If the "NoTitles" attribute exists and is set True, then +; don't create the top-left titles, and leave the main titles alone. +; This resource can be useful if you are planning to panel +; the plots. +; +; If PanelPlot is set to True, then this flags to wrf_map_overlay +; that these plots are going to be eventually paneled (likely +; by gsn_panel), and hence 1) draw and frame should not be called +; (unless gsnDraw and/or gsnFrame are explicitly set to True), +; and 2) the overlays and titles should not be removed with +; NhlRemoveOverlay and NhlRemoveAnnotation. +; +begin + print("wrf_map_overlay: Warning: This procedure is obsolete. Consider" ) + print(" using wrf_map_overlays instead.") + + opts = opt_arg ; Make a copy of the resource list + opts = True + + if(opts.and.isatt(opts,"NoTitles").and.opts@NoTitles) then + no_titles = True + else + no_titles = False + end if + + panel_plot = get_res_value(opts,"PanelPlot",False) ; Are we paneling? + latlon_overlay = get_res_value(opts,"LatLonOverlay",False) ; Lat/lon Overlay? + + nplots = dimsizes(plots) +; font_color = "Black" + + do i=0,nplots-1 + if(.not.ismissing(plots(i))) then +; class_name = NhlClassName(plots(i)) +; print(class_name) +; if(class_name.eq."contourPlotClass") then +; getvalues plots(i) +; "cnFillOn" : fill_on +; "cnLineColor" : line_color +; end getvalues +; if (.not.fill_on) then +; font_color = line_color +; end if +; end if + if(.not.no_titles) then + getvalues plots(i) + "tiMainString" : SubTitle + end getvalues + if(i.eq.0) then + SubTitles = SubTitle + else + SubTitles = SubTitles + "~C~" + SubTitle + end if + if(.not.latlon_overlay) then + setvalues plots(i) + "tfDoNDCOverlay" : True + "tiMainOn" : False + end setvalues + else + setvalues plots(i) + "tiMainOn" : False + end setvalues + end if + else + if(.not.latlon_overlay) then + setvalues plots(i) + "tfDoNDCOverlay" : True + end setvalues + end if + end if + overlay(base,plots(i)) + else + print("wrf_map_overlay: Warning: overlay plot #" + i + " is not valid.") + end if + end do + + if(.not.no_titles) then + font_height = get_res_value_keep(opts,"FontHeightF",0.01) + txt = create "map_titles" textItemClass wks + "txString" : SubTitles + "txFontHeightF" : font_height + ;"txFontColor" : font_color + end create + anno = NhlAddAnnotation(base,txt) + setvalues anno + "amZone" : 3 + "amJust" : "BottomLeft" + "amSide" : "Top" + "amParallelPosF" : 0.005 + "amOrthogonalPosF" : 0.03 + "amResizeNotify" : False + end setvalues + base@map_titles = anno + end if +; +; gsnDraw and gsnFrame should default to True if not a panel plot. +; gsnFrame will default to False if opt_arg is False. +; + if(panel_plot.or..not.opt_arg) then + call_frame = False + else + call_frame = True + end if + if(panel_plot) then + call_draw = False + else + call_draw = True + end if + opts@gsnDraw = get_res_value_keep(opts,"gsnDraw", call_draw) + opts@gsnFrame = get_res_value_keep(opts,"gsnFrame", call_frame) + opts@gsnMaximize = get_res_value_keep(opts,"gsnMaximize", True) + + draw_and_frame(wks,base,opts@gsnDraw,opts@gsnFrame,False, \ + opts@gsnMaximize) + + if(.not.panel_plot) then + do i=0,nplots-1 + if(.not.ismissing(plots(i))) then + NhlRemoveOverlay(base,plots(i),False) + else + print("wrf_remove_map_overlay: Warning: overlay plot #" + i + " is not valid.") + print(" Nothing to remove.") + end if + end do + end if + + if(.not.no_titles.and..not.panel_plot) then + if(isatt(base,"map_titles")) then + NhlRemoveAnnotation(base,base@map_titles) + delete(base@map_titles) + end if + end if +end + +;-------------------------------------------------------------------------------- + +undef("wrf_overlay") +procedure wrf_overlay(wks:graphic, plots[*]:graphic, \ + opt_arg[1]:logical) + +; As of version 5.0.1, this procedure is obsolete. Use wrf_overlays +; instead. It is being kept for backwards capability. Do not make any +; changes to it except possibly to fix bugs. +; +; This procedure takes an array of plots and overlays them. +; +; It will advance the plot and cleanup, unless you set the +; PanelPlot resource to True. +; +; Attributes recognized by this procedure: +; NoTitles (don't do any titles) +; PanelPlot +; +; If the "NoTitles" attribute exists and is set True, then +; don't create the top-left titles, and leave the main titles alone. +; This resource can be useful if you are planning to panel +; the plots. +; +; If PanelPlot is set to True, then this flags to wrf_overlay +; that these plots are going to be eventually paneled (likely +; by gsn_panel), and hence 1) draw and frame should not be called +; (unless gsnDraw and/or gsnFrame are explicitly set to True), +; and 2) the overlays and titles should not be removed with +; NhlRemoveOverlay and NhlRemoveAnnotation. +; +; If LatLonOverlay is set to True, then this means the user is +; using the 2D lat/lon coordinates to do the overlay, and hence +; tfDoNDCOverlay should not be set to True. (The default is False.) +; +begin + print("wrf_overlay: Warning: This procedure is obsolete. Consider using") + print(" wrf_overlays instead.") + + opts = opt_arg ; Make a copy of the resource list. + opts = True + + if(opts.and.isatt(opts,"NoTitles").and.opts@NoTitles) then + no_titles = True + else + no_titles = False + end if + + panel_plot = get_res_value(opts,"PanelPlot",False) ; Are we paneling? + latlon_overlay = get_res_value(opts,"LatLonOverlay",False) ; lat/lon overlay? + + nplots = dimsizes(plots) + + base = plots(0) + if(.not.no_titles) then + getvalues plots(0) + "tiMainString" : SubTitle + end getvalues + SubTitles = SubTitle + if(.not.latlon_overlay) then + setvalues plots(0) + "tfDoNDCOverlay" : True + "tiMainOn" : False + end setvalues + else + setvalues plots(0) + "tiMainOn" : False + end setvalues + end if + else + setvalues plots(0) + "tfDoNDCOverlay" : True + end setvalues + end if + + if (nplots.eq.1) then + blank = create "BlankPlot" logLinPlotClass wks + ;"cnConstFLabelOn" : False + end create + overlay(base,blank) + end if + + do i=1,nplots-1 + if(.not.ismissing(plots(i))) then + if(.not.no_titles) then + getvalues plots(i) + "tiMainString" : SubTitle + end getvalues + SubTitles = SubTitles + "~C~" + SubTitle + if(.not.latlon_overlay) then + setvalues plots(i) + "tfDoNDCOverlay" : True + "tiMainOn" : False + end setvalues + else + setvalues plots(i) + "tiMainOn" : False + end setvalues + end if + else + if(.not.latlon_overlay) then + setvalues plots(i) + "tfDoNDCOverlay" : True + end setvalues + end if + end if + overlay(base,plots(i)) + else + print("wrf_overlay: Warning: overlay plot #" + i + " is not valid.") + end if + end do + + if(.not.no_titles) then + font_height = get_res_value_keep(opts,"FontHeightF",0.01) + + txt = create "map_titles" textItemClass wks + "txString" : SubTitles + "txFontHeightF" : font_height + end create + anno = NhlAddAnnotation(base,txt) + setvalues anno + "amZone" : 3 + "amJust" : "BottomLeft" + "amSide" : "Top" + "amParallelPosF" : 0.005 + "amOrthogonalPosF" : 0.03 + "amResizeNotify" : False + end setvalues + base@map_titles = anno + end if + +; +; gsnDraw and gsnFrame should default to True if not a panel plot. +; gsnFrame will default to False if opt_arg is False. +; + if(panel_plot.or..not.opt_arg) then + call_frame = False + else + call_frame = True + end if + if(panel_plot) then + call_draw = False + else + call_draw = True + end if + opts@gsnDraw = get_res_value_keep(opts,"gsnDraw", call_draw) + opts@gsnFrame = get_res_value_keep(opts,"gsnFrame", call_frame) + opts@gsnMaximize = get_res_value_keep(opts,"gsnMaximize", True) + + draw_and_frame(wks,base,opts@gsnDraw,opts@gsnFrame,False, \ + opts@gsnMaximize) + + if(.not.no_titles.and..not.panel_plot) then + NhlRemoveAnnotation(base,base@map_titles) + delete(base@map_titles) + end if + + if(.not.panel_plot) then + if ( nplots .ge. 2 ) then + do i=1,nplots-1 + if(.not.ismissing(plots(i))) then + NhlRemoveOverlay(base,plots(i),False) + else + print("wrf_remove_overlay: Warning: overlay plot #" + i + " is not valid.") + print(" Nothing to remove.") + end if + end do + end if + end if +end + +;-------------------------------------------------------------------------------- + +undef("add_white_space") +function add_white_space(str:string,maxlen:integer) + +begin + cstr = stringtochar(str) + len = dimsizes(cstr)-1 + ws = "" + if(len.lt.maxlen) then + do i=1,maxlen-len + ws = ws + " " + end do + end if + return(ws) + +end + +;-------------------------------------------------------------------------------- + +undef("print_opts") +procedure print_opts(opts_name,opts,debug) + +begin + if(.not.debug) then + return + end if + varatts = getvaratts(opts) +; +; Sort attributes alphabetically/ +; + sqsort(varatts) +; +; Get length of longest attribute name. +; + cvaratts = stringtochar(varatts) + cmaxlen = dimsizes(cvaratts(0,:))-1 + + print("------------------------------------------------------------") + print(opts_name + "...") ; Print name of option variable. +; +; Loop through each attribute in the list. If its value is an array, +; then print out the array with '(/' and '/)' around it. +; +; If the value is a string, then put ticks (') around each string. +; + do i=0,dimsizes(varatts)-1 + x = opts@$varatts(i)$ +; +; Use add_white_space to make sure all the equal signs line up. +; + tmp_str = " " + varatts(i) + \ + add_white_space(varatts(i),cmaxlen) + " = " +; +; Check if attribute is an array. +; + if(dimsizes(x).gt.1) then + tmp_str = tmp_str + "(/" + do j=0,dimsizes(x)-1 + if(typeof(x(j)).eq."string") then + tmp_str = tmp_str + "'" + x(j) + "'" + else + tmp_str = tmp_str + x(j) + end if + if(j.lt.dimsizes(x)-1) then + tmp_str = tmp_str + "," + else + tmp_str = tmp_str + "/)" + end if + end do + else if(typeof(x).eq."string") then + tmp_str = tmp_str + "'" + x + "'" + else + tmp_str = tmp_str + x + end if + end if + print("" + tmp_str) + delete(x) + end do + +end + +;-------------------------------------------------------------------------------- + +undef("print_header") +procedure print_header(icount:integer,debug) +begin + icount = icount + 1 + if(.not.debug) then + return + end if + print("END plot #" + icount) + print("------------------------------------------------------------") + +end + +;-------------------------------------------------------------------------------- +undef("wrf_cloud_fraction") +function wrf_cloud_fraction(file_handle,time:integer) +begin + + print("in wrf cloud fraction") + if(typeof(file_handle).eq."file") then + ISFILE = True + nc_file = file_handle + else if(typeof(file_handle).eq."list") then + ISFILE = False + nc_file = file_handle[0] + else + print("wrf_user_getvar: error: the first argument must be a file or a list of files opened with addfile or addfiles") + return + end if + end if + + time_in = time + if ( time .eq. -1 ) then + if(ISFILE) then + P = nc_file->P + PB = nc_file->PB + rh = wrf_user_getvar(nc_file,"rh",-1) + else + P = file_handle[:]->P + PB = file_handle[:]->PB + print("here now before rh") + rh = wrf_user_getvar(file_handle,"rh",-1) + end if + else + if(ISFILE) then + P = nc_file->P(time_in,:,:,:) + PB = nc_file->PB(time_in,:,:,:) + rh = wrf_user_getvar(file_handle,"rh",time_in) + else + P = file_handle[:]->P(time_in,:,:,:) + PB = file_handle[:]->PB(time_in,:,:,:) + rh = wrf_user_getvar(file_handle,"rh",time_in) + end if + end if + + + pres = (P + PB) + thedims = dimsizes(pres) + + + if(time .eq. -1) then + nt = thedims(0) + nz = thedims(1) + ns = thedims(2) + ew = thedims(3) + out_array = new( (/nt,3,ns,ew/),float) + else + nt = 1 + nz = thedims(0) + ns = thedims(1) + ew = thedims(2) + out_array = new( (/3,ns,ew/),float) + end if + + lowc = new((/ns,ew/),float) + midc = new((/ns,ew/),float) + highc = new((/ns,ew/),float) + lowc = 0.0 + midc = 0.0 + highc = 0.0 + + if(nt .gt. 1 ) then + do it = 0, nt-1 + print("Working on Time "+it) + fortran_clouds::cloud_frac(pres(it,:,:,:),rh(it,:,:,:),lowc(:,:),midc(:,:),highc(:,:),nz,ns,ew) + out_array(it,0,:,:) = lowc(:,:) + out_array(it,1,:,:) = midc(:,:) + out_array(it,2,:,:) = highc(:,:) + end do + else + fortran_clouds::cloud_frac(pres(:,:,:),rh(:,:,:),lowc(:,:),midc(:,:),highc(:,:),nz,ns,ew) + out_array(0,:,:) = lowc(:,:) + out_array(1,:,:) = midc(:,:) + out_array(2,:,:) = highc(:,:) + end if + + out_array@units = "%" + out_array@description = "Low, Med High Clouds" + print("Done with clouds") + return(out_array) +end \ No newline at end of file diff --git a/ncl_reference/cloud_fracf.f b/ncl_reference/cloud_fracf.f new file mode 100644 index 0000000..bb78187 --- /dev/null +++ b/ncl_reference/cloud_fracf.f @@ -0,0 +1,60 @@ +C NCLFORTSTART + subroutine cloud_frac(pres,rh,lowc,midc,highc,nz,ns,ew) + + implicit none + integer nz,ns,ew + real pres(ew,ns,nz),rh(ew,ns,nz) + real lowc(ew,ns),midc(ew,ns),highc(ew,ns) +C NCLEND + + integer i,j,k + integer kchi,kcmi,kclo + + + DO j = 1,ns + DO i = 1,ew + DO k = 1,nz-1 + +c if((pres(i,j,k) .ge. 45000. ) .and. +c & (pres(i,j,k) .lt. 80000.)) then +c kchi = k + +c else if((pres(i,j,k) .ge. 80000.) .and. +c & (pres(i,j,k) .lt. 97000.)) then +c kcmi = k + +c else if (pres(i,j,k) .ge. 97000.) then +c kclo = k +c end if + IF ( pres(i,j,k) .gt. 97000. ) kclo=k + IF ( pres(i,j,k) .gt. 80000. ) kcmi=k + IF ( pres(i,j,k) .gt. 45000. ) kchi=k + + end do + + DO k = 1,nz-1 + IF ( k .ge. kclo .AND. k .lt. kcmi ) then + lowc(i,j) = AMAX1(rh(i,j,k),lowc(i,j)) + else IF ( k .ge. kcmi .AND. k .lt. kchi ) then !! mid cloud + midc(i,j) = AMAX1(rh(i,j,k),midc(i,j)) + else if ( k .ge. kchi ) then !! high cloud + highc(i,j) = AMAX1(rh(i,j,k),highc(i,j)) + end if + END DO + + + lowc(i,j) = 4.0 * lowc(i,j)/100.-3.0 + midc(i,j) = 4.0 * midc(i,j)/100.-3.0 + highc(i,j) = 2.5 * highc(i,j)/100.-1.5 + + lowc(i,j) = amin1(lowc(i,j),1.0) + lowc(i,j) = amax1(lowc(i,j),0.0) + midc(i,j) = amin1(midc(i,j),1.0) + midc(i,j) = amax1(midc(i,j),0.0) + highc(i,j) = amin1(highc(i,j),1.0) + highc(i,j) = amax1(highc(i,j),0.0) + + END DO + END DO + return + end diff --git a/ncl_reference/module_model_constants.f b/ncl_reference/module_model_constants.f new file mode 100644 index 0000000..aaa1750 --- /dev/null +++ b/ncl_reference/module_model_constants.f @@ -0,0 +1,170 @@ +!WRF:MODEL_LAYER:CONSTANTS +! + + MODULE module_model_constants + + ! 2. Following are constants for use in defining real number bounds. + + ! A really small number. + + REAL , PARAMETER :: epsilon = 1.E-15 + + ! 4. Following is information related to the physical constants. + + ! These are the physical constants used within the model. + +! JM NOTE -- can we name this grav instead? + REAL , PARAMETER :: g = 9.81 ! acceleration due to gravity (m {s}^-2) + +#if ( NMM_CORE == 1 ) + REAL , PARAMETER :: r_d = 287.04 + REAL , PARAMETER :: cp = 1004.6 +#else + REAL , PARAMETER :: r_d = 287. + REAL , PARAMETER :: cp = 7.*r_d/2. +#endif + + REAL , PARAMETER :: r_v = 461.6 + REAL , PARAMETER :: cv = cp-r_d + REAL , PARAMETER :: cpv = 4.*r_v + REAL , PARAMETER :: cvv = cpv-r_v + REAL , PARAMETER :: cvpm = -cv/cp + REAL , PARAMETER :: cliq = 4190. + REAL , PARAMETER :: cice = 2106. + REAL , PARAMETER :: psat = 610.78 + REAL , PARAMETER :: rcv = r_d/cv + REAL , PARAMETER :: rcp = r_d/cp + REAL , PARAMETER :: rovg = r_d/g + REAL , PARAMETER :: c2 = cp * rcv + real , parameter :: mwdry = 28.966 ! molecular weight of dry air (g/mole) + + REAL , PARAMETER :: p1000mb = 100000. + REAL , PARAMETER :: t0 = 300. + REAL , PARAMETER :: p0 = p1000mb + REAL , PARAMETER :: cpovcv = cp/(cp-r_d) + REAL , PARAMETER :: cvovcp = 1./cpovcv + REAL , PARAMETER :: rvovrd = r_v/r_d + + REAL , PARAMETER :: reradius = 1./6370.0e03 + + REAL , PARAMETER :: asselin = .025 +! REAL , PARAMETER :: asselin = .0 + REAL , PARAMETER :: cb = 25. + + REAL , PARAMETER :: XLV0 = 3.15E6 + REAL , PARAMETER :: XLV1 = 2370. + REAL , PARAMETER :: XLS0 = 2.905E6 + REAL , PARAMETER :: XLS1 = 259.532 + + REAL , PARAMETER :: XLS = 2.85E6 + REAL , PARAMETER :: XLV = 2.5E6 + REAL , PARAMETER :: XLF = 3.50E5 + + REAL , PARAMETER :: rhowater = 1000. + REAL , PARAMETER :: rhosnow = 100. + REAL , PARAMETER :: rhoair0 = 1.28 +! +! Now namelist-specified parameter: ccn_conc - RAS +! REAL , PARAMETER :: n_ccn0 = 1.0E8 +! + REAL , PARAMETER :: piconst = 3.1415926535897932384626433 + REAL , PARAMETER :: DEGRAD = piconst/180. + REAL , PARAMETER :: DPD = 360./365. + + REAL , PARAMETER :: SVP1=0.6112 + REAL , PARAMETER :: SVP2=17.67 + REAL , PARAMETER :: SVP3=29.65 + REAL , PARAMETER :: SVPT0=273.15 + REAL , PARAMETER :: EP_1=R_v/R_d-1. + REAL , PARAMETER :: EP_2=R_d/R_v + REAL , PARAMETER :: KARMAN=0.4 + REAL , PARAMETER :: EOMEG=7.2921E-5 + REAL , PARAMETER :: STBOLT=5.67051E-8 + + REAL , PARAMETER :: prandtl = 1./3.0 + ! constants for w-damping option + REAL , PARAMETER :: w_alpha = 0.3 ! strength m/s/s + REAL , PARAMETER :: w_beta = 1.0 ! activation cfl number + + REAL , PARAMETER :: pq0=379.90516 + REAL , PARAMETER :: epsq2=0.2 + REAL , PARAMETER :: a2=17.2693882 + REAL , PARAMETER :: a3=273.16 + REAL , PARAMETER :: a4=35.86 + REAL , PARAMETER :: epsq=1.e-12 + REAL , PARAMETER :: p608=rvovrd-1. +!#if ( NMM_CORE == 1 ) + REAL , PARAMETER :: climit=1.e-20 + REAL , PARAMETER :: cm1=2937.4 + REAL , PARAMETER :: cm2=4.9283 + REAL , PARAMETER :: cm3=23.5518 +! REAL , PARAMETER :: defc=8.0 +! REAL , PARAMETER :: defm=32.0 + REAL , PARAMETER :: defc=0.0 + REAL , PARAMETER :: defm=99999.0 + REAL , PARAMETER :: epsfc=1./1.05 + REAL , PARAMETER :: epswet=0.0 + REAL , PARAMETER :: fcdif=1./3. +#if ( HWRF == 1 ) + REAL , PARAMETER :: fcm=0.0 +#else + REAL , PARAMETER :: fcm=0.00003 +#endif + REAL , PARAMETER :: gma=-r_d*(1.-rcp)*0.5 + REAL , PARAMETER :: p400=40000.0 + REAL , PARAMETER :: phitp=15000.0 + REAL , PARAMETER :: pi2=2.*3.1415926, pi1=3.1415926 + REAL , PARAMETER :: plbtm=105000.0 + REAL , PARAMETER :: plomd=64200.0 + REAL , PARAMETER :: pmdhi=35000.0 + REAL , PARAMETER :: q2ini=0.50 + REAL , PARAMETER :: rfcp=0.25/cp + REAL , PARAMETER :: rhcrit_land=0.75 + REAL , PARAMETER :: rhcrit_sea=0.80 + REAL , PARAMETER :: rlag=14.8125 + REAL , PARAMETER :: rlx=0.90 + REAL , PARAMETER :: scq2=50.0 + REAL , PARAMETER :: slopht=0.001 + REAL , PARAMETER :: tlc=2.*0.703972477 + REAL , PARAMETER :: wa=0.15 + REAL , PARAMETER :: wght=0.35 + REAL , PARAMETER :: wpc=0.075 + REAL , PARAMETER :: z0land=0.10 +#if ( HWRF == 1 ) + REAL , PARAMETER :: z0max=0.01 +#else + REAL , PARAMETER :: z0max=0.008 +#endif + REAL , PARAMETER :: z0sea=0.001 +!#endif + + + ! Earth + + ! The value for P2SI *must* be set to 1.0 for Earth + ! Although, now we may not need this declaration here (see above) + !REAL , PARAMETER :: P2SI = 1.0 + + ! Orbital constants: + + INTEGER , PARAMETER :: PLANET_YEAR = 365 + REAL , PARAMETER :: OBLIQUITY = 23.5 + REAL , PARAMETER :: ECCENTRICITY = 0.014 + REAL , PARAMETER :: SEMIMAJORAXIS = 1.0 ! In AU + ! Don't know the following values, so we'll fake them for now + REAL , PARAMETER :: zero_date = 0.0 ! Time of perihelion passage + ! Fraction into the year (from perhelion) of the + ! occurrence of the Northern Spring Equinox + REAL , PARAMETER :: EQUINOX_FRACTION= 0.0 + +! 2012103 +#if (EM_CORE == 1) +! for calls to set_tiles + INTEGER, PARAMETER :: ZONE_SOLVE_EM = 1 + INTEGER, PARAMETER :: ZONE_SFS = 2 +#endif + + CONTAINS + SUBROUTINE init_module_model_constants + END SUBROUTINE init_module_model_constants + END MODULE module_model_constants diff --git a/ncl_reference/wrf_map_fix.ncl b/ncl_reference/wrf_map_fix.ncl new file mode 100644 index 0000000..5a663ff --- /dev/null +++ b/ncl_reference/wrf_map_fix.ncl @@ -0,0 +1,380 @@ +undef("set_mp_wrf_map_resources") +function set_mp_wrf_map_resources(in_file[1]:file,opt_args[1]:logical) + +begin +; + opts = opt_args ; Make a copy of the resource list + +; Set some resources depending on what kind of map projection is +; chosen. +; +; MAP_PROJ = 0 : "CylindricalEquidistant" +; MAP_PROJ = 1 : "LambertConformal" +; MAP_PROJ = 2 : "Stereographic" +; MAP_PROJ = 3 : "Mercator" +; MAP_PROJ = 6 : "Lat/Lon" + + if(isatt(in_file,"MAP_PROJ")) + +; CylindricalEquidistant + if(in_file@MAP_PROJ .eq. 0) + projection = "CylindricalEquidistant" + opts@mpProjection = projection + opts@mpGridSpacingF = 45 + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF", 0.0) + if(isatt(in_file,"STAND_LON")) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; LambertConformal projection + if(in_file@MAP_PROJ .eq. 1) + projection = "LambertConformal" + opts@mpProjection = projection + opts@mpLambertParallel1F = get_res_value_keep(opts, "mpLambertParallel1F",in_file@TRUELAT1) + opts@mpLambertParallel2F = get_res_value_keep(opts, "mpLambertParallel2F",in_file@TRUELAT2) + if(isatt(in_file,"STAND_LON")) + opts@mpLambertMeridianF = get_res_value_keep(opts, "mpLambertMeridianF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + opts@mpLambertMeridianF = get_res_value_keep(opts, "mpLambertMeridianF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; Stereographic projection + if(in_file@MAP_PROJ .eq. 2) + projection = "Stereographic" + opts@mpProjection = projection + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF", in_file@CEN_LAT) + if(isatt(in_file,"STAND_LON")) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; Mercator projection + if(in_file@MAP_PROJ .eq. 3) + projection = "Mercator" + opts@mpProjection = projection + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF", 0.0) + if(isatt(in_file,"STAND_LON")) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; global WRF CylindricalEquidistant + if(in_file@MAP_PROJ .eq. 6) + projection = "CylindricalEquidistant" + opts@mpProjection = projection + opts@mpGridSpacingF = 45 + + if (isatt(in_file,"POLE_LON") .and. isatt(in_file,"POLE_LAT") .and. isatt(in_file,"STAND_LON")) then + + if (in_file@POLE_LON .eq. 0 .and. in_file@POLE_LAT .eq. 90) then + ; not rotated + + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF", 0.0) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",180 - in_file@STAND_LON) + + else + ; rotated + + southern = False ; default to northern hemisphere + if (in_file@POLE_LON .eq. 0.0) then + southern = True + else if (in_file@POLE_LON .ne. 180) then + if (isatt(in_file,"CEN_LAT") .and. in_file@CEN_LAT .lt. 0.0) then + southern = True ; probably but not necessarily true -- no way to tell for sure + end if + end if + end if + + if (.not. southern) then + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF", 90.0 - in_file@POLE_LAT) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF", -in_file@STAND_LON) + else + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF", in_file@POLE_LAT - 90) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF", 180 - in_file@STAND_LON) + end if + + end if + + else if (isatt(in_file,"ref_lon") .and. isatt(in_file,"ref_lat")) then + ;; this is definitely true for NMM grids but unlikely for ARW grids especially if ref_x and ref_y are set + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF", in_file@REF_LAT) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF", in_file@REF_LON) + + else if (isatt(in_file,"cen_lat") .and. isatt(in_file,"cen_lon")) then + ;; these usually specifiy the center of the coarse domain --- not necessarily the center of the projection + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF",in_file@CEN_LAT) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF",in_file@CEN_LON) + + else + ;; default values for global grid + opts@mpCenterLatF = get_res_value_keep(opts, "mpCenterLatF", 0.0) + opts@mpCenterLonF = get_res_value_keep(opts, "mpCenterLonF", 180.0) + + end if + end if + end if + end if + + end if + + return(opts) ; Return. + +end + + +undef("wrf_map_resources") +function wrf_map_resources(in_file[1]:file,map_args[1]:logical) +local lat, lon, x1, x2, y1, y2, dims, ii, jj, southern +begin +; +; This function sets resources for a WRF map plot, basing the projection on +; the MAP_PROJ attribute in the given file. It's intended to be callable +; by users who need to set mpXXXX resources for other plotting scripts. +; + +; Set some resources depending on what kind of map projection is +; chosen. +; +; MAP_PROJ = 0 : "CylindricalEquidistant" +; MAP_PROJ = 1 : "LambertConformal" +; MAP_PROJ = 2 : "Stereographic" +; MAP_PROJ = 3 : "Mercator" +; MAP_PROJ = 6 : "Lat/Lon" + + if(isatt(in_file,"MAP_PROJ")) + +; CylindricalEquidistant + if(in_file@MAP_PROJ .eq. 0) + map_args@mpProjection = "CylindricalEquidistant" + map_args@mpGridSpacingF = 45 + map_args@mpCenterLatF = get_res_value_keep(map_args, "mpCenterLatF", 0.0) + if(isatt(in_file,"STAND_LON")) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; LambertConformal projection + if(in_file@MAP_PROJ .eq. 1) + map_args@mpProjection = "LambertConformal" + map_args@mpLambertParallel1F = get_res_value_keep(map_args, "mpLambertParallel1F",in_file@TRUELAT1) + map_args@mpLambertParallel2F = get_res_value_keep(map_args, "mpLambertParallel2F",in_file@TRUELAT2) + if(isatt(in_file,"STAND_LON")) + map_args@mpLambertMeridianF = get_res_value_keep(map_args, "mpLambertMeridianF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + map_args@mpLambertMeridianF = get_res_value_keep(map_args, "mpLambertMeridianF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; Stereographic projection + if(in_file@MAP_PROJ .eq. 2) + map_args@mpProjection = "Stereographic" + map_args@mpCenterLatF = get_res_value_keep(map_args, "mpCenterLatF", in_file@CEN_LAT) + if(isatt(in_file,"STAND_LON")) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; Mercator projection + if(in_file@MAP_PROJ .eq. 3) + map_args@mpProjection = "Mercator" + map_args@mpCenterLatF = get_res_value_keep(map_args, "mpCenterLatF", 0.0) + if(isatt(in_file,"STAND_LON")) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",in_file@STAND_LON) + else + if(isatt(in_file,"CEN_LON")) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",in_file@CEN_LON) + else + print("ERROR: Found neither STAND_LON or CEN_LON in file") + end if + end if + end if + +; global WRF CylindricalEquidistant + if(in_file@MAP_PROJ .eq. 6) + print ("YES, THIS WORKED") + projection = "CylindricalEquidistant" + map_args@mpProjection = projection + map_args@mpGridSpacingF = 45 + + ;; according to the docs if POLE_LON is 0 then the projection center is in the southern hemisphere + ;; if POLE_LON is 180 the projection center is in the northern hemisphere + ;; otherwise you can't tell for sure -- CEN_LAT does not have to be the projection center but hopefully + ;; it is in the same hemisphere. The same is true for REF_LAT except that if REF_Y is specified REF_LAT might + ;; be in a corner or somewhere else and therefore it is even less reliable + ;; + + if (isatt(in_file,"POLE_LON") .and. isatt(in_file,"POLE_LAT") .and. isatt(in_file,"STAND_LON")) then + + if (in_file@POLE_LON .eq. 0 .and. in_file@POLE_LAT .eq. 90) then + ; not rotated + + map_args@mpCenterLatF = get_res_value_keep(map_args, "mpCenterLatF", 0.0) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",180 - in_file@STAND_LON) + + else + ; rotated + + southern = False ; default to northern hemisphere + if (in_file@POLE_LON .eq. 0.0) then + southern = True + else if (in_file@POLE_LON .ne. 180) then + if (isatt(in_file,"CEN_LAT") .and. in_file@CEN_LAT .lt. 0.0) then + southern = True ; probably but not necessarily true -- no way to tell for sure + end if + end if + end if + + if (.not. southern) then + map_args@mpCenterLatF = get_res_value_keep(map_args, "mpCenterLatF", 90.0 - in_file@POLE_LAT) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF", -in_file@STAND_LON) + else + map_args@mpCenterLatF = get_res_value_keep(map_args, "mpCenterLatF", in_file@POLE_LAT - 90) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF", 180 - in_file@STAND_LON) + end if + + end if + + else if (isatt(in_file,"ref_lon") .and. isatt(in_file,"ref_lat")) then + ;; this is definitely true for NMM grids but unlikely for ARW grids especially if ref_x and ref_y are set + map_args@mpCenterLatF = get_res_value_keep(map_args, "mpCenterLatF", in_file@REF_LAT) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF", in_file@REF_LON) + + else if (isatt(in_file,"cen_lat") .and. isatt(in_file,"cen_lon")) then + ;; these usually specifiy the center of the coarse domain --- not necessarily the center of the projection + map_args@mpCenterLatF = get_res_value_keep(map_args, "mpCenterLatF",in_file@CEN_LAT) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF",in_file@CEN_LON) + + else + ;; default values for global grid + map_args@mpCenterLatF = get_res_value_keep(map_args, "mpCenterLatF", 0.0) + map_args@mpCenterLonF = get_res_value_keep(map_args, "mpCenterLonF", 180.0) + + end if + end if + end if + + end if + + else + + return(map_args) + + end if + + map_args@mpNestTime = get_res_value_keep(map_args, "mpNestTime",0) + + if(isfilevar(in_file,"XLAT")) + lat = in_file->XLAT(map_args@mpNestTime,:,:) + lon = in_file->XLONG(map_args@mpNestTime,:,:) + else + lat = in_file->XLAT_M(map_args@mpNestTime,:,:) + lon = in_file->XLONG_M(map_args@mpNestTime,:,:) + end if + dims = dimsizes(lat) + + do ii = 0, dims(0)-1 + do jj = 0, dims(1)-1 + if ( lon(ii,jj) .lt. 0.0) then + lon(ii,jj) = lon(ii,jj) + 360. + end if + end do + end do + + map_args@start_lat = lat(0,0) + map_args@start_lon = lon(0,0) + map_args@end_lat = lat(dims(0)-1,dims(1)-1) + map_args@end_lon = lon(dims(0)-1,dims(1)-1) + + ; end_lon must be greater than start_lon, or errors are thrown + if (map_args@end_lon .le. map_args@start_lon) then + map_args@end_lon = map_args@end_lon + 360.0 + end if + + +; Set some resources common to all map projections. + map_args = set_mp_resources(map_args) + + if ( isatt(map_args,"ZoomIn") .and. map_args@ZoomIn ) then + y1 = 0 + x1 = 0 + y2 = dims(0)-1 + x2 = dims(1)-1 + if ( isatt(map_args,"Ystart") ) then + y1 = map_args@Ystart + delete(map_args@Ystart) + end if + if ( isatt(map_args,"Xstart") ) then + x1 = map_args@Xstart + delete(map_args@Xstart) + end if + if ( isatt(map_args,"Yend") ) then + if ( map_args@Yend .le. y2 ) then + y2 = map_args@Yend + end if + delete(map_args@Yend) + end if + if ( isatt(map_args,"Xend") ) then + if ( map_args@Xend .le. x2 ) then + x2 = map_args@Xend + end if + delete(map_args@Xend) + end if + + map_args@mpLeftCornerLatF = lat(y1,x1) + map_args@mpLeftCornerLonF = lon(y1,x1) + map_args@mpRightCornerLatF = lat(y2,x2) + map_args@mpRightCornerLonF = lon(y2,x2) + + if ( map_args@mpRightCornerLonF .lt. 0.0 ) then + map_args@mpRightCornerLonF = map_args@mpRightCornerLonF + 360.0 + end if + + if ( map_args@mpRightCornerLonF .le. map_args@mpRightCornerLonF ) then + map_args@mpRightCornerLonF = map_args@mpRightCornerLonF + 360.0 + end if + + delete(map_args@ZoomIn) + end if + + return(map_args) +end \ No newline at end of file diff --git a/setup.py b/setup.py index 16f257e..dc12688 100755 --- a/setup.py +++ b/setup.py @@ -1,22 +1,34 @@ import setuptools import numpy.distutils.core -ext1 = numpy.distutils.core.Extension( - name = "wrf._wrfext", - sources = ["src/wrf/wrfext.f90", - "src/wrf/wrfext.pyf"] - ) +#ext1 = numpy.distutils.core.Extension( +# name = "wrf._wrfext", +# sources = ["src/wrf/wrfext.f90", +# "src/wrf/wrfext.pyf"] +# ) -ext2 = numpy.distutils.core.Extension( - name = "wrf._wrfcape", - sources = ["src/wrf/wrfcape.f90", - "src/wrf/wrfcape.pyf"] - ) +#ext2 = numpy.distutils.core.Extension( +# name = "wrf._wrfcape", +# sources = ["src/wrf/wrfcape.f90", +# "src/wrf/wrfcape.pyf"] +# ) -ext3 = numpy.distutils.core.Extension( +ext1 = numpy.distutils.core.Extension( name = "wrf._wrffortran", sources = ["fortran/constants.f90", "fortran/wrf_user.f90", + "fortran/rip_cape.f90", + "fortran/cloud_fracf.f90", + "fortran/wrf_fctt.f90", + "fortran/wrf_user_dbz.f90", + "fortran/wrf_relhl.f90", + "fortran/calc_uh.f90", + "fortran/wrf_user_latlon_routines.f90", + "fortran/wrf_pvo.f90", + "fortran/eqthecalc.f90", + "fortran/wrf_rip_phys_routines.f90", + "fortran/wrf_pw.f90", + "fortran/wrf_vinterp.f90", "fortran/wrffortran.pyf"] ) @@ -24,8 +36,10 @@ numpy.distutils.core.setup( name = "wrf", version = "0.0.1", packages = setuptools.find_packages("src"), - ext_modules = [ext1,ext2,ext3], - package_dir={"":"src"}, + ext_modules = [ext1], + package_dir={"" : "src"}, #namespace_packages=["wrf"], - scripts=[], + # Note: If this doesn't work, you need to add the file to MANIFEST + package_data={"wrf" : ["data/psadilookup.dat"]}, + scripts=[] ) diff --git a/src/wrf/api.py b/src/wrf/api.py index 21779e2..88f4315 100644 --- a/src/wrf/api.py +++ b/src/wrf/api.py @@ -6,27 +6,31 @@ from .constants import ALL_TIMES, Constants, ConversionFactors from .destag import destagger from .routines import getvar from .computation import (xy, interp1d, interp2dxy, interpz3d, slp, tk, td, rh, - uvmet, smooth2d) + uvmet, smooth2d, cape_2d, cape_3d, cloudfrac) from .interp import (interplevel, vertcross, interpline, vinterp) -from .util import (viewitems, viewkeys, viewvalues, isstr, py2round, - py3range, ucode, npvalues, extract_global_attrs, +from .latlon import (xy_to_ll, ll_to_xy) +from .py3compat import (viewitems, viewkeys, viewvalues, isstr, py2round, + py3range, ucode) +from .util import (npvalues, extract_global_attrs, extract_dim, extract_vars, extract_times, combine_files, is_staggered, get_left_indexes, iter_left_indexes, get_right_slices, get_proj_params) __all__ = [] __all__ += ["xarray_enabled", "disable_xarray", "enable_xarray", - "cartopy_enabled", "enable_cartopy", "enable_cartopy", - "basemap_enabled", "disable_basemap", "enable_basemap", - "pyngl_enabled", "enable_pyngl", "disable_pyngl"] + "cartopy_enabled", "enable_cartopy", "enable_cartopy", + "basemap_enabled", "disable_basemap", "enable_basemap", + "pyngl_enabled", "enable_pyngl", "disable_pyngl"] __all__ += ["ALL_TIMES", "Constants", "ConversionFactors"] __all__ += ["destagger"] __all__ += ["getvar"] -__all__ += ["xy", "interp1d", "interp2dxy", "interpz3d", "slp", "tk", "td", "rh", - "uvmet", "smooth2d"] +__all__ += ["xy", "interp1d", "interp2dxy", "interpz3d", "slp", "tk", "td", + "rh", "uvmet", "smooth2d", "cape_2d", "cape_3d", "cloudfrac"] __all__ += ["interplevel", "vertcross", "interpline", "vinterp"] +__all__ += ["xy_to_ll", "ll_to_xy"] __all__ += ["viewitems", "viewkeys", "viewvalues", "isstr", "py2round", - "py3range", "ucode", "npvalues", "extract_global_attrs", + "py3range", "ucode"] +__all__ += ["npvalues", "extract_global_attrs", "extract_dim", "extract_vars", "extract_times", "combine_files", "is_staggered", "get_left_indexes", "iter_left_indexes", "get_right_slices", "get_proj_params"] diff --git a/src/wrf/cape.py b/src/wrf/cape.py index e0a9382..e86f58a 100755 --- a/src/wrf/cape.py +++ b/src/wrf/cape.py @@ -1,26 +1,28 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) -import numpy as n +import numpy as np import numpy.ma as ma #from .extension import computetk,computecape -from .extension import _tk,computecape +from .extension import _tk, _cape from .destag import destagger from .constants import Constants, ConversionFactors from .util import extract_vars, combine_with -from .metadecorators import copy_and_set_metadata +from .metadecorators import set_cape_metadata -@copy_and_set_metadata(copy_varname="T", - name="cape_2d", - dimnames=combine_with("T", remove_dims=("bottom_top",), - insert_before="south_north", - new_dimnames=["mcape_mcin_lcl_lfc"]), - description="mcape ; mcin ; lcl ; lfc", - units="J/kg ; J/kg ; m ; m", - MemoryOrder="XY") +#@copy_and_set_metadata(copy_varname="T", +# name="cape_2d", +# dimnames=combine_with("T", remove_dims=("bottom_top",), +# insert_before="south_north", +# new_dimnames=["mcape_mcin_lcl_lfc"]), +# description="mcape ; mcin ; lcl ; lfc", +# units="J/kg ; J/kg ; m ; m", +# MemoryOrder="XY") +@set_cape_metadata(is2d=True) def get_2dcape(wrfnc, timeidx=0, method="cat", + squeeze=True, cache=None, meta=True, missing=Constants.DEFAULT_FILL): """Return the 2d fields of cape, cin, lcl, and lfc""" @@ -53,37 +55,35 @@ def get_2dcape(wrfnc, timeidx=0, method="cat", i3dflag = 0 ter_follow = 1 - cape_res,cin_res = computecape(p_hpa,tk,qv,z,ter,psfc_hpa, - missing,i3dflag,ter_follow) + cape_cin = _cape(p_hpa, tk, qv, z, ter, psfc_hpa, missing, i3dflag, + ter_follow) - cape = cape_res[...,0,:,:] - cin = cin_res[...,0,:,:] - lcl = cin_res[...,1,:,:] - lfc = cin_res[...,2,:,:] + left_dims = cape_cin.shape[1:-3] + right_dims = cape_cin.shape[-2:] - left_dims = [x for x in cape_res.shape[0:-3]] - right_dims = [x for x in cape_res.shape[-2:]] - - resdim = left_dims + [4] + right_dims + resdim = (4,) + left_dims + right_dims # Make a new output array for the result - res = n.zeros(resdim, cape.dtype) + result = np.zeros(resdim, cape_cin.dtype) - res[...,0,:,:] = cape[:] - res[...,1,:,:] = cin[:] - res[...,2,:,:] = lcl[:] - res[...,3,:,:] = lfc[:] + # Cape 2D output is not flipped in the vertical, so index from the + # end + result[0,...,:,:] = cape_cin[0,...,-1,:,:] + result[1,...,:,:] = cape_cin[1,...,-1,:,:] + result[2,...,:,:] = cape_cin[1,...,-2,:,:] + result[3,...,:,:] = cape_cin[1,...,-3,:,:] - return ma.masked_values(res, missing) + return ma.masked_values(result, missing) -@copy_and_set_metadata(copy_varname="T", name="cape_3d", - dimnames=combine_with("T", - insert_before="bottom_top", - new_dimnames=["cape_cin"]), - description="cape ; cin", - units="J kg-1 ; J kg-1", - MemoryOrder="XY") +#@copy_and_set_metadata(copy_varname="T", name="cape_3d", +# dimnames=combine_with("T", +# insert_before="bottom_top", +# new_dimnames=["cape_cin"]), +# description="cape ; cin", +# units="J kg-1 ; J kg-1", +# MemoryOrder="XY") +@set_cape_metadata(is2d=False) def get_3dcape(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, meta=True, missing=Constants.DEFAULT_FILL): @@ -115,21 +115,11 @@ def get_3dcape(wrfnc, timeidx=0, method="cat", i3dflag = 1 ter_follow = 1 - cape,cin = computecape(p_hpa,tk,qv,z,ter,psfc_hpa, - missing,i3dflag,ter_follow) - - # Make a new output array for the result - left_dims = [x for x in cape.shape[0:-3]] - right_dims = [x for x in cape.shape[-3:]] - - resdim = left_dims + [2] + right_dims - - res = n.zeros(resdim, cape.dtype) + cape_cin = _cape(p_hpa, tk, qv, z, ter, psfc_hpa, missing, i3dflag, + ter_follow) - res[...,0,:,:,:] = cape[:] - res[...,1,:,:,:] = cin[:] - return ma.masked_values(res, missing) + return ma.masked_values(cape_cin, missing) \ No newline at end of file diff --git a/src/wrf/cloudfrac.py b/src/wrf/cloudfrac.py new file mode 100644 index 0000000..ac61031 --- /dev/null +++ b/src/wrf/cloudfrac.py @@ -0,0 +1,27 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +from .constants import Constants +from .extension import _tk, _rh, _cloudfrac +from .metadecorators import set_cloudfrac_metadata +from .util import extract_vars + +@set_cloudfrac_metadata() +def get_cloudfrac(wrfnc, timeidx=0, method="cat", squeeze=True, + cache=None, meta=True): + + vars = extract_vars(wrfnc, timeidx, ("P", "PB", "QVAPOR", "T"), + method, squeeze, cache, meta=False) + + p = vars["P"] + pb = vars["PB"] + qv = vars["QVAPOR"] + t = vars["T"] + + full_p = p + pb + full_t = t + Constants.T_BASE + + tk = _tk(full_p, full_t) + rh = _rh(qv, full_p, tk) + + return _cloudfrac(full_p, rh) diff --git a/src/wrf/computation.py b/src/wrf/computation.py index 159f058..5dc015c 100644 --- a/src/wrf/computation.py +++ b/src/wrf/computation.py @@ -1,10 +1,17 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import numpy as np +import numpy.ma as ma from .constants import Constants from .extension import (_interpz3d, _interp2dxy, _interp1d, _slp, _tk, _td, - _rh, _uvmet, _smooth2d) + _rh, _uvmet, _smooth2d, _cape, _cloudfrac, _ctt, _dbz, + _srhel, _udhel, _eth, _wetbulb, _tv, _omega) from .util import from_var from .metadecorators import (set_alg_metadata, set_uvmet_alg_metadata, - set_interp_metadata) + set_interp_metadata, set_cape_alg_metadata, + set_cloudfrac_alg_metadata) from .interputils import get_xy @set_interp_metadata("xy") @@ -30,25 +37,25 @@ def interpz3d(field3d, z, desiredloc, missingval=Constants.DEFAULT_FILL, return _interpz3d(field3d, z, desiredloc, missingval) -@set_alg_metadata(2, refvarname="z", refvarndims=3, units="hpa", +@set_alg_metadata(2, "z", refvarndims=3, units="hpa", description="sea level pressure") def slp(z, t, p, q, meta=True): return _slp(z, t, p, q) -@set_alg_metadata(3, refvarname="pressure", units="K", +@set_alg_metadata(3, "pressure", units="K", description="temperature") def tk(pressure, theta, meta=True): return _tk(pressure, theta) -@set_alg_metadata(3, refvarname="pressure", units="degC", +@set_alg_metadata(3, "pressure", units="degC", description="dew point temperature") def td(pressure, qv_in, meta=True): return _td(pressure, qv_in) -@set_alg_metadata(3, refvarname="pressure", +@set_alg_metadata(3, "pressure", description="relative humidity", units=None) def rh(qv, q, t, meta=True): return _rh(qv, q, t, meta) @@ -59,9 +66,148 @@ def uvmet(u, v, lat, lon, cen_long, cone, meta=True): return _uvmet(u, v, lat, lon, cen_long, cone) -@set_alg_metadata(2, - refvarname="field", +@set_alg_metadata(2, "field", description=from_var("field", "description"), units=from_var("field", "units")) def smooth2d(field, passes, meta=True): return _smooth2d(field, passes) + + +@set_cape_alg_metadata(is2d=True) +def cape_2d(p_hpa, tk, qvapor, height, terrain, psfc_hpa, ter_follow, + missing=Constants.DEFAULT_FILL, meta=True): + + if isinstance(ter_follow, bool): + ter_follow = 1 if ter_follow else 0 + + i3dflag = 0 + cape_cin = _cape(p_hpa, tk, qvapor, height, terrain, psfc_hpa, + missing, i3dflag, ter_follow) + + left_dims = cape_cin.shape[1:-3] + right_dims = cape_cin.shape[-2:] + + resdim = (4,) + left_dims + right_dims + + # Make a new output array for the result + result = np.zeros(resdim, cape_cin.dtype) + + # Cape 2D output is not flipped in the vertical, so index from the + # end + result[0,...,:,:] = cape_cin[0,...,-1,:,:] + result[1,...,:,:] = cape_cin[1,...,-1,:,:] + result[2,...,:,:] = cape_cin[1,...,-2,:,:] + result[3,...,:,:] = cape_cin[1,...,-3,:,:] + + return ma.masked_values(result, missing) + + +@set_cape_alg_metadata(is2d=False) +def cape_3d(p_hpa, tk, qvapor, height, terrain, psfc_hpa, ter_follow, + missing=Constants.DEFAULT_FILL, meta=True): + + if isinstance(ter_follow, bool): + ter_follow = 1 if ter_follow else 0 + + i3dflag = 1 + cape_cin = _cape(p_hpa, tk, qvapor, height, terrain, psfc_hpa, + missing, i3dflag, ter_follow) + + return ma.masked_values(cape_cin, missing) + + +@set_cloudfrac_alg_metadata() +def cloudfrac(p, rh, meta=True): + return _cloudfrac(p, rh) + + +@set_alg_metadata(2, "p_hpa", refvarndims=3, units="degC", + description="cloud top temperature") +def ctt(p_hpa, tk, qv, qcld, ght, ter, qice=None, meta=True): + + # Qice and QCLD need to be in g/kg + if qice is None: + qice = n.zeros(qv.shape, qv.dtype) + haveqci = 0 + else: + haveqci = 1 if qice.any() else 0 + + ctt = _ctt(p_hpa, tk, qice, qcld, qv, ght, ter, haveqci) + return _ctt(p, rh) + + +@set_alg_metadata(3, "p", units="dBZ", + description="radar reflectivity") +def dbz(p, tk, qv, qr, ivarint, iliqskin, qs=None, qg=None, meta=True): + + if qs is None: + qs = np.zeros(qv.shape, qv.dtype) + + if qg is None: + qg = np.zeros(qv.shape, qv.dtype) + + sn0 = 1 if qs.any() else 0 + ivarint = 1 if do_varint else 0 + iliqskin = 1 if do_liqskin else 0 + + return _dbz(p, tk, qv, qr, qs, qg, sn0, ivarint, iliqskin) + + +@set_alg_metadata(2, "ter", units="m-2/s-2", + description="storm relative helicity") +def srhel(u, v, z, ter, top): + return _srhel(u, v, z, ter, top=3000.0) + + +@set_alg_metadata(2, "u", refvarndims=3, units="m-2/s-2", + description="updraft helicity") +def udhel(zstag, mapfct, u, v, wstag, dx, dy, bottom=2000.0, top=5000.0): + return _udhel(zstag, mapfct, u, v, wstag, dx, dy, bottom, top) + + +# Requires both u an v for dimnames +@set_alg_metadata(3, "u", units="10-5 s-1", + stagdim=-1, stagsubvar="vstag", + description="absolute vorticity") +def avo(ustag, vstag, msfu, msfv, msfm, cor, dx, dy): + return _avo(ustag, vstag, msfu, msfv, msfm, cor, dx, dy) + + +@set_alg_metadata(3, "t", units="PVU", + description="potential vorticity") +def pvo(ustag, vstag, t, p, msfu, msfv, msfm, cor, dx, dy): + return _pvo(ustag, vstag, t, p, msfu, msfv, msfm, cor, dx, dy) + + +@set_alg_metadata(3, "qv", units="K", + description="equivalent potential temperature") +def eth(qv, tk, p): + return _eth(qv, tk, p) + + +@set_alg_metadata(3, "p", units="K", + description="wetbulb temperature") +def wetbulb(p, tk, qv): + return _wetbulb(p, tk, qv) + + +@set_alg_metadata(3, "tk", units="K", + description="virtual temperature") +def tvirtual(tk, qv): + return _tv(tk, qv) + + +@set_alg_metadata(3, "qv", units="Pa/s", + description="omega") +def omega(qv, tk, w, p): + return _omega(qv, tk, w, p) + + +@set_alg_metadata(2, "p", refvarndims=3, units="kg m-2", + description="precipitable water") +def pw(p, tk, qv, ht): + tv = _tv(tk, qv) + return _pw(full_p, tv, qv, ht) + + + diff --git a/src/wrf/config.py b/src/wrf/config.py index 27570f4..642685e 100644 --- a/src/wrf/config.py +++ b/src/wrf/config.py @@ -28,11 +28,6 @@ except ImportError: _PYNGL_ENABLED = False else: _PYNGL_ENABLED = True - -__all__ = ["xarray_enabled", "disable_xarray", "enable_xarray", - "cartopy_enabled", "enable_cartopy", "enable_cartopy", - "basemap_enabled", "disable_basemap", "enable_basemap", - "pyngl_enabled", "enable_pyngl", "disable_pyngl"] def xarray_enabled(): global _XARRAY_ENABLED diff --git a/src/wrf/constants.py b/src/wrf/constants.py index 4620a04..b364acc 100755 --- a/src/wrf/constants.py +++ b/src/wrf/constants.py @@ -1,18 +1,18 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) +import numpy as np + +from .py3compat import viewitems +from wrf._wrffortran import constants + ALL_TIMES = None class Constants(object): - R = 287.06 - CP = 1005.0 - G = 9.81 - TCK0 = 273.15 - T_BASE = 300.0 # In WRF the base temperature is always 300 (not var T00) - PI = 3.141592653589793 - DEFAULT_FILL = 9.9692099683868690e+36 # Value is from netcdf.h - WRF_EARTH_RADIUS = 6370000. - ERRLEN = 512 + pass + +for key,val in viewitems(constants.__dict__): + setattr(Constants, key.upper(), np.asscalar(val)) class ConversionFactors(object): PA_TO_HPA = .01 diff --git a/src/wrf/ctt.py b/src/wrf/ctt.py index 8185703..4f3bd80 100644 --- a/src/wrf/ctt.py +++ b/src/wrf/ctt.py @@ -4,7 +4,7 @@ from __future__ import (absolute_import, division, print_function, import numpy as n #from .extension import computectt, computetk -from .extension import computectt, _tk +from .extension import _ctt, _tk from .constants import Constants, ConversionFactors from .destag import destagger from .decorators import convert_units @@ -61,6 +61,6 @@ def get_ctt(wrfnc, timeidx=0, method="cat", geopt_unstag = destagger(geopt, -3) ght = geopt_unstag / Constants.G - ctt = computectt(p_hpa, tk, qice, qcld, qv, ght, ter, haveqci) + ctt = _ctt(p_hpa, tk, qice, qcld, qv, ght, ter, haveqci) return ctt diff --git a/src/wrf/data/psadilookup.dat b/src/wrf/data/psadilookup.dat new file mode 100644 index 0000000..a9950bf --- /dev/null +++ b/src/wrf/data/psadilookup.dat @@ -0,0 +1,4575 @@ + This formatted F77 output file contains lookup data + for obtaining temperature (K) on a pseudoadiabat, + given pressure (hPa) and theta_e (K). It is based + on the Bolton (1980) formula for theta_e. It can be + read in as follows: + do i=1,14 + read(iunit,*) + enddo + read(iunit,*) nthte,nprs + read(iunit,173) (thtelevs(jt),jt=1,nthte) + read(iunit,173) (prslevs(ip),ip=1,nprs) + read(iunit,173) ((arr(ip,jt),ip=1,nprs),jt=1,nthte) + 173 format(5e15.7) + Start data: + 150 150 + 0.2000000E+03 0.2016653E+03 0.2033444E+03 0.2050374E+03 0.2067446E+03 + 0.2084660E+03 0.2102018E+03 0.2119519E+03 0.2137168E+03 0.2154962E+03 + 0.2172905E+03 0.2190997E+03 0.2209240E+03 0.2227634E+03 0.2246182E+03 + 0.2264884E+03 0.2283742E+03 0.2302757E+03 0.2321930E+03 0.2341263E+03 + 0.2360757E+03 0.2380413E+03 0.2400232E+03 0.2420218E+03 0.2440370E+03 + 0.2460689E+03 0.2481177E+03 0.2501835E+03 0.2522666E+03 0.2543671E+03 + 0.2564850E+03 0.2586205E+03 0.2607738E+03 0.2629451E+03 0.2651344E+03 + 0.2673420E+03 0.2695679E+03 0.2718124E+03 0.2740757E+03 0.2763577E+03 + 0.2786587E+03 0.2809789E+03 0.2833184E+03 0.2856773E+03 0.2880559E+03 + 0.2904543E+03 0.2928727E+03 0.2953112E+03 0.2977700E+03 0.3002493E+03 + 0.3027493E+03 0.3052700E+03 0.3078117E+03 0.3103748E+03 0.3129590E+03 + 0.3155648E+03 0.3181922E+03 0.3208416E+03 0.3235130E+03 0.3262066E+03 + 0.3289226E+03 0.3316613E+03 0.3344228E+03 0.3372073E+03 0.3400149E+03 + 0.3428459E+03 0.3457006E+03 0.3485789E+03 0.3514814E+03 0.3544079E+03 + 0.3573588E+03 0.3603342E+03 0.3633344E+03 0.3663596E+03 0.3694100E+03 + 0.3724858E+03 0.3755872E+03 0.3787144E+03 0.3818676E+03 0.3850471E+03 + 0.3882531E+03 0.3914858E+03 0.3947454E+03 0.3980323E+03 0.4013464E+03 + 0.4046881E+03 0.4080576E+03 0.4114552E+03 0.4148810E+03 0.4183354E+03 + 0.4218185E+03 0.4253307E+03 0.4288721E+03 0.4324429E+03 0.4360435E+03 + 0.4396741E+03 0.4433349E+03 0.4470262E+03 0.4507485E+03 0.4545015E+03 + 0.4582858E+03 0.4621015E+03 0.4659491E+03 0.4698286E+03 0.4737405E+03 + 0.4776850E+03 0.4816623E+03 0.4856727E+03 0.4897165E+03 0.4937940E+03 + 0.4979054E+03 0.5020511E+03 0.5062312E+03 0.5104465E+03 0.5146965E+03 + 0.5189820E+03 0.5233032E+03 0.5276603E+03 0.5320536E+03 0.5364836E+03 + 0.5409505E+03 0.5454546E+03 0.5499962E+03 0.5545755E+03 0.5591930E+03 + 0.5638489E+03 0.5685437E+03 0.5732775E+03 0.5780510E+03 0.5828636E+03 + 0.5877170E+03 0.5926104E+03 0.5975446E+03 0.6025199E+03 0.6075366E+03 + 0.6125950E+03 0.6176956E+03 0.6228387E+03 0.6280245E+03 0.6332536E+03 + 0.6385262E+03 0.6438427E+03 0.6492034E+03 0.6546091E+03 0.6600593E+03 + 0.6655554E+03 0.6710969E+03 0.6766846E+03 0.6823188E+03 0.6879999E+03 + 0.1100000E+04 0.1075803E+04 0.1052138E+04 0.1028994E+04 0.1006359E+04 + 0.9842219E+03 0.9625715E+03 0.9413974E+03 0.9206895E+03 0.9004366E+03 + 0.8806293E+03 0.8612581E+03 0.8423126E+03 0.8237839E+03 0.8056631E+03 + 0.7879406E+03 0.7706078E+03 0.7536568E+03 0.7370782E+03 0.7208644E+03 + 0.7050075E+03 0.6894991E+03 0.6743322E+03 0.6594986E+03 0.6449913E+03 + 0.6308035E+03 0.6169274E+03 0.6033565E+03 0.5900845E+03 0.5771041E+03 + 0.5644093E+03 0.5519940E+03 0.5398515E+03 0.5279761E+03 0.5163622E+03 + 0.5050036E+03 0.4938948E+03 0.4830306E+03 0.4724051E+03 0.4620134E+03 + 0.4518505E+03 0.4419109E+03 0.4321902E+03 0.4226831E+03 0.4133852E+03 + 0.4042919E+03 0.3953985E+03 0.3867007E+03 0.3781945E+03 0.3698752E+03 + 0.3617389E+03 0.3537817E+03 0.3459994E+03 0.3383883E+03 0.3309447E+03 + 0.3236648E+03 0.3165450E+03 0.3095819E+03 0.3027719E+03 0.2961117E+03 + 0.2895981E+03 0.2832277E+03 0.2769974E+03 0.2709043E+03 0.2649451E+03 + 0.2591170E+03 0.2534172E+03 0.2478426E+03 0.2423907E+03 0.2370589E+03 + 0.2318442E+03 0.2267442E+03 0.2217565E+03 0.2168784E+03 0.2121076E+03 + 0.2074419E+03 0.2028787E+03 0.1984159E+03 0.1940513E+03 0.1897827E+03 + 0.1856079E+03 0.1815251E+03 0.1775320E+03 0.1736268E+03 0.1698075E+03 + 0.1660722E+03 0.1624190E+03 0.1588463E+03 0.1553521E+03 0.1519347E+03 + 0.1485926E+03 0.1453240E+03 0.1421272E+03 0.1390008E+03 0.1359432E+03 + 0.1329527E+03 0.1300282E+03 0.1271679E+03 0.1243705E+03 0.1216347E+03 + 0.1189591E+03 0.1163423E+03 0.1137831E+03 0.1112802E+03 0.1088323E+03 + 0.1064383E+03 0.1040970E+03 0.1018071E+03 0.9956760E+02 0.9737740E+02 + 0.9523535E+02 0.9314041E+02 0.9109160E+02 0.8908781E+02 0.8712811E+02 + 0.8521156E+02 0.8333711E+02 0.8150391E+02 0.7971107E+02 0.7795763E+02 + 0.7624275E+02 0.7456564E+02 0.7292538E+02 0.7132121E+02 0.6975236E+02 + 0.6821799E+02 0.6671736E+02 0.6524978E+02 0.6381445E+02 0.6241069E+02 + 0.6103785E+02 0.5969517E+02 0.5838202E+02 0.5709779E+02 0.5584179E+02 + 0.5461341E+02 0.5341208E+02 0.5223714E+02 0.5108807E+02 0.4996428E+02 + 0.4886519E+02 0.4779029E+02 0.4673904E+02 0.4571090E+02 0.4470538E+02 + 0.4372198E+02 0.4276021E+02 0.4181961E+02 0.4089969E+02 0.4000000E+02 + 0.2055137E+03 0.2042125E+03 0.2029193E+03 0.2016342E+03 0.2003570E+03 + 0.1990878E+03 0.1978265E+03 0.1965731E+03 0.1953276E+03 0.1940898E+03 + 0.1928599E+03 0.1916377E+03 0.1904232E+03 0.1892163E+03 0.1880171E+03 + 0.1868254E+03 0.1856413E+03 0.1844646E+03 0.1832954E+03 0.1821335E+03 + 0.1809791E+03 0.1798319E+03 0.1786920E+03 0.1775593E+03 0.1764338E+03 + 0.1753154E+03 0.1742041E+03 0.1730999E+03 0.1720026E+03 0.1709123E+03 + 0.1698289E+03 0.1687524E+03 0.1676826E+03 0.1666197E+03 0.1655635E+03 + 0.1645140E+03 0.1634712E+03 0.1624350E+03 0.1614053E+03 0.1603821E+03 + 0.1593655E+03 0.1583553E+03 0.1573515E+03 0.1563540E+03 0.1553629E+03 + 0.1543781E+03 0.1533994E+03 0.1524270E+03 0.1514608E+03 0.1505007E+03 + 0.1495467E+03 0.1485987E+03 0.1476568E+03 0.1467207E+03 0.1457907E+03 + 0.1448665E+03 0.1439482E+03 0.1430358E+03 0.1421290E+03 0.1412281E+03 + 0.1403329E+03 0.1394433E+03 0.1385594E+03 0.1376810E+03 0.1368083E+03 + 0.1359410E+03 0.1350793E+03 0.1342231E+03 0.1333722E+03 0.1325268E+03 + 0.1316867E+03 0.1308519E+03 0.1300225E+03 0.1291983E+03 0.1283793E+03 + 0.1275655E+03 0.1267568E+03 0.1259533E+03 0.1251549E+03 0.1243616E+03 + 0.1235732E+03 0.1227899E+03 0.1220116E+03 0.1212381E+03 0.1204696E+03 + 0.1197059E+03 0.1189471E+03 0.1181931E+03 0.1174439E+03 0.1166994E+03 + 0.1159597E+03 0.1152246E+03 0.1144942E+03 0.1137684E+03 0.1130473E+03 + 0.1123306E+03 0.1116186E+03 0.1109110E+03 0.1102080E+03 0.1095094E+03 + 0.1088152E+03 0.1081254E+03 0.1074400E+03 0.1067590E+03 0.1060822E+03 + 0.1054098E+03 0.1047416E+03 0.1040776E+03 0.1034179E+03 0.1027623E+03 + 0.1021109E+03 0.1014636E+03 0.1008204E+03 0.1001813E+03 0.9954629E+02 + 0.9891528E+02 0.9828825E+02 0.9766520E+02 0.9704611E+02 0.9643093E+02 + 0.9581966E+02 0.9521227E+02 0.9460871E+02 0.9400898E+02 0.9341307E+02 + 0.9282092E+02 0.9223253E+02 0.9164787E+02 0.9106693E+02 0.9048965E+02 + 0.8991605E+02 0.8934606E+02 0.8877969E+02 0.8821693E+02 0.8765772E+02 + 0.8710206E+02 0.8654993E+02 0.8600128E+02 0.8545613E+02 0.8491442E+02 + 0.8437615E+02 0.8384129E+02 0.8330983E+02 0.8278172E+02 0.8225697E+02 + 0.8173555E+02 0.8121742E+02 0.8070259E+02 0.8019102E+02 0.7968269E+02 + 0.2072220E+03 0.2059104E+03 0.2046068E+03 0.2033112E+03 0.2020237E+03 + 0.2007441E+03 0.1994725E+03 0.1982088E+03 0.1969531E+03 0.1957052E+03 + 0.1944651E+03 0.1932328E+03 0.1920082E+03 0.1907914E+03 0.1895822E+03 + 0.1883807E+03 0.1871867E+03 0.1860003E+03 0.1848214E+03 0.1836499E+03 + 0.1824858E+03 0.1813291E+03 0.1801797E+03 0.1790376E+03 0.1779028E+03 + 0.1767751E+03 0.1756546E+03 0.1745411E+03 0.1734347E+03 0.1723353E+03 + 0.1712429E+03 0.1701574E+03 0.1690788E+03 0.1680070E+03 0.1669420E+03 + 0.1658838E+03 0.1648323E+03 0.1637874E+03 0.1627491E+03 0.1617175E+03 + 0.1606924E+03 0.1596737E+03 0.1586616E+03 0.1576558E+03 0.1566565E+03 + 0.1556634E+03 0.1546767E+03 0.1536962E+03 0.1527219E+03 0.1517538E+03 + 0.1507918E+03 0.1498360E+03 0.1488862E+03 0.1479424E+03 0.1470046E+03 + 0.1460727E+03 0.1451468E+03 0.1442267E+03 0.1433124E+03 0.1424040E+03 + 0.1415013E+03 0.1406043E+03 0.1397130E+03 0.1388274E+03 0.1379474E+03 + 0.1370729E+03 0.1362040E+03 0.1353406E+03 0.1344827E+03 0.1336302E+03 + 0.1327831E+03 0.1319414E+03 0.1311051E+03 0.1302740E+03 0.1294482E+03 + 0.1286276E+03 0.1278122E+03 0.1270020E+03 0.1261970E+03 0.1253970E+03 + 0.1246021E+03 0.1238123E+03 0.1230274E+03 0.1222476E+03 0.1214727E+03 + 0.1207026E+03 0.1199375E+03 0.1191772E+03 0.1184218E+03 0.1176711E+03 + 0.1169252E+03 0.1161840E+03 0.1154475E+03 0.1147157E+03 0.1139885E+03 + 0.1132659E+03 0.1125479E+03 0.1118345E+03 0.1111256E+03 0.1104212E+03 + 0.1097212E+03 0.1090257E+03 0.1083346E+03 0.1076479E+03 0.1069655E+03 + 0.1062874E+03 0.1056137E+03 0.1049442E+03 0.1042789E+03 0.1036179E+03 + 0.1029611E+03 0.1023084E+03 0.1016599E+03 0.1010155E+03 0.1003751E+03 + 0.9973886E+02 0.9910662E+02 0.9847838E+02 0.9785413E+02 0.9723383E+02 + 0.9661746E+02 0.9600502E+02 0.9539644E+02 0.9479172E+02 0.9419085E+02 + 0.9359377E+02 0.9300048E+02 0.9241096E+02 0.9182516E+02 0.9124308E+02 + 0.9066470E+02 0.9008997E+02 0.8951889E+02 0.8895144E+02 0.8838757E+02 + 0.8782729E+02 0.8727055E+02 0.8671735E+02 0.8616765E+02 0.8562144E+02 + 0.8507868E+02 0.8453938E+02 0.8400348E+02 0.8347099E+02 0.8294186E+02 + 0.8241610E+02 0.8189366E+02 0.8137453E+02 0.8085871E+02 0.8034615E+02 + 0.2089439E+03 0.2076218E+03 0.2063078E+03 0.2050018E+03 0.2037038E+03 + 0.2024139E+03 0.2011320E+03 0.1998580E+03 0.1985919E+03 0.1973338E+03 + 0.1960835E+03 0.1948410E+03 0.1936064E+03 0.1923795E+03 0.1911603E+03 + 0.1899489E+03 0.1887450E+03 0.1875488E+03 0.1863600E+03 0.1851788E+03 + 0.1840051E+03 0.1828388E+03 0.1816799E+03 0.1805283E+03 0.1793840E+03 + 0.1782469E+03 0.1771171E+03 0.1759943E+03 0.1748787E+03 0.1737702E+03 + 0.1726687E+03 0.1715742E+03 0.1704866E+03 0.1694059E+03 0.1683320E+03 + 0.1672650E+03 0.1662047E+03 0.1651511E+03 0.1641042E+03 0.1630640E+03 + 0.1620303E+03 0.1610032E+03 0.1599826E+03 0.1589685E+03 0.1579608E+03 + 0.1569595E+03 0.1559646E+03 0.1549759E+03 0.1539935E+03 0.1530173E+03 + 0.1520474E+03 0.1510835E+03 0.1501258E+03 0.1491742E+03 0.1482286E+03 + 0.1472890E+03 0.1463553E+03 0.1454276E+03 0.1445057E+03 0.1435897E+03 + 0.1426795E+03 0.1417750E+03 0.1408763E+03 0.1399833E+03 0.1390959E+03 + 0.1382142E+03 0.1373381E+03 0.1364675E+03 0.1356024E+03 0.1347429E+03 + 0.1338887E+03 0.1330400E+03 0.1321967E+03 0.1313587E+03 0.1305260E+03 + 0.1296986E+03 0.1288764E+03 0.1280595E+03 0.1272477E+03 0.1264411E+03 + 0.1256396E+03 0.1248432E+03 0.1240518E+03 0.1232654E+03 0.1224841E+03 + 0.1217076E+03 0.1209361E+03 0.1201695E+03 0.1194078E+03 0.1186508E+03 + 0.1178987E+03 0.1171514E+03 0.1164087E+03 0.1156708E+03 0.1149376E+03 + 0.1142090E+03 0.1134850E+03 0.1127657E+03 0.1120508E+03 0.1113406E+03 + 0.1106348E+03 0.1099334E+03 0.1092366E+03 0.1085442E+03 0.1078561E+03 + 0.1071724E+03 0.1064930E+03 0.1058180E+03 0.1051472E+03 0.1044807E+03 + 0.1038184E+03 0.1031603E+03 0.1025063E+03 0.1018565E+03 0.1012109E+03 + 0.1005693E+03 0.9993180E+02 0.9929833E+02 0.9866888E+02 0.9804343E+02 + 0.9742192E+02 0.9680437E+02 0.9619073E+02 0.9558098E+02 0.9497511E+02 + 0.9437305E+02 0.9377482E+02 0.9318039E+02 0.9258971E+02 0.9200278E+02 + 0.9141959E+02 0.9084009E+02 0.9026424E+02 0.8969207E+02 0.8912351E+02 + 0.8855856E+02 0.8799719E+02 0.8743938E+02 0.8688510E+02 0.8633434E+02 + 0.8578706E+02 0.8524326E+02 0.8470291E+02 0.8416598E+02 0.8363245E+02 + 0.8310231E+02 0.8257552E+02 0.8205208E+02 0.8153195E+02 0.8101512E+02 + 0.2106792E+03 0.2093467E+03 0.2080223E+03 0.2067059E+03 0.2053975E+03 + 0.2040972E+03 0.2028048E+03 0.2015205E+03 0.2002441E+03 0.1989757E+03 + 0.1977151E+03 0.1964625E+03 0.1952177E+03 0.1939807E+03 0.1927515E+03 + 0.1915300E+03 0.1903162E+03 0.1891100E+03 0.1879115E+03 0.1867205E+03 + 0.1855370E+03 0.1843610E+03 0.1831925E+03 0.1820313E+03 0.1808775E+03 + 0.1797310E+03 0.1785917E+03 0.1774596E+03 0.1763348E+03 0.1752170E+03 + 0.1741063E+03 0.1730027E+03 0.1719061E+03 0.1708164E+03 0.1697336E+03 + 0.1686576E+03 0.1675885E+03 0.1665262E+03 0.1654706E+03 0.1644217E+03 + 0.1633794E+03 0.1623438E+03 0.1613147E+03 0.1602921E+03 0.1592760E+03 + 0.1582664E+03 0.1572631E+03 0.1562663E+03 0.1552757E+03 0.1542914E+03 + 0.1533133E+03 0.1523415E+03 0.1513758E+03 0.1504162E+03 0.1494628E+03 + 0.1485153E+03 0.1475739E+03 0.1466384E+03 0.1457089E+03 0.1447852E+03 + 0.1438674E+03 0.1429555E+03 0.1420493E+03 0.1411488E+03 0.1402541E+03 + 0.1393650E+03 0.1384816E+03 0.1376037E+03 0.1367315E+03 0.1358647E+03 + 0.1350035E+03 0.1341477E+03 0.1332974E+03 0.1324524E+03 0.1316128E+03 + 0.1307785E+03 0.1299495E+03 0.1291257E+03 0.1283072E+03 0.1274939E+03 + 0.1266857E+03 0.1258826E+03 0.1250847E+03 0.1242918E+03 0.1235039E+03 + 0.1227210E+03 0.1219431E+03 0.1211701E+03 0.1204020E+03 0.1196387E+03 + 0.1188804E+03 0.1181268E+03 0.1173780E+03 0.1166339E+03 0.1158946E+03 + 0.1151599E+03 0.1144299E+03 0.1137046E+03 0.1129838E+03 0.1122676E+03 + 0.1115559E+03 0.1108488E+03 0.1101461E+03 0.1094479E+03 0.1087541E+03 + 0.1080647E+03 0.1073797E+03 0.1066990E+03 0.1060227E+03 0.1053506E+03 + 0.1046828E+03 0.1040192E+03 0.1033598E+03 0.1027046E+03 0.1020536E+03 + 0.1014067E+03 0.1007639E+03 0.1001251E+03 0.9949043E+02 0.9885976E+02 + 0.9823308E+02 0.9761039E+02 0.9699163E+02 0.9637680E+02 0.9576588E+02 + 0.9515882E+02 0.9455560E+02 0.9395622E+02 0.9336064E+02 0.9276882E+02 + 0.9218077E+02 0.9159644E+02 0.9101580E+02 0.9043887E+02 0.8986557E+02 + 0.8929591E+02 0.8872987E+02 0.8816741E+02 0.8760852E+02 0.8705318E+02 + 0.8650134E+02 0.8595302E+02 0.8540816E+02 0.8486676E+02 0.8432879E+02 + 0.8379424E+02 0.8326306E+02 0.8273526E+02 0.8221081E+02 0.8168967E+02 + 0.2124279E+03 0.2110851E+03 0.2097502E+03 0.2084234E+03 0.2071046E+03 + 0.2057939E+03 0.2044911E+03 0.2031965E+03 0.2019097E+03 0.2006310E+03 + 0.1993601E+03 0.1980973E+03 0.1968422E+03 0.1955951E+03 0.1943557E+03 + 0.1931241E+03 0.1919003E+03 0.1906842E+03 0.1894757E+03 0.1882748E+03 + 0.1870816E+03 0.1858958E+03 0.1847176E+03 0.1835468E+03 0.1823834E+03 + 0.1812273E+03 0.1800786E+03 0.1789371E+03 0.1778029E+03 0.1766758E+03 + 0.1755559E+03 0.1744431E+03 0.1733374E+03 0.1722386E+03 0.1711468E+03 + 0.1700619E+03 0.1689839E+03 0.1679127E+03 0.1668483E+03 0.1657907E+03 + 0.1647397E+03 0.1636955E+03 0.1626578E+03 0.1616267E+03 0.1606022E+03 + 0.1595841E+03 0.1585725E+03 0.1575673E+03 0.1565685E+03 0.1555760E+03 + 0.1545898E+03 0.1536099E+03 0.1526362E+03 0.1516686E+03 0.1507072E+03 + 0.1497519E+03 0.1488026E+03 0.1478593E+03 0.1469221E+03 0.1459907E+03 + 0.1450653E+03 0.1441457E+03 0.1432320E+03 0.1423241E+03 0.1414219E+03 + 0.1405254E+03 0.1396346E+03 0.1387495E+03 0.1378699E+03 0.1369960E+03 + 0.1361275E+03 0.1352646E+03 0.1344072E+03 0.1335552E+03 0.1327086E+03 + 0.1318674E+03 0.1310315E+03 0.1302009E+03 0.1293755E+03 0.1285554E+03 + 0.1277405E+03 0.1269308E+03 0.1261261E+03 0.1253266E+03 0.1245322E+03 + 0.1237428E+03 0.1229584E+03 0.1221789E+03 0.1214044E+03 0.1206349E+03 + 0.1198702E+03 0.1191103E+03 0.1183553E+03 0.1176050E+03 0.1168596E+03 + 0.1161188E+03 0.1153827E+03 0.1146513E+03 0.1139245E+03 0.1132024E+03 + 0.1124848E+03 0.1117717E+03 0.1110632E+03 0.1103592E+03 0.1096596E+03 + 0.1089645E+03 0.1082738E+03 0.1075874E+03 0.1069054E+03 0.1062278E+03 + 0.1055544E+03 0.1048853E+03 0.1042204E+03 0.1035598E+03 0.1029033E+03 + 0.1022510E+03 0.1016028E+03 0.1009588E+03 0.1003188E+03 0.9968288E+02 + 0.9905098E+02 0.9842310E+02 0.9779919E+02 0.9717924E+02 0.9656324E+02 + 0.9595113E+02 0.9534289E+02 0.9473852E+02 0.9413797E+02 0.9354123E+02 + 0.9294828E+02 0.9235908E+02 0.9177361E+02 0.9119187E+02 0.9061380E+02 + 0.9003940E+02 0.8946865E+02 0.8890150E+02 0.8833797E+02 0.8777799E+02 + 0.8722157E+02 0.8666867E+02 0.8611929E+02 0.8557337E+02 0.8503092E+02 + 0.8449192E+02 0.8395632E+02 0.8342413E+02 0.8289530E+02 0.8236983E+02 + 0.2141900E+03 0.2128368E+03 0.2114916E+03 0.2101544E+03 0.2088253E+03 + 0.2075041E+03 0.2061910E+03 0.2048859E+03 0.2035888E+03 0.2022997E+03 + 0.2010186E+03 0.1997454E+03 0.1984801E+03 0.1972227E+03 0.1959732E+03 + 0.1947315E+03 0.1934975E+03 0.1922714E+03 0.1910529E+03 0.1898421E+03 + 0.1886390E+03 0.1874434E+03 0.1862554E+03 0.1850749E+03 0.1839018E+03 + 0.1827361E+03 0.1815779E+03 0.1804269E+03 0.1792833E+03 0.1781469E+03 + 0.1770176E+03 0.1758956E+03 0.1747806E+03 0.1736727E+03 0.1725718E+03 + 0.1714778E+03 0.1703909E+03 0.1693108E+03 0.1682375E+03 0.1671711E+03 + 0.1661114E+03 0.1650584E+03 0.1640121E+03 0.1629725E+03 0.1619394E+03 + 0.1609129E+03 0.1598928E+03 0.1588793E+03 0.1578722E+03 0.1568714E+03 + 0.1558770E+03 0.1548889E+03 0.1539071E+03 0.1529314E+03 0.1519620E+03 + 0.1509987E+03 0.1500415E+03 0.1490905E+03 0.1481454E+03 0.1472063E+03 + 0.1462731E+03 0.1453459E+03 0.1444246E+03 0.1435091E+03 0.1425994E+03 + 0.1416954E+03 0.1407972E+03 0.1399047E+03 0.1390179E+03 0.1381366E+03 + 0.1372610E+03 0.1363909E+03 0.1355263E+03 0.1346672E+03 0.1338136E+03 + 0.1329653E+03 0.1321225E+03 0.1312849E+03 0.1304527E+03 0.1296258E+03 + 0.1288041E+03 0.1279876E+03 0.1271763E+03 0.1263701E+03 0.1255691E+03 + 0.1247731E+03 0.1239822E+03 0.1231962E+03 0.1224153E+03 0.1216393E+03 + 0.1208682E+03 0.1201021E+03 0.1193407E+03 0.1185842E+03 0.1178326E+03 + 0.1170856E+03 0.1163434E+03 0.1156059E+03 0.1148731E+03 0.1141449E+03 + 0.1134213E+03 0.1127024E+03 0.1119879E+03 0.1112781E+03 0.1105727E+03 + 0.1098717E+03 0.1091753E+03 0.1084832E+03 0.1077955E+03 0.1071122E+03 + 0.1064333E+03 0.1057586E+03 0.1050882E+03 0.1044220E+03 0.1037601E+03 + 0.1031024E+03 0.1024488E+03 0.1017994E+03 0.1011541E+03 0.1005129E+03 + 0.9987570E+02 0.9924260E+02 0.9861349E+02 0.9798839E+02 0.9736725E+02 + 0.9675004E+02 0.9613673E+02 0.9552733E+02 0.9492178E+02 0.9432008E+02 + 0.9372219E+02 0.9312808E+02 0.9253774E+02 0.9195116E+02 0.9136827E+02 + 0.9078909E+02 0.9021358E+02 0.8964172E+02 0.8907349E+02 0.8850885E+02 + 0.8794779E+02 0.8739030E+02 0.8683633E+02 0.8628588E+02 0.8573891E+02 + 0.8519542E+02 0.8465536E+02 0.8411874E+02 0.8358551E+02 0.8305566E+02 + 0.2159651E+03 0.2146017E+03 0.2132463E+03 0.2118988E+03 0.2105593E+03 + 0.2092278E+03 0.2079043E+03 0.2065888E+03 0.2052813E+03 0.2039818E+03 + 0.2026904E+03 0.2014068E+03 0.2001312E+03 0.1988636E+03 0.1976039E+03 + 0.1963520E+03 0.1951079E+03 0.1938716E+03 0.1926431E+03 0.1914223E+03 + 0.1902092E+03 0.1890038E+03 0.1878059E+03 0.1866156E+03 0.1854328E+03 + 0.1842575E+03 0.1830896E+03 0.1819291E+03 0.1807759E+03 0.1796301E+03 + 0.1784914E+03 0.1773600E+03 0.1762358E+03 0.1751186E+03 0.1740086E+03 + 0.1729056E+03 0.1718096E+03 0.1707205E+03 0.1696383E+03 0.1685630E+03 + 0.1674945E+03 0.1664327E+03 0.1653777E+03 0.1643294E+03 0.1632877E+03 + 0.1622527E+03 0.1612241E+03 0.1602021E+03 0.1591866E+03 0.1581776E+03 + 0.1571749E+03 0.1561785E+03 0.1551885E+03 0.1542048E+03 0.1532273E+03 + 0.1522560E+03 0.1512908E+03 0.1503318E+03 0.1493789E+03 0.1484319E+03 + 0.1474910E+03 0.1465561E+03 0.1456271E+03 0.1447040E+03 0.1437867E+03 + 0.1428752E+03 0.1419695E+03 0.1410696E+03 0.1401754E+03 0.1392868E+03 + 0.1384039E+03 0.1375265E+03 0.1366548E+03 0.1357885E+03 0.1349277E+03 + 0.1340724E+03 0.1332225E+03 0.1323780E+03 0.1315389E+03 0.1307051E+03 + 0.1298765E+03 0.1290533E+03 0.1282352E+03 0.1274223E+03 0.1266146E+03 + 0.1258120E+03 0.1250145E+03 0.1242220E+03 0.1234345E+03 0.1226521E+03 + 0.1218746E+03 0.1211021E+03 0.1203344E+03 0.1195716E+03 0.1188137E+03 + 0.1180605E+03 0.1173121E+03 0.1165685E+03 0.1158295E+03 0.1150953E+03 + 0.1143657E+03 0.1136407E+03 0.1129204E+03 0.1122046E+03 0.1114933E+03 + 0.1107866E+03 0.1100843E+03 0.1093865E+03 0.1086931E+03 0.1080041E+03 + 0.1073194E+03 0.1066391E+03 0.1059632E+03 0.1052915E+03 0.1046240E+03 + 0.1039608E+03 0.1033018E+03 0.1026470E+03 0.1019963E+03 0.1013497E+03 + 0.1007073E+03 0.1000689E+03 0.9943457E+02 0.9880426E+02 0.9817795E+02 + 0.9755560E+02 0.9693719E+02 0.9632272E+02 0.9571213E+02 0.9510540E+02 + 0.9450254E+02 0.9390349E+02 0.9330823E+02 0.9271676E+02 0.9212903E+02 + 0.9154501E+02 0.9096472E+02 0.9038809E+02 0.8981513E+02 0.8924580E+02 + 0.8868007E+02 0.8811793E+02 0.8755936E+02 0.8700431E+02 0.8645279E+02 + 0.8590478E+02 0.8536022E+02 0.8481912E+02 0.8428146E+02 0.8374720E+02 + 0.2177531E+03 0.2163797E+03 0.2150141E+03 0.2136564E+03 0.2123066E+03 + 0.2109648E+03 0.2096309E+03 0.2083051E+03 0.2069873E+03 0.2056774E+03 + 0.2043755E+03 0.2030817E+03 0.2017958E+03 0.2005179E+03 0.1992478E+03 + 0.1979857E+03 0.1967314E+03 0.1954850E+03 0.1942464E+03 0.1930155E+03 + 0.1917924E+03 0.1905770E+03 0.1893693E+03 0.1881691E+03 0.1869765E+03 + 0.1857914E+03 0.1846139E+03 0.1834437E+03 0.1822810E+03 0.1811256E+03 + 0.1799775E+03 0.1788367E+03 0.1777031E+03 0.1765767E+03 0.1754574E+03 + 0.1743452E+03 0.1732400E+03 0.1721419E+03 0.1710507E+03 0.1699664E+03 + 0.1688891E+03 0.1678185E+03 0.1667547E+03 0.1656976E+03 0.1646473E+03 + 0.1636036E+03 0.1625665E+03 0.1615360E+03 0.1605120E+03 0.1594946E+03 + 0.1584835E+03 0.1574789E+03 0.1564807E+03 0.1554887E+03 0.1545031E+03 + 0.1535237E+03 0.1525505E+03 0.1515835E+03 0.1506226E+03 0.1496678E+03 + 0.1487191E+03 0.1477764E+03 0.1468396E+03 0.1459088E+03 0.1449839E+03 + 0.1440648E+03 0.1431516E+03 0.1422442E+03 0.1413425E+03 0.1404465E+03 + 0.1395562E+03 0.1386716E+03 0.1377926E+03 0.1369191E+03 0.1360511E+03 + 0.1351887E+03 0.1343318E+03 0.1334802E+03 0.1326341E+03 0.1317934E+03 + 0.1309579E+03 0.1301278E+03 0.1293029E+03 0.1284832E+03 0.1276688E+03 + 0.1268595E+03 0.1260553E+03 0.1252563E+03 0.1244623E+03 0.1236733E+03 + 0.1228894E+03 0.1221104E+03 0.1213363E+03 0.1205672E+03 0.1198029E+03 + 0.1190435E+03 0.1182889E+03 0.1175390E+03 0.1167939E+03 0.1160536E+03 + 0.1153179E+03 0.1145869E+03 0.1138606E+03 0.1131388E+03 0.1124216E+03 + 0.1117090E+03 0.1110009E+03 0.1102972E+03 0.1095981E+03 0.1089033E+03 + 0.1082130E+03 0.1075270E+03 0.1068454E+03 0.1061681E+03 0.1054951E+03 + 0.1048264E+03 0.1041619E+03 0.1035016E+03 0.1028455E+03 0.1021936E+03 + 0.1015458E+03 0.1009021E+03 0.1002625E+03 0.9962691E+02 0.9899539E+02 + 0.9836786E+02 0.9774430E+02 0.9712471E+02 0.9650903E+02 0.9589726E+02 + 0.9528938E+02 0.9468534E+02 0.9408513E+02 0.9348873E+02 0.9289610E+02 + 0.9230724E+02 0.9172211E+02 0.9114068E+02 0.9056294E+02 0.8998887E+02 + 0.8941843E+02 0.8885161E+02 0.8828838E+02 0.8772872E+02 0.8717261E+02 + 0.8662003E+02 0.8607094E+02 0.8552534E+02 0.8498320E+02 0.8444449E+02 + 0.2195538E+03 0.2181705E+03 0.2167950E+03 0.2154272E+03 0.2140672E+03 + 0.2127152E+03 0.2113710E+03 0.2100349E+03 0.2087067E+03 0.2073865E+03 + 0.2060743E+03 0.2047701E+03 0.2034738E+03 0.2021856E+03 0.2009053E+03 + 0.1996329E+03 0.1983683E+03 0.1971118E+03 0.1958630E+03 0.1946220E+03 + 0.1933888E+03 0.1921634E+03 0.1909456E+03 0.1897355E+03 0.1885331E+03 + 0.1873382E+03 0.1861509E+03 0.1849710E+03 0.1837986E+03 0.1826336E+03 + 0.1814760E+03 0.1803257E+03 0.1791827E+03 0.1780469E+03 0.1769183E+03 + 0.1757969E+03 0.1746825E+03 0.1735753E+03 0.1724750E+03 0.1713817E+03 + 0.1702953E+03 0.1692158E+03 0.1681432E+03 0.1670773E+03 0.1660182E+03 + 0.1649659E+03 0.1639202E+03 0.1628811E+03 0.1618486E+03 0.1608226E+03 + 0.1598031E+03 0.1587902E+03 0.1577836E+03 0.1567834E+03 0.1557896E+03 + 0.1548020E+03 0.1538207E+03 0.1528457E+03 0.1518768E+03 0.1509140E+03 + 0.1499574E+03 0.1490068E+03 0.1480623E+03 0.1471237E+03 0.1461911E+03 + 0.1452644E+03 0.1443436E+03 0.1434286E+03 0.1425194E+03 0.1416160E+03 + 0.1407183E+03 0.1398262E+03 0.1389399E+03 0.1380592E+03 0.1371840E+03 + 0.1363144E+03 0.1354503E+03 0.1345917E+03 0.1337385E+03 0.1328907E+03 + 0.1320484E+03 0.1312113E+03 0.1303796E+03 0.1295531E+03 0.1287319E+03 + 0.1279158E+03 0.1271050E+03 0.1262993E+03 0.1254986E+03 0.1247031E+03 + 0.1239126E+03 0.1231272E+03 0.1223466E+03 0.1215711E+03 0.1208005E+03 + 0.1200347E+03 0.1192738E+03 0.1185177E+03 0.1177664E+03 0.1170199E+03 + 0.1162782E+03 0.1155411E+03 0.1148086E+03 0.1140809E+03 0.1133577E+03 + 0.1126392E+03 0.1119251E+03 0.1112157E+03 0.1105107E+03 0.1098101E+03 + 0.1091141E+03 0.1084224E+03 0.1077351E+03 0.1070522E+03 0.1063736E+03 + 0.1056993E+03 0.1050292E+03 0.1043634E+03 0.1037019E+03 0.1030445E+03 + 0.1023913E+03 0.1017423E+03 0.1010973E+03 0.1004565E+03 0.9981970E+02 + 0.9918694E+02 0.9855819E+02 0.9793344E+02 0.9731264E+02 0.9669577E+02 + 0.9608283E+02 0.9547376E+02 0.9486855E+02 0.9426719E+02 0.9366962E+02 + 0.9307585E+02 0.9248586E+02 0.9189958E+02 0.9131704E+02 0.9073818E+02 + 0.9016299E+02 0.8959145E+02 0.8902354E+02 0.8845921E+02 0.8789847E+02 + 0.8734129E+02 0.8678763E+02 0.8623748E+02 0.8569083E+02 0.8514764E+02 + 0.2213667E+03 0.2199737E+03 0.2185884E+03 0.2172107E+03 0.2158407E+03 + 0.2144786E+03 0.2131243E+03 0.2117778E+03 0.2104394E+03 0.2091089E+03 + 0.2077863E+03 0.2064718E+03 0.2051652E+03 0.2038666E+03 0.2025760E+03 + 0.2012933E+03 0.2000185E+03 0.1987517E+03 0.1974927E+03 0.1962415E+03 + 0.1949982E+03 0.1937627E+03 0.1925349E+03 0.1913148E+03 0.1901024E+03 + 0.1888977E+03 0.1877005E+03 0.1865108E+03 0.1853288E+03 0.1841541E+03 + 0.1829869E+03 0.1818270E+03 0.1806745E+03 0.1795293E+03 0.1783913E+03 + 0.1772605E+03 0.1761369E+03 0.1750204E+03 0.1739110E+03 0.1728086E+03 + 0.1717132E+03 0.1706247E+03 0.1695432E+03 0.1684684E+03 0.1674005E+03 + 0.1663394E+03 0.1652850E+03 0.1642372E+03 0.1631962E+03 0.1621617E+03 + 0.1611337E+03 0.1601123E+03 0.1590973E+03 0.1580888E+03 0.1570867E+03 + 0.1560910E+03 0.1551015E+03 0.1541183E+03 0.1531414E+03 0.1521706E+03 + 0.1512060E+03 0.1502475E+03 0.1492951E+03 0.1483487E+03 0.1474083E+03 + 0.1464739E+03 0.1455454E+03 0.1446228E+03 0.1437060E+03 0.1427951E+03 + 0.1418899E+03 0.1409905E+03 0.1400968E+03 0.1392087E+03 0.1383262E+03 + 0.1374494E+03 0.1365781E+03 0.1357123E+03 0.1348521E+03 0.1339972E+03 + 0.1331478E+03 0.1323038E+03 0.1314651E+03 0.1306318E+03 0.1298037E+03 + 0.1289809E+03 0.1281633E+03 0.1273509E+03 0.1265436E+03 0.1257414E+03 + 0.1249444E+03 0.1241524E+03 0.1233653E+03 0.1225833E+03 0.1218063E+03 + 0.1210341E+03 0.1202669E+03 0.1195045E+03 0.1187470E+03 0.1179943E+03 + 0.1172463E+03 0.1165031E+03 0.1157646E+03 0.1150308E+03 0.1143016E+03 + 0.1135770E+03 0.1128571E+03 0.1121417E+03 0.1114308E+03 0.1107244E+03 + 0.1100226E+03 0.1093251E+03 0.1086321E+03 0.1079435E+03 0.1072592E+03 + 0.1065793E+03 0.1059037E+03 0.1052324E+03 0.1045653E+03 0.1039025E+03 + 0.1032439E+03 0.1025894E+03 0.1019391E+03 0.1012929E+03 0.1006508E+03 + 0.1000128E+03 0.9937881E+02 0.9874886E+02 0.9812289E+02 0.9750088E+02 + 0.9688284E+02 0.9626869E+02 0.9565844E+02 0.9505207E+02 0.9444953E+02 + 0.9385081E+02 0.9325591E+02 0.9266476E+02 0.9207736E+02 0.9149368E+02 + 0.9091370E+02 0.9033741E+02 0.8976476E+02 0.8919574E+02 0.8863033E+02 + 0.8806851E+02 0.8751024E+02 0.8695551E+02 0.8640431E+02 0.8585659E+02 + 0.2231913E+03 0.2217890E+03 0.2203941E+03 0.2190067E+03 0.2176269E+03 + 0.2162548E+03 0.2148905E+03 0.2135339E+03 0.2121853E+03 0.2108445E+03 + 0.2095117E+03 0.2081869E+03 0.2068700E+03 0.2055610E+03 0.2042601E+03 + 0.2029671E+03 0.2016820E+03 0.2004049E+03 0.1991356E+03 0.1978743E+03 + 0.1966208E+03 0.1953751E+03 0.1941373E+03 0.1929071E+03 0.1916847E+03 + 0.1904700E+03 0.1892629E+03 0.1880635E+03 0.1868716E+03 0.1856872E+03 + 0.1845103E+03 0.1833408E+03 0.1821787E+03 0.1810240E+03 0.1798766E+03 + 0.1787364E+03 0.1776034E+03 0.1764777E+03 0.1753590E+03 0.1742474E+03 + 0.1731429E+03 0.1720454E+03 0.1709548E+03 0.1698711E+03 0.1687943E+03 + 0.1677244E+03 0.1666612E+03 0.1656047E+03 0.1645550E+03 0.1635118E+03 + 0.1624753E+03 0.1614454E+03 0.1604220E+03 0.1594051E+03 0.1583947E+03 + 0.1573906E+03 0.1563929E+03 0.1554015E+03 0.1544164E+03 0.1534376E+03 + 0.1524650E+03 0.1514985E+03 0.1505381E+03 0.1495839E+03 0.1486357E+03 + 0.1476935E+03 0.1467572E+03 0.1458270E+03 0.1449026E+03 0.1439840E+03 + 0.1430713E+03 0.1421644E+03 0.1412632E+03 0.1403678E+03 0.1394780E+03 + 0.1385938E+03 0.1377153E+03 0.1368423E+03 0.1359749E+03 0.1351129E+03 + 0.1342564E+03 0.1334054E+03 0.1325597E+03 0.1317194E+03 0.1308845E+03 + 0.1300548E+03 0.1292304E+03 0.1284112E+03 0.1275972E+03 0.1267884E+03 + 0.1259847E+03 0.1251861E+03 0.1243925E+03 0.1236040E+03 0.1228205E+03 + 0.1220419E+03 0.1212683E+03 0.1204996E+03 0.1197357E+03 0.1189767E+03 + 0.1182225E+03 0.1174731E+03 0.1167284E+03 0.1159885E+03 0.1152533E+03 + 0.1145227E+03 0.1137967E+03 0.1130754E+03 0.1123586E+03 0.1116463E+03 + 0.1109386E+03 0.1102354E+03 0.1095366E+03 0.1088423E+03 0.1081523E+03 + 0.1074667E+03 0.1067855E+03 0.1061086E+03 0.1054360E+03 0.1047676E+03 + 0.1041035E+03 0.1034436E+03 0.1027879E+03 0.1021363E+03 0.1014889E+03 + 0.1008455E+03 0.1002063E+03 0.9957105E+02 0.9893987E+02 0.9831269E+02 + 0.9768951E+02 0.9707024E+02 0.9645491E+02 0.9584350E+02 0.9523594E+02 + 0.9463224E+02 0.9403238E+02 0.9343630E+02 0.9284402E+02 0.9225548E+02 + 0.9167067E+02 0.9108958E+02 0.9051216E+02 0.8993841E+02 0.8936829E+02 + 0.8880179E+02 0.8823887E+02 0.8767953E+02 0.8712373E+02 0.8657145E+02 + 0.2250271E+03 0.2236158E+03 0.2222117E+03 0.2208149E+03 0.2194255E+03 + 0.2180437E+03 0.2166694E+03 0.2153029E+03 0.2139442E+03 0.2125933E+03 + 0.2112503E+03 0.2099152E+03 0.2085880E+03 0.2072688E+03 0.2059575E+03 + 0.2046542E+03 0.2033588E+03 0.2020714E+03 0.2007919E+03 0.1995203E+03 + 0.1982566E+03 0.1970007E+03 0.1957528E+03 0.1945125E+03 0.1932801E+03 + 0.1920553E+03 0.1908383E+03 0.1896289E+03 0.1884272E+03 0.1872330E+03 + 0.1860463E+03 0.1848671E+03 0.1836954E+03 0.1825311E+03 0.1813741E+03 + 0.1802244E+03 0.1790821E+03 0.1779470E+03 0.1768190E+03 0.1756982E+03 + 0.1745845E+03 0.1734778E+03 0.1723782E+03 0.1712855E+03 0.1701997E+03 + 0.1691209E+03 0.1680488E+03 0.1669835E+03 0.1659250E+03 0.1648733E+03 + 0.1638281E+03 0.1627896E+03 0.1617577E+03 0.1607323E+03 0.1597135E+03 + 0.1587010E+03 0.1576950E+03 0.1566954E+03 0.1557021E+03 0.1547151E+03 + 0.1537344E+03 0.1527599E+03 0.1517915E+03 0.1508293E+03 0.1498732E+03 + 0.1489232E+03 0.1479792E+03 0.1470411E+03 0.1461090E+03 0.1451829E+03 + 0.1442625E+03 0.1433481E+03 0.1424394E+03 0.1415365E+03 0.1406393E+03 + 0.1397478E+03 0.1388619E+03 0.1379817E+03 0.1371070E+03 0.1362379E+03 + 0.1353743E+03 0.1345161E+03 0.1336635E+03 0.1328161E+03 0.1319743E+03 + 0.1311376E+03 0.1303064E+03 0.1294804E+03 0.1286596E+03 0.1278440E+03 + 0.1270336E+03 0.1262284E+03 0.1254282E+03 0.1246331E+03 0.1238431E+03 + 0.1230580E+03 0.1222780E+03 0.1215029E+03 0.1207326E+03 0.1199673E+03 + 0.1192069E+03 0.1184512E+03 0.1177003E+03 0.1169543E+03 0.1162129E+03 + 0.1154762E+03 0.1147442E+03 0.1140168E+03 0.1132941E+03 0.1125759E+03 + 0.1118623E+03 0.1111532E+03 0.1104486E+03 0.1097485E+03 0.1090528E+03 + 0.1083615E+03 0.1076746E+03 0.1069921E+03 0.1063139E+03 0.1056399E+03 + 0.1049703E+03 0.1043049E+03 0.1036437E+03 0.1029867E+03 0.1023339E+03 + 0.1016852E+03 0.1010406E+03 0.1004001E+03 0.9976366E+02 0.9913126E+02 + 0.9850288E+02 0.9787846E+02 0.9725801E+02 0.9664150E+02 0.9602888E+02 + 0.9542016E+02 0.9481530E+02 0.9421426E+02 0.9361704E+02 0.9302361E+02 + 0.9243394E+02 0.9184800E+02 0.9126578E+02 0.9068724E+02 0.9011238E+02 + 0.8954116E+02 0.8897356E+02 0.8840955E+02 0.8784913E+02 0.8729225E+02 + 0.2268734E+03 0.2254536E+03 0.2240407E+03 0.2226348E+03 0.2212361E+03 + 0.2198448E+03 0.2184609E+03 0.2170846E+03 0.2157160E+03 0.2143551E+03 + 0.2130020E+03 0.2116567E+03 0.2103193E+03 0.2089899E+03 0.2076683E+03 + 0.2063547E+03 0.2050490E+03 0.2037513E+03 0.2024615E+03 0.2011796E+03 + 0.1999057E+03 0.1986396E+03 0.1973814E+03 0.1961311E+03 0.1948885E+03 + 0.1936537E+03 0.1924266E+03 0.1912073E+03 0.1899956E+03 0.1887915E+03 + 0.1875950E+03 0.1864061E+03 0.1852247E+03 0.1840507E+03 0.1828841E+03 + 0.1817249E+03 0.1805731E+03 0.1794285E+03 0.1782912E+03 0.1771610E+03 + 0.1760381E+03 0.1749222E+03 0.1738134E+03 0.1727116E+03 0.1716168E+03 + 0.1705290E+03 0.1694480E+03 0.1683739E+03 0.1673066E+03 0.1662460E+03 + 0.1651922E+03 0.1641451E+03 0.1631046E+03 0.1620706E+03 0.1610433E+03 + 0.1600224E+03 0.1590080E+03 0.1580001E+03 0.1569986E+03 0.1560033E+03 + 0.1550144E+03 0.1540318E+03 0.1530554E+03 0.1520852E+03 0.1511211E+03 + 0.1501632E+03 0.1492113E+03 0.1482654E+03 0.1473256E+03 0.1463917E+03 + 0.1454637E+03 0.1445416E+03 0.1436254E+03 0.1427149E+03 0.1418103E+03 + 0.1409113E+03 0.1400181E+03 0.1391305E+03 0.1382486E+03 0.1373722E+03 + 0.1365014E+03 0.1356362E+03 0.1347764E+03 0.1339220E+03 0.1330731E+03 + 0.1322295E+03 0.1313913E+03 0.1305585E+03 0.1297308E+03 0.1289085E+03 + 0.1280914E+03 0.1272794E+03 0.1264725E+03 0.1256708E+03 0.1248742E+03 + 0.1240826E+03 0.1232961E+03 0.1225145E+03 0.1217379E+03 0.1209662E+03 + 0.1201994E+03 0.1194375E+03 0.1186804E+03 0.1179281E+03 0.1171805E+03 + 0.1164377E+03 0.1156996E+03 0.1149662E+03 0.1142374E+03 0.1135133E+03 + 0.1127937E+03 0.1120787E+03 0.1113682E+03 0.1106623E+03 0.1099608E+03 + 0.1092638E+03 0.1085711E+03 0.1078829E+03 0.1071991E+03 0.1065195E+03 + 0.1058443E+03 0.1051733E+03 0.1045066E+03 0.1038442E+03 0.1031859E+03 + 0.1025318E+03 0.1018819E+03 0.1012361E+03 0.1005943E+03 0.9995665E+02 + 0.9932304E+02 0.9869343E+02 0.9806780E+02 0.9744617E+02 0.9682845E+02 + 0.9621465E+02 0.9560476E+02 0.9499872E+02 0.9439652E+02 0.9379815E+02 + 0.9320356E+02 0.9261275E+02 0.9202568E+02 0.9144233E+02 0.9086268E+02 + 0.9028671E+02 0.8971437E+02 0.8914568E+02 0.8858059E+02 0.8801907E+02 + 0.2287293E+03 0.2273016E+03 0.2258803E+03 0.2244658E+03 0.2230582E+03 + 0.2216577E+03 0.2202645E+03 0.2188786E+03 0.2175004E+03 0.2161296E+03 + 0.2147665E+03 0.2134112E+03 0.2120637E+03 0.2107241E+03 0.2093923E+03 + 0.2080685E+03 0.2067525E+03 0.2054445E+03 0.2041444E+03 0.2028523E+03 + 0.2015681E+03 0.2002918E+03 0.1990234E+03 0.1977628E+03 0.1965101E+03 + 0.1952652E+03 0.1940280E+03 0.1927986E+03 0.1915770E+03 0.1903630E+03 + 0.1891566E+03 0.1879578E+03 0.1867666E+03 0.1855829E+03 0.1844067E+03 + 0.1832378E+03 0.1820764E+03 0.1809223E+03 0.1797756E+03 0.1786360E+03 + 0.1775037E+03 0.1763786E+03 0.1752606E+03 0.1741496E+03 0.1730457E+03 + 0.1719488E+03 0.1708588E+03 0.1697758E+03 0.1686996E+03 0.1676302E+03 + 0.1665676E+03 0.1655117E+03 0.1644626E+03 0.1634201E+03 0.1623842E+03 + 0.1613548E+03 0.1603320E+03 0.1593156E+03 0.1583057E+03 0.1573022E+03 + 0.1563051E+03 0.1553143E+03 0.1543298E+03 0.1533515E+03 0.1523794E+03 + 0.1514134E+03 0.1504536E+03 0.1494999E+03 0.1485522E+03 0.1476106E+03 + 0.1466749E+03 0.1457451E+03 0.1448212E+03 0.1439032E+03 0.1429910E+03 + 0.1420846E+03 0.1411839E+03 0.1402890E+03 0.1393997E+03 0.1385160E+03 + 0.1376380E+03 0.1367655E+03 0.1358985E+03 0.1350371E+03 0.1341811E+03 + 0.1333305E+03 0.1324853E+03 0.1316455E+03 0.1308110E+03 0.1299818E+03 + 0.1291579E+03 0.1283391E+03 0.1275256E+03 0.1267172E+03 0.1259140E+03 + 0.1251158E+03 0.1243227E+03 0.1235346E+03 0.1227515E+03 0.1219734E+03 + 0.1212002E+03 0.1204319E+03 0.1196685E+03 0.1189099E+03 0.1181562E+03 + 0.1174072E+03 0.1166629E+03 0.1159234E+03 0.1151886E+03 0.1144584E+03 + 0.1137328E+03 0.1130119E+03 0.1122955E+03 0.1115837E+03 0.1108764E+03 + 0.1101735E+03 0.1094751E+03 0.1087812E+03 0.1080916E+03 0.1074064E+03 + 0.1067256E+03 0.1060490E+03 0.1053768E+03 0.1047088E+03 0.1040451E+03 + 0.1033855E+03 0.1027302E+03 0.1020790E+03 0.1014319E+03 0.1007889E+03 + 0.1001500E+03 0.9951516E+02 0.9888433E+02 0.9825751E+02 0.9763466E+02 + 0.9701575E+02 0.9640078E+02 0.9578969E+02 0.9518249E+02 0.9457912E+02 + 0.9397959E+02 0.9338386E+02 0.9279190E+02 0.9220369E+02 0.9161922E+02 + 0.9103844E+02 0.9046135E+02 0.8988792E+02 0.8931812E+02 0.8875193E+02 + 0.2305941E+03 0.2291589E+03 0.2277299E+03 0.2263072E+03 0.2248912E+03 + 0.2234819E+03 0.2220797E+03 0.2206846E+03 0.2192969E+03 0.2179165E+03 + 0.2165437E+03 0.2151785E+03 0.2138211E+03 0.2124713E+03 0.2111295E+03 + 0.2097954E+03 0.2084693E+03 0.2071510E+03 0.2058407E+03 0.2045383E+03 + 0.2032438E+03 0.2019572E+03 0.2006786E+03 0.1994078E+03 0.1981449E+03 + 0.1968898E+03 0.1956426E+03 0.1944031E+03 0.1931714E+03 0.1919473E+03 + 0.1907310E+03 0.1895223E+03 0.1883213E+03 0.1871278E+03 0.1859418E+03 + 0.1847633E+03 0.1835922E+03 0.1824286E+03 0.1812723E+03 0.1801233E+03 + 0.1789816E+03 0.1778470E+03 0.1767197E+03 0.1755995E+03 0.1744865E+03 + 0.1733804E+03 0.1722814E+03 0.1711893E+03 0.1701042E+03 0.1690259E+03 + 0.1679545E+03 0.1668898E+03 0.1658319E+03 0.1647807E+03 0.1637362E+03 + 0.1626983E+03 0.1616669E+03 0.1606421E+03 0.1596238E+03 0.1586119E+03 + 0.1576065E+03 0.1566075E+03 0.1556147E+03 0.1546283E+03 0.1536481E+03 + 0.1526741E+03 0.1517063E+03 0.1507447E+03 0.1497891E+03 0.1488396E+03 + 0.1478961E+03 0.1469586E+03 0.1460271E+03 0.1451014E+03 0.1441816E+03 + 0.1432676E+03 0.1423595E+03 0.1414570E+03 0.1405603E+03 0.1396693E+03 + 0.1387840E+03 0.1379042E+03 0.1370301E+03 0.1361614E+03 0.1352983E+03 + 0.1344406E+03 0.1335884E+03 0.1327416E+03 0.1319002E+03 0.1310640E+03 + 0.1302332E+03 0.1294077E+03 0.1285874E+03 0.1277723E+03 0.1269623E+03 + 0.1261575E+03 0.1253578E+03 0.1245632E+03 0.1237735E+03 0.1229890E+03 + 0.1222094E+03 0.1214347E+03 0.1206649E+03 0.1199000E+03 0.1191400E+03 + 0.1183847E+03 0.1176343E+03 0.1168886E+03 0.1161477E+03 0.1154114E+03 + 0.1146798E+03 0.1139529E+03 0.1132305E+03 0.1125127E+03 0.1117995E+03 + 0.1110908E+03 0.1103866E+03 0.1096869E+03 0.1089916E+03 0.1083007E+03 + 0.1076142E+03 0.1069320E+03 0.1062542E+03 0.1055806E+03 0.1049114E+03 + 0.1042463E+03 0.1035855E+03 0.1029289E+03 0.1022764E+03 0.1016281E+03 + 0.1009839E+03 0.1003437E+03 0.9970766E+02 0.9907562E+02 0.9844758E+02 + 0.9782352E+02 0.9720343E+02 0.9658725E+02 0.9597499E+02 0.9536661E+02 + 0.9476208E+02 0.9416138E+02 0.9356451E+02 0.9297140E+02 0.9238205E+02 + 0.9179645E+02 0.9121455E+02 0.9063634E+02 0.9006180E+02 0.8949090E+02 + 0.2324663E+03 0.2310246E+03 0.2295885E+03 0.2281583E+03 0.2267343E+03 + 0.2253168E+03 0.2239060E+03 0.2225020E+03 0.2211052E+03 0.2197155E+03 + 0.2183332E+03 0.2169584E+03 0.2155911E+03 0.2142315E+03 0.2128796E+03 + 0.2115355E+03 0.2101992E+03 0.2088708E+03 0.2075502E+03 0.2062375E+03 + 0.2049328E+03 0.2036360E+03 0.2023471E+03 0.2010661E+03 0.1997929E+03 + 0.1985277E+03 0.1972702E+03 0.1960206E+03 0.1947788E+03 0.1935448E+03 + 0.1923184E+03 0.1910998E+03 0.1898888E+03 0.1886854E+03 0.1874897E+03 + 0.1863014E+03 0.1851206E+03 0.1839473E+03 0.1827814E+03 0.1816229E+03 + 0.1804717E+03 0.1793278E+03 0.1781911E+03 0.1770616E+03 0.1759392E+03 + 0.1748240E+03 0.1737158E+03 0.1726147E+03 0.1715205E+03 0.1704332E+03 + 0.1693529E+03 0.1682794E+03 0.1672126E+03 0.1661527E+03 0.1650995E+03 + 0.1640529E+03 0.1630130E+03 0.1619797E+03 0.1609529E+03 0.1599326E+03 + 0.1589188E+03 0.1579114E+03 0.1569104E+03 0.1559158E+03 0.1549274E+03 + 0.1539453E+03 0.1529695E+03 0.1519998E+03 0.1510363E+03 0.1500789E+03 + 0.1491275E+03 0.1481822E+03 0.1472429E+03 0.1463095E+03 0.1453820E+03 + 0.1444605E+03 0.1435448E+03 0.1426348E+03 0.1417307E+03 0.1408322E+03 + 0.1399395E+03 0.1390524E+03 0.1381710E+03 0.1372951E+03 0.1364248E+03 + 0.1355600E+03 0.1347007E+03 0.1338468E+03 0.1329984E+03 0.1321553E+03 + 0.1313176E+03 0.1304852E+03 0.1296580E+03 0.1288361E+03 0.1280195E+03 + 0.1272079E+03 0.1264016E+03 0.1256003E+03 0.1248041E+03 0.1240130E+03 + 0.1232269E+03 0.1224457E+03 0.1216696E+03 0.1208983E+03 0.1201319E+03 + 0.1193704E+03 0.1186137E+03 0.1178618E+03 0.1171147E+03 0.1163723E+03 + 0.1156347E+03 0.1149016E+03 0.1141733E+03 0.1134495E+03 0.1127304E+03 + 0.1120158E+03 0.1113057E+03 0.1106002E+03 0.1098991E+03 0.1092024E+03 + 0.1085102E+03 0.1078224E+03 0.1071389E+03 0.1064597E+03 0.1057849E+03 + 0.1051143E+03 0.1044480E+03 0.1037859E+03 0.1031280E+03 0.1024743E+03 + 0.1018247E+03 0.1011792E+03 0.1005378E+03 0.9990055E+02 0.9926728E+02 + 0.9863802E+02 0.9801276E+02 0.9739146E+02 0.9677410E+02 0.9616065E+02 + 0.9555109E+02 0.9494540E+02 0.9434354E+02 0.9374550E+02 0.9315125E+02 + 0.9256077E+02 0.9197402E+02 0.9139100E+02 0.9081168E+02 0.9023602E+02 + 0.2343449E+03 0.2328973E+03 0.2314549E+03 0.2300179E+03 0.2285866E+03 + 0.2271615E+03 0.2257426E+03 0.2243302E+03 0.2229247E+03 0.2215261E+03 + 0.2201346E+03 0.2187504E+03 0.2173735E+03 0.2160042E+03 0.2146425E+03 + 0.2132884E+03 0.2119421E+03 0.2106036E+03 0.2092729E+03 0.2079500E+03 + 0.2066351E+03 0.2053280E+03 0.2040289E+03 0.2027376E+03 0.2014542E+03 + 0.2001788E+03 0.1989111E+03 0.1976514E+03 0.1963994E+03 0.1951553E+03 + 0.1939189E+03 0.1926902E+03 0.1914692E+03 0.1902560E+03 0.1890503E+03 + 0.1878522E+03 0.1866617E+03 0.1854787E+03 0.1843031E+03 0.1831349E+03 + 0.1819742E+03 0.1808207E+03 0.1796746E+03 0.1785357E+03 0.1774041E+03 + 0.1762796E+03 0.1751622E+03 0.1740518E+03 0.1729486E+03 0.1718523E+03 + 0.1707629E+03 0.1696805E+03 0.1686049E+03 0.1675361E+03 0.1664741E+03 + 0.1654189E+03 0.1643703E+03 0.1633283E+03 0.1622930E+03 0.1612642E+03 + 0.1602420E+03 0.1592262E+03 0.1582169E+03 0.1572140E+03 0.1562174E+03 + 0.1552271E+03 0.1542431E+03 0.1532654E+03 0.1522938E+03 0.1513285E+03 + 0.1503692E+03 0.1494160E+03 0.1484689E+03 0.1475277E+03 0.1465925E+03 + 0.1456633E+03 0.1447399E+03 0.1438224E+03 0.1429108E+03 0.1420048E+03 + 0.1411047E+03 0.1402102E+03 0.1393214E+03 0.1384383E+03 0.1375607E+03 + 0.1366887E+03 0.1358223E+03 0.1349613E+03 0.1341058E+03 0.1332557E+03 + 0.1324110E+03 0.1315716E+03 0.1307376E+03 0.1299088E+03 0.1290854E+03 + 0.1282671E+03 0.1274540E+03 0.1266461E+03 0.1258433E+03 0.1250456E+03 + 0.1242529E+03 0.1234653E+03 0.1226826E+03 0.1219049E+03 0.1211322E+03 + 0.1203643E+03 0.1196013E+03 0.1188432E+03 0.1180899E+03 0.1173413E+03 + 0.1165975E+03 0.1158583E+03 0.1151239E+03 0.1143941E+03 0.1136690E+03 + 0.1129485E+03 0.1122325E+03 0.1115210E+03 0.1108141E+03 0.1101117E+03 + 0.1094137E+03 0.1087201E+03 0.1080309E+03 0.1073461E+03 0.1066657E+03 + 0.1059895E+03 0.1053176E+03 0.1046500E+03 0.1039867E+03 0.1033275E+03 + 0.1026725E+03 0.1020217E+03 0.1013749E+03 0.1007323E+03 0.1000938E+03 + 0.9945930E+02 0.9882884E+02 0.9820236E+02 0.9757986E+02 0.9696130E+02 + 0.9634667E+02 0.9573593E+02 0.9512907E+02 0.9452604E+02 0.9392684E+02 + 0.9333144E+02 0.9273981E+02 0.9215194E+02 0.9156779E+02 0.9098734E+02 + 0.2362281E+03 0.2347758E+03 0.2333280E+03 0.2318850E+03 0.2304472E+03 + 0.2290150E+03 0.2275886E+03 0.2261685E+03 0.2247547E+03 0.2233476E+03 + 0.2219473E+03 0.2205540E+03 0.2191679E+03 0.2177891E+03 0.2164178E+03 + 0.2150540E+03 0.2136978E+03 0.2123493E+03 0.2110085E+03 0.2096756E+03 + 0.2083505E+03 0.2070332E+03 0.2057239E+03 0.2044224E+03 0.2031288E+03 + 0.2018431E+03 0.2005653E+03 0.1992953E+03 0.1980332E+03 0.1967789E+03 + 0.1955324E+03 0.1942937E+03 0.1930627E+03 0.1918394E+03 0.1906238E+03 + 0.1894158E+03 0.1882155E+03 0.1870227E+03 0.1858374E+03 0.1846595E+03 + 0.1834891E+03 0.1823261E+03 0.1811705E+03 0.1800222E+03 0.1788811E+03 + 0.1777472E+03 0.1766205E+03 0.1755010E+03 0.1743885E+03 0.1732831E+03 + 0.1721847E+03 0.1710932E+03 0.1700087E+03 0.1689310E+03 0.1678602E+03 + 0.1667961E+03 0.1657388E+03 0.1646882E+03 0.1636443E+03 0.1626069E+03 + 0.1615762E+03 0.1605520E+03 0.1595342E+03 0.1585229E+03 0.1575181E+03 + 0.1565196E+03 0.1555274E+03 0.1545415E+03 0.1535619E+03 0.1525885E+03 + 0.1516212E+03 0.1506601E+03 0.1497051E+03 0.1487561E+03 0.1478131E+03 + 0.1468761E+03 0.1459451E+03 0.1450199E+03 0.1441007E+03 0.1431872E+03 + 0.1422795E+03 0.1413777E+03 0.1404815E+03 0.1395909E+03 0.1387061E+03 + 0.1378268E+03 0.1369531E+03 0.1360850E+03 0.1352224E+03 0.1343652E+03 + 0.1335135E+03 0.1326671E+03 0.1318261E+03 0.1309905E+03 0.1301602E+03 + 0.1293351E+03 0.1285152E+03 0.1277006E+03 0.1268911E+03 0.1260867E+03 + 0.1252875E+03 0.1244932E+03 0.1237041E+03 0.1229200E+03 0.1221408E+03 + 0.1213665E+03 0.1205972E+03 0.1198327E+03 0.1190731E+03 0.1183183E+03 + 0.1175683E+03 0.1168230E+03 0.1160825E+03 0.1153466E+03 0.1146154E+03 + 0.1138889E+03 0.1131670E+03 0.1124496E+03 0.1117368E+03 0.1110285E+03 + 0.1103247E+03 0.1096253E+03 0.1089304E+03 0.1082399E+03 0.1075538E+03 + 0.1068720E+03 0.1061945E+03 0.1055214E+03 0.1048525E+03 0.1041878E+03 + 0.1035274E+03 0.1028711E+03 0.1022190E+03 0.1015711E+03 0.1009272E+03 + 0.1002874E+03 0.9965171E+02 0.9902001E+02 0.9839233E+02 0.9776862E+02 + 0.9714887E+02 0.9653305E+02 0.9592113E+02 0.9531309E+02 0.9470889E+02 + 0.9410854E+02 0.9351199E+02 0.9291921E+02 0.9233021E+02 0.9174492E+02 + 0.2381144E+03 0.2366584E+03 0.2352062E+03 0.2337581E+03 0.2323147E+03 + 0.2308763E+03 0.2294432E+03 0.2280158E+03 0.2265945E+03 0.2251793E+03 + 0.2237707E+03 0.2223688E+03 0.2209738E+03 0.2195859E+03 0.2182052E+03 + 0.2168319E+03 0.2154660E+03 0.2141077E+03 0.2127571E+03 0.2114141E+03 + 0.2100790E+03 0.2087516E+03 0.2074321E+03 0.2061204E+03 0.2048166E+03 + 0.2035207E+03 0.2022326E+03 0.2009524E+03 0.1996802E+03 0.1984157E+03 + 0.1971591E+03 0.1959102E+03 0.1946692E+03 0.1934359E+03 0.1922103E+03 + 0.1909924E+03 0.1897820E+03 0.1885794E+03 0.1873843E+03 0.1861967E+03 + 0.1850166E+03 0.1838440E+03 0.1826788E+03 0.1815209E+03 0.1803703E+03 + 0.1792271E+03 0.1780910E+03 0.1769622E+03 0.1758405E+03 0.1747259E+03 + 0.1736183E+03 0.1725178E+03 0.1714242E+03 0.1703376E+03 0.1692578E+03 + 0.1681849E+03 0.1671188E+03 0.1660594E+03 0.1650068E+03 0.1639608E+03 + 0.1629215E+03 0.1618887E+03 0.1608625E+03 0.1598428E+03 0.1588296E+03 + 0.1578228E+03 0.1568223E+03 0.1558282E+03 0.1548405E+03 0.1538589E+03 + 0.1528836E+03 0.1519145E+03 0.1509515E+03 0.1499946E+03 0.1490438E+03 + 0.1480990E+03 0.1471602E+03 0.1462274E+03 0.1453005E+03 0.1443794E+03 + 0.1434642E+03 0.1425548E+03 0.1416511E+03 0.1407532E+03 0.1398610E+03 + 0.1389744E+03 0.1380934E+03 0.1372181E+03 0.1363482E+03 0.1354839E+03 + 0.1346251E+03 0.1337717E+03 0.1329237E+03 0.1320811E+03 0.1312439E+03 + 0.1304119E+03 0.1295853E+03 0.1287638E+03 0.1279476E+03 0.1271365E+03 + 0.1263306E+03 0.1255298E+03 0.1247341E+03 0.1239434E+03 0.1231577E+03 + 0.1223770E+03 0.1216013E+03 0.1208305E+03 0.1200645E+03 0.1193034E+03 + 0.1185472E+03 0.1177957E+03 0.1170490E+03 0.1163070E+03 0.1155697E+03 + 0.1148372E+03 0.1141092E+03 0.1133859E+03 0.1126671E+03 0.1119529E+03 + 0.1112433E+03 0.1105381E+03 0.1098374E+03 0.1091411E+03 0.1084493E+03 + 0.1077618E+03 0.1070787E+03 0.1064000E+03 0.1057255E+03 0.1050553E+03 + 0.1043894E+03 0.1037276E+03 0.1030701E+03 0.1024168E+03 0.1017675E+03 + 0.1011224E+03 0.1004814E+03 0.9984447E+02 0.9921156E+02 0.9858266E+02 + 0.9795775E+02 0.9733680E+02 0.9671979E+02 0.9610667E+02 0.9549746E+02 + 0.9489211E+02 0.9429058E+02 0.9369287E+02 0.9309896E+02 0.9250880E+02 + 0.2400018E+03 0.2385434E+03 0.2370879E+03 0.2356359E+03 0.2341878E+03 + 0.2327440E+03 0.2313051E+03 0.2298713E+03 0.2284430E+03 0.2270205E+03 + 0.2256040E+03 0.2241940E+03 0.2227906E+03 0.2213939E+03 0.2200042E+03 + 0.2186217E+03 0.2172464E+03 0.2158786E+03 0.2145182E+03 0.2131654E+03 + 0.2118203E+03 0.2104829E+03 0.2091533E+03 0.2078315E+03 0.2065176E+03 + 0.2052115E+03 0.2039132E+03 0.2026228E+03 0.2013404E+03 0.2000657E+03 + 0.1987989E+03 0.1975399E+03 0.1962888E+03 0.1950454E+03 0.1938098E+03 + 0.1925818E+03 0.1913616E+03 0.1901490E+03 0.1889440E+03 0.1877466E+03 + 0.1865568E+03 0.1853745E+03 0.1841996E+03 0.1830321E+03 0.1818720E+03 + 0.1807192E+03 0.1795737E+03 0.1784355E+03 0.1773045E+03 0.1761806E+03 + 0.1750638E+03 0.1739541E+03 0.1728515E+03 0.1717558E+03 0.1706671E+03 + 0.1695852E+03 0.1685102E+03 0.1674421E+03 0.1663807E+03 0.1653260E+03 + 0.1642780E+03 0.1632367E+03 0.1622019E+03 0.1611737E+03 0.1601520E+03 + 0.1591368E+03 0.1581281E+03 0.1571257E+03 0.1561297E+03 0.1551400E+03 + 0.1541566E+03 0.1531794E+03 0.1522084E+03 0.1512435E+03 0.1502848E+03 + 0.1493321E+03 0.1483855E+03 0.1474449E+03 0.1465103E+03 0.1455815E+03 + 0.1446587E+03 0.1437417E+03 0.1428306E+03 0.1419251E+03 0.1410255E+03 + 0.1401315E+03 0.1392432E+03 0.1383606E+03 0.1374835E+03 0.1366120E+03 + 0.1357460E+03 0.1348855E+03 0.1340305E+03 0.1331809E+03 0.1323367E+03 + 0.1314978E+03 0.1306642E+03 0.1298359E+03 0.1290129E+03 0.1281951E+03 + 0.1273825E+03 0.1265750E+03 0.1257726E+03 0.1249754E+03 0.1241832E+03 + 0.1233960E+03 0.1226138E+03 0.1218365E+03 0.1210642E+03 0.1202968E+03 + 0.1195342E+03 0.1187765E+03 0.1180236E+03 0.1172754E+03 0.1165320E+03 + 0.1157933E+03 0.1150593E+03 0.1143299E+03 0.1136052E+03 0.1128851E+03 + 0.1121695E+03 0.1114585E+03 0.1107519E+03 0.1100499E+03 0.1093523E+03 + 0.1086591E+03 0.1079703E+03 0.1072859E+03 0.1066058E+03 0.1059300E+03 + 0.1052585E+03 0.1045913E+03 0.1039283E+03 0.1032695E+03 0.1026149E+03 + 0.1019644E+03 0.1013181E+03 0.1006758E+03 0.1000376E+03 0.9940348E+02 + 0.9877336E+02 0.9814725E+02 0.9752509E+02 0.9690688E+02 0.9629259E+02 + 0.9568220E+02 0.9507566E+02 0.9447298E+02 0.9387412E+02 0.9327905E+02 + 0.2418880E+03 0.2404285E+03 0.2389712E+03 0.2375164E+03 0.2360648E+03 + 0.2346168E+03 0.2331729E+03 0.2317335E+03 0.2302991E+03 0.2288700E+03 + 0.2274464E+03 0.2260289E+03 0.2246175E+03 0.2232126E+03 0.2218143E+03 + 0.2204229E+03 0.2190385E+03 0.2176614E+03 0.2162915E+03 0.2149292E+03 + 0.2135743E+03 0.2122271E+03 0.2108875E+03 0.2095557E+03 0.2082316E+03 + 0.2069154E+03 0.2056070E+03 0.2043064E+03 0.2030138E+03 0.2017289E+03 + 0.2004520E+03 0.1991828E+03 0.1979215E+03 0.1966680E+03 0.1954223E+03 + 0.1941843E+03 0.1929541E+03 0.1917315E+03 0.1905166E+03 0.1893094E+03 + 0.1881097E+03 0.1869176E+03 0.1857330E+03 0.1845558E+03 0.1833861E+03 + 0.1822238E+03 0.1810688E+03 0.1799211E+03 0.1787806E+03 0.1776474E+03 + 0.1765214E+03 0.1754025E+03 0.1742906E+03 0.1731858E+03 0.1720880E+03 + 0.1709972E+03 0.1699133E+03 0.1688362E+03 0.1677660E+03 0.1667025E+03 + 0.1656458E+03 0.1645958E+03 0.1635524E+03 0.1625157E+03 0.1614855E+03 + 0.1604618E+03 0.1594447E+03 0.1584339E+03 0.1574296E+03 0.1564317E+03 + 0.1554401E+03 0.1544548E+03 0.1534757E+03 0.1525028E+03 0.1515361E+03 + 0.1505755E+03 0.1496210E+03 0.1486726E+03 0.1477301E+03 0.1467937E+03 + 0.1458631E+03 0.1449385E+03 0.1440198E+03 0.1431068E+03 0.1421997E+03 + 0.1412983E+03 0.1404026E+03 0.1395126E+03 0.1386282E+03 0.1377495E+03 + 0.1368763E+03 0.1360086E+03 0.1351464E+03 0.1342898E+03 0.1334385E+03 + 0.1325926E+03 0.1317522E+03 0.1309170E+03 0.1300871E+03 0.1292625E+03 + 0.1284431E+03 0.1276289E+03 0.1268198E+03 0.1260159E+03 0.1252171E+03 + 0.1244234E+03 0.1236347E+03 0.1228509E+03 0.1220722E+03 0.1212984E+03 + 0.1205295E+03 0.1197654E+03 0.1190062E+03 0.1182519E+03 0.1175023E+03 + 0.1167574E+03 0.1160173E+03 0.1152819E+03 0.1145511E+03 0.1138250E+03 + 0.1131034E+03 0.1123865E+03 0.1116741E+03 0.1109662E+03 0.1102628E+03 + 0.1095638E+03 0.1088693E+03 0.1081792E+03 0.1074934E+03 0.1068120E+03 + 0.1061349E+03 0.1054621E+03 0.1047936E+03 0.1041293E+03 0.1034693E+03 + 0.1028134E+03 0.1021616E+03 0.1015140E+03 0.1008705E+03 0.1002311E+03 + 0.9959576E+02 0.9896443E+02 0.9833710E+02 0.9771375E+02 0.9709434E+02 + 0.9647886E+02 0.9586728E+02 0.9525957E+02 0.9465573E+02 0.9405571E+02 + 0.2437707E+03 0.2423118E+03 0.2408539E+03 0.2393978E+03 0.2379439E+03 + 0.2364928E+03 0.2350451E+03 0.2336012E+03 0.2321616E+03 0.2307267E+03 + 0.2292968E+03 0.2278724E+03 0.2264537E+03 0.2250411E+03 0.2236348E+03 + 0.2222350E+03 0.2208419E+03 0.2194558E+03 0.2180768E+03 0.2167050E+03 + 0.2153407E+03 0.2139837E+03 0.2126344E+03 0.2112926E+03 0.2099586E+03 + 0.2086324E+03 0.2073139E+03 0.2060032E+03 0.2047004E+03 0.2034053E+03 + 0.2021182E+03 0.2008389E+03 0.1995674E+03 0.1983038E+03 0.1970479E+03 + 0.1957999E+03 0.1945596E+03 0.1933270E+03 0.1921021E+03 0.1908849E+03 + 0.1896754E+03 0.1884734E+03 0.1872790E+03 0.1860921E+03 0.1849127E+03 + 0.1837408E+03 0.1825762E+03 0.1814190E+03 0.1802691E+03 0.1791264E+03 + 0.1779910E+03 0.1768628E+03 0.1757417E+03 0.1746278E+03 0.1735208E+03 + 0.1724209E+03 0.1713280E+03 0.1702419E+03 0.1691628E+03 0.1680905E+03 + 0.1670250E+03 0.1659662E+03 0.1649142E+03 0.1638688E+03 0.1628300E+03 + 0.1617979E+03 0.1607722E+03 0.1597531E+03 0.1587404E+03 0.1577342E+03 + 0.1567343E+03 0.1557408E+03 0.1547536E+03 0.1537726E+03 0.1527978E+03 + 0.1518292E+03 0.1508668E+03 0.1499104E+03 0.1489602E+03 0.1480159E+03 + 0.1470776E+03 0.1461453E+03 0.1452189E+03 0.1442984E+03 0.1433837E+03 + 0.1424748E+03 0.1415716E+03 0.1406742E+03 0.1397825E+03 0.1388964E+03 + 0.1380159E+03 0.1371411E+03 0.1362717E+03 0.1354079E+03 0.1345496E+03 + 0.1336966E+03 0.1328491E+03 0.1320070E+03 0.1311702E+03 0.1303387E+03 + 0.1295125E+03 0.1286915E+03 0.1278758E+03 0.1270652E+03 0.1262597E+03 + 0.1254593E+03 0.1246641E+03 0.1238738E+03 0.1230886E+03 0.1223083E+03 + 0.1215330E+03 0.1207626E+03 0.1199971E+03 0.1192365E+03 0.1184806E+03 + 0.1177296E+03 0.1169833E+03 0.1162417E+03 0.1155049E+03 0.1147727E+03 + 0.1140452E+03 0.1133222E+03 0.1126039E+03 0.1118901E+03 0.1111808E+03 + 0.1104761E+03 0.1097757E+03 0.1090799E+03 0.1083884E+03 0.1077013E+03 + 0.1070186E+03 0.1063402E+03 0.1056662E+03 0.1049963E+03 0.1043308E+03 + 0.1036694E+03 0.1030123E+03 0.1023593E+03 0.1017104E+03 0.1010657E+03 + 0.1004250E+03 0.9978844E+02 0.9915588E+02 0.9852733E+02 0.9790276E+02 + 0.9728217E+02 0.9666549E+02 0.9605273E+02 0.9544386E+02 0.9483884E+02 + 0.2456473E+03 0.2441905E+03 0.2427338E+03 0.2412778E+03 0.2398230E+03 + 0.2383702E+03 0.2369199E+03 0.2354726E+03 0.2340289E+03 0.2325892E+03 + 0.2311539E+03 0.2297234E+03 0.2282982E+03 0.2268785E+03 0.2254648E+03 + 0.2240571E+03 0.2226558E+03 0.2212612E+03 0.2198734E+03 0.2184926E+03 + 0.2171190E+03 0.2157526E+03 0.2143937E+03 0.2130422E+03 0.2116984E+03 + 0.2103622E+03 0.2090337E+03 0.2077130E+03 0.2064000E+03 0.2050949E+03 + 0.2037976E+03 0.2025081E+03 0.2012265E+03 0.1999527E+03 0.1986867E+03 + 0.1974285E+03 0.1961781E+03 0.1949355E+03 0.1937007E+03 0.1924734E+03 + 0.1912540E+03 0.1900421E+03 0.1888378E+03 0.1876411E+03 0.1864520E+03 + 0.1852703E+03 0.1840961E+03 0.1829293E+03 0.1817699E+03 0.1806177E+03 + 0.1794729E+03 0.1783353E+03 0.1772049E+03 0.1760817E+03 0.1749656E+03 + 0.1738565E+03 0.1727544E+03 0.1716594E+03 0.1705713E+03 0.1694900E+03 + 0.1684156E+03 0.1673481E+03 0.1662873E+03 0.1652332E+03 0.1641858E+03 + 0.1631450E+03 0.1621109E+03 0.1610832E+03 0.1600621E+03 0.1590475E+03 + 0.1580393E+03 0.1570375E+03 0.1560421E+03 0.1550529E+03 0.1540700E+03 + 0.1530934E+03 0.1521229E+03 0.1511586E+03 0.1502004E+03 0.1492483E+03 + 0.1483022E+03 0.1473622E+03 0.1464280E+03 0.1454998E+03 0.1445775E+03 + 0.1436610E+03 0.1427504E+03 0.1418455E+03 0.1409463E+03 0.1400529E+03 + 0.1391651E+03 0.1382829E+03 0.1374063E+03 0.1365353E+03 0.1356698E+03 + 0.1348098E+03 0.1339553E+03 0.1331061E+03 0.1322623E+03 0.1314240E+03 + 0.1305909E+03 0.1297630E+03 0.1289405E+03 0.1281232E+03 0.1273110E+03 + 0.1265039E+03 0.1257020E+03 0.1249052E+03 0.1241134E+03 0.1233267E+03 + 0.1225449E+03 0.1217681E+03 0.1209962E+03 0.1202292E+03 0.1194671E+03 + 0.1187098E+03 0.1179573E+03 0.1172096E+03 0.1164666E+03 0.1157283E+03 + 0.1149947E+03 0.1142658E+03 0.1135414E+03 0.1128217E+03 0.1121065E+03 + 0.1113959E+03 0.1106898E+03 0.1099881E+03 0.1092909E+03 0.1085981E+03 + 0.1079097E+03 0.1072256E+03 0.1065459E+03 0.1058706E+03 0.1051994E+03 + 0.1045326E+03 0.1038700E+03 0.1032115E+03 0.1025573E+03 0.1019072E+03 + 0.1012612E+03 0.1006193E+03 0.9998147E+02 0.9934769E+02 0.9871792E+02 + 0.9809216E+02 0.9747034E+02 0.9685248E+02 0.9623854E+02 0.9562848E+02 + 0.2475152E+03 0.2460623E+03 0.2446083E+03 0.2431540E+03 0.2417000E+03 + 0.2402469E+03 0.2387954E+03 0.2373461E+03 0.2358994E+03 0.2344560E+03 + 0.2330163E+03 0.2315808E+03 0.2301499E+03 0.2287240E+03 0.2273034E+03 + 0.2258885E+03 0.2244796E+03 0.2230770E+03 0.2216809E+03 0.2202914E+03 + 0.2189089E+03 0.2175334E+03 0.2161652E+03 0.2148042E+03 0.2134507E+03 + 0.2121048E+03 0.2107664E+03 0.2094357E+03 0.2081128E+03 0.2067976E+03 + 0.2054902E+03 0.2041906E+03 0.2028988E+03 0.2016149E+03 0.2003387E+03 + 0.1990705E+03 0.1978099E+03 0.1965572E+03 0.1953123E+03 0.1940750E+03 + 0.1928456E+03 0.1916237E+03 0.1904096E+03 0.1892030E+03 0.1880040E+03 + 0.1868126E+03 0.1856287E+03 0.1844522E+03 0.1832832E+03 0.1821215E+03 + 0.1809672E+03 0.1798201E+03 0.1786803E+03 0.1775477E+03 0.1764224E+03 + 0.1753041E+03 0.1741929E+03 0.1730887E+03 0.1719915E+03 0.1709013E+03 + 0.1698180E+03 0.1687415E+03 0.1676719E+03 0.1666090E+03 0.1655529E+03 + 0.1645034E+03 0.1634607E+03 0.1624245E+03 0.1613949E+03 0.1603718E+03 + 0.1593552E+03 0.1583451E+03 0.1573414E+03 0.1563440E+03 0.1553529E+03 + 0.1543681E+03 0.1533896E+03 0.1524173E+03 0.1514511E+03 0.1504911E+03 + 0.1495371E+03 0.1485892E+03 0.1476473E+03 0.1467113E+03 0.1457814E+03 + 0.1448572E+03 0.1439390E+03 0.1430266E+03 0.1421199E+03 0.1412190E+03 + 0.1403239E+03 0.1394344E+03 0.1385505E+03 0.1376722E+03 0.1367995E+03 + 0.1359323E+03 0.1350707E+03 0.1342145E+03 0.1333636E+03 0.1325183E+03 + 0.1316783E+03 0.1308435E+03 0.1300141E+03 0.1291900E+03 0.1283710E+03 + 0.1275573E+03 0.1267487E+03 0.1259453E+03 0.1251469E+03 0.1243536E+03 + 0.1235653E+03 0.1227820E+03 0.1220037E+03 0.1212303E+03 0.1204619E+03 + 0.1196983E+03 0.1189395E+03 0.1181855E+03 0.1174364E+03 0.1166919E+03 + 0.1159522E+03 0.1152172E+03 0.1144869E+03 0.1137611E+03 0.1130400E+03 + 0.1123234E+03 0.1116114E+03 0.1109039E+03 0.1102009E+03 0.1095023E+03 + 0.1088082E+03 0.1081185E+03 0.1074331E+03 0.1067521E+03 0.1060754E+03 + 0.1054030E+03 0.1047349E+03 0.1040709E+03 0.1034112E+03 0.1027557E+03 + 0.1021043E+03 0.1014571E+03 0.1008140E+03 0.1001749E+03 0.9953991E+02 + 0.9890894E+02 0.9828194E+02 0.9765894E+02 0.9703989E+02 0.9642474E+02 + 0.2493711E+03 0.2479239E+03 0.2464746E+03 0.2450238E+03 0.2435721E+03 + 0.2421204E+03 0.2406692E+03 0.2392191E+03 0.2377710E+03 0.2363251E+03 + 0.2348821E+03 0.2334427E+03 0.2320070E+03 0.2305758E+03 0.2291494E+03 + 0.2277280E+03 0.2263122E+03 0.2249022E+03 0.2234982E+03 0.2221006E+03 + 0.2207097E+03 0.2193254E+03 0.2179482E+03 0.2165780E+03 0.2152152E+03 + 0.2138597E+03 0.2125116E+03 0.2111711E+03 0.2098383E+03 0.2085131E+03 + 0.2071957E+03 0.2058860E+03 0.2045841E+03 0.2032901E+03 0.2020038E+03 + 0.2007254E+03 0.1994548E+03 0.1981919E+03 0.1969369E+03 0.1956896E+03 + 0.1944501E+03 0.1932183E+03 0.1919942E+03 0.1907777E+03 0.1895688E+03 + 0.1883676E+03 0.1871739E+03 0.1859876E+03 0.1848089E+03 0.1836376E+03 + 0.1824737E+03 0.1813172E+03 0.1801679E+03 0.1790259E+03 0.1778912E+03 + 0.1767636E+03 0.1756432E+03 0.1745298E+03 0.1734235E+03 0.1723242E+03 + 0.1712319E+03 0.1701465E+03 0.1690679E+03 0.1679962E+03 0.1669313E+03 + 0.1658731E+03 0.1648217E+03 0.1637769E+03 0.1627387E+03 0.1617071E+03 + 0.1606821E+03 0.1596635E+03 0.1586514E+03 0.1576457E+03 0.1566464E+03 + 0.1556534E+03 0.1546668E+03 0.1536863E+03 0.1527121E+03 0.1517441E+03 + 0.1507822E+03 0.1498264E+03 0.1488766E+03 0.1479329E+03 0.1469952E+03 + 0.1460634E+03 0.1451375E+03 0.1442174E+03 0.1433032E+03 0.1423948E+03 + 0.1414922E+03 0.1405953E+03 0.1397041E+03 0.1388185E+03 0.1379385E+03 + 0.1370641E+03 0.1361953E+03 0.1353320E+03 0.1344741E+03 0.1336217E+03 + 0.1327746E+03 0.1319330E+03 0.1310966E+03 0.1302657E+03 0.1294399E+03 + 0.1286194E+03 0.1278041E+03 0.1269939E+03 0.1261889E+03 0.1253890E+03 + 0.1245941E+03 0.1238043E+03 0.1230196E+03 0.1222397E+03 0.1214649E+03 + 0.1206949E+03 0.1199298E+03 0.1191696E+03 0.1184142E+03 0.1176636E+03 + 0.1169177E+03 0.1161765E+03 0.1154401E+03 0.1147083E+03 0.1139812E+03 + 0.1132587E+03 0.1125407E+03 0.1118273E+03 0.1111185E+03 0.1104141E+03 + 0.1097142E+03 0.1090187E+03 0.1083276E+03 0.1076409E+03 0.1069586E+03 + 0.1062806E+03 0.1056069E+03 0.1049374E+03 0.1042723E+03 0.1036113E+03 + 0.1029545E+03 0.1023019E+03 0.1016534E+03 0.1010090E+03 0.1003687E+03 + 0.9973247E+02 0.9910026E+02 0.9847207E+02 0.9784785E+02 0.9722760E+02 + 0.2512121E+03 0.2497727E+03 0.2483298E+03 0.2468843E+03 0.2454368E+03 + 0.2439881E+03 0.2425388E+03 0.2410897E+03 0.2396415E+03 0.2381945E+03 + 0.2367497E+03 0.2353074E+03 0.2338683E+03 0.2324328E+03 0.2310013E+03 + 0.2295744E+03 0.2281524E+03 0.2267358E+03 0.2253247E+03 0.2239195E+03 + 0.2225206E+03 0.2211281E+03 0.2197423E+03 0.2183633E+03 0.2169913E+03 + 0.2156266E+03 0.2142691E+03 0.2129190E+03 0.2115764E+03 0.2102414E+03 + 0.2089141E+03 0.2075944E+03 0.2062825E+03 0.2049784E+03 0.2036820E+03 + 0.2023935E+03 0.2011127E+03 0.1998398E+03 0.1985746E+03 0.1973173E+03 + 0.1960677E+03 0.1948258E+03 0.1935917E+03 0.1923652E+03 0.1911465E+03 + 0.1899353E+03 0.1887318E+03 0.1875358E+03 0.1863473E+03 0.1851663E+03 + 0.1839928E+03 0.1828267E+03 0.1816679E+03 0.1805164E+03 0.1793722E+03 + 0.1782353E+03 0.1771055E+03 0.1759829E+03 0.1748674E+03 0.1737590E+03 + 0.1726576E+03 0.1715631E+03 0.1704756E+03 0.1693950E+03 0.1683212E+03 + 0.1672542E+03 0.1661940E+03 0.1651405E+03 0.1640937E+03 0.1630535E+03 + 0.1620199E+03 0.1609929E+03 0.1599724E+03 0.1589583E+03 0.1579507E+03 + 0.1569494E+03 0.1559545E+03 0.1549659E+03 0.1539836E+03 0.1530075E+03 + 0.1520376E+03 0.1510739E+03 0.1501162E+03 0.1491646E+03 0.1482191E+03 + 0.1472795E+03 0.1463459E+03 0.1454182E+03 0.1444964E+03 0.1435805E+03 + 0.1426703E+03 0.1417659E+03 0.1408673E+03 0.1399743E+03 0.1390871E+03 + 0.1382054E+03 0.1373293E+03 0.1364588E+03 0.1355937E+03 0.1347342E+03 + 0.1338802E+03 0.1330315E+03 0.1321882E+03 0.1313503E+03 0.1305176E+03 + 0.1296903E+03 0.1288682E+03 0.1280513E+03 0.1272396E+03 0.1264330E+03 + 0.1256315E+03 0.1248352E+03 0.1240438E+03 0.1232575E+03 0.1224762E+03 + 0.1216998E+03 0.1209284E+03 0.1201618E+03 0.1194001E+03 0.1186432E+03 + 0.1178912E+03 0.1171439E+03 0.1164013E+03 0.1156634E+03 0.1149302E+03 + 0.1142017E+03 0.1134778E+03 0.1127584E+03 0.1120437E+03 0.1113334E+03 + 0.1106277E+03 0.1099264E+03 0.1092296E+03 0.1085372E+03 0.1078492E+03 + 0.1071655E+03 0.1064862E+03 0.1058112E+03 0.1051404E+03 0.1044740E+03 + 0.1038117E+03 0.1031536E+03 0.1024998E+03 0.1018500E+03 0.1012044E+03 + 0.1005629E+03 0.9992539E+02 0.9929197E+02 0.9866256E+02 0.9803714E+02 + 0.2530353E+03 0.2516054E+03 0.2501709E+03 0.2487326E+03 0.2472911E+03 + 0.2458473E+03 0.2444017E+03 0.2429552E+03 0.2415085E+03 0.2400621E+03 + 0.2386168E+03 0.2371731E+03 0.2357317E+03 0.2342931E+03 0.2328578E+03 + 0.2314263E+03 0.2299991E+03 0.2285766E+03 0.2271592E+03 0.2257472E+03 + 0.2243409E+03 0.2229407E+03 0.2215468E+03 0.2201594E+03 0.2187787E+03 + 0.2174050E+03 0.2160384E+03 0.2146789E+03 0.2133269E+03 0.2119822E+03 + 0.2106451E+03 0.2093156E+03 0.2079938E+03 0.2066796E+03 0.2053732E+03 + 0.2040746E+03 0.2027838E+03 0.2015007E+03 0.2002255E+03 0.1989580E+03 + 0.1976983E+03 0.1964464E+03 0.1952022E+03 0.1939658E+03 0.1927370E+03 + 0.1915160E+03 0.1903025E+03 0.1890966E+03 0.1878984E+03 0.1867077E+03 + 0.1855244E+03 0.1843486E+03 0.1831802E+03 0.1820192E+03 0.1808656E+03 + 0.1797192E+03 0.1785800E+03 0.1774481E+03 0.1763233E+03 0.1752056E+03 + 0.1740951E+03 0.1729915E+03 0.1718950E+03 0.1708054E+03 0.1697227E+03 + 0.1686468E+03 0.1675778E+03 0.1665155E+03 0.1654600E+03 0.1644111E+03 + 0.1633689E+03 0.1623333E+03 0.1613044E+03 0.1602818E+03 0.1592658E+03 + 0.1582562E+03 0.1572530E+03 0.1562562E+03 0.1552657E+03 0.1542815E+03 + 0.1533035E+03 0.1523317E+03 0.1513661E+03 0.1504066E+03 0.1494532E+03 + 0.1485058E+03 0.1475644E+03 0.1466290E+03 0.1456995E+03 0.1447759E+03 + 0.1438582E+03 0.1429463E+03 0.1420401E+03 0.1411398E+03 0.1402451E+03 + 0.1393561E+03 0.1384727E+03 0.1375949E+03 0.1367227E+03 0.1358560E+03 + 0.1349949E+03 0.1341391E+03 0.1332888E+03 0.1324439E+03 0.1316043E+03 + 0.1307701E+03 0.1299412E+03 0.1291175E+03 0.1282990E+03 0.1274857E+03 + 0.1266776E+03 0.1258746E+03 0.1250767E+03 0.1242838E+03 0.1234960E+03 + 0.1227131E+03 0.1219353E+03 0.1211623E+03 0.1203943E+03 0.1196311E+03 + 0.1188727E+03 0.1181192E+03 0.1173705E+03 0.1166264E+03 0.1158872E+03 + 0.1151525E+03 0.1144226E+03 0.1136973E+03 0.1129766E+03 0.1122604E+03 + 0.1115488E+03 0.1108417E+03 0.1101390E+03 0.1094409E+03 0.1087471E+03 + 0.1080578E+03 0.1073728E+03 0.1066922E+03 0.1060159E+03 0.1053438E+03 + 0.1046761E+03 0.1040125E+03 0.1033532E+03 0.1026980E+03 0.1020470E+03 + 0.1014002E+03 0.1007574E+03 0.1001187E+03 0.9948404E+02 0.9885341E+02 + 0.2548374E+03 0.2534189E+03 0.2519948E+03 0.2505656E+03 0.2491321E+03 + 0.2476950E+03 0.2462550E+03 0.2448129E+03 0.2433695E+03 0.2419252E+03 + 0.2404810E+03 0.2390375E+03 0.2375952E+03 0.2361549E+03 0.2347170E+03 + 0.2332821E+03 0.2318507E+03 0.2304234E+03 0.2290005E+03 0.2275824E+03 + 0.2261696E+03 0.2247623E+03 0.2233609E+03 0.2219656E+03 0.2205767E+03 + 0.2191945E+03 0.2178190E+03 0.2164506E+03 0.2150893E+03 0.2137352E+03 + 0.2123885E+03 0.2110494E+03 0.2097177E+03 0.2083937E+03 0.2070774E+03 + 0.2057687E+03 0.2044678E+03 0.2031747E+03 0.2018894E+03 0.2006118E+03 + 0.1993421E+03 0.1980800E+03 0.1968258E+03 0.1955793E+03 0.1943405E+03 + 0.1931095E+03 0.1918861E+03 0.1906704E+03 0.1894622E+03 0.1882617E+03 + 0.1870687E+03 0.1858832E+03 0.1847051E+03 0.1835345E+03 0.1823712E+03 + 0.1812153E+03 0.1800668E+03 0.1789254E+03 0.1777913E+03 0.1766644E+03 + 0.1755446E+03 0.1744318E+03 0.1733262E+03 0.1722275E+03 0.1711358E+03 + 0.1700509E+03 0.1689730E+03 0.1679019E+03 0.1668376E+03 0.1657800E+03 + 0.1647292E+03 0.1636850E+03 0.1626474E+03 0.1616164E+03 0.1605919E+03 + 0.1595739E+03 0.1585624E+03 0.1575572E+03 0.1565585E+03 0.1555661E+03 + 0.1545799E+03 0.1536001E+03 0.1526264E+03 0.1516589E+03 0.1506976E+03 + 0.1497423E+03 0.1487931E+03 0.1478499E+03 0.1469126E+03 0.1459814E+03 + 0.1450560E+03 0.1441365E+03 0.1432228E+03 0.1423149E+03 0.1414128E+03 + 0.1405164E+03 0.1396257E+03 0.1387406E+03 0.1378611E+03 0.1369872E+03 + 0.1361189E+03 0.1352560E+03 0.1343986E+03 0.1335467E+03 0.1327001E+03 + 0.1318589E+03 0.1310231E+03 0.1301925E+03 0.1293672E+03 0.1285472E+03 + 0.1277323E+03 0.1269226E+03 0.1261181E+03 0.1253186E+03 0.1245242E+03 + 0.1237349E+03 0.1229505E+03 0.1221711E+03 0.1213967E+03 0.1206272E+03 + 0.1198625E+03 0.1191027E+03 0.1183477E+03 0.1175975E+03 0.1168521E+03 + 0.1161113E+03 0.1153753E+03 0.1146439E+03 0.1139172E+03 0.1131951E+03 + 0.1124776E+03 0.1117646E+03 0.1110561E+03 0.1103521E+03 0.1096526E+03 + 0.1089575E+03 0.1082668E+03 0.1075805E+03 0.1068986E+03 0.1062209E+03 + 0.1055476E+03 0.1048786E+03 0.1042137E+03 0.1035531E+03 0.1028967E+03 + 0.1022444E+03 0.1015963E+03 0.1009523E+03 0.1003124E+03 0.9967648E+02 + 0.2566152E+03 0.2552103E+03 0.2537984E+03 0.2523802E+03 0.2509566E+03 + 0.2495282E+03 0.2480957E+03 0.2466599E+03 0.2452216E+03 0.2437813E+03 + 0.2423400E+03 0.2408982E+03 0.2394566E+03 0.2380160E+03 0.2365768E+03 + 0.2351398E+03 0.2337055E+03 0.2322745E+03 0.2308471E+03 0.2294239E+03 + 0.2280054E+03 0.2265918E+03 0.2251836E+03 0.2237811E+03 0.2223846E+03 + 0.2209943E+03 0.2196105E+03 0.2182334E+03 0.2168632E+03 0.2155000E+03 + 0.2141441E+03 0.2127954E+03 0.2114541E+03 0.2101204E+03 0.2087943E+03 + 0.2074757E+03 0.2061648E+03 0.2048617E+03 0.2035663E+03 0.2022787E+03 + 0.2009989E+03 0.1997268E+03 0.1984625E+03 0.1972059E+03 0.1959571E+03 + 0.1947161E+03 0.1934827E+03 0.1922570E+03 0.1910389E+03 0.1898285E+03 + 0.1886257E+03 0.1874304E+03 0.1862426E+03 0.1850623E+03 0.1838894E+03 + 0.1827240E+03 0.1815658E+03 0.1804151E+03 0.1792715E+03 0.1781352E+03 + 0.1770061E+03 0.1758841E+03 0.1747692E+03 0.1736614E+03 0.1725606E+03 + 0.1714668E+03 0.1703799E+03 0.1692999E+03 0.1682267E+03 0.1671603E+03 + 0.1661007E+03 0.1650478E+03 0.1640016E+03 0.1629620E+03 0.1619290E+03 + 0.1609025E+03 0.1598826E+03 0.1588691E+03 0.1578620E+03 0.1568613E+03 + 0.1558670E+03 0.1548790E+03 0.1538972E+03 0.1529216E+03 0.1519523E+03 + 0.1509891E+03 0.1500319E+03 0.1490809E+03 0.1481359E+03 0.1471968E+03 + 0.1462638E+03 0.1453366E+03 0.1444153E+03 0.1434999E+03 0.1425903E+03 + 0.1416863E+03 0.1407882E+03 0.1398958E+03 0.1390089E+03 0.1381278E+03 + 0.1372522E+03 0.1363822E+03 0.1355176E+03 0.1346586E+03 0.1338050E+03 + 0.1329568E+03 0.1321140E+03 0.1312765E+03 0.1304444E+03 0.1296175E+03 + 0.1287959E+03 0.1279794E+03 0.1271682E+03 0.1263620E+03 0.1255610E+03 + 0.1247651E+03 0.1239742E+03 0.1231883E+03 0.1224075E+03 0.1216315E+03 + 0.1208605E+03 0.1200944E+03 0.1193331E+03 0.1185766E+03 0.1178250E+03 + 0.1170781E+03 0.1163359E+03 0.1155985E+03 0.1148657E+03 0.1141376E+03 + 0.1134141E+03 0.1126951E+03 0.1119808E+03 0.1112709E+03 0.1105656E+03 + 0.1098647E+03 0.1091683E+03 0.1084763E+03 0.1077886E+03 0.1071054E+03 + 0.1064264E+03 0.1057518E+03 0.1050814E+03 0.1044153E+03 0.1037534E+03 + 0.1030958E+03 0.1024422E+03 0.1017928E+03 0.1011476E+03 0.1005064E+03 + 0.2583661E+03 0.2569763E+03 0.2555784E+03 0.2541734E+03 0.2527615E+03 + 0.2513438E+03 0.2499207E+03 0.2484932E+03 0.2470618E+03 0.2456274E+03 + 0.2441907E+03 0.2427525E+03 0.2413133E+03 0.2398739E+03 0.2384352E+03 + 0.2369975E+03 0.2355616E+03 0.2341281E+03 0.2326974E+03 0.2312702E+03 + 0.2298469E+03 0.2284280E+03 0.2270138E+03 0.2256048E+03 0.2242013E+03 + 0.2228036E+03 0.2214120E+03 0.2200268E+03 0.2186481E+03 0.2172762E+03 + 0.2159112E+03 0.2145534E+03 0.2132027E+03 0.2118595E+03 0.2105236E+03 + 0.2091953E+03 0.2078746E+03 0.2065616E+03 0.2052562E+03 0.2039586E+03 + 0.2026687E+03 0.2013866E+03 0.2001122E+03 0.1988456E+03 0.1975867E+03 + 0.1963356E+03 0.1950922E+03 0.1938565E+03 0.1926285E+03 0.1914082E+03 + 0.1901954E+03 0.1889903E+03 0.1877928E+03 0.1866027E+03 0.1854202E+03 + 0.1842450E+03 0.1830773E+03 0.1819170E+03 0.1807640E+03 0.1796182E+03 + 0.1784798E+03 0.1773485E+03 0.1762243E+03 0.1751073E+03 0.1739973E+03 + 0.1728944E+03 0.1717985E+03 0.1707095E+03 0.1696274E+03 0.1685521E+03 + 0.1674837E+03 0.1664220E+03 0.1653671E+03 0.1643188E+03 0.1632772E+03 + 0.1622422E+03 0.1612138E+03 0.1601918E+03 0.1591764E+03 0.1581674E+03 + 0.1571648E+03 0.1561685E+03 0.1551786E+03 0.1541949E+03 0.1532175E+03 + 0.1522462E+03 0.1512811E+03 0.1503222E+03 0.1493693E+03 0.1484224E+03 + 0.1474816E+03 0.1465467E+03 0.1456177E+03 0.1446947E+03 0.1437775E+03 + 0.1428661E+03 0.1419604E+03 0.1410606E+03 0.1401664E+03 0.1392779E+03 + 0.1383950E+03 0.1375177E+03 0.1366460E+03 0.1357798E+03 0.1349191E+03 + 0.1340638E+03 0.1332140E+03 0.1323696E+03 0.1315305E+03 0.1306967E+03 + 0.1298682E+03 0.1290450E+03 0.1282270E+03 0.1274141E+03 0.1266065E+03 + 0.1258039E+03 0.1250065E+03 0.1242140E+03 0.1234267E+03 0.1226443E+03 + 0.1218668E+03 0.1210943E+03 0.1203267E+03 0.1195639E+03 0.1188060E+03 + 0.1180529E+03 0.1173046E+03 0.1165610E+03 0.1158221E+03 0.1150879E+03 + 0.1143584E+03 0.1136335E+03 0.1129131E+03 0.1121974E+03 0.1114862E+03 + 0.1107795E+03 0.1100772E+03 0.1093795E+03 0.1086861E+03 0.1079971E+03 + 0.1073126E+03 0.1066323E+03 0.1059564E+03 0.1052847E+03 0.1046173E+03 + 0.1039541E+03 0.1032952E+03 0.1026404E+03 0.1019898E+03 0.1013432E+03 + 0.2600871E+03 0.2587141E+03 0.2573321E+03 0.2559418E+03 0.2545437E+03 + 0.2531384E+03 0.2517269E+03 0.2503095E+03 0.2488872E+03 0.2474605E+03 + 0.2460304E+03 0.2445975E+03 0.2431626E+03 0.2417263E+03 0.2402894E+03 + 0.2388527E+03 0.2374167E+03 0.2359821E+03 0.2345495E+03 0.2331195E+03 + 0.2316926E+03 0.2302694E+03 0.2288502E+03 0.2274356E+03 0.2260259E+03 + 0.2246215E+03 0.2232227E+03 0.2218298E+03 0.2204432E+03 0.2190630E+03 + 0.2176895E+03 0.2163228E+03 0.2149631E+03 0.2136105E+03 0.2122653E+03 + 0.2109274E+03 0.2095970E+03 0.2082742E+03 0.2069589E+03 0.2056513E+03 + 0.2043515E+03 0.2030593E+03 0.2017749E+03 0.2004982E+03 0.1992293E+03 + 0.1979682E+03 0.1967148E+03 0.1954691E+03 0.1942311E+03 0.1930008E+03 + 0.1917781E+03 0.1905631E+03 0.1893557E+03 0.1881558E+03 0.1869635E+03 + 0.1857787E+03 0.1846013E+03 0.1834314E+03 0.1822688E+03 0.1811136E+03 + 0.1799657E+03 0.1788250E+03 0.1776915E+03 0.1765652E+03 0.1754460E+03 + 0.1743339E+03 0.1732289E+03 0.1721308E+03 0.1710397E+03 0.1699555E+03 + 0.1688782E+03 0.1678077E+03 0.1667440E+03 0.1656870E+03 0.1646367E+03 + 0.1635931E+03 0.1625561E+03 0.1615256E+03 0.1605017E+03 0.1594843E+03 + 0.1584733E+03 0.1574688E+03 0.1564706E+03 0.1554787E+03 0.1544932E+03 + 0.1535138E+03 0.1525407E+03 0.1515738E+03 0.1506129E+03 0.1496582E+03 + 0.1487095E+03 0.1477669E+03 0.1468302E+03 0.1458994E+03 0.1449746E+03 + 0.1440556E+03 0.1431424E+03 0.1422351E+03 0.1413334E+03 0.1404375E+03 + 0.1395473E+03 0.1386627E+03 0.1377837E+03 0.1369103E+03 0.1360424E+03 + 0.1351801E+03 0.1343232E+03 0.1334717E+03 0.1326256E+03 0.1317849E+03 + 0.1309495E+03 0.1301194E+03 0.1292946E+03 0.1284750E+03 0.1276606E+03 + 0.1268514E+03 0.1260473E+03 0.1252483E+03 0.1244543E+03 0.1236654E+03 + 0.1228815E+03 0.1221026E+03 0.1213285E+03 0.1205594E+03 0.1197952E+03 + 0.1190358E+03 0.1182813E+03 0.1175315E+03 0.1167865E+03 0.1160462E+03 + 0.1153106E+03 0.1145796E+03 0.1138533E+03 0.1131316E+03 0.1124144E+03 + 0.1117018E+03 0.1109938E+03 0.1102902E+03 0.1095910E+03 0.1088963E+03 + 0.1082061E+03 0.1075201E+03 0.1068386E+03 0.1061613E+03 0.1054884E+03 + 0.1048197E+03 0.1041552E+03 0.1034950E+03 0.1028389E+03 0.1021870E+03 + 0.2617758E+03 0.2604211E+03 0.2590566E+03 0.2576828E+03 0.2563001E+03 + 0.2549094E+03 0.2535110E+03 0.2521058E+03 0.2506944E+03 0.2492775E+03 + 0.2478559E+03 0.2464304E+03 0.2450015E+03 0.2435701E+03 0.2421371E+03 + 0.2407029E+03 0.2392685E+03 0.2378344E+03 0.2364013E+03 0.2349698E+03 + 0.2335407E+03 0.2321143E+03 0.2306912E+03 0.2292720E+03 0.2278570E+03 + 0.2264467E+03 0.2250416E+03 0.2236418E+03 0.2222478E+03 0.2208599E+03 + 0.2194782E+03 0.2181031E+03 0.2167347E+03 0.2153732E+03 0.2140188E+03 + 0.2126716E+03 0.2113317E+03 0.2099993E+03 0.2086743E+03 0.2073569E+03 + 0.2060471E+03 0.2047450E+03 0.2034506E+03 0.2021639E+03 0.2008850E+03 + 0.1996138E+03 0.1983503E+03 0.1970946E+03 0.1958466E+03 0.1946063E+03 + 0.1933737E+03 0.1921488E+03 0.1909314E+03 0.1897217E+03 0.1885196E+03 + 0.1873250E+03 0.1861379E+03 0.1849583E+03 0.1837861E+03 0.1826213E+03 + 0.1814639E+03 0.1803137E+03 0.1791709E+03 0.1780352E+03 0.1769067E+03 + 0.1757854E+03 0.1746711E+03 0.1735639E+03 0.1724638E+03 0.1713706E+03 + 0.1702843E+03 0.1692048E+03 0.1681323E+03 0.1670665E+03 0.1660075E+03 + 0.1649552E+03 0.1639096E+03 0.1628705E+03 0.1618381E+03 0.1608122E+03 + 0.1597928E+03 0.1587799E+03 0.1577734E+03 0.1567733E+03 0.1557795E+03 + 0.1547920E+03 0.1538108E+03 0.1528358E+03 0.1518670E+03 0.1509043E+03 + 0.1499477E+03 0.1489972E+03 0.1480527E+03 0.1471142E+03 0.1461817E+03 + 0.1452550E+03 0.1443343E+03 0.1434193E+03 0.1425102E+03 0.1416068E+03 + 0.1407092E+03 0.1398172E+03 0.1389309E+03 0.1380503E+03 0.1371752E+03 + 0.1363056E+03 0.1354416E+03 0.1345830E+03 0.1337299E+03 0.1328822E+03 + 0.1320399E+03 0.1312029E+03 0.1303712E+03 0.1295447E+03 0.1287236E+03 + 0.1279076E+03 0.1270968E+03 0.1262911E+03 0.1254906E+03 0.1246951E+03 + 0.1239046E+03 0.1231192E+03 0.1223388E+03 0.1215632E+03 0.1207927E+03 + 0.1200270E+03 0.1192661E+03 0.1185101E+03 0.1177589E+03 0.1170124E+03 + 0.1162707E+03 0.1155336E+03 0.1148012E+03 0.1140735E+03 0.1133504E+03 + 0.1126319E+03 0.1119179E+03 0.1112085E+03 0.1105035E+03 0.1098030E+03 + 0.1091070E+03 0.1084154E+03 0.1077281E+03 0.1070453E+03 0.1063667E+03 + 0.1056924E+03 0.1050225E+03 0.1043567E+03 0.1036952E+03 0.1030379E+03 + 0.2634300E+03 0.2620948E+03 0.2607492E+03 0.2593935E+03 0.2580279E+03 + 0.2566534E+03 0.2552701E+03 0.2538790E+03 0.2524804E+03 0.2510752E+03 + 0.2496641E+03 0.2482478E+03 0.2468271E+03 0.2454026E+03 0.2439751E+03 + 0.2425454E+03 0.2411142E+03 0.2396824E+03 0.2382504E+03 0.2368190E+03 + 0.2353889E+03 0.2339608E+03 0.2325350E+03 0.2311123E+03 0.2296931E+03 + 0.2282780E+03 0.2268673E+03 0.2254614E+03 0.2240608E+03 0.2226657E+03 + 0.2212766E+03 0.2198936E+03 0.2185169E+03 0.2171469E+03 0.2157837E+03 + 0.2144275E+03 0.2130784E+03 0.2117365E+03 0.2104020E+03 0.2090749E+03 + 0.2077554E+03 0.2064435E+03 0.2051392E+03 0.2038425E+03 0.2025536E+03 + 0.2012724E+03 0.1999989E+03 0.1987331E+03 0.1974751E+03 0.1962248E+03 + 0.1949822E+03 0.1937473E+03 0.1925201E+03 0.1913004E+03 0.1900885E+03 + 0.1888840E+03 0.1876872E+03 0.1864978E+03 0.1853160E+03 0.1841415E+03 + 0.1829745E+03 0.1818148E+03 0.1806625E+03 0.1795174E+03 0.1783795E+03 + 0.1772489E+03 0.1761254E+03 0.1750090E+03 0.1738997E+03 0.1727974E+03 + 0.1717020E+03 0.1706136E+03 0.1695322E+03 0.1684575E+03 0.1673897E+03 + 0.1663286E+03 0.1652743E+03 0.1642266E+03 0.1631856E+03 0.1621512E+03 + 0.1611233E+03 0.1601020E+03 0.1590871E+03 0.1580786E+03 0.1570766E+03 + 0.1560809E+03 0.1550915E+03 0.1541084E+03 0.1531315E+03 0.1521608E+03 + 0.1511962E+03 0.1502378E+03 0.1492854E+03 0.1483391E+03 0.1473988E+03 + 0.1464644E+03 0.1455360E+03 0.1446135E+03 0.1436967E+03 0.1427859E+03 + 0.1418808E+03 0.1409814E+03 0.1400877E+03 0.1391997E+03 0.1383173E+03 + 0.1374405E+03 0.1365693E+03 0.1357036E+03 0.1348434E+03 0.1339886E+03 + 0.1331392E+03 0.1322953E+03 0.1314566E+03 0.1306234E+03 0.1297953E+03 + 0.1289726E+03 0.1281550E+03 0.1273426E+03 0.1265354E+03 0.1257333E+03 + 0.1249363E+03 0.1241443E+03 0.1233574E+03 0.1225754E+03 0.1217984E+03 + 0.1210263E+03 0.1202591E+03 0.1194968E+03 0.1187393E+03 0.1179866E+03 + 0.1172388E+03 0.1164956E+03 0.1157571E+03 0.1150233E+03 0.1142942E+03 + 0.1135697E+03 0.1128498E+03 0.1121344E+03 0.1114236E+03 0.1107173E+03 + 0.1100155E+03 0.1093181E+03 0.1086251E+03 0.1079365E+03 0.1072523E+03 + 0.1065725E+03 0.1058969E+03 0.1052256E+03 0.1045586E+03 0.1038958E+03 + 0.2650474E+03 0.2637332E+03 0.2624078E+03 0.2610713E+03 0.2597245E+03 + 0.2583677E+03 0.2570013E+03 0.2556258E+03 0.2542421E+03 0.2528506E+03 + 0.2514519E+03 0.2500468E+03 0.2486361E+03 0.2472204E+03 0.2458005E+03 + 0.2443772E+03 0.2429512E+03 0.2415233E+03 0.2400942E+03 0.2386646E+03 + 0.2372352E+03 0.2358066E+03 0.2343797E+03 0.2329548E+03 0.2315326E+03 + 0.2301137E+03 0.2286985E+03 0.2272874E+03 0.2258811E+03 0.2244797E+03 + 0.2230837E+03 0.2216934E+03 0.2203091E+03 0.2189310E+03 0.2175594E+03 + 0.2161945E+03 0.2148365E+03 0.2134856E+03 0.2121418E+03 0.2108053E+03 + 0.2094761E+03 0.2081545E+03 0.2068404E+03 0.2055339E+03 0.2042351E+03 + 0.2029439E+03 0.2016604E+03 0.2003846E+03 0.1991166E+03 0.1978563E+03 + 0.1966037E+03 0.1953588E+03 0.1941216E+03 0.1928920E+03 0.1916702E+03 + 0.1904559E+03 0.1892492E+03 0.1880500E+03 0.1868584E+03 0.1856743E+03 + 0.1844976E+03 0.1833283E+03 0.1821664E+03 0.1810119E+03 0.1798646E+03 + 0.1787245E+03 0.1775917E+03 0.1764660E+03 0.1753475E+03 0.1742360E+03 + 0.1731316E+03 0.1720342E+03 0.1709437E+03 0.1698601E+03 0.1687834E+03 + 0.1677135E+03 0.1666504E+03 0.1655940E+03 0.1645443E+03 0.1635013E+03 + 0.1624648E+03 0.1614350E+03 0.1604117E+03 0.1593948E+03 0.1583844E+03 + 0.1573804E+03 0.1563828E+03 0.1553915E+03 0.1544064E+03 0.1534277E+03 + 0.1524551E+03 0.1514887E+03 0.1505284E+03 0.1495742E+03 0.1486261E+03 + 0.1476839E+03 0.1467478E+03 0.1458176E+03 0.1448932E+03 0.1439747E+03 + 0.1430621E+03 0.1421552E+03 0.1412541E+03 0.1403587E+03 0.1394690E+03 + 0.1385849E+03 0.1377064E+03 0.1368335E+03 0.1359661E+03 0.1351042E+03 + 0.1342478E+03 0.1333968E+03 0.1325512E+03 0.1317109E+03 0.1308760E+03 + 0.1300464E+03 0.1292220E+03 0.1284029E+03 0.1275890E+03 0.1267802E+03 + 0.1259765E+03 0.1251780E+03 0.1243845E+03 0.1235960E+03 0.1228125E+03 + 0.1220340E+03 0.1212604E+03 0.1204918E+03 0.1197280E+03 0.1189690E+03 + 0.1182149E+03 0.1174655E+03 0.1167209E+03 0.1159810E+03 0.1152458E+03 + 0.1145153E+03 0.1137894E+03 0.1130681E+03 0.1123513E+03 0.1116391E+03 + 0.1109315E+03 0.1102283E+03 0.1095295E+03 0.1088352E+03 0.1081453E+03 + 0.1074598E+03 0.1067786E+03 0.1061017E+03 0.1054292E+03 0.1047608E+03 + 0.2666269E+03 0.2653343E+03 0.2640300E+03 0.2627142E+03 0.2613873E+03 + 0.2600497E+03 0.2587016E+03 0.2573437E+03 0.2559765E+03 0.2546003E+03 + 0.2532160E+03 0.2518242E+03 0.2504254E+03 0.2490205E+03 0.2476102E+03 + 0.2461953E+03 0.2447764E+03 0.2433543E+03 0.2419299E+03 0.2405038E+03 + 0.2390768E+03 0.2376496E+03 0.2362229E+03 0.2347973E+03 0.2333735E+03 + 0.2319520E+03 0.2305335E+03 0.2291184E+03 0.2277072E+03 0.2263004E+03 + 0.2248984E+03 0.2235015E+03 0.2221102E+03 0.2207247E+03 0.2193453E+03 + 0.2179722E+03 0.2166057E+03 0.2152460E+03 0.2138932E+03 0.2125475E+03 + 0.2112090E+03 0.2098779E+03 0.2085542E+03 0.2072379E+03 0.2059293E+03 + 0.2046282E+03 0.2033348E+03 0.2020491E+03 0.2007711E+03 0.1995008E+03 + 0.1982381E+03 0.1969833E+03 0.1957361E+03 0.1944966E+03 0.1932647E+03 + 0.1920406E+03 0.1908240E+03 0.1896150E+03 0.1884136E+03 0.1872197E+03 + 0.1860333E+03 0.1848544E+03 0.1836828E+03 0.1825187E+03 0.1813619E+03 + 0.1802124E+03 0.1790702E+03 0.1779352E+03 0.1768074E+03 0.1756867E+03 + 0.1745730E+03 0.1734665E+03 0.1723669E+03 0.1712743E+03 0.1701887E+03 + 0.1691099E+03 0.1680379E+03 0.1669727E+03 0.1659143E+03 0.1648626E+03 + 0.1638175E+03 0.1627791E+03 0.1617473E+03 0.1607219E+03 0.1597032E+03 + 0.1586908E+03 0.1576848E+03 0.1566853E+03 0.1556920E+03 0.1547051E+03 + 0.1537245E+03 0.1527500E+03 0.1517817E+03 0.1508196E+03 0.1498636E+03 + 0.1489136E+03 0.1479696E+03 0.1470316E+03 0.1460996E+03 0.1451735E+03 + 0.1442533E+03 0.1433388E+03 0.1424302E+03 0.1415274E+03 0.1406302E+03 + 0.1397387E+03 0.1388530E+03 0.1379728E+03 0.1370982E+03 0.1362291E+03 + 0.1353655E+03 0.1345075E+03 0.1336548E+03 0.1328076E+03 0.1319657E+03 + 0.1311292E+03 0.1302980E+03 0.1294720E+03 0.1286513E+03 0.1278358E+03 + 0.1270254E+03 0.1262202E+03 0.1254201E+03 0.1246251E+03 0.1238351E+03 + 0.1230501E+03 0.1222701E+03 0.1214950E+03 0.1207249E+03 0.1199596E+03 + 0.1191992E+03 0.1184436E+03 0.1176927E+03 0.1169467E+03 0.1162054E+03 + 0.1154688E+03 0.1147368E+03 0.1140095E+03 0.1132868E+03 0.1125687E+03 + 0.1118551E+03 0.1111460E+03 0.1104415E+03 0.1097414E+03 0.1090458E+03 + 0.1083545E+03 0.1076677E+03 0.1069852E+03 0.1063070E+03 0.1056331E+03 + 0.2681671E+03 0.2668968E+03 0.2656145E+03 0.2643203E+03 0.2630144E+03 + 0.2616972E+03 0.2603688E+03 0.2590299E+03 0.2576805E+03 0.2563216E+03 + 0.2549535E+03 0.2535766E+03 0.2521918E+03 0.2507998E+03 0.2494010E+03 + 0.2479964E+03 0.2465866E+03 0.2451724E+03 0.2437546E+03 0.2423339E+03 + 0.2409112E+03 0.2394870E+03 0.2380623E+03 0.2366376E+03 0.2352136E+03 + 0.2337910E+03 0.2323705E+03 0.2309525E+03 0.2295377E+03 0.2281265E+03 + 0.2267194E+03 0.2253169E+03 0.2239193E+03 0.2225270E+03 0.2211404E+03 + 0.2197597E+03 0.2183852E+03 0.2170172E+03 0.2156558E+03 0.2143012E+03 + 0.2129537E+03 0.2116133E+03 0.2102802E+03 0.2089544E+03 0.2076361E+03 + 0.2063253E+03 0.2050220E+03 0.2037264E+03 0.2024385E+03 0.2011582E+03 + 0.1998856E+03 0.1986207E+03 0.1973635E+03 0.1961140E+03 0.1948723E+03 + 0.1936381E+03 0.1924116E+03 0.1911928E+03 0.1899815E+03 0.1887778E+03 + 0.1875817E+03 0.1863930E+03 0.1852118E+03 0.1840381E+03 0.1828717E+03 + 0.1817127E+03 0.1805610E+03 0.1794166E+03 0.1782794E+03 0.1771494E+03 + 0.1760265E+03 0.1749108E+03 0.1738021E+03 0.1727004E+03 0.1716057E+03 + 0.1705179E+03 0.1694370E+03 0.1683630E+03 0.1672957E+03 0.1662353E+03 + 0.1651815E+03 0.1641344E+03 0.1630940E+03 0.1620602E+03 0.1610329E+03 + 0.1600121E+03 0.1589978E+03 0.1579899E+03 0.1569884E+03 0.1559932E+03 + 0.1550044E+03 0.1540219E+03 0.1530455E+03 0.1520754E+03 0.1511114E+03 + 0.1501535E+03 0.1492017E+03 0.1482559E+03 0.1473161E+03 0.1463822E+03 + 0.1454543E+03 0.1445323E+03 0.1436161E+03 0.1427057E+03 0.1418011E+03 + 0.1409023E+03 0.1400091E+03 0.1391216E+03 0.1382397E+03 0.1373634E+03 + 0.1364926E+03 0.1356274E+03 0.1347677E+03 0.1339134E+03 0.1330645E+03 + 0.1322210E+03 0.1313829E+03 0.1305500E+03 0.1297225E+03 0.1289002E+03 + 0.1280831E+03 0.1272712E+03 0.1264644E+03 0.1256627E+03 0.1248662E+03 + 0.1240746E+03 0.1232881E+03 0.1225066E+03 0.1217300E+03 0.1209584E+03 + 0.1201917E+03 0.1194298E+03 0.1186727E+03 0.1179204E+03 0.1171729E+03 + 0.1164302E+03 0.1156921E+03 0.1149588E+03 0.1142300E+03 0.1135059E+03 + 0.1127864E+03 0.1120715E+03 0.1113611E+03 0.1106551E+03 0.1099537E+03 + 0.1092567E+03 0.1085641E+03 0.1078759E+03 0.1071921E+03 0.1065126E+03 + 0.2696669E+03 0.2684195E+03 0.2671598E+03 0.2658879E+03 0.2646039E+03 + 0.2633082E+03 0.2620007E+03 0.2606819E+03 0.2593521E+03 0.2580118E+03 + 0.2566614E+03 0.2553013E+03 0.2539324E+03 0.2525548E+03 0.2511696E+03 + 0.2497773E+03 0.2483786E+03 0.2469744E+03 0.2455652E+03 0.2441518E+03 + 0.2427352E+03 0.2413160E+03 0.2398950E+03 0.2384729E+03 0.2370505E+03 + 0.2356284E+03 0.2342072E+03 0.2327878E+03 0.2313706E+03 0.2299562E+03 + 0.2285451E+03 0.2271379E+03 0.2257350E+03 0.2243368E+03 0.2229437E+03 + 0.2215561E+03 0.2201742E+03 0.2187984E+03 0.2174289E+03 0.2160659E+03 + 0.2147097E+03 0.2133603E+03 0.2120180E+03 0.2106829E+03 0.2093551E+03 + 0.2080347E+03 0.2067218E+03 0.2054164E+03 0.2041186E+03 0.2028284E+03 + 0.2015459E+03 0.2002711E+03 0.1990039E+03 0.1977444E+03 0.1964927E+03 + 0.1952486E+03 0.1940121E+03 0.1927834E+03 0.1915622E+03 0.1903487E+03 + 0.1891427E+03 0.1879443E+03 0.1867534E+03 0.1855699E+03 0.1843939E+03 + 0.1832253E+03 0.1820641E+03 0.1809102E+03 0.1797636E+03 0.1786242E+03 + 0.1774920E+03 0.1763670E+03 0.1752491E+03 0.1741382E+03 0.1730344E+03 + 0.1719376E+03 0.1708477E+03 0.1697647E+03 0.1686886E+03 0.1676193E+03 + 0.1665568E+03 0.1655010E+03 0.1644519E+03 0.1634095E+03 0.1623736E+03 + 0.1613444E+03 0.1603216E+03 0.1593053E+03 0.1582955E+03 0.1572921E+03 + 0.1562950E+03 0.1553043E+03 0.1543198E+03 0.1533416E+03 0.1523696E+03 + 0.1514037E+03 0.1504439E+03 0.1494903E+03 0.1485426E+03 0.1476010E+03 + 0.1466654E+03 0.1457357E+03 0.1448119E+03 0.1438939E+03 0.1429818E+03 + 0.1420754E+03 0.1411748E+03 0.1402799E+03 0.1393907E+03 0.1385071E+03 + 0.1376291E+03 0.1367567E+03 0.1358898E+03 0.1350284E+03 0.1341724E+03 + 0.1333219E+03 0.1324768E+03 0.1316370E+03 0.1308026E+03 0.1299734E+03 + 0.1291495E+03 0.1283308E+03 0.1275173E+03 0.1267090E+03 0.1259058E+03 + 0.1251077E+03 0.1243146E+03 0.1235266E+03 0.1227436E+03 0.1219655E+03 + 0.1211924E+03 0.1204241E+03 0.1196608E+03 0.1189023E+03 0.1181485E+03 + 0.1173996E+03 0.1166554E+03 0.1159159E+03 0.1151811E+03 0.1144510E+03 + 0.1137255E+03 0.1130046E+03 0.1122883E+03 0.1115765E+03 0.1108692E+03 + 0.1101664E+03 0.1094680E+03 0.1087741E+03 0.1080846E+03 0.1073995E+03 + 0.2711260E+03 0.2699018E+03 0.2686649E+03 0.2674160E+03 0.2661545E+03 + 0.2648809E+03 0.2635952E+03 0.2622977E+03 0.2609886E+03 0.2596683E+03 + 0.2583370E+03 0.2569955E+03 0.2556439E+03 0.2542828E+03 0.2529130E+03 + 0.2515349E+03 0.2501492E+03 0.2487568E+03 0.2473584E+03 0.2459544E+03 + 0.2445459E+03 0.2431337E+03 0.2417183E+03 0.2403007E+03 0.2388815E+03 + 0.2374616E+03 0.2360415E+03 0.2346221E+03 0.2332039E+03 0.2317877E+03 + 0.2303739E+03 0.2289631E+03 0.2275559E+03 0.2261528E+03 0.2247541E+03 + 0.2233603E+03 0.2219717E+03 0.2205888E+03 0.2192117E+03 0.2178408E+03 + 0.2164763E+03 0.2151184E+03 0.2137673E+03 0.2124232E+03 0.2110861E+03 + 0.2097564E+03 0.2084339E+03 0.2071189E+03 0.2058114E+03 0.2045114E+03 + 0.2032190E+03 0.2019343E+03 0.2006572E+03 0.1993877E+03 0.1981260E+03 + 0.1968720E+03 0.1956256E+03 0.1943869E+03 0.1931558E+03 0.1919324E+03 + 0.1907166E+03 0.1895083E+03 0.1883076E+03 0.1871144E+03 0.1859287E+03 + 0.1847505E+03 0.1835797E+03 0.1824162E+03 0.1812601E+03 0.1801113E+03 + 0.1789697E+03 0.1778353E+03 0.1767081E+03 0.1755880E+03 0.1744750E+03 + 0.1733691E+03 0.1722702E+03 0.1711782E+03 0.1700931E+03 0.1690149E+03 + 0.1679436E+03 0.1668790E+03 0.1658212E+03 0.1647700E+03 0.1637256E+03 + 0.1626877E+03 0.1616565E+03 0.1606317E+03 0.1596135E+03 0.1586017E+03 + 0.1575963E+03 0.1565974E+03 0.1556047E+03 0.1546183E+03 0.1536382E+03 + 0.1526643E+03 0.1516966E+03 0.1507350E+03 0.1497794E+03 0.1488300E+03 + 0.1478866E+03 0.1469491E+03 0.1460176E+03 0.1450920E+03 0.1441723E+03 + 0.1432584E+03 0.1423503E+03 0.1414479E+03 0.1405513E+03 0.1396603E+03 + 0.1387750E+03 0.1378953E+03 0.1370212E+03 0.1361526E+03 0.1352896E+03 + 0.1344320E+03 0.1335798E+03 0.1327330E+03 0.1318917E+03 0.1310556E+03 + 0.1302248E+03 0.1293994E+03 0.1285791E+03 0.1277640E+03 0.1269541E+03 + 0.1261494E+03 0.1253497E+03 0.1245551E+03 0.1237656E+03 0.1229810E+03 + 0.1222015E+03 0.1214268E+03 0.1206571E+03 0.1198923E+03 0.1191323E+03 + 0.1183771E+03 0.1176267E+03 0.1168811E+03 0.1161402E+03 0.1154039E+03 + 0.1146724E+03 0.1139455E+03 0.1132232E+03 0.1125055E+03 0.1117923E+03 + 0.1110837E+03 0.1103795E+03 0.1096798E+03 0.1089846E+03 0.1082937E+03 + 0.2725441E+03 0.2713430E+03 0.2701295E+03 0.2689036E+03 0.2676651E+03 + 0.2664143E+03 0.2651512E+03 0.2638758E+03 0.2625883E+03 0.2612892E+03 + 0.2599785E+03 0.2586566E+03 0.2573239E+03 0.2559809E+03 0.2546283E+03 + 0.2532661E+03 0.2518956E+03 0.2505170E+03 0.2491310E+03 0.2477385E+03 + 0.2463402E+03 0.2449368E+03 0.2435291E+03 0.2421179E+03 0.2407039E+03 + 0.2392879E+03 0.2378707E+03 0.2364530E+03 0.2350355E+03 0.2336189E+03 + 0.2322037E+03 0.2307908E+03 0.2293805E+03 0.2279735E+03 0.2265702E+03 + 0.2251712E+03 0.2237768E+03 0.2223875E+03 0.2210035E+03 0.2196252E+03 + 0.2182530E+03 0.2168870E+03 0.2155276E+03 0.2141748E+03 0.2128288E+03 + 0.2114900E+03 0.2101582E+03 0.2088338E+03 0.2075166E+03 0.2062070E+03 + 0.2049049E+03 0.2036103E+03 0.2023234E+03 0.2010440E+03 0.1997724E+03 + 0.1985084E+03 0.1972520E+03 0.1960034E+03 0.1947624E+03 0.1935290E+03 + 0.1923033E+03 0.1910852E+03 0.1898747E+03 0.1886717E+03 0.1874763E+03 + 0.1862883E+03 0.1851078E+03 0.1839348E+03 0.1827690E+03 0.1816107E+03 + 0.1804597E+03 0.1793159E+03 0.1781794E+03 0.1770500E+03 0.1759278E+03 + 0.1748126E+03 0.1737046E+03 0.1726035E+03 0.1715094E+03 0.1704222E+03 + 0.1693419E+03 0.1682685E+03 0.1672019E+03 0.1661420E+03 0.1650889E+03 + 0.1640424E+03 0.1630025E+03 0.1619693E+03 0.1609426E+03 0.1599223E+03 + 0.1589086E+03 0.1579013E+03 0.1569003E+03 0.1559058E+03 0.1549175E+03 + 0.1539355E+03 0.1529597E+03 0.1519901E+03 0.1510266E+03 0.1500693E+03 + 0.1491180E+03 0.1481727E+03 0.1472334E+03 0.1463002E+03 0.1453728E+03 + 0.1444512E+03 0.1435356E+03 0.1426257E+03 0.1417216E+03 0.1408232E+03 + 0.1399306E+03 0.1390435E+03 0.1381621E+03 0.1372863E+03 0.1364161E+03 + 0.1355513E+03 0.1346921E+03 0.1338383E+03 0.1329899E+03 0.1321469E+03 + 0.1313092E+03 0.1304768E+03 0.1296497E+03 0.1288279E+03 0.1280112E+03 + 0.1271998E+03 0.1263935E+03 0.1255923E+03 0.1247961E+03 0.1240050E+03 + 0.1232190E+03 0.1224379E+03 0.1216618E+03 0.1208906E+03 0.1201242E+03 + 0.1193628E+03 0.1186061E+03 0.1178543E+03 0.1171072E+03 0.1163649E+03 + 0.1156273E+03 0.1148943E+03 0.1141660E+03 0.1134423E+03 0.1127232E+03 + 0.1120086E+03 0.1112986E+03 0.1105931E+03 0.1098920E+03 0.1091954E+03 + 0.2739214E+03 0.2727433E+03 0.2715530E+03 0.2703502E+03 0.2691350E+03 + 0.2679073E+03 0.2666672E+03 0.2654145E+03 0.2641496E+03 0.2628723E+03 + 0.2615832E+03 0.2602823E+03 0.2589699E+03 0.2576465E+03 0.2563123E+03 + 0.2549680E+03 0.2536142E+03 0.2522512E+03 0.2508799E+03 0.2495008E+03 + 0.2481146E+03 0.2467222E+03 0.2453241E+03 0.2439213E+03 0.2425145E+03 + 0.2411044E+03 0.2396919E+03 0.2382777E+03 0.2368625E+03 0.2354472E+03 + 0.2340322E+03 0.2326185E+03 0.2312065E+03 0.2297969E+03 0.2283902E+03 + 0.2269870E+03 0.2255878E+03 0.2241929E+03 0.2228029E+03 0.2214180E+03 + 0.2200387E+03 0.2186652E+03 0.2172979E+03 0.2159369E+03 0.2145825E+03 + 0.2132348E+03 0.2118941E+03 0.2105604E+03 0.2092340E+03 0.2079149E+03 + 0.2066031E+03 0.2052989E+03 0.2040022E+03 0.2027130E+03 0.2014315E+03 + 0.2001575E+03 0.1988913E+03 0.1976327E+03 0.1963817E+03 0.1951385E+03 + 0.1939028E+03 0.1926749E+03 0.1914544E+03 0.1902416E+03 0.1890364E+03 + 0.1878387E+03 0.1866485E+03 0.1854657E+03 0.1842904E+03 0.1831225E+03 + 0.1819619E+03 0.1808087E+03 0.1796627E+03 0.1785240E+03 0.1773924E+03 + 0.1762681E+03 0.1751508E+03 0.1740405E+03 0.1729374E+03 0.1718412E+03 + 0.1707519E+03 0.1696695E+03 0.1685940E+03 0.1675253E+03 0.1664634E+03 + 0.1654082E+03 0.1643597E+03 0.1633178E+03 0.1622826E+03 0.1612539E+03 + 0.1602317E+03 0.1592160E+03 0.1582067E+03 0.1572039E+03 0.1562074E+03 + 0.1552171E+03 0.1542333E+03 0.1532556E+03 0.1522841E+03 0.1513188E+03 + 0.1503596E+03 0.1494064E+03 0.1484594E+03 0.1475183E+03 0.1465832E+03 + 0.1456540E+03 0.1447307E+03 0.1438132E+03 0.1429016E+03 0.1419958E+03 + 0.1410956E+03 0.1402012E+03 0.1393125E+03 0.1384294E+03 0.1375519E+03 + 0.1366800E+03 0.1358136E+03 0.1349526E+03 0.1340972E+03 0.1332471E+03 + 0.1324025E+03 0.1315632E+03 0.1307292E+03 0.1299005E+03 0.1290771E+03 + 0.1282589E+03 0.1274458E+03 0.1266380E+03 0.1258352E+03 0.1250375E+03 + 0.1242449E+03 0.1234574E+03 0.1226748E+03 0.1218971E+03 0.1211244E+03 + 0.1203566E+03 0.1195937E+03 0.1188356E+03 0.1180823E+03 0.1173338E+03 + 0.1165900E+03 0.1158509E+03 0.1151166E+03 0.1143868E+03 0.1136617E+03 + 0.1129412E+03 0.1122253E+03 0.1115139E+03 0.1108070E+03 0.1101046E+03 + 0.2752579E+03 0.2741026E+03 0.2729354E+03 0.2717556E+03 0.2705638E+03 + 0.2693593E+03 0.2681426E+03 0.2669130E+03 0.2656710E+03 0.2644165E+03 + 0.2631498E+03 0.2618707E+03 0.2605797E+03 0.2592769E+03 0.2579629E+03 + 0.2566379E+03 0.2553024E+03 0.2539568E+03 0.2526019E+03 0.2512380E+03 + 0.2498661E+03 0.2484865E+03 0.2471001E+03 0.2457078E+03 0.2443101E+03 + 0.2429080E+03 0.2415021E+03 0.2400933E+03 0.2386824E+03 0.2372700E+03 + 0.2358570E+03 0.2344441E+03 0.2330319E+03 0.2316211E+03 0.2302123E+03 + 0.2288062E+03 0.2274032E+03 0.2260039E+03 0.2246087E+03 0.2232181E+03 + 0.2218325E+03 0.2204522E+03 0.2190776E+03 0.2177089E+03 0.2163465E+03 + 0.2149905E+03 0.2136411E+03 0.2122986E+03 0.2109631E+03 0.2096347E+03 + 0.2083136E+03 0.2069998E+03 0.2056935E+03 0.2043945E+03 0.2031032E+03 + 0.2018195E+03 0.2005433E+03 0.1992748E+03 0.1980140E+03 0.1967608E+03 + 0.1955152E+03 0.1942773E+03 0.1930470E+03 0.1918244E+03 0.1906093E+03 + 0.1894017E+03 0.1882018E+03 0.1870093E+03 0.1858243E+03 0.1846468E+03 + 0.1834766E+03 0.1823138E+03 0.1811584E+03 0.1800102E+03 0.1788692E+03 + 0.1777355E+03 0.1766090E+03 0.1754895E+03 0.1743772E+03 0.1732719E+03 + 0.1721735E+03 0.1710822E+03 0.1699977E+03 0.1689201E+03 0.1678494E+03 + 0.1667854E+03 0.1657282E+03 0.1646776E+03 0.1636337E+03 0.1625965E+03 + 0.1615658E+03 0.1605417E+03 0.1595240E+03 0.1585128E+03 0.1575080E+03 + 0.1565095E+03 0.1555174E+03 0.1545316E+03 0.1535520E+03 0.1525787E+03 + 0.1516115E+03 0.1506504E+03 0.1496954E+03 0.1487466E+03 0.1478036E+03 + 0.1468667E+03 0.1459357E+03 0.1450106E+03 0.1440914E+03 0.1431780E+03 + 0.1422704E+03 0.1413686E+03 0.1404725E+03 0.1395820E+03 0.1386972E+03 + 0.1378180E+03 0.1369444E+03 0.1360763E+03 0.1352137E+03 0.1343566E+03 + 0.1335049E+03 0.1326586E+03 0.1318177E+03 0.1309821E+03 0.1301518E+03 + 0.1293268E+03 0.1285070E+03 0.1276924E+03 0.1268829E+03 0.1260786E+03 + 0.1252794E+03 0.1244853E+03 0.1236962E+03 0.1229121E+03 0.1221329E+03 + 0.1213587E+03 0.1205894E+03 0.1198250E+03 0.1190655E+03 0.1183107E+03 + 0.1175607E+03 0.1168155E+03 0.1160750E+03 0.1153392E+03 0.1146081E+03 + 0.1138816E+03 0.1131597E+03 0.1124424E+03 0.1117296E+03 0.1110214E+03 + 0.2765544E+03 0.2754214E+03 0.2742769E+03 0.2731202E+03 0.2719514E+03 + 0.2707703E+03 0.2695768E+03 0.2683706E+03 0.2671519E+03 0.2659205E+03 + 0.2646767E+03 0.2634203E+03 0.2621515E+03 0.2608706E+03 0.2595779E+03 + 0.2582733E+03 0.2569576E+03 0.2556310E+03 0.2542941E+03 0.2529473E+03 + 0.2515912E+03 0.2502265E+03 0.2488539E+03 0.2474740E+03 0.2460876E+03 + 0.2446954E+03 0.2432982E+03 0.2418968E+03 0.2404921E+03 0.2390846E+03 + 0.2376754E+03 0.2362650E+03 0.2348542E+03 0.2334438E+03 0.2320345E+03 + 0.2306267E+03 0.2292213E+03 0.2278187E+03 0.2264194E+03 0.2250240E+03 + 0.2236331E+03 0.2222467E+03 0.2208656E+03 0.2194899E+03 0.2181200E+03 + 0.2167562E+03 0.2153987E+03 0.2140477E+03 0.2127036E+03 0.2113662E+03 + 0.2100359E+03 0.2087128E+03 0.2073970E+03 0.2060886E+03 0.2047876E+03 + 0.2034941E+03 0.2022081E+03 0.2009298E+03 0.1996590E+03 0.1983959E+03 + 0.1971405E+03 0.1958926E+03 0.1946524E+03 0.1934199E+03 0.1921950E+03 + 0.1909776E+03 0.1897678E+03 0.1885656E+03 0.1873708E+03 0.1861836E+03 + 0.1850038E+03 0.1838314E+03 0.1826664E+03 0.1815087E+03 0.1803583E+03 + 0.1792152E+03 0.1780793E+03 0.1769506E+03 0.1758290E+03 0.1747145E+03 + 0.1736070E+03 0.1725066E+03 0.1714131E+03 0.1703265E+03 0.1692469E+03 + 0.1681741E+03 0.1671080E+03 0.1660488E+03 0.1649962E+03 0.1639503E+03 + 0.1629110E+03 0.1618784E+03 0.1608522E+03 0.1598326E+03 0.1588194E+03 + 0.1578126E+03 0.1568123E+03 0.1558183E+03 0.1548305E+03 0.1538491E+03 + 0.1528738E+03 0.1519048E+03 0.1509418E+03 0.1499850E+03 0.1490343E+03 + 0.1480895E+03 0.1471508E+03 0.1462180E+03 0.1452912E+03 0.1443702E+03 + 0.1434550E+03 0.1425456E+03 0.1416420E+03 0.1407442E+03 0.1398520E+03 + 0.1389655E+03 0.1380846E+03 0.1372093E+03 0.1363395E+03 0.1354753E+03 + 0.1346165E+03 0.1337632E+03 0.1329152E+03 0.1320727E+03 0.1312355E+03 + 0.1304036E+03 0.1295770E+03 0.1287556E+03 0.1279394E+03 0.1271284E+03 + 0.1263225E+03 0.1255218E+03 0.1247261E+03 0.1239354E+03 0.1231498E+03 + 0.1223692E+03 0.1215935E+03 0.1208227E+03 0.1200568E+03 0.1192958E+03 + 0.1185396E+03 0.1177881E+03 0.1170415E+03 0.1162996E+03 0.1155623E+03 + 0.1148298E+03 0.1141019E+03 0.1133786E+03 0.1126599E+03 0.1119457E+03 + 0.2778113E+03 0.2767004E+03 0.2755780E+03 0.2744440E+03 0.2732981E+03 + 0.2721401E+03 0.2709697E+03 0.2697870E+03 0.2685917E+03 0.2673839E+03 + 0.2661632E+03 0.2649300E+03 0.2636841E+03 0.2624258E+03 0.2611551E+03 + 0.2598722E+03 0.2585775E+03 0.2572713E+03 0.2559538E+03 0.2546257E+03 + 0.2532874E+03 0.2519393E+03 0.2505823E+03 0.2492168E+03 0.2478436E+03 + 0.2464635E+03 0.2450770E+03 0.2436851E+03 0.2422885E+03 0.2408880E+03 + 0.2394844E+03 0.2380784E+03 0.2366709E+03 0.2352626E+03 0.2338542E+03 + 0.2324465E+03 0.2310400E+03 0.2296354E+03 0.2282334E+03 0.2268344E+03 + 0.2254390E+03 0.2240477E+03 0.2226609E+03 0.2212789E+03 0.2199023E+03 + 0.2185313E+03 0.2171662E+03 0.2158072E+03 0.2144548E+03 0.2131089E+03 + 0.2117697E+03 0.2104376E+03 0.2091126E+03 0.2077947E+03 0.2064843E+03 + 0.2051812E+03 0.2038855E+03 0.2025974E+03 0.2013169E+03 0.2000439E+03 + 0.1987785E+03 0.1975208E+03 0.1962707E+03 0.1950283E+03 0.1937935E+03 + 0.1925662E+03 0.1913466E+03 0.1901346E+03 0.1889300E+03 0.1877330E+03 + 0.1865435E+03 0.1853615E+03 0.1841869E+03 0.1830196E+03 0.1818597E+03 + 0.1807071E+03 0.1795618E+03 0.1784237E+03 0.1772928E+03 0.1761691E+03 + 0.1750524E+03 0.1739429E+03 0.1728403E+03 0.1717447E+03 0.1706561E+03 + 0.1695743E+03 0.1684994E+03 0.1674313E+03 0.1663700E+03 0.1653154E+03 + 0.1642675E+03 0.1632262E+03 0.1621915E+03 0.1611634E+03 0.1601418E+03 + 0.1591266E+03 0.1581180E+03 0.1571156E+03 0.1561197E+03 0.1551301E+03 + 0.1541467E+03 0.1531696E+03 0.1521986E+03 0.1512339E+03 0.1502752E+03 + 0.1493226E+03 0.1483760E+03 0.1474355E+03 0.1465009E+03 0.1455722E+03 + 0.1446494E+03 0.1437325E+03 0.1428214E+03 0.1419160E+03 0.1410164E+03 + 0.1401226E+03 0.1392343E+03 0.1383517E+03 0.1374747E+03 0.1366033E+03 + 0.1357373E+03 0.1348769E+03 0.1340219E+03 0.1331723E+03 0.1323282E+03 + 0.1314893E+03 0.1306558E+03 0.1298276E+03 0.1290046E+03 0.1281869E+03 + 0.1273743E+03 0.1265669E+03 0.1257646E+03 0.1249674E+03 0.1241752E+03 + 0.1233880E+03 0.1226059E+03 0.1218287E+03 0.1210564E+03 0.1202891E+03 + 0.1195266E+03 0.1187689E+03 0.1180160E+03 0.1172679E+03 0.1165245E+03 + 0.1157859E+03 0.1150519E+03 0.1143226E+03 0.1135979E+03 0.1128778E+03 + 0.2790297E+03 0.2779402E+03 0.2768397E+03 0.2757278E+03 0.2746043E+03 + 0.2734689E+03 0.2723217E+03 0.2711623E+03 0.2699902E+03 0.2688058E+03 + 0.2676086E+03 0.2663989E+03 0.2651764E+03 0.2639411E+03 0.2626932E+03 + 0.2614329E+03 0.2601602E+03 0.2588754E+03 0.2575788E+03 0.2562707E+03 + 0.2549516E+03 0.2536219E+03 0.2522822E+03 0.2509330E+03 0.2495750E+03 + 0.2482088E+03 0.2468351E+03 0.2454548E+03 0.2440684E+03 0.2426768E+03 + 0.2412809E+03 0.2398814E+03 0.2384790E+03 0.2370746E+03 0.2356691E+03 + 0.2342629E+03 0.2328570E+03 0.2314520E+03 0.2300485E+03 0.2286472E+03 + 0.2272486E+03 0.2258533E+03 0.2244619E+03 0.2230746E+03 0.2216921E+03 + 0.2203146E+03 0.2189426E+03 0.2175762E+03 0.2162160E+03 0.2148620E+03 + 0.2135144E+03 0.2121736E+03 0.2108397E+03 0.2095128E+03 0.2081930E+03 + 0.2068805E+03 0.2055753E+03 0.2042775E+03 0.2029873E+03 0.2017045E+03 + 0.2004294E+03 0.1991618E+03 0.1979018E+03 0.1966495E+03 0.1954048E+03 + 0.1941677E+03 0.1929382E+03 0.1917163E+03 0.1905019E+03 0.1892952E+03 + 0.1880959E+03 0.1869041E+03 0.1857198E+03 0.1845430E+03 0.1833735E+03 + 0.1822114E+03 0.1810566E+03 0.1799091E+03 0.1787688E+03 0.1776357E+03 + 0.1765098E+03 0.1753910E+03 0.1742793E+03 0.1731746E+03 0.1720769E+03 + 0.1709861E+03 0.1699023E+03 0.1688253E+03 0.1677552E+03 0.1666918E+03 + 0.1656351E+03 0.1645852E+03 0.1635419E+03 0.1625052E+03 0.1614751E+03 + 0.1604515E+03 0.1594345E+03 0.1584238E+03 0.1574195E+03 0.1564217E+03 + 0.1554301E+03 0.1544449E+03 0.1534658E+03 0.1524931E+03 0.1515264E+03 + 0.1505659E+03 0.1496114E+03 0.1486630E+03 0.1477207E+03 0.1467843E+03 + 0.1458538E+03 0.1449292E+03 0.1440105E+03 0.1430977E+03 0.1421906E+03 + 0.1412892E+03 0.1403936E+03 0.1395036E+03 0.1386193E+03 0.1377406E+03 + 0.1368675E+03 0.1359999E+03 0.1351378E+03 0.1342812E+03 0.1334300E+03 + 0.1325842E+03 0.1317437E+03 0.1309086E+03 0.1300788E+03 0.1292542E+03 + 0.1284349E+03 0.1276207E+03 0.1268117E+03 0.1260079E+03 0.1252091E+03 + 0.1244154E+03 0.1236267E+03 0.1228431E+03 0.1220644E+03 0.1212906E+03 + 0.1205218E+03 0.1197578E+03 0.1189986E+03 0.1182443E+03 0.1174947E+03 + 0.1167500E+03 0.1160099E+03 0.1152745E+03 0.1145438E+03 0.1138177E+03 + 0.2802106E+03 0.2791419E+03 0.2780625E+03 0.2769722E+03 0.2758707E+03 + 0.2747577E+03 0.2736330E+03 0.2724964E+03 0.2713476E+03 0.2701866E+03 + 0.2690128E+03 0.2678265E+03 0.2666275E+03 0.2654157E+03 0.2641913E+03 + 0.2629539E+03 0.2617040E+03 0.2604416E+03 0.2591667E+03 0.2578800E+03 + 0.2565815E+03 0.2552716E+03 0.2539510E+03 0.2526197E+03 0.2512786E+03 + 0.2499284E+03 0.2485694E+03 0.2472025E+03 0.2458285E+03 0.2444479E+03 + 0.2430617E+03 0.2416707E+03 0.2402755E+03 0.2388770E+03 0.2374761E+03 + 0.2360734E+03 0.2346697E+03 0.2332659E+03 0.2318626E+03 0.2304604E+03 + 0.2290600E+03 0.2276620E+03 0.2262671E+03 0.2248756E+03 0.2234881E+03 + 0.2221050E+03 0.2207268E+03 0.2193538E+03 0.2179864E+03 0.2166248E+03 + 0.2152694E+03 0.2139203E+03 0.2125779E+03 0.2112422E+03 0.2099134E+03 + 0.2085917E+03 0.2072772E+03 0.2059700E+03 0.2046701E+03 0.2033777E+03 + 0.2020928E+03 0.2008155E+03 0.1995457E+03 0.1982835E+03 0.1970289E+03 + 0.1957819E+03 0.1945425E+03 0.1933108E+03 0.1920866E+03 0.1908700E+03 + 0.1896610E+03 0.1884594E+03 0.1872655E+03 0.1860789E+03 0.1848998E+03 + 0.1837281E+03 0.1825637E+03 0.1814067E+03 0.1802570E+03 0.1791145E+03 + 0.1779793E+03 0.1768512E+03 0.1757302E+03 0.1746164E+03 0.1735096E+03 + 0.1724097E+03 0.1713169E+03 0.1702310E+03 0.1691519E+03 0.1680797E+03 + 0.1670143E+03 0.1659556E+03 0.1649036E+03 0.1638583E+03 0.1628196E+03 + 0.1617875E+03 0.1607619E+03 0.1597429E+03 0.1587302E+03 0.1577241E+03 + 0.1567243E+03 0.1557308E+03 0.1547436E+03 0.1537627E+03 0.1527880E+03 + 0.1518195E+03 0.1508571E+03 0.1499008E+03 0.1489506E+03 0.1480064E+03 + 0.1470682E+03 0.1461360E+03 0.1452096E+03 0.1442891E+03 0.1433745E+03 + 0.1424656E+03 0.1415625E+03 0.1406652E+03 0.1397735E+03 0.1388875E+03 + 0.1380071E+03 0.1371323E+03 0.1362630E+03 0.1353992E+03 0.1345409E+03 + 0.1336881E+03 0.1328406E+03 0.1319986E+03 0.1311618E+03 0.1303304E+03 + 0.1295042E+03 0.1286833E+03 0.1278676E+03 0.1270570E+03 0.1262516E+03 + 0.1254513E+03 0.1246561E+03 0.1238659E+03 0.1230807E+03 0.1223005E+03 + 0.1215252E+03 0.1207549E+03 0.1199894E+03 0.1192288E+03 0.1184730E+03 + 0.1177220E+03 0.1169758E+03 0.1162343E+03 0.1154975E+03 0.1147653E+03 + 0.2813550E+03 0.2803063E+03 0.2792475E+03 0.2781781E+03 0.2770980E+03 + 0.2760068E+03 0.2749042E+03 0.2737901E+03 0.2726641E+03 0.2715260E+03 + 0.2703756E+03 0.2692127E+03 0.2680374E+03 0.2668492E+03 0.2656482E+03 + 0.2644343E+03 0.2632078E+03 0.2619685E+03 0.2607164E+03 0.2594519E+03 + 0.2581750E+03 0.2568862E+03 0.2555858E+03 0.2542742E+03 0.2529517E+03 + 0.2516191E+03 0.2502767E+03 0.2489253E+03 0.2475656E+03 0.2461980E+03 + 0.2448236E+03 0.2434431E+03 0.2420571E+03 0.2406666E+03 0.2392723E+03 + 0.2378750E+03 0.2364756E+03 0.2350747E+03 0.2336732E+03 0.2322717E+03 + 0.2308710E+03 0.2294717E+03 0.2280746E+03 0.2266800E+03 0.2252887E+03 + 0.2239011E+03 0.2225177E+03 0.2211388E+03 0.2197650E+03 0.2183966E+03 + 0.2170338E+03 0.2156771E+03 0.2143265E+03 0.2129825E+03 0.2116451E+03 + 0.2103145E+03 0.2089909E+03 0.2076744E+03 0.2063652E+03 0.2050633E+03 + 0.2037688E+03 0.2024817E+03 0.2012022E+03 0.1999302E+03 0.1986658E+03 + 0.1974090E+03 0.1961597E+03 0.1949181E+03 0.1936841E+03 0.1924576E+03 + 0.1912388E+03 0.1900275E+03 0.1888237E+03 0.1876274E+03 0.1864386E+03 + 0.1852573E+03 0.1840833E+03 0.1829167E+03 0.1817575E+03 0.1806056E+03 + 0.1794610E+03 0.1783235E+03 0.1771933E+03 0.1760701E+03 0.1749541E+03 + 0.1738452E+03 0.1727432E+03 0.1716483E+03 0.1705602E+03 0.1694791E+03 + 0.1684048E+03 0.1673373E+03 0.1662766E+03 0.1652226E+03 0.1641753E+03 + 0.1631345E+03 0.1621005E+03 0.1610729E+03 0.1600519E+03 0.1590373E+03 + 0.1580292E+03 0.1570274E+03 0.1560320E+03 0.1550430E+03 0.1540602E+03 + 0.1530836E+03 0.1521132E+03 0.1511489E+03 0.1501908E+03 0.1492388E+03 + 0.1482927E+03 0.1473527E+03 0.1464187E+03 0.1454905E+03 0.1445682E+03 + 0.1436518E+03 0.1427412E+03 0.1418364E+03 0.1409373E+03 0.1400439E+03 + 0.1391561E+03 0.1382740E+03 0.1373975E+03 0.1365266E+03 0.1356611E+03 + 0.1348012E+03 0.1339467E+03 0.1330976E+03 0.1322539E+03 0.1314155E+03 + 0.1305825E+03 0.1297547E+03 0.1289322E+03 0.1281149E+03 0.1273028E+03 + 0.1264958E+03 0.1256940E+03 0.1248972E+03 0.1241055E+03 0.1233188E+03 + 0.1225371E+03 0.1217603E+03 0.1209885E+03 0.1202215E+03 0.1194595E+03 + 0.1187022E+03 0.1179498E+03 0.1172021E+03 0.1164591E+03 0.1157209E+03 + 0.2824640E+03 0.2814348E+03 0.2803958E+03 0.2793467E+03 0.2782873E+03 + 0.2772172E+03 0.2761363E+03 0.2750441E+03 0.2739404E+03 0.2728250E+03 + 0.2716977E+03 0.2705579E+03 0.2694058E+03 0.2682412E+03 0.2670639E+03 + 0.2658737E+03 0.2646708E+03 0.2634548E+03 0.2622260E+03 0.2609844E+03 + 0.2597303E+03 0.2584636E+03 0.2571847E+03 0.2558939E+03 0.2545915E+03 + 0.2532781E+03 0.2519540E+03 0.2506199E+03 0.2492763E+03 0.2479238E+03 + 0.2465633E+03 0.2451953E+03 0.2438206E+03 0.2424401E+03 0.2410546E+03 + 0.2396647E+03 0.2382714E+03 0.2368754E+03 0.2354775E+03 0.2340785E+03 + 0.2326792E+03 0.2312803E+03 0.2298824E+03 0.2284861E+03 0.2270922E+03 + 0.2257012E+03 0.2243136E+03 0.2229299E+03 0.2215506E+03 0.2201761E+03 + 0.2188067E+03 0.2174429E+03 0.2160849E+03 0.2147329E+03 0.2133874E+03 + 0.2120483E+03 0.2107159E+03 0.2093905E+03 0.2080722E+03 0.2067609E+03 + 0.2054570E+03 0.2041604E+03 0.2028712E+03 0.2015896E+03 0.2003154E+03 + 0.1990487E+03 0.1977897E+03 0.1965382E+03 0.1952943E+03 0.1940580E+03 + 0.1928293E+03 0.1916082E+03 0.1903946E+03 0.1891886E+03 0.1879901E+03 + 0.1867990E+03 0.1856154E+03 0.1844392E+03 0.1832705E+03 0.1821090E+03 + 0.1809549E+03 0.1798080E+03 0.1786684E+03 0.1775360E+03 0.1764107E+03 + 0.1752925E+03 0.1741814E+03 0.1730774E+03 0.1719803E+03 0.1708902E+03 + 0.1698069E+03 0.1687306E+03 0.1676610E+03 0.1665982E+03 0.1655422E+03 + 0.1644928E+03 0.1634501E+03 0.1624140E+03 0.1613845E+03 0.1603615E+03 + 0.1593450E+03 0.1583349E+03 0.1573312E+03 0.1563339E+03 0.1553429E+03 + 0.1543582E+03 0.1533797E+03 0.1524074E+03 0.1514413E+03 0.1504814E+03 + 0.1495275E+03 0.1485796E+03 0.1476378E+03 0.1467019E+03 0.1457719E+03 + 0.1448479E+03 0.1439297E+03 0.1430173E+03 0.1421108E+03 0.1412099E+03 + 0.1403148E+03 0.1394254E+03 0.1385415E+03 0.1376633E+03 0.1367907E+03 + 0.1359236E+03 0.1350620E+03 0.1342058E+03 0.1333551E+03 0.1325097E+03 + 0.1316698E+03 0.1308351E+03 0.1300057E+03 0.1291817E+03 0.1283628E+03 + 0.1275491E+03 0.1267405E+03 0.1259371E+03 0.1251388E+03 0.1243456E+03 + 0.1235574E+03 0.1227741E+03 0.1219959E+03 0.1212225E+03 0.1204541E+03 + 0.1196906E+03 0.1189318E+03 0.1181779E+03 0.1174288E+03 0.1166844E+03 + 0.2835388E+03 0.2825283E+03 0.2815084E+03 0.2804789E+03 0.2794395E+03 + 0.2783900E+03 0.2773300E+03 0.2762591E+03 0.2751772E+03 0.2740839E+03 + 0.2729789E+03 0.2718621E+03 0.2707331E+03 0.2695919E+03 0.2684380E+03 + 0.2672717E+03 0.2660922E+03 0.2649001E+03 0.2636949E+03 0.2624767E+03 + 0.2612458E+03 0.2600020E+03 0.2587455E+03 0.2574767E+03 0.2561956E+03 + 0.2549029E+03 0.2535987E+03 0.2522834E+03 0.2509577E+03 0.2496222E+03 + 0.2482774E+03 0.2469240E+03 0.2455628E+03 0.2441943E+03 0.2428195E+03 + 0.2414392E+03 0.2400540E+03 0.2386649E+03 0.2372727E+03 0.2358781E+03 + 0.2344819E+03 0.2330850E+03 0.2316880E+03 0.2302916E+03 0.2288965E+03 + 0.2275035E+03 0.2261130E+03 0.2247255E+03 0.2233418E+03 0.2219621E+03 + 0.2205870E+03 0.2192168E+03 0.2178520E+03 0.2164928E+03 0.2151396E+03 + 0.2137925E+03 0.2124518E+03 0.2111178E+03 0.2097906E+03 0.2084703E+03 + 0.2071572E+03 0.2058512E+03 0.2045526E+03 0.2032613E+03 0.2019775E+03 + 0.2007011E+03 0.1994323E+03 0.1981710E+03 0.1969173E+03 0.1956712E+03 + 0.1944327E+03 0.1932017E+03 0.1919783E+03 0.1907625E+03 0.1895542E+03 + 0.1883534E+03 0.1871601E+03 0.1859742E+03 0.1847958E+03 0.1836248E+03 + 0.1824612E+03 0.1813048E+03 0.1801557E+03 0.1790139E+03 0.1778793E+03 + 0.1767519E+03 0.1756316E+03 0.1745184E+03 0.1734122E+03 0.1723129E+03 + 0.1712207E+03 0.1701354E+03 0.1690569E+03 0.1679853E+03 0.1669205E+03 + 0.1658624E+03 0.1648110E+03 0.1637663E+03 0.1627282E+03 0.1616967E+03 + 0.1606717E+03 0.1596532E+03 0.1586412E+03 0.1576356E+03 0.1566363E+03 + 0.1556434E+03 0.1546568E+03 0.1536764E+03 0.1527023E+03 0.1517343E+03 + 0.1507724E+03 0.1498167E+03 0.1488670E+03 0.1479234E+03 0.1469857E+03 + 0.1460539E+03 0.1451281E+03 0.1442081E+03 0.1432940E+03 0.1423857E+03 + 0.1414831E+03 0.1405862E+03 0.1396951E+03 0.1388095E+03 0.1379296E+03 + 0.1370553E+03 0.1361865E+03 0.1353232E+03 0.1344654E+03 0.1336130E+03 + 0.1327661E+03 0.1319245E+03 0.1310882E+03 0.1302572E+03 0.1294315E+03 + 0.1286111E+03 0.1277958E+03 0.1269857E+03 0.1261808E+03 0.1253809E+03 + 0.1245861E+03 0.1237964E+03 0.1230116E+03 0.1222318E+03 0.1214570E+03 + 0.1206871E+03 0.1199221E+03 0.1191619E+03 0.1184065E+03 0.1176560E+03 + 0.2845808E+03 0.2835882E+03 0.2825866E+03 0.2815757E+03 0.2805559E+03 + 0.2795262E+03 0.2784862E+03 0.2774361E+03 0.2763753E+03 0.2753036E+03 + 0.2742206E+03 0.2731261E+03 0.2720198E+03 0.2709015E+03 0.2697710E+03 + 0.2686279E+03 0.2674722E+03 0.2663037E+03 0.2651224E+03 0.2639280E+03 + 0.2627207E+03 0.2615004E+03 0.2602671E+03 0.2590210E+03 0.2577623E+03 + 0.2564913E+03 0.2552082E+03 0.2539133E+03 0.2526071E+03 0.2512902E+03 + 0.2499629E+03 0.2486261E+03 0.2472800E+03 0.2459257E+03 0.2445639E+03 + 0.2431951E+03 0.2418202E+03 0.2404401E+03 0.2390555E+03 0.2376673E+03 + 0.2362763E+03 0.2348831E+03 0.2334889E+03 0.2320940E+03 0.2306994E+03 + 0.2293058E+03 0.2279137E+03 0.2265239E+03 0.2251368E+03 0.2237531E+03 + 0.2223732E+03 0.2209977E+03 0.2196268E+03 0.2182611E+03 0.2169008E+03 + 0.2155463E+03 0.2141978E+03 0.2128557E+03 0.2115200E+03 0.2101911E+03 + 0.2088690E+03 0.2075539E+03 0.2062460E+03 0.2049453E+03 0.2036519E+03 + 0.2023660E+03 0.2010875E+03 0.1998165E+03 0.1985530E+03 0.1972971E+03 + 0.1960487E+03 0.1948079E+03 0.1935747E+03 0.1923491E+03 0.1911310E+03 + 0.1899204E+03 0.1887174E+03 0.1875218E+03 0.1863337E+03 0.1851531E+03 + 0.1839798E+03 0.1828140E+03 0.1816554E+03 0.1805041E+03 0.1793601E+03 + 0.1782234E+03 0.1770937E+03 0.1759713E+03 0.1748559E+03 0.1737476E+03 + 0.1726463E+03 0.1715519E+03 0.1704645E+03 0.1693839E+03 0.1683103E+03 + 0.1672434E+03 0.1661833E+03 0.1651298E+03 0.1640831E+03 0.1630430E+03 + 0.1620095E+03 0.1609825E+03 0.1599620E+03 0.1589481E+03 0.1579405E+03 + 0.1569393E+03 0.1559445E+03 0.1549559E+03 0.1539737E+03 0.1529977E+03 + 0.1520278E+03 0.1510641E+03 0.1501065E+03 0.1491550E+03 0.1482095E+03 + 0.1472700E+03 0.1463365E+03 0.1454088E+03 0.1444871E+03 0.1435712E+03 + 0.1426611E+03 0.1417568E+03 0.1408582E+03 0.1399653E+03 0.1390780E+03 + 0.1381964E+03 0.1373204E+03 0.1364499E+03 0.1355850E+03 0.1347255E+03 + 0.1338715E+03 0.1330229E+03 0.1321796E+03 0.1313418E+03 0.1305092E+03 + 0.1296819E+03 0.1288599E+03 0.1280430E+03 0.1272314E+03 0.1264248E+03 + 0.1256234E+03 0.1248271E+03 0.1240358E+03 0.1232496E+03 0.1224683E+03 + 0.1216920E+03 0.1209206E+03 0.1201541E+03 0.1193924E+03 0.1186356E+03 + 0.2855910E+03 0.2846154E+03 0.2836314E+03 0.2826389E+03 0.2816375E+03 + 0.2806268E+03 0.2796065E+03 0.2785764E+03 0.2775360E+03 0.2764851E+03 + 0.2754234E+03 0.2743507E+03 0.2732665E+03 0.2721705E+03 0.2710629E+03 + 0.2699431E+03 0.2688108E+03 0.2676659E+03 0.2665083E+03 0.2653378E+03 + 0.2641542E+03 0.2629576E+03 0.2617482E+03 0.2605254E+03 0.2592898E+03 + 0.2580415E+03 0.2567805E+03 0.2555072E+03 0.2542220E+03 0.2529251E+03 + 0.2516170E+03 0.2502983E+03 0.2489696E+03 0.2476314E+03 0.2462843E+03 + 0.2449291E+03 0.2435666E+03 0.2421976E+03 0.2408228E+03 0.2394430E+03 + 0.2380591E+03 0.2366719E+03 0.2352822E+03 0.2338908E+03 0.2324984E+03 + 0.2311058E+03 0.2297137E+03 0.2283229E+03 0.2269339E+03 0.2255473E+03 + 0.2241638E+03 0.2227839E+03 0.2214080E+03 0.2200366E+03 0.2186701E+03 + 0.2173088E+03 0.2159532E+03 0.2146034E+03 0.2132598E+03 0.2119225E+03 + 0.2105919E+03 0.2092681E+03 0.2079511E+03 0.2066413E+03 0.2053386E+03 + 0.2040432E+03 0.2027551E+03 0.2014745E+03 0.2002013E+03 0.1989356E+03 + 0.1976775E+03 0.1964269E+03 0.1951839E+03 0.1939484E+03 0.1927205E+03 + 0.1915002E+03 0.1902874E+03 0.1890821E+03 0.1878843E+03 0.1866939E+03 + 0.1855110E+03 0.1843356E+03 0.1831674E+03 0.1820067E+03 0.1808532E+03 + 0.1797070E+03 0.1785680E+03 0.1774363E+03 0.1763116E+03 0.1751941E+03 + 0.1740836E+03 0.1729802E+03 0.1718837E+03 0.1707942E+03 0.1697116E+03 + 0.1686358E+03 0.1675669E+03 0.1665047E+03 0.1654492E+03 0.1644005E+03 + 0.1633584E+03 0.1623228E+03 0.1612939E+03 0.1602715E+03 0.1592555E+03 + 0.1582460E+03 0.1572429E+03 0.1562461E+03 0.1552557E+03 0.1542715E+03 + 0.1532936E+03 0.1523219E+03 0.1513563E+03 0.1503969E+03 0.1494435E+03 + 0.1484962E+03 0.1475549E+03 0.1466195E+03 0.1456901E+03 0.1447666E+03 + 0.1438489E+03 0.1429371E+03 0.1420310E+03 0.1411307E+03 0.1402361E+03 + 0.1393471E+03 0.1384638E+03 0.1375861E+03 0.1367139E+03 0.1358473E+03 + 0.1349861E+03 0.1341305E+03 0.1332802E+03 0.1324354E+03 0.1315959E+03 + 0.1307617E+03 0.1299328E+03 0.1291091E+03 0.1282907E+03 0.1274775E+03 + 0.1266694E+03 0.1258665E+03 0.1250686E+03 0.1242758E+03 0.1234880E+03 + 0.1227052E+03 0.1219274E+03 0.1211545E+03 0.1203865E+03 0.1196234E+03 + 0.2865706E+03 0.2856115E+03 0.2846445E+03 0.2836693E+03 0.2826856E+03 + 0.2816933E+03 0.2806917E+03 0.2796808E+03 0.2786601E+03 0.2776295E+03 + 0.2765884E+03 0.2755368E+03 0.2744742E+03 0.2734003E+03 0.2723148E+03 + 0.2712178E+03 0.2701082E+03 0.2689868E+03 0.2678527E+03 0.2667058E+03 + 0.2655461E+03 0.2643735E+03 0.2631878E+03 0.2619889E+03 0.2607769E+03 + 0.2595520E+03 0.2583141E+03 0.2570633E+03 0.2558000E+03 0.2545246E+03 + 0.2532371E+03 0.2519382E+03 0.2506283E+03 0.2493079E+03 0.2479776E+03 + 0.2466381E+03 0.2452900E+03 0.2439341E+03 0.2425712E+03 0.2412020E+03 + 0.2398273E+03 0.2384480E+03 0.2370649E+03 0.2356788E+03 0.2342905E+03 + 0.2329008E+03 0.2315104E+03 0.2301202E+03 0.2287308E+03 0.2273429E+03 + 0.2259570E+03 0.2245739E+03 0.2231941E+03 0.2218180E+03 0.2204461E+03 + 0.2190789E+03 0.2177168E+03 0.2163601E+03 0.2150091E+03 0.2136641E+03 + 0.2123254E+03 0.2109931E+03 0.2096675E+03 0.2083488E+03 0.2070370E+03 + 0.2057323E+03 0.2044349E+03 0.2031448E+03 0.2018620E+03 0.2005867E+03 + 0.1993189E+03 0.1980585E+03 0.1968057E+03 0.1955605E+03 0.1943228E+03 + 0.1930926E+03 0.1918700E+03 0.1906549E+03 0.1894474E+03 0.1882474E+03 + 0.1870548E+03 0.1858697E+03 0.1846919E+03 0.1835216E+03 0.1823586E+03 + 0.1812029E+03 0.1800546E+03 0.1789134E+03 0.1777795E+03 0.1766526E+03 + 0.1755330E+03 0.1744204E+03 0.1733148E+03 0.1722162E+03 0.1711246E+03 + 0.1700399E+03 0.1689621E+03 0.1678910E+03 0.1668268E+03 0.1657693E+03 + 0.1647185E+03 0.1636744E+03 0.1626369E+03 0.1616059E+03 0.1605815E+03 + 0.1595636E+03 0.1585521E+03 0.1575471E+03 0.1565484E+03 0.1555560E+03 + 0.1545700E+03 0.1535901E+03 0.1526166E+03 0.1516491E+03 0.1506878E+03 + 0.1497326E+03 0.1487835E+03 0.1478403E+03 0.1469032E+03 0.1459720E+03 + 0.1450466E+03 0.1441272E+03 0.1432136E+03 0.1423057E+03 0.1414037E+03 + 0.1405073E+03 0.1396167E+03 0.1387316E+03 0.1378522E+03 0.1369784E+03 + 0.1361101E+03 0.1352473E+03 0.1343899E+03 0.1335380E+03 0.1326915E+03 + 0.1318504E+03 0.1310146E+03 0.1301841E+03 0.1293589E+03 0.1285389E+03 + 0.1277241E+03 0.1269144E+03 0.1261099E+03 0.1253105E+03 0.1245162E+03 + 0.1237269E+03 0.1229426E+03 0.1221632E+03 0.1213889E+03 0.1206194E+03 + 0.2875207E+03 0.2865776E+03 0.2856266E+03 0.2846679E+03 0.2837015E+03 + 0.2827266E+03 0.2817432E+03 0.2807507E+03 0.2797491E+03 0.2787379E+03 + 0.2777167E+03 0.2766854E+03 0.2756436E+03 0.2745911E+03 0.2735274E+03 + 0.2724522E+03 0.2713654E+03 0.2702670E+03 0.2691559E+03 0.2680325E+03 + 0.2668964E+03 0.2657476E+03 0.2645857E+03 0.2634109E+03 0.2622229E+03 + 0.2610216E+03 0.2598073E+03 0.2585798E+03 0.2573395E+03 0.2560864E+03 + 0.2548208E+03 0.2535430E+03 0.2522535E+03 0.2509526E+03 0.2496408E+03 + 0.2483188E+03 0.2469870E+03 0.2456464E+03 0.2442973E+03 0.2429408E+03 + 0.2415775E+03 0.2402082E+03 0.2388338E+03 0.2374550E+03 0.2360728E+03 + 0.2346879E+03 0.2333012E+03 0.2319133E+03 0.2305252E+03 0.2291374E+03 + 0.2277507E+03 0.2263658E+03 0.2249832E+03 0.2236036E+03 0.2222275E+03 + 0.2208553E+03 0.2194876E+03 0.2181247E+03 0.2167670E+03 0.2154149E+03 + 0.2140686E+03 0.2127284E+03 0.2113946E+03 0.2100673E+03 0.2087468E+03 + 0.2074332E+03 0.2061266E+03 0.2048272E+03 0.2035350E+03 0.2022502E+03 + 0.2009727E+03 0.1997027E+03 0.1984402E+03 0.1971852E+03 0.1959377E+03 + 0.1946978E+03 0.1934654E+03 0.1922405E+03 0.1910232E+03 0.1898134E+03 + 0.1886111E+03 0.1874163E+03 0.1862289E+03 0.1850490E+03 0.1838764E+03 + 0.1827112E+03 0.1815533E+03 0.1804028E+03 0.1792594E+03 0.1781233E+03 + 0.1769943E+03 0.1758725E+03 0.1747577E+03 0.1736500E+03 0.1725493E+03 + 0.1714556E+03 0.1703688E+03 0.1692889E+03 0.1682158E+03 0.1671495E+03 + 0.1660900E+03 0.1650371E+03 0.1639910E+03 0.1629515E+03 0.1619185E+03 + 0.1608921E+03 0.1598723E+03 0.1588588E+03 0.1578519E+03 0.1568512E+03 + 0.1558569E+03 0.1548690E+03 0.1538873E+03 0.1529118E+03 0.1519425E+03 + 0.1509793E+03 0.1500223E+03 0.1490713E+03 0.1481263E+03 0.1471874E+03 + 0.1462543E+03 0.1453272E+03 0.1444060E+03 0.1434906E+03 0.1425810E+03 + 0.1416772E+03 0.1407791E+03 0.1398867E+03 0.1390000E+03 0.1381189E+03 + 0.1372433E+03 0.1363734E+03 0.1355089E+03 0.1346499E+03 0.1337964E+03 + 0.1329482E+03 0.1321055E+03 0.1312681E+03 0.1304360E+03 0.1296091E+03 + 0.1287875E+03 0.1279712E+03 0.1271600E+03 0.1263539E+03 0.1255529E+03 + 0.1247571E+03 0.1239662E+03 0.1231804E+03 0.1223996E+03 0.1216237E+03 + 0.2884430E+03 0.2875147E+03 0.2865791E+03 0.2856365E+03 0.2846863E+03 + 0.2837283E+03 0.2827620E+03 0.2817874E+03 0.2808039E+03 0.2798114E+03 + 0.2788095E+03 0.2777979E+03 0.2767762E+03 0.2757442E+03 0.2747016E+03 + 0.2736480E+03 0.2725831E+03 0.2715067E+03 0.2704183E+03 0.2693181E+03 + 0.2682053E+03 0.2670801E+03 0.2659421E+03 0.2647911E+03 0.2636271E+03 + 0.2624499E+03 0.2612595E+03 0.2600558E+03 0.2588390E+03 0.2576091E+03 + 0.2563663E+03 0.2551108E+03 0.2538429E+03 0.2525628E+03 0.2512711E+03 + 0.2499683E+03 0.2486547E+03 0.2473310E+03 0.2459979E+03 0.2446561E+03 + 0.2433062E+03 0.2419491E+03 0.2405855E+03 0.2392162E+03 0.2378422E+03 + 0.2364641E+03 0.2350829E+03 0.2336994E+03 0.2323143E+03 0.2309284E+03 + 0.2295425E+03 0.2281573E+03 0.2267735E+03 0.2253917E+03 0.2240125E+03 + 0.2226365E+03 0.2212641E+03 0.2198960E+03 0.2185325E+03 0.2171739E+03 + 0.2158207E+03 0.2144732E+03 0.2131317E+03 0.2117964E+03 0.2104675E+03 + 0.2091452E+03 0.2078298E+03 0.2065214E+03 0.2052200E+03 0.2039258E+03 + 0.2026389E+03 0.2013593E+03 0.2000872E+03 0.1988225E+03 0.1975653E+03 + 0.1963156E+03 0.1950734E+03 0.1938388E+03 0.1926117E+03 0.1913922E+03 + 0.1901801E+03 0.1889756E+03 0.1877785E+03 0.1865889E+03 0.1854067E+03 + 0.1842319E+03 0.1830645E+03 0.1819044E+03 0.1807516E+03 0.1796061E+03 + 0.1784678E+03 0.1773366E+03 0.1762126E+03 0.1750957E+03 0.1739859E+03 + 0.1728831E+03 0.1717872E+03 0.1706984E+03 0.1696163E+03 0.1685412E+03 + 0.1674728E+03 0.1664112E+03 0.1653564E+03 0.1643082E+03 0.1632667E+03 + 0.1622317E+03 0.1612034E+03 0.1601815E+03 0.1591661E+03 0.1581572E+03 + 0.1571546E+03 0.1561584E+03 0.1551685E+03 0.1541849E+03 0.1532076E+03 + 0.1522364E+03 0.1512714E+03 0.1503125E+03 0.1493596E+03 0.1484129E+03 + 0.1474721E+03 0.1465372E+03 0.1456083E+03 0.1446853E+03 0.1437682E+03 + 0.1428568E+03 0.1419513E+03 0.1410515E+03 0.1401573E+03 0.1392689E+03 + 0.1383861E+03 0.1375088E+03 0.1366371E+03 0.1357710E+03 0.1349104E+03 + 0.1340552E+03 0.1332054E+03 0.1323610E+03 0.1315220E+03 0.1306883E+03 + 0.1298598E+03 0.1290367E+03 0.1282187E+03 0.1274059E+03 0.1265983E+03 + 0.1257958E+03 0.1249984E+03 0.1242060E+03 0.1234187E+03 0.1226363E+03 + 0.2893380E+03 0.2884240E+03 0.2875036E+03 0.2865759E+03 0.2856413E+03 + 0.2846994E+03 0.2837497E+03 0.2827921E+03 0.2818260E+03 0.2808514E+03 + 0.2798679E+03 0.2788752E+03 0.2778730E+03 0.2768608E+03 0.2758386E+03 + 0.2748057E+03 0.2737621E+03 0.2727074E+03 0.2716412E+03 0.2705635E+03 + 0.2694736E+03 0.2683716E+03 0.2672570E+03 0.2661297E+03 0.2649897E+03 + 0.2638364E+03 0.2626701E+03 0.2614905E+03 0.2602976E+03 0.2590915E+03 + 0.2578722E+03 0.2566398E+03 0.2553945E+03 0.2541365E+03 0.2528662E+03 + 0.2515839E+03 0.2502901E+03 0.2489853E+03 0.2476699E+03 0.2463447E+03 + 0.2450103E+03 0.2436675E+03 0.2423168E+03 0.2409592E+03 0.2395954E+03 + 0.2382263E+03 0.2368527E+03 0.2354754E+03 0.2340954E+03 0.2327132E+03 + 0.2313299E+03 0.2299461E+03 0.2285626E+03 0.2271801E+03 0.2257993E+03 + 0.2244207E+03 0.2230449E+03 0.2216726E+03 0.2203042E+03 0.2189401E+03 + 0.2175808E+03 0.2162267E+03 0.2148781E+03 0.2135352E+03 0.2121985E+03 + 0.2108680E+03 0.2095442E+03 0.2082270E+03 0.2069166E+03 0.2056134E+03 + 0.2043172E+03 0.2030282E+03 0.2017466E+03 0.2004723E+03 0.1992054E+03 + 0.1979461E+03 0.1966942E+03 0.1954498E+03 0.1942130E+03 0.1929837E+03 + 0.1917618E+03 0.1905475E+03 0.1893407E+03 0.1881414E+03 0.1869496E+03 + 0.1857652E+03 0.1845882E+03 0.1834185E+03 0.1822562E+03 0.1811012E+03 + 0.1799535E+03 0.1788130E+03 0.1776797E+03 0.1765535E+03 0.1754345E+03 + 0.1743225E+03 0.1732176E+03 0.1721196E+03 0.1710286E+03 0.1699445E+03 + 0.1688673E+03 0.1677969E+03 0.1667332E+03 0.1656763E+03 0.1646261E+03 + 0.1635826E+03 0.1625457E+03 0.1615153E+03 0.1604915E+03 0.1594741E+03 + 0.1584632E+03 0.1574587E+03 0.1564606E+03 0.1554688E+03 0.1544833E+03 + 0.1535040E+03 0.1525310E+03 0.1515641E+03 0.1506033E+03 0.1496486E+03 + 0.1487000E+03 0.1477574E+03 0.1468208E+03 0.1458901E+03 0.1449653E+03 + 0.1440464E+03 0.1431333E+03 0.1422259E+03 0.1413244E+03 0.1404285E+03 + 0.1395384E+03 0.1386538E+03 0.1377749E+03 0.1369016E+03 0.1360337E+03 + 0.1351714E+03 0.1343146E+03 0.1334631E+03 0.1326171E+03 0.1317765E+03 + 0.1309411E+03 0.1301111E+03 0.1292863E+03 0.1284668E+03 0.1276524E+03 + 0.1268433E+03 0.1260392E+03 0.1252402E+03 0.1244464E+03 0.1236575E+03 + 0.2902071E+03 0.2893069E+03 0.2884004E+03 0.2874875E+03 0.2865676E+03 + 0.2856411E+03 0.2847072E+03 0.2837658E+03 0.2828165E+03 0.2818591E+03 + 0.2808933E+03 0.2799188E+03 0.2789351E+03 0.2779421E+03 0.2769394E+03 + 0.2759267E+03 0.2749036E+03 0.2738698E+03 0.2728251E+03 0.2717692E+03 + 0.2707017E+03 0.2696223E+03 0.2685309E+03 0.2674269E+03 0.2663104E+03 + 0.2651812E+03 0.2640388E+03 0.2628832E+03 0.2617146E+03 0.2605325E+03 + 0.2593372E+03 0.2581286E+03 0.2569066E+03 0.2556715E+03 0.2544237E+03 + 0.2531633E+03 0.2518907E+03 0.2506062E+03 0.2493103E+03 0.2480034E+03 + 0.2466864E+03 0.2453597E+03 0.2440240E+03 0.2426801E+03 0.2413288E+03 + 0.2399708E+03 0.2386070E+03 0.2372381E+03 0.2358651E+03 0.2344888E+03 + 0.2331100E+03 0.2317294E+03 0.2303480E+03 0.2289664E+03 0.2275854E+03 + 0.2262057E+03 0.2248279E+03 0.2234526E+03 0.2220804E+03 0.2207119E+03 + 0.2193474E+03 0.2179875E+03 0.2166325E+03 0.2152829E+03 0.2139388E+03 + 0.2126007E+03 0.2112688E+03 0.2099433E+03 0.2086244E+03 0.2073123E+03 + 0.2060071E+03 0.2047090E+03 0.2034181E+03 0.2021344E+03 0.2008580E+03 + 0.1995890E+03 0.1983274E+03 0.1970734E+03 0.1958268E+03 0.1945877E+03 + 0.1933561E+03 0.1921321E+03 0.1909156E+03 0.1897065E+03 0.1885050E+03 + 0.1873109E+03 0.1861242E+03 0.1849450E+03 0.1837731E+03 0.1826086E+03 + 0.1814514E+03 0.1803015E+03 0.1791588E+03 0.1780233E+03 0.1768950E+03 + 0.1757738E+03 0.1746597E+03 0.1735526E+03 0.1724525E+03 0.1713594E+03 + 0.1702733E+03 0.1691939E+03 0.1681214E+03 0.1670558E+03 0.1659968E+03 + 0.1649446E+03 0.1638990E+03 0.1628601E+03 0.1618277E+03 0.1608019E+03 + 0.1597826E+03 0.1587697E+03 0.1577633E+03 0.1567632E+03 0.1557695E+03 + 0.1547821E+03 0.1538010E+03 0.1528260E+03 0.1518573E+03 0.1508947E+03 + 0.1499381E+03 0.1489877E+03 0.1480432E+03 0.1471048E+03 0.1461723E+03 + 0.1452457E+03 0.1443250E+03 0.1434101E+03 0.1425011E+03 0.1415977E+03 + 0.1407002E+03 0.1398083E+03 0.1389220E+03 0.1380414E+03 0.1371664E+03 + 0.1362969E+03 0.1354329E+03 0.1345744E+03 0.1337213E+03 0.1328737E+03 + 0.1320314E+03 0.1311944E+03 0.1303628E+03 0.1295364E+03 0.1287153E+03 + 0.1278994E+03 0.1270886E+03 0.1262830E+03 0.1254825E+03 0.1246871E+03 + 0.2910515E+03 0.2901642E+03 0.2892712E+03 0.2883721E+03 0.2874668E+03 + 0.2865545E+03 0.2856360E+03 0.2847100E+03 0.2837767E+03 0.2828357E+03 + 0.2818868E+03 0.2809296E+03 0.2799638E+03 0.2789891E+03 0.2780052E+03 + 0.2770118E+03 0.2760085E+03 0.2749952E+03 0.2739711E+03 0.2729363E+03 + 0.2718905E+03 0.2708333E+03 0.2697644E+03 0.2686833E+03 0.2675901E+03 + 0.2664843E+03 0.2653657E+03 0.2642342E+03 0.2630896E+03 0.2619317E+03 + 0.2607605E+03 0.2595760E+03 0.2583779E+03 0.2571666E+03 0.2559421E+03 + 0.2547046E+03 0.2534542E+03 0.2521914E+03 0.2509162E+03 0.2496296E+03 + 0.2483316E+03 0.2470228E+03 0.2457041E+03 0.2443760E+03 0.2430391E+03 + 0.2416943E+03 0.2403424E+03 0.2389841E+03 0.2376204E+03 0.2362519E+03 + 0.2348796E+03 0.2335043E+03 0.2321268E+03 0.2307480E+03 0.2293686E+03 + 0.2279893E+03 0.2266110E+03 0.2252341E+03 0.2238595E+03 0.2224876E+03 + 0.2211191E+03 0.2197543E+03 0.2183939E+03 0.2170383E+03 0.2156877E+03 + 0.2143425E+03 0.2130032E+03 0.2116698E+03 0.2103428E+03 0.2090222E+03 + 0.2077083E+03 0.2064013E+03 0.2051013E+03 0.2038083E+03 0.2025226E+03 + 0.2012442E+03 0.1999731E+03 0.1987094E+03 0.1974531E+03 0.1962044E+03 + 0.1949631E+03 0.1937293E+03 0.1925030E+03 0.1912842E+03 0.1900730E+03 + 0.1888692E+03 0.1876729E+03 0.1864840E+03 0.1853025E+03 0.1841284E+03 + 0.1829617E+03 0.1818023E+03 0.1806501E+03 0.1795053E+03 0.1783676E+03 + 0.1772371E+03 0.1761138E+03 0.1749975E+03 0.1738883E+03 0.1727861E+03 + 0.1716909E+03 0.1706026E+03 0.1695212E+03 0.1684467E+03 0.1673789E+03 + 0.1663179E+03 0.1652637E+03 0.1642161E+03 0.1631751E+03 0.1621408E+03 + 0.1611130E+03 0.1600917E+03 0.1590769E+03 0.1580685E+03 0.1570665E+03 + 0.1560709E+03 0.1550815E+03 0.1540985E+03 0.1531216E+03 0.1521510E+03 + 0.1511865E+03 0.1502282E+03 0.1492759E+03 0.1483296E+03 0.1473894E+03 + 0.1464551E+03 0.1455267E+03 0.1446042E+03 0.1436876E+03 0.1427767E+03 + 0.1418717E+03 0.1409724E+03 0.1400787E+03 0.1391908E+03 0.1383084E+03 + 0.1374317E+03 0.1365605E+03 0.1356949E+03 0.1348347E+03 0.1339800E+03 + 0.1331307E+03 0.1322868E+03 0.1314482E+03 0.1306150E+03 0.1297870E+03 + 0.1289643E+03 0.1281468E+03 0.1273345E+03 0.1265273E+03 0.1257253E+03 + 0.2918719E+03 0.2909971E+03 0.2901168E+03 0.2892310E+03 0.2883392E+03 + 0.2874413E+03 0.2865366E+03 0.2856259E+03 0.2847077E+03 0.2837824E+03 + 0.2828498E+03 0.2819091E+03 0.2809604E+03 0.2800033E+03 0.2790374E+03 + 0.2780626E+03 0.2770783E+03 0.2760844E+03 0.2750805E+03 0.2740663E+03 + 0.2730414E+03 0.2720056E+03 0.2709586E+03 0.2698997E+03 0.2688292E+03 + 0.2677464E+03 0.2666512E+03 0.2655434E+03 0.2644226E+03 0.2632889E+03 + 0.2621419E+03 0.2609815E+03 0.2598078E+03 0.2586206E+03 0.2574200E+03 + 0.2562061E+03 0.2549789E+03 0.2537387E+03 0.2524858E+03 0.2512204E+03 + 0.2499431E+03 0.2486541E+03 0.2473540E+03 0.2460435E+03 0.2447232E+03 + 0.2433937E+03 0.2420557E+03 0.2407101E+03 0.2393577E+03 0.2379992E+03 + 0.2366356E+03 0.2352676E+03 0.2338961E+03 0.2325220E+03 0.2311460E+03 + 0.2297690E+03 0.2283918E+03 0.2270150E+03 0.2256393E+03 0.2242655E+03 + 0.2228941E+03 0.2215257E+03 0.2201609E+03 0.2188001E+03 0.2174438E+03 + 0.2160924E+03 0.2147463E+03 0.2134057E+03 0.2120710E+03 0.2107425E+03 + 0.2094204E+03 0.2081048E+03 0.2067960E+03 0.2054941E+03 0.2041992E+03 + 0.2029115E+03 0.2016309E+03 0.2003578E+03 0.1990919E+03 0.1978335E+03 + 0.1965826E+03 0.1953391E+03 0.1941031E+03 0.1928746E+03 0.1916536E+03 + 0.1904401E+03 0.1892340E+03 0.1880355E+03 0.1868444E+03 0.1856607E+03 + 0.1844843E+03 0.1833154E+03 0.1821538E+03 0.1809995E+03 0.1798524E+03 + 0.1787125E+03 0.1775799E+03 0.1764544E+03 0.1753360E+03 0.1742246E+03 + 0.1731203E+03 0.1720230E+03 0.1709326E+03 0.1698491E+03 0.1687725E+03 + 0.1677027E+03 0.1666396E+03 0.1655833E+03 0.1645337E+03 0.1634908E+03 + 0.1624544E+03 0.1614246E+03 0.1604014E+03 0.1593846E+03 0.1583743E+03 + 0.1573703E+03 0.1563728E+03 0.1553815E+03 0.1543966E+03 0.1534178E+03 + 0.1524453E+03 0.1514790E+03 0.1505188E+03 0.1495646E+03 0.1486166E+03 + 0.1476745E+03 0.1467384E+03 0.1458082E+03 0.1448839E+03 0.1439655E+03 + 0.1430529E+03 0.1421461E+03 0.1412450E+03 0.1403497E+03 0.1394600E+03 + 0.1385760E+03 0.1376976E+03 0.1368247E+03 0.1359574E+03 0.1350955E+03 + 0.1342392E+03 0.1333882E+03 0.1325427E+03 0.1317025E+03 0.1308676E+03 + 0.1300381E+03 0.1292138E+03 0.1283947E+03 0.1275808E+03 0.1267721E+03 + 0.2926696E+03 0.2918066E+03 0.2909386E+03 0.2900654E+03 0.2891866E+03 + 0.2883020E+03 0.2874114E+03 0.2865143E+03 0.2856110E+03 0.2847006E+03 + 0.2837831E+03 0.2828585E+03 0.2819261E+03 0.2809858E+03 0.2800374E+03 + 0.2790803E+03 0.2781143E+03 0.2771392E+03 0.2761545E+03 0.2751600E+03 + 0.2741553E+03 0.2731402E+03 0.2721142E+03 0.2710771E+03 0.2700288E+03 + 0.2689684E+03 0.2678961E+03 0.2668115E+03 0.2657143E+03 0.2646044E+03 + 0.2634814E+03 0.2623452E+03 0.2611958E+03 0.2600329E+03 0.2588565E+03 + 0.2576667E+03 0.2564633E+03 0.2552468E+03 0.2540169E+03 0.2527740E+03 + 0.2515185E+03 0.2502506E+03 0.2489709E+03 0.2476797E+03 0.2463777E+03 + 0.2450654E+03 0.2437435E+03 0.2424127E+03 0.2410738E+03 0.2397275E+03 + 0.2383746E+03 0.2370161E+03 0.2356527E+03 0.2342853E+03 0.2329148E+03 + 0.2315420E+03 0.2301677E+03 0.2287926E+03 0.2274176E+03 0.2260433E+03 + 0.2246705E+03 0.2232998E+03 0.2219318E+03 0.2205670E+03 0.2192060E+03 + 0.2178492E+03 0.2164971E+03 0.2151500E+03 0.2138084E+03 0.2124724E+03 + 0.2111425E+03 0.2098188E+03 0.2085016E+03 0.2071911E+03 0.2058873E+03 + 0.2045905E+03 0.2033008E+03 0.2020183E+03 0.2007430E+03 0.1994751E+03 + 0.1982145E+03 0.1969614E+03 0.1957157E+03 0.1944775E+03 0.1932468E+03 + 0.1920236E+03 0.1908079E+03 0.1895996E+03 0.1883988E+03 0.1872054E+03 + 0.1860195E+03 0.1848410E+03 0.1836698E+03 0.1825060E+03 0.1813495E+03 + 0.1802002E+03 0.1790581E+03 0.1779234E+03 0.1767957E+03 0.1756751E+03 + 0.1745616E+03 0.1734552E+03 0.1723557E+03 0.1712632E+03 0.1701777E+03 + 0.1690989E+03 0.1680271E+03 0.1669620E+03 0.1659037E+03 0.1648520E+03 + 0.1638070E+03 0.1627687E+03 0.1617369E+03 0.1607117E+03 0.1596929E+03 + 0.1586806E+03 0.1576748E+03 0.1566753E+03 0.1556821E+03 0.1546952E+03 + 0.1537146E+03 0.1527402E+03 0.1517720E+03 0.1508099E+03 0.1498540E+03 + 0.1489041E+03 0.1479601E+03 0.1470222E+03 0.1460903E+03 0.1451642E+03 + 0.1442440E+03 0.1433297E+03 0.1424211E+03 0.1415183E+03 0.1406212E+03 + 0.1397298E+03 0.1388441E+03 0.1379639E+03 0.1370894E+03 0.1362204E+03 + 0.1353569E+03 0.1344989E+03 0.1336463E+03 0.1327991E+03 0.1319573E+03 + 0.1311208E+03 0.1302896E+03 0.1294637E+03 0.1286431E+03 0.1278276E+03 + 0.2934454E+03 0.2925936E+03 0.2917375E+03 0.2908762E+03 0.2900096E+03 + 0.2891378E+03 0.2882603E+03 0.2873769E+03 0.2864872E+03 0.2855913E+03 + 0.2846886E+03 0.2837791E+03 0.2828623E+03 0.2819380E+03 0.2810060E+03 + 0.2800659E+03 0.2791175E+03 0.2781603E+03 0.2771943E+03 0.2762185E+03 + 0.2752334E+03 0.2742381E+03 0.2732326E+03 0.2722165E+03 0.2711893E+03 + 0.2701510E+03 0.2691010E+03 0.2680390E+03 0.2669650E+03 0.2658784E+03 + 0.2647792E+03 0.2636670E+03 0.2625417E+03 0.2614032E+03 0.2602510E+03 + 0.2590856E+03 0.2579065E+03 0.2567139E+03 0.2555078E+03 0.2542884E+03 + 0.2530558E+03 0.2518103E+03 0.2505522E+03 0.2492819E+03 0.2479998E+03 + 0.2467065E+03 0.2454025E+03 0.2440884E+03 0.2427651E+03 0.2414331E+03 + 0.2400932E+03 0.2387463E+03 0.2373932E+03 0.2360348E+03 0.2346718E+03 + 0.2333051E+03 0.2319357E+03 0.2305643E+03 0.2291917E+03 0.2278187E+03 + 0.2264460E+03 0.2250744E+03 0.2237046E+03 0.2223371E+03 0.2209725E+03 + 0.2196114E+03 0.2182543E+03 0.2169016E+03 0.2155537E+03 0.2142111E+03 + 0.2128740E+03 0.2115427E+03 0.2102176E+03 0.2088987E+03 0.2075865E+03 + 0.2062810E+03 0.2049823E+03 0.2036907E+03 0.2024062E+03 0.2011289E+03 + 0.1998588E+03 0.1985962E+03 0.1973409E+03 0.1960930E+03 0.1948526E+03 + 0.1936197E+03 0.1923943E+03 0.1911763E+03 0.1899658E+03 0.1887628E+03 + 0.1875672E+03 0.1863790E+03 0.1851982E+03 0.1840249E+03 0.1828588E+03 + 0.1817001E+03 0.1805486E+03 0.1794044E+03 0.1782674E+03 0.1771376E+03 + 0.1760149E+03 0.1748992E+03 0.1737907E+03 0.1726891E+03 0.1715945E+03 + 0.1705068E+03 0.1694260E+03 0.1683521E+03 0.1672850E+03 0.1662246E+03 + 0.1651709E+03 0.1641239E+03 0.1630835E+03 0.1620497E+03 0.1610225E+03 + 0.1600018E+03 0.1589876E+03 0.1579798E+03 0.1569783E+03 0.1559833E+03 + 0.1549945E+03 0.1540120E+03 0.1530357E+03 0.1520656E+03 0.1511017E+03 + 0.1501439E+03 0.1491921E+03 0.1482464E+03 0.1473066E+03 0.1463729E+03 + 0.1454450E+03 0.1445230E+03 0.1436069E+03 0.1426966E+03 0.1417920E+03 + 0.1408932E+03 0.1400001E+03 0.1391126E+03 0.1382308E+03 0.1373546E+03 + 0.1364839E+03 0.1356187E+03 0.1347590E+03 0.1339048E+03 0.1330560E+03 + 0.1322125E+03 0.1313745E+03 0.1305417E+03 0.1297142E+03 0.1288919E+03 + 0.2942003E+03 0.2933594E+03 0.2925143E+03 0.2916643E+03 0.2908097E+03 + 0.2899499E+03 0.2890849E+03 0.2882143E+03 0.2873381E+03 0.2864555E+03 + 0.2855671E+03 0.2846718E+03 0.2837701E+03 0.2828612E+03 0.2819449E+03 + 0.2810211E+03 0.2800893E+03 0.2791493E+03 0.2782008E+03 0.2772433E+03 + 0.2762768E+03 0.2753009E+03 0.2743150E+03 0.2733190E+03 0.2723125E+03 + 0.2712951E+03 0.2702671E+03 0.2692270E+03 0.2681754E+03 0.2671118E+03 + 0.2660358E+03 0.2649473E+03 0.2638457E+03 0.2627313E+03 0.2616035E+03 + 0.2604624E+03 0.2593079E+03 0.2581395E+03 0.2569577E+03 0.2557623E+03 + 0.2545534E+03 0.2533312E+03 0.2520959E+03 0.2508477E+03 0.2495870E+03 + 0.2483142E+03 0.2470298E+03 0.2457344E+03 0.2444285E+03 0.2431128E+03 + 0.2417879E+03 0.2404548E+03 0.2391142E+03 0.2377668E+03 0.2364135E+03 + 0.2350552E+03 0.2336927E+03 0.2323270E+03 0.2309588E+03 0.2295889E+03 + 0.2282181E+03 0.2268473E+03 0.2254772E+03 0.2241084E+03 0.2227416E+03 + 0.2213773E+03 0.2200163E+03 0.2186590E+03 0.2173058E+03 0.2159573E+03 + 0.2146137E+03 0.2132755E+03 0.2119431E+03 0.2106165E+03 0.2092962E+03 + 0.2079823E+03 0.2066750E+03 0.2053746E+03 0.2040810E+03 0.2027946E+03 + 0.2015152E+03 0.2002432E+03 0.1989784E+03 0.1977209E+03 0.1964709E+03 + 0.1952283E+03 0.1939932E+03 0.1927656E+03 0.1915454E+03 0.1903326E+03 + 0.1891274E+03 0.1879296E+03 0.1867392E+03 0.1855562E+03 0.1843806E+03 + 0.1832123E+03 0.1820514E+03 0.1808978E+03 0.1797513E+03 0.1786122E+03 + 0.1774802E+03 0.1763553E+03 0.1752375E+03 0.1741268E+03 0.1730231E+03 + 0.1719264E+03 0.1708367E+03 0.1697538E+03 0.1686777E+03 0.1676085E+03 + 0.1665461E+03 0.1654904E+03 0.1644414E+03 0.1633990E+03 0.1623632E+03 + 0.1613340E+03 0.1603113E+03 0.1592951E+03 0.1582854E+03 0.1572820E+03 + 0.1562850E+03 0.1552943E+03 0.1543099E+03 0.1533317E+03 0.1523598E+03 + 0.1513940E+03 0.1504343E+03 0.1494807E+03 0.1485331E+03 0.1475916E+03 + 0.1466560E+03 0.1457264E+03 0.1448026E+03 0.1438847E+03 0.1429726E+03 + 0.1420663E+03 0.1411658E+03 0.1402709E+03 0.1393818E+03 0.1384982E+03 + 0.1376203E+03 0.1367479E+03 0.1358811E+03 0.1350197E+03 0.1341638E+03 + 0.1333134E+03 0.1324683E+03 0.1316286E+03 0.1307942E+03 0.1299651E+03 + 0.2949350E+03 0.2941045E+03 0.2932699E+03 0.2924309E+03 0.2915874E+03 + 0.2907392E+03 0.2898861E+03 0.2890279E+03 0.2881642E+03 0.2872947E+03 + 0.2864192E+03 0.2855383E+03 0.2846506E+03 0.2837563E+03 0.2828551E+03 + 0.2819468E+03 0.2810310E+03 0.2801074E+03 0.2791758E+03 0.2782357E+03 + 0.2772872E+03 0.2763295E+03 0.2753626E+03 0.2743860E+03 0.2733994E+03 + 0.2724025E+03 0.2713949E+03 0.2703764E+03 0.2693467E+03 0.2683053E+03 + 0.2672520E+03 0.2661865E+03 0.2651084E+03 0.2640177E+03 0.2629140E+03 + 0.2617971E+03 0.2606668E+03 0.2595231E+03 0.2583657E+03 0.2571947E+03 + 0.2560100E+03 0.2548118E+03 0.2536001E+03 0.2523750E+03 0.2511369E+03 + 0.2498860E+03 0.2486228E+03 0.2473474E+03 0.2460609E+03 0.2447634E+03 + 0.2434557E+03 0.2421383E+03 0.2408122E+03 0.2394780E+03 0.2381367E+03 + 0.2367889E+03 0.2354355E+03 0.2340775E+03 0.2327157E+03 0.2313509E+03 + 0.2299840E+03 0.2286158E+03 0.2272471E+03 0.2258786E+03 0.2245110E+03 + 0.2231451E+03 0.2217815E+03 0.2204207E+03 0.2190633E+03 0.2177098E+03 + 0.2163607E+03 0.2150163E+03 0.2136772E+03 0.2123435E+03 0.2110157E+03 + 0.2096939E+03 0.2083784E+03 0.2070695E+03 0.2057673E+03 0.2044718E+03 + 0.2031834E+03 0.2019021E+03 0.2006280E+03 0.1993611E+03 0.1981016E+03 + 0.1968494E+03 0.1956047E+03 0.1943674E+03 0.1931375E+03 0.1919151E+03 + 0.1907002E+03 0.1894927E+03 0.1882926E+03 0.1871000E+03 0.1859148E+03 + 0.1847370E+03 0.1835665E+03 0.1824034E+03 0.1812475E+03 0.1800989E+03 + 0.1789576E+03 0.1778234E+03 0.1766964E+03 0.1755764E+03 0.1744636E+03 + 0.1733578E+03 0.1722590E+03 0.1711671E+03 0.1700821E+03 0.1690040E+03 + 0.1679327E+03 0.1668682E+03 0.1658105E+03 0.1647594E+03 0.1637151E+03 + 0.1626773E+03 0.1616461E+03 0.1606214E+03 0.1596033E+03 0.1585916E+03 + 0.1575862E+03 0.1565873E+03 0.1555947E+03 0.1546084E+03 0.1536283E+03 + 0.1526545E+03 0.1516868E+03 0.1507253E+03 0.1497699E+03 0.1488204E+03 + 0.1478771E+03 0.1469397E+03 0.1460082E+03 0.1450827E+03 0.1441630E+03 + 0.1432492E+03 0.1423411E+03 0.1414388E+03 0.1405423E+03 0.1396514E+03 + 0.1387661E+03 0.1378865E+03 0.1370124E+03 0.1361439E+03 0.1352809E+03 + 0.1344234E+03 0.1335712E+03 0.1327245E+03 0.1318832E+03 0.1310472E+03 + 0.2956505E+03 0.2948298E+03 0.2940053E+03 0.2931767E+03 0.2923439E+03 + 0.2915068E+03 0.2906650E+03 0.2898184E+03 0.2889669E+03 0.2881097E+03 + 0.2872472E+03 0.2863791E+03 0.2855051E+03 0.2846247E+03 0.2837379E+03 + 0.2828443E+03 0.2819438E+03 0.2810359E+03 0.2801204E+03 0.2791969E+03 + 0.2782656E+03 0.2773255E+03 0.2763766E+03 0.2754185E+03 0.2744510E+03 + 0.2734738E+03 0.2724863E+03 0.2714885E+03 0.2704799E+03 0.2694599E+03 + 0.2684288E+03 0.2673856E+03 0.2663304E+03 0.2652630E+03 0.2641829E+03 + 0.2630899E+03 0.2619838E+03 0.2608644E+03 0.2597314E+03 0.2585851E+03 + 0.2574249E+03 0.2562510E+03 0.2550636E+03 0.2538623E+03 0.2526476E+03 + 0.2514198E+03 0.2501789E+03 0.2489253E+03 0.2476595E+03 0.2463819E+03 + 0.2450930E+03 0.2437934E+03 0.2424840E+03 0.2411651E+03 0.2398377E+03 + 0.2385027E+03 0.2371606E+03 0.2358126E+03 0.2344593E+03 0.2331017E+03 + 0.2317407E+03 0.2303771E+03 0.2290116E+03 0.2276452E+03 0.2262786E+03 + 0.2249125E+03 0.2235477E+03 0.2221848E+03 0.2208244E+03 0.2194671E+03 + 0.2181134E+03 0.2167639E+03 0.2154189E+03 0.2140788E+03 0.2127441E+03 + 0.2114151E+03 0.2100919E+03 0.2087749E+03 0.2074643E+03 0.2061603E+03 + 0.2048631E+03 0.2035728E+03 0.2022896E+03 0.2010134E+03 0.1997445E+03 + 0.1984828E+03 0.1972285E+03 0.1959816E+03 0.1947422E+03 0.1935101E+03 + 0.1922855E+03 0.1910684E+03 0.1898586E+03 0.1886564E+03 0.1874615E+03 + 0.1862741E+03 0.1850940E+03 0.1839214E+03 0.1827560E+03 0.1815979E+03 + 0.1804472E+03 0.1793036E+03 0.1781673E+03 0.1770381E+03 0.1759160E+03 + 0.1748010E+03 0.1736931E+03 0.1725921E+03 0.1714982E+03 0.1704111E+03 + 0.1693309E+03 0.1682576E+03 0.1671910E+03 0.1661312E+03 0.1650782E+03 + 0.1640318E+03 0.1629920E+03 0.1619588E+03 0.1609321E+03 0.1599120E+03 + 0.1588983E+03 0.1578911E+03 0.1568902E+03 0.1558957E+03 0.1549075E+03 + 0.1539255E+03 0.1529498E+03 0.1519803E+03 0.1510169E+03 0.1500596E+03 + 0.1491084E+03 0.1481631E+03 0.1472239E+03 0.1462907E+03 0.1453634E+03 + 0.1444419E+03 0.1435263E+03 0.1426165E+03 0.1417124E+03 0.1408141E+03 + 0.1399215E+03 0.1390346E+03 0.1381532E+03 0.1372775E+03 0.1364073E+03 + 0.1355426E+03 0.1346834E+03 0.1338296E+03 0.1329813E+03 0.1321383E+03 + 0.2963476E+03 0.2955363E+03 0.2947213E+03 0.2939027E+03 0.2930801E+03 + 0.2922534E+03 0.2914224E+03 0.2905869E+03 0.2897467E+03 0.2889015E+03 + 0.2880512E+03 0.2871956E+03 0.2863342E+03 0.2854676E+03 0.2845943E+03 + 0.2837149E+03 0.2828288E+03 0.2819359E+03 0.2810358E+03 0.2801283E+03 + 0.2792132E+03 0.2782900E+03 0.2773584E+03 0.2764181E+03 0.2754689E+03 + 0.2745105E+03 0.2735424E+03 0.2725642E+03 0.2715759E+03 0.2705767E+03 + 0.2695669E+03 0.2685456E+03 0.2675128E+03 0.2664680E+03 0.2654109E+03 + 0.2643414E+03 0.2632590E+03 0.2621637E+03 0.2610552E+03 0.2599331E+03 + 0.2587976E+03 0.2576483E+03 0.2564853E+03 0.2553085E+03 0.2541180E+03 + 0.2529139E+03 0.2516964E+03 0.2504655E+03 0.2492218E+03 0.2479656E+03 + 0.2466972E+03 0.2454172E+03 0.2441262E+03 0.2428245E+03 0.2415134E+03 + 0.2401931E+03 0.2388646E+03 0.2375287E+03 0.2361862E+03 0.2348380E+03 + 0.2334850E+03 0.2321280E+03 0.2307678E+03 0.2294054E+03 0.2280415E+03 + 0.2266770E+03 0.2253127E+03 0.2239491E+03 0.2225871E+03 0.2212273E+03 + 0.2198703E+03 0.2185166E+03 0.2171668E+03 0.2158212E+03 0.2144804E+03 + 0.2131447E+03 0.2118145E+03 0.2104900E+03 0.2091716E+03 0.2078595E+03 + 0.2065538E+03 0.2052549E+03 0.2039627E+03 0.2026774E+03 0.2013994E+03 + 0.2001284E+03 0.1988647E+03 0.1976083E+03 0.1963592E+03 0.1951176E+03 + 0.1938833E+03 0.1926565E+03 0.1914371E+03 0.1902252E+03 0.1890208E+03 + 0.1878237E+03 0.1866340E+03 0.1854518E+03 0.1842768E+03 0.1831093E+03 + 0.1819491E+03 0.1807961E+03 0.1796503E+03 0.1785118E+03 0.1773805E+03 + 0.1762562E+03 0.1751391E+03 0.1740290E+03 0.1729260E+03 0.1718299E+03 + 0.1707407E+03 0.1696584E+03 0.1685830E+03 0.1675144E+03 0.1664526E+03 + 0.1653975E+03 0.1643491E+03 0.1633073E+03 0.1622721E+03 0.1612435E+03 + 0.1602213E+03 0.1592057E+03 0.1581965E+03 0.1571937E+03 0.1561973E+03 + 0.1552071E+03 0.1542233E+03 0.1532457E+03 0.1522742E+03 0.1513090E+03 + 0.1503499E+03 0.1493968E+03 0.1484498E+03 0.1475087E+03 0.1465737E+03 + 0.1456445E+03 0.1447213E+03 0.1438039E+03 0.1428924E+03 0.1419866E+03 + 0.1410865E+03 0.1401922E+03 0.1393035E+03 0.1384205E+03 0.1375430E+03 + 0.1366711E+03 0.1358048E+03 0.1349439E+03 0.1340885E+03 0.1332385E+03 + 0.2970271E+03 0.2962245E+03 0.2954188E+03 0.2946096E+03 0.2937967E+03 + 0.2929800E+03 0.2921593E+03 0.2913344E+03 0.2905051E+03 0.2896712E+03 + 0.2888324E+03 0.2879887E+03 0.2871400E+03 0.2862856E+03 0.2854256E+03 + 0.2845596E+03 0.2836874E+03 0.2828086E+03 0.2819234E+03 0.2810310E+03 + 0.2801314E+03 0.2792242E+03 0.2783092E+03 0.2773859E+03 0.2764542E+03 + 0.2755138E+03 0.2745642E+03 0.2736051E+03 0.2726363E+03 0.2716573E+03 + 0.2706678E+03 0.2696676E+03 0.2686563E+03 0.2676335E+03 0.2665989E+03 + 0.2655522E+03 0.2644931E+03 0.2634215E+03 0.2623370E+03 0.2612390E+03 + 0.2601280E+03 0.2590032E+03 0.2578648E+03 0.2567127E+03 0.2555467E+03 + 0.2543670E+03 0.2531735E+03 0.2519664E+03 0.2507459E+03 0.2495122E+03 + 0.2482657E+03 0.2470067E+03 0.2457358E+03 0.2444535E+03 0.2431603E+03 + 0.2418568E+03 0.2405439E+03 0.2392224E+03 0.2378928E+03 0.2365562E+03 + 0.2352133E+03 0.2338652E+03 0.2325125E+03 0.2311561E+03 0.2297970E+03 + 0.2284359E+03 0.2270738E+03 0.2257114E+03 0.2243494E+03 0.2229885E+03 + 0.2216295E+03 0.2202729E+03 0.2189193E+03 0.2175693E+03 0.2162233E+03 + 0.2148819E+03 0.2135453E+03 0.2122140E+03 0.2108884E+03 0.2095686E+03 + 0.2082549E+03 0.2069477E+03 0.2056469E+03 0.2043530E+03 0.2030659E+03 + 0.2017858E+03 0.2005128E+03 0.1992471E+03 0.1979886E+03 0.1967374E+03 + 0.1954936E+03 0.1942572E+03 0.1930282E+03 0.1918066E+03 0.1905925E+03 + 0.1893858E+03 0.1881865E+03 0.1869947E+03 0.1858102E+03 0.1846330E+03 + 0.1834633E+03 0.1823008E+03 0.1811457E+03 0.1799977E+03 0.1788570E+03 + 0.1777235E+03 0.1765971E+03 0.1754778E+03 0.1743656E+03 0.1732605E+03 + 0.1721623E+03 0.1710710E+03 0.1699866E+03 0.1689091E+03 0.1678385E+03 + 0.1667746E+03 0.1657174E+03 0.1646670E+03 0.1636232E+03 0.1625860E+03 + 0.1615554E+03 0.1605313E+03 0.1595137E+03 0.1585025E+03 0.1574978E+03 + 0.1564994E+03 0.1555074E+03 0.1545216E+03 0.1535421E+03 0.1525688E+03 + 0.1516017E+03 0.1506407E+03 0.1496858E+03 0.1487369E+03 0.1477941E+03 + 0.1468572E+03 0.1459263E+03 0.1450013E+03 0.1440821E+03 0.1431688E+03 + 0.1422612E+03 0.1413595E+03 0.1404634E+03 0.1395730E+03 0.1386882E+03 + 0.1378091E+03 0.1369355E+03 0.1360675E+03 0.1352050E+03 0.1343479E+03 + 0.2976893E+03 0.2968954E+03 0.2960984E+03 0.2952982E+03 0.2944946E+03 + 0.2936875E+03 0.2928766E+03 0.2920619E+03 0.2912430E+03 0.2904198E+03 + 0.2895921E+03 0.2887598E+03 0.2879224E+03 0.2870804E+03 0.2862325E+03 + 0.2853795E+03 0.2845205E+03 0.2836555E+03 0.2827842E+03 0.2819062E+03 + 0.2810214E+03 0.2801296E+03 0.2792303E+03 0.2783233E+03 0.2774082E+03 + 0.2764851E+03 0.2755532E+03 0.2746123E+03 0.2736621E+03 0.2727025E+03 + 0.2717328E+03 0.2707528E+03 0.2697622E+03 0.2687607E+03 0.2677479E+03 + 0.2667234E+03 0.2656870E+03 0.2646384E+03 0.2635773E+03 0.2625032E+03 + 0.2614162E+03 0.2603159E+03 0.2592021E+03 0.2580746E+03 0.2569333E+03 + 0.2557782E+03 0.2546092E+03 0.2534264E+03 0.2522299E+03 0.2510198E+03 + 0.2497963E+03 0.2485597E+03 0.2473104E+03 0.2460488E+03 0.2447754E+03 + 0.2434907E+03 0.2421954E+03 0.2408902E+03 0.2395758E+03 0.2382529E+03 + 0.2369225E+03 0.2355853E+03 0.2342422E+03 0.2328941E+03 0.2315418E+03 + 0.2301862E+03 0.2288283E+03 0.2274688E+03 0.2261085E+03 0.2247482E+03 + 0.2233887E+03 0.2220306E+03 0.2206747E+03 0.2193214E+03 0.2179714E+03 + 0.2166251E+03 0.2152831E+03 0.2139458E+03 0.2126136E+03 0.2112868E+03 + 0.2099657E+03 0.2086507E+03 0.2073418E+03 0.2060394E+03 0.2047437E+03 + 0.2034548E+03 0.2021728E+03 0.2008978E+03 0.1996301E+03 0.1983695E+03 + 0.1971162E+03 0.1958703E+03 0.1946317E+03 0.1934005E+03 0.1921768E+03 + 0.1909604E+03 0.1897515E+03 0.1885500E+03 0.1873559E+03 0.1861692E+03 + 0.1849899E+03 0.1838179E+03 0.1826532E+03 0.1814959E+03 0.1803458E+03 + 0.1792029E+03 0.1780672E+03 0.1769386E+03 0.1758172E+03 0.1747029E+03 + 0.1735956E+03 0.1724952E+03 0.1714019E+03 0.1703154E+03 0.1692359E+03 + 0.1681631E+03 0.1670972E+03 0.1660380E+03 0.1649855E+03 0.1639397E+03 + 0.1629005E+03 0.1618679E+03 0.1608418E+03 0.1598223E+03 0.1588092E+03 + 0.1578025E+03 0.1568022E+03 0.1558082E+03 0.1548205E+03 0.1538391E+03 + 0.1528640E+03 0.1518949E+03 0.1509321E+03 0.1499754E+03 0.1490247E+03 + 0.1480800E+03 0.1471413E+03 0.1462086E+03 0.1452818E+03 0.1443608E+03 + 0.1434457E+03 0.1425364E+03 0.1416329E+03 0.1407351E+03 0.1398430E+03 + 0.1389565E+03 0.1380757E+03 0.1372004E+03 0.1363307E+03 0.1354665E+03 + 0.2983355E+03 0.2975495E+03 0.2967610E+03 0.2959695E+03 0.2951747E+03 + 0.2943766E+03 0.2935751E+03 0.2927698E+03 0.2919611E+03 0.2911481E+03 + 0.2903310E+03 0.2895095E+03 0.2886833E+03 0.2878524E+03 0.2870168E+03 + 0.2861757E+03 0.2853294E+03 0.2844773E+03 0.2836192E+03 0.2827552E+03 + 0.2818845E+03 0.2810071E+03 0.2801230E+03 0.2792315E+03 0.2783324E+03 + 0.2774257E+03 0.2765107E+03 0.2755872E+03 0.2746550E+03 0.2737137E+03 + 0.2727630E+03 0.2718025E+03 0.2708316E+03 0.2698508E+03 0.2688589E+03 + 0.2678559E+03 0.2668415E+03 0.2658152E+03 0.2647770E+03 0.2637263E+03 + 0.2626629E+03 0.2615866E+03 0.2604970E+03 0.2593940E+03 0.2582774E+03 + 0.2571471E+03 0.2560029E+03 0.2548449E+03 0.2536727E+03 0.2524869E+03 + 0.2512872E+03 0.2500741E+03 0.2488475E+03 0.2476080E+03 0.2463560E+03 + 0.2450917E+03 0.2438159E+03 0.2425289E+03 0.2412317E+03 0.2399246E+03 + 0.2386088E+03 0.2372848E+03 0.2359535E+03 0.2346158E+03 0.2332726E+03 + 0.2319247E+03 0.2305730E+03 0.2292185E+03 0.2278618E+03 0.2265040E+03 + 0.2251457E+03 0.2237877E+03 0.2224308E+03 0.2210756E+03 0.2197228E+03 + 0.2183729E+03 0.2170265E+03 0.2156841E+03 0.2143462E+03 0.2130131E+03 + 0.2116853E+03 0.2103630E+03 0.2090466E+03 0.2077362E+03 0.2064323E+03 + 0.2051348E+03 0.2038441E+03 0.2025602E+03 0.2012833E+03 0.2000135E+03 + 0.1987510E+03 0.1974956E+03 0.1962475E+03 0.1950068E+03 0.1937735E+03 + 0.1925475E+03 0.1913289E+03 0.1901178E+03 0.1889141E+03 0.1877178E+03 + 0.1865289E+03 0.1853474E+03 0.1841732E+03 0.1830063E+03 0.1818468E+03 + 0.1806944E+03 0.1795494E+03 0.1784115E+03 0.1772808E+03 0.1761573E+03 + 0.1750408E+03 0.1739313E+03 0.1728289E+03 0.1717334E+03 0.1706449E+03 + 0.1695632E+03 0.1684884E+03 0.1674204E+03 0.1663592E+03 0.1653046E+03 + 0.1642568E+03 0.1632156E+03 0.1621810E+03 0.1611529E+03 0.1601314E+03 + 0.1591163E+03 0.1581077E+03 0.1571055E+03 0.1561096E+03 0.1551200E+03 + 0.1541367E+03 0.1531597E+03 0.1521888E+03 0.1512241E+03 0.1502655E+03 + 0.1493129E+03 0.1483664E+03 0.1474259E+03 0.1464914E+03 0.1455628E+03 + 0.1446401E+03 0.1437232E+03 0.1428122E+03 0.1419069E+03 0.1410073E+03 + 0.1401135E+03 0.1392253E+03 0.1383428E+03 0.1374658E+03 0.1365944E+03 + 0.2989657E+03 0.2981877E+03 0.2974071E+03 0.2966238E+03 0.2958374E+03 + 0.2950481E+03 0.2942556E+03 0.2934595E+03 0.2926600E+03 0.2918569E+03 + 0.2910499E+03 0.2902387E+03 0.2894233E+03 0.2886033E+03 0.2877786E+03 + 0.2869494E+03 0.2861150E+03 0.2852750E+03 0.2844299E+03 0.2835788E+03 + 0.2827219E+03 0.2818584E+03 0.2809884E+03 0.2801117E+03 0.2792279E+03 + 0.2783366E+03 0.2774379E+03 0.2765310E+03 0.2756159E+03 0.2746924E+03 + 0.2737597E+03 0.2728178E+03 0.2718663E+03 0.2709051E+03 0.2699334E+03 + 0.2689511E+03 0.2679578E+03 0.2669534E+03 0.2659373E+03 0.2649093E+03 + 0.2638688E+03 0.2628159E+03 0.2617501E+03 0.2606714E+03 0.2595792E+03 + 0.2584735E+03 0.2573540E+03 0.2562207E+03 0.2550735E+03 0.2539123E+03 + 0.2527372E+03 0.2515482E+03 0.2503454E+03 0.2491292E+03 0.2478996E+03 + 0.2466572E+03 0.2454023E+03 0.2441355E+03 0.2428572E+03 0.2415680E+03 + 0.2402689E+03 0.2389602E+03 0.2376430E+03 0.2363180E+03 0.2349860E+03 + 0.2336479E+03 0.2323047E+03 0.2309572E+03 0.2296063E+03 0.2282528E+03 + 0.2268976E+03 0.2255415E+03 0.2241854E+03 0.2228298E+03 0.2214756E+03 + 0.2201234E+03 0.2187739E+03 0.2174275E+03 0.2160849E+03 0.2147464E+03 + 0.2134126E+03 0.2120838E+03 0.2107604E+03 0.2094427E+03 0.2081310E+03 + 0.2068254E+03 0.2055263E+03 0.2042339E+03 0.2029482E+03 0.2016693E+03 + 0.2003976E+03 0.1991330E+03 0.1978755E+03 0.1966254E+03 0.1953825E+03 + 0.1941470E+03 0.1929189E+03 0.1916982E+03 0.1904848E+03 0.1892789E+03 + 0.1880804E+03 0.1868893E+03 0.1857055E+03 0.1845291E+03 0.1833601E+03 + 0.1821983E+03 0.1810438E+03 0.1798966E+03 0.1787565E+03 0.1776237E+03 + 0.1764979E+03 0.1753793E+03 0.1742677E+03 0.1731632E+03 0.1720656E+03 + 0.1709750E+03 0.1698912E+03 0.1688143E+03 0.1677443E+03 0.1666810E+03 + 0.1656244E+03 0.1645746E+03 0.1635313E+03 0.1624947E+03 0.1614647E+03 + 0.1604412E+03 0.1594241E+03 0.1584136E+03 0.1574094E+03 0.1564116E+03 + 0.1554201E+03 0.1544349E+03 0.1534559E+03 0.1524832E+03 0.1515166E+03 + 0.1505561E+03 0.1496018E+03 0.1486534E+03 0.1477112E+03 0.1467748E+03 + 0.1458444E+03 0.1449199E+03 0.1440013E+03 0.1430884E+03 0.1421814E+03 + 0.1412801E+03 0.1403845E+03 0.1394946E+03 0.1386104E+03 0.1377318E+03 + 0.2995810E+03 0.2988104E+03 0.2980375E+03 0.2972619E+03 0.2964836E+03 + 0.2957026E+03 0.2949185E+03 0.2941314E+03 0.2933409E+03 0.2925470E+03 + 0.2917495E+03 0.2909481E+03 0.2901428E+03 0.2893334E+03 0.2885196E+03 + 0.2877014E+03 0.2868780E+03 0.2860502E+03 0.2852169E+03 0.2843785E+03 + 0.2835342E+03 0.2826841E+03 0.2818278E+03 0.2809651E+03 0.2800959E+03 + 0.2792196E+03 0.2783362E+03 0.2774452E+03 0.2765464E+03 0.2756396E+03 + 0.2747243E+03 0.2738003E+03 0.2728671E+03 0.2719246E+03 0.2709724E+03 + 0.2700100E+03 0.2690372E+03 0.2680537E+03 0.2670589E+03 0.2660527E+03 + 0.2650348E+03 0.2640048E+03 0.2629622E+03 0.2619072E+03 0.2608391E+03 + 0.2597577E+03 0.2586628E+03 0.2575541E+03 0.2564318E+03 0.2552955E+03 + 0.2541451E+03 0.2529808E+03 0.2518024E+03 0.2506103E+03 0.2494044E+03 + 0.2481850E+03 0.2469524E+03 0.2457071E+03 0.2444495E+03 0.2431801E+03 + 0.2418995E+03 0.2406082E+03 0.2393071E+03 0.2379969E+03 0.2366784E+03 + 0.2353524E+03 0.2340200E+03 0.2326817E+03 0.2313386E+03 0.2299916E+03 + 0.2286415E+03 0.2272893E+03 0.2259357E+03 0.2245815E+03 0.2232275E+03 + 0.2218746E+03 0.2205232E+03 0.2191741E+03 0.2178280E+03 0.2164852E+03 + 0.2151464E+03 0.2138120E+03 0.2124823E+03 0.2111579E+03 0.2098390E+03 + 0.2085259E+03 0.2072189E+03 0.2059182E+03 0.2046240E+03 0.2033365E+03 + 0.2020559E+03 0.2007822E+03 0.1995155E+03 0.1982560E+03 0.1970038E+03 + 0.1957588E+03 0.1945211E+03 0.1932909E+03 0.1920680E+03 0.1908525E+03 + 0.1896444E+03 0.1884436E+03 0.1872503E+03 0.1860644E+03 0.1848857E+03 + 0.1837145E+03 0.1825505E+03 0.1813938E+03 0.1802444E+03 0.1791022E+03 + 0.1779671E+03 0.1768392E+03 0.1757185E+03 0.1746048E+03 0.1734981E+03 + 0.1723984E+03 0.1713056E+03 0.1702198E+03 0.1691409E+03 0.1680687E+03 + 0.1670034E+03 0.1659448E+03 0.1648929E+03 0.1638476E+03 0.1628091E+03 + 0.1617770E+03 0.1607515E+03 0.1597325E+03 0.1587200E+03 0.1577139E+03 + 0.1567142E+03 0.1557207E+03 0.1547336E+03 0.1537528E+03 0.1527781E+03 + 0.1518097E+03 0.1508474E+03 0.1498912E+03 0.1489410E+03 0.1479969E+03 + 0.1470587E+03 0.1461265E+03 0.1452002E+03 0.1442798E+03 0.1433652E+03 + 0.1424564E+03 0.1415534E+03 0.1406561E+03 0.1397645E+03 0.1388785E+03 + 0.3001818E+03 0.2994183E+03 0.2986526E+03 0.2978847E+03 0.2971142E+03 + 0.2963410E+03 0.2955651E+03 0.2947862E+03 0.2940044E+03 0.2932194E+03 + 0.2924310E+03 0.2916389E+03 0.2908434E+03 0.2900438E+03 0.2892401E+03 + 0.2884325E+03 0.2876203E+03 0.2868036E+03 0.2859818E+03 0.2851549E+03 + 0.2843232E+03 0.2834855E+03 0.2826422E+03 0.2817931E+03 0.2809374E+03 + 0.2800756E+03 0.2792067E+03 0.2783310E+03 0.2774478E+03 0.2765568E+03 + 0.2756582E+03 0.2747511E+03 0.2738355E+03 0.2729111E+03 0.2719774E+03 + 0.2710341E+03 0.2700809E+03 0.2691176E+03 0.2681435E+03 0.2671586E+03 + 0.2661623E+03 0.2651543E+03 0.2641345E+03 0.2631024E+03 0.2620577E+03 + 0.2610002E+03 0.2599296E+03 0.2588453E+03 0.2577477E+03 0.2566361E+03 + 0.2555107E+03 0.2543713E+03 0.2532178E+03 0.2520503E+03 0.2508687E+03 + 0.2496733E+03 0.2484641E+03 0.2472417E+03 0.2460061E+03 0.2447579E+03 + 0.2434977E+03 0.2422256E+03 0.2409427E+03 0.2396494E+03 0.2383465E+03 + 0.2370349E+03 0.2357153E+03 0.2343885E+03 0.2330555E+03 0.2317171E+03 + 0.2303744E+03 0.2290280E+03 0.2276790E+03 0.2263281E+03 0.2249761E+03 + 0.2236241E+03 0.2222725E+03 0.2209221E+03 0.2195738E+03 0.2182279E+03 + 0.2168852E+03 0.2155461E+03 0.2142112E+03 0.2128809E+03 0.2115555E+03 + 0.2102355E+03 0.2089211E+03 0.2076127E+03 0.2063105E+03 0.2050146E+03 + 0.2037254E+03 0.2024429E+03 0.2011673E+03 0.1998987E+03 0.1986372E+03 + 0.1973829E+03 0.1961358E+03 0.1948961E+03 0.1936636E+03 0.1924385E+03 + 0.1912208E+03 0.1900105E+03 0.1888076E+03 0.1876121E+03 0.1864239E+03 + 0.1852431E+03 0.1840696E+03 0.1829035E+03 0.1817446E+03 0.1805930E+03 + 0.1794486E+03 0.1783114E+03 0.1771813E+03 0.1760584E+03 0.1749425E+03 + 0.1738337E+03 0.1727319E+03 0.1716371E+03 0.1705491E+03 0.1694681E+03 + 0.1683939E+03 0.1673265E+03 0.1662659E+03 0.1652119E+03 0.1641647E+03 + 0.1631241E+03 0.1620900E+03 0.1610626E+03 0.1600416E+03 0.1590271E+03 + 0.1580191E+03 0.1570174E+03 0.1560220E+03 0.1550330E+03 0.1540503E+03 + 0.1530737E+03 0.1521034E+03 0.1511393E+03 0.1501812E+03 0.1492292E+03 + 0.1482832E+03 0.1473433E+03 0.1464093E+03 0.1454812E+03 0.1445590E+03 + 0.1436426E+03 0.1427321E+03 0.1418273E+03 0.1409283E+03 0.1400349E+03 + 0.3007687E+03 0.3000117E+03 0.2992534E+03 0.2984927E+03 0.2977292E+03 + 0.2969637E+03 0.2961956E+03 0.2954248E+03 0.2946511E+03 0.2938745E+03 + 0.2930948E+03 0.2923118E+03 0.2915255E+03 0.2907354E+03 0.2899415E+03 + 0.2891436E+03 0.2883418E+03 0.2875357E+03 0.2867250E+03 0.2859096E+03 + 0.2850892E+03 0.2842637E+03 0.2834328E+03 0.2825964E+03 0.2817540E+03 + 0.2809055E+03 0.2800508E+03 0.2791892E+03 0.2783210E+03 0.2774454E+03 + 0.2765625E+03 0.2756717E+03 0.2747728E+03 0.2738656E+03 0.2729496E+03 + 0.2720246E+03 0.2710902E+03 0.2701460E+03 0.2691919E+03 0.2682273E+03 + 0.2672519E+03 0.2662653E+03 0.2652675E+03 0.2642578E+03 0.2632358E+03 + 0.2622015E+03 0.2611545E+03 0.2600944E+03 0.2590211E+03 0.2579342E+03 + 0.2568336E+03 0.2557191E+03 0.2545906E+03 0.2534480E+03 0.2522913E+03 + 0.2511204E+03 0.2499355E+03 0.2487369E+03 0.2475245E+03 0.2462990E+03 + 0.2450605E+03 0.2438094E+03 0.2425464E+03 0.2412719E+03 0.2399868E+03 + 0.2386915E+03 0.2373870E+03 0.2360740E+03 0.2347533E+03 0.2334259E+03 + 0.2320925E+03 0.2307542E+03 0.2294119E+03 0.2280663E+03 0.2267184E+03 + 0.2253690E+03 0.2240189E+03 0.2226690E+03 0.2213199E+03 0.2199724E+03 + 0.2186270E+03 0.2172845E+03 0.2159454E+03 0.2146101E+03 0.2132792E+03 + 0.2119530E+03 0.2106320E+03 0.2093164E+03 0.2080067E+03 0.2067029E+03 + 0.2054055E+03 0.2041146E+03 0.2028303E+03 0.2015528E+03 0.2002823E+03 + 0.1990188E+03 0.1977625E+03 0.1965134E+03 0.1952714E+03 0.1940369E+03 + 0.1928097E+03 0.1915898E+03 0.1903773E+03 0.1891722E+03 0.1879744E+03 + 0.1867840E+03 0.1856010E+03 0.1844254E+03 0.1832570E+03 0.1820959E+03 + 0.1809421E+03 0.1797955E+03 0.1786562E+03 0.1775240E+03 0.1763989E+03 + 0.1752809E+03 0.1741699E+03 0.1730660E+03 0.1719691E+03 0.1708790E+03 + 0.1697959E+03 0.1687196E+03 0.1676501E+03 0.1665875E+03 0.1655315E+03 + 0.1644822E+03 0.1634396E+03 0.1624036E+03 0.1613741E+03 0.1603512E+03 + 0.1593347E+03 0.1583247E+03 0.1573211E+03 0.1563239E+03 0.1553329E+03 + 0.1543483E+03 0.1533699E+03 0.1523977E+03 0.1514316E+03 0.1504717E+03 + 0.1495179E+03 0.1485701E+03 0.1476283E+03 0.1466925E+03 0.1457626E+03 + 0.1448386E+03 0.1439205E+03 0.1430082E+03 0.1421017E+03 0.1412009E+03 + 0.3013422E+03 0.3005921E+03 0.2998403E+03 0.2990859E+03 0.2983299E+03 + 0.2975716E+03 0.2968108E+03 0.2960478E+03 0.2952818E+03 0.2945133E+03 + 0.2937419E+03 0.2929673E+03 0.2921896E+03 0.2914086E+03 0.2906241E+03 + 0.2898362E+03 0.2890440E+03 0.2882477E+03 0.2874477E+03 0.2866430E+03 + 0.2858337E+03 0.2850199E+03 0.2842006E+03 0.2833762E+03 0.2825464E+03 + 0.2817108E+03 0.2808693E+03 0.2800217E+03 0.2791673E+03 0.2783065E+03 + 0.2774384E+03 0.2765633E+03 0.2756803E+03 0.2747894E+03 0.2738904E+03 + 0.2729828E+03 0.2720664E+03 0.2711408E+03 0.2702056E+03 0.2692605E+03 + 0.2683052E+03 0.2673392E+03 0.2663626E+03 0.2653743E+03 0.2643745E+03 + 0.2633629E+03 0.2623387E+03 0.2613023E+03 0.2602527E+03 0.2591902E+03 + 0.2581141E+03 0.2570243E+03 0.2559206E+03 0.2548031E+03 0.2536714E+03 + 0.2525256E+03 0.2513655E+03 0.2501913E+03 0.2490032E+03 0.2478012E+03 + 0.2465857E+03 0.2453570E+03 0.2441154E+03 0.2428616E+03 0.2415959E+03 + 0.2403190E+03 0.2390317E+03 0.2377345E+03 0.2364285E+03 0.2351142E+03 + 0.2337926E+03 0.2324647E+03 0.2311312E+03 0.2297930E+03 0.2284512E+03 + 0.2271066E+03 0.2257600E+03 0.2244122E+03 0.2230641E+03 0.2217165E+03 + 0.2203700E+03 0.2190254E+03 0.2176833E+03 0.2163441E+03 0.2150087E+03 + 0.2136773E+03 0.2123504E+03 0.2110285E+03 0.2097118E+03 0.2084008E+03 + 0.2070957E+03 0.2057968E+03 0.2045041E+03 0.2032181E+03 0.2019388E+03 + 0.2006664E+03 0.1994010E+03 0.1981426E+03 0.1968914E+03 0.1956474E+03 + 0.1944107E+03 0.1931813E+03 0.1919593E+03 0.1907447E+03 0.1895373E+03 + 0.1883374E+03 0.1871449E+03 0.1859596E+03 0.1847817E+03 0.1836112E+03 + 0.1824479E+03 0.1812919E+03 0.1801432E+03 0.1790016E+03 0.1778672E+03 + 0.1767400E+03 0.1756199E+03 0.1745068E+03 0.1734007E+03 0.1723017E+03 + 0.1712095E+03 0.1701243E+03 0.1690460E+03 0.1679744E+03 0.1669097E+03 + 0.1658517E+03 0.1648004E+03 0.1637558E+03 0.1627177E+03 0.1616863E+03 + 0.1606614E+03 0.1596430E+03 0.1586310E+03 0.1576255E+03 0.1566263E+03 + 0.1556334E+03 0.1546469E+03 0.1536665E+03 0.1526925E+03 0.1517245E+03 + 0.1507628E+03 0.1498071E+03 0.1488575E+03 0.1479139E+03 0.1469763E+03 + 0.1460446E+03 0.1451188E+03 0.1441989E+03 0.1432848E+03 0.1423765E+03 + 0.3019030E+03 0.3011588E+03 0.3004132E+03 0.2996656E+03 0.2989163E+03 + 0.2981650E+03 0.2974112E+03 0.2966555E+03 0.2958972E+03 0.2951363E+03 + 0.2943727E+03 0.2936064E+03 0.2928372E+03 0.2920648E+03 0.2912890E+03 + 0.2905099E+03 0.2897273E+03 0.2889410E+03 0.2881508E+03 0.2873563E+03 + 0.2865575E+03 0.2857542E+03 0.2849465E+03 0.2841336E+03 0.2833159E+03 + 0.2824926E+03 0.2816637E+03 0.2808289E+03 0.2799883E+03 0.2791411E+03 + 0.2782875E+03 0.2774269E+03 0.2765594E+03 0.2756841E+03 0.2748013E+03 + 0.2739103E+03 0.2730110E+03 0.2721030E+03 0.2711859E+03 0.2702596E+03 + 0.2693234E+03 0.2683773E+03 0.2674209E+03 0.2664534E+03 0.2654749E+03 + 0.2644853E+03 0.2634836E+03 0.2624698E+03 0.2614436E+03 0.2604046E+03 + 0.2593525E+03 0.2582872E+03 0.2572083E+03 0.2561156E+03 0.2550089E+03 + 0.2538880E+03 0.2527531E+03 0.2516039E+03 0.2504405E+03 0.2492630E+03 + 0.2480715E+03 0.2468662E+03 0.2456475E+03 0.2444156E+03 0.2431711E+03 + 0.2419144E+03 0.2406462E+03 0.2393670E+03 0.2380776E+03 0.2367786E+03 + 0.2354710E+03 0.2341557E+03 0.2328334E+03 0.2315050E+03 0.2301714E+03 + 0.2288336E+03 0.2274925E+03 0.2261489E+03 0.2248037E+03 0.2234578E+03 + 0.2221118E+03 0.2207666E+03 0.2194229E+03 0.2180813E+03 0.2167424E+03 + 0.2154068E+03 0.2140751E+03 0.2127477E+03 0.2114249E+03 0.2101073E+03 + 0.2087951E+03 0.2074887E+03 0.2061882E+03 0.2048940E+03 0.2036064E+03 + 0.2023252E+03 0.2010510E+03 0.1997836E+03 0.1985232E+03 0.1972700E+03 + 0.1960240E+03 0.1947852E+03 0.1935537E+03 0.1923295E+03 0.1911127E+03 + 0.1899032E+03 0.1887010E+03 0.1875063E+03 0.1863189E+03 0.1851388E+03 + 0.1839660E+03 0.1828006E+03 0.1816424E+03 0.1804914E+03 0.1793477E+03 + 0.1782112E+03 0.1770818E+03 0.1759595E+03 0.1748443E+03 0.1737361E+03 + 0.1726349E+03 0.1715407E+03 0.1704534E+03 0.1693729E+03 0.1682994E+03 + 0.1672326E+03 0.1661725E+03 0.1651192E+03 0.1640725E+03 0.1630325E+03 + 0.1619991E+03 0.1609722E+03 0.1599518E+03 0.1589379E+03 0.1579303E+03 + 0.1569292E+03 0.1559345E+03 0.1549460E+03 0.1539638E+03 0.1529878E+03 + 0.1520181E+03 0.1510544E+03 0.1500969E+03 0.1491454E+03 0.1482000E+03 + 0.1472606E+03 0.1463271E+03 0.1453995E+03 0.1444778E+03 0.1435620E+03 + 0.3024511E+03 0.3017130E+03 0.3009735E+03 0.3002324E+03 0.2994895E+03 + 0.2987444E+03 0.2979978E+03 0.2972487E+03 0.2964976E+03 0.2957441E+03 + 0.2949882E+03 0.2942296E+03 0.2934682E+03 0.2927041E+03 0.2919370E+03 + 0.2911668E+03 0.2903929E+03 0.2896155E+03 0.2888346E+03 0.2880502E+03 + 0.2872617E+03 0.2864688E+03 0.2856715E+03 0.2848695E+03 0.2840631E+03 + 0.2832517E+03 0.2824348E+03 0.2816125E+03 0.2807845E+03 0.2799507E+03 + 0.2791105E+03 0.2782642E+03 0.2774108E+03 0.2765508E+03 0.2756831E+03 + 0.2748081E+03 0.2739251E+03 0.2730340E+03 0.2721345E+03 0.2712259E+03 + 0.2703080E+03 0.2693809E+03 0.2684438E+03 0.2674964E+03 0.2665386E+03 + 0.2655699E+03 0.2645898E+03 0.2635981E+03 0.2625944E+03 0.2615785E+03 + 0.2605498E+03 0.2595084E+03 0.2584537E+03 0.2573855E+03 0.2563036E+03 + 0.2552078E+03 0.2540979E+03 0.2529739E+03 0.2518356E+03 0.2506829E+03 + 0.2495161E+03 0.2483353E+03 0.2471404E+03 0.2459318E+03 0.2447099E+03 + 0.2434748E+03 0.2422275E+03 0.2409680E+03 0.2396973E+03 0.2384158E+03 + 0.2371244E+03 0.2358238E+03 0.2345148E+03 0.2331984E+03 0.2318754E+03 + 0.2305468E+03 0.2292134E+03 0.2278761E+03 0.2265358E+03 0.2251934E+03 + 0.2238498E+03 0.2225057E+03 0.2211620E+03 0.2198194E+03 0.2184785E+03 + 0.2171400E+03 0.2158046E+03 0.2144726E+03 0.2131447E+03 0.2118213E+03 + 0.2105027E+03 0.2091895E+03 0.2078818E+03 0.2065800E+03 0.2052843E+03 + 0.2039949E+03 0.2027121E+03 0.2014360E+03 0.2001667E+03 0.1989045E+03 + 0.1976492E+03 0.1964011E+03 0.1951602E+03 0.1939266E+03 0.1927003E+03 + 0.1914813E+03 0.1902696E+03 0.1890653E+03 0.1878683E+03 0.1866788E+03 + 0.1854965E+03 0.1843215E+03 0.1831539E+03 0.1819935E+03 0.1808404E+03 + 0.1796945E+03 0.1785558E+03 0.1774242E+03 0.1762998E+03 0.1751824E+03 + 0.1740721E+03 0.1729688E+03 0.1718725E+03 0.1707831E+03 0.1697006E+03 + 0.1686249E+03 0.1675560E+03 0.1664940E+03 0.1654386E+03 0.1643899E+03 + 0.1633479E+03 0.1623124E+03 0.1612835E+03 0.1602612E+03 0.1592453E+03 + 0.1582358E+03 0.1572328E+03 0.1562361E+03 0.1552457E+03 0.1542616E+03 + 0.1532838E+03 0.1523121E+03 0.1513466E+03 0.1503873E+03 0.1494339E+03 + 0.1484867E+03 0.1475454E+03 0.1466101E+03 0.1456808E+03 0.1447573E+03 + 0.3029872E+03 0.3022549E+03 0.3015215E+03 0.3007861E+03 0.3000493E+03 + 0.2993106E+03 0.2985704E+03 0.2978282E+03 0.2970839E+03 0.2963376E+03 + 0.2955887E+03 0.2948374E+03 0.2940839E+03 0.2933277E+03 0.2925685E+03 + 0.2918063E+03 0.2910412E+03 0.2902728E+03 0.2895012E+03 0.2887255E+03 + 0.2879466E+03 0.2871637E+03 0.2863767E+03 0.2855853E+03 0.2847893E+03 + 0.2839891E+03 0.2831837E+03 0.2823731E+03 0.2815575E+03 0.2807362E+03 + 0.2799091E+03 0.2790758E+03 0.2782365E+03 0.2773903E+03 0.2765376E+03 + 0.2756775E+03 0.2748102E+03 0.2739351E+03 0.2730520E+03 0.2721605E+03 + 0.2712603E+03 0.2703512E+03 0.2694328E+03 0.2685046E+03 0.2675663E+03 + 0.2666179E+03 0.2656584E+03 0.2646880E+03 0.2637062E+03 0.2627127E+03 + 0.2617070E+03 0.2606888E+03 0.2596577E+03 0.2586136E+03 0.2575561E+03 + 0.2564850E+03 0.2554000E+03 0.2543010E+03 0.2531880E+03 0.2520606E+03 + 0.2509189E+03 0.2497629E+03 0.2485926E+03 0.2474082E+03 0.2462099E+03 + 0.2449980E+03 0.2437728E+03 0.2425347E+03 0.2412845E+03 0.2400223E+03 + 0.2387491E+03 0.2374654E+03 0.2361722E+03 0.2348700E+03 0.2335598E+03 + 0.2322425E+03 0.2309190E+03 0.2295902E+03 0.2282570E+03 0.2269203E+03 + 0.2255810E+03 0.2242400E+03 0.2228981E+03 0.2215561E+03 0.2202148E+03 + 0.2188749E+03 0.2175370E+03 0.2162017E+03 0.2148697E+03 0.2135415E+03 + 0.2122175E+03 0.2108982E+03 0.2095839E+03 0.2082751E+03 0.2069720E+03 + 0.2056748E+03 0.2043839E+03 0.2030994E+03 0.2018215E+03 0.2005504E+03 + 0.1992862E+03 0.1980289E+03 0.1967788E+03 0.1955359E+03 0.1943002E+03 + 0.1930717E+03 0.1918506E+03 0.1906367E+03 0.1894302E+03 0.1882311E+03 + 0.1870393E+03 0.1858548E+03 0.1846777E+03 0.1835079E+03 0.1823453E+03 + 0.1811900E+03 0.1800419E+03 0.1789010E+03 0.1777673E+03 0.1766407E+03 + 0.1755212E+03 0.1744088E+03 0.1733034E+03 0.1722049E+03 0.1711134E+03 + 0.1700288E+03 0.1689511E+03 0.1678802E+03 0.1668160E+03 0.1657586E+03 + 0.1647079E+03 0.1636639E+03 0.1626264E+03 0.1615956E+03 0.1605712E+03 + 0.1595533E+03 0.1585420E+03 0.1575370E+03 0.1565384E+03 0.1555461E+03 + 0.1545601E+03 0.1535803E+03 0.1526068E+03 0.1516394E+03 0.1506782E+03 + 0.1497230E+03 0.1487739E+03 0.1478309E+03 0.1468938E+03 0.1459626E+03 + 0.3035119E+03 0.3027850E+03 0.3020572E+03 0.3013277E+03 0.3005967E+03 + 0.2998644E+03 0.2991304E+03 0.2983941E+03 0.2976567E+03 0.2969169E+03 + 0.2961749E+03 0.2954309E+03 0.2946847E+03 0.2939357E+03 0.2931842E+03 + 0.2924301E+03 0.2916733E+03 0.2909130E+03 0.2901498E+03 0.2893834E+03 + 0.2886138E+03 0.2878398E+03 0.2870625E+03 0.2862812E+03 0.2854957E+03 + 0.2847058E+03 0.2839114E+03 0.2831122E+03 0.2823080E+03 0.2814987E+03 + 0.2806839E+03 0.2798634E+03 0.2790370E+03 0.2782047E+03 0.2773655E+03 + 0.2765201E+03 0.2756674E+03 0.2748077E+03 0.2739402E+03 0.2730651E+03 + 0.2721816E+03 0.2712898E+03 0.2703891E+03 0.2694793E+03 0.2685599E+03 + 0.2676308E+03 0.2666913E+03 0.2657414E+03 0.2647807E+03 0.2638086E+03 + 0.2628248E+03 0.2618290E+03 0.2608210E+03 0.2598004E+03 0.2587668E+03 + 0.2577200E+03 0.2566597E+03 0.2555856E+03 0.2544976E+03 0.2533954E+03 + 0.2522789E+03 0.2511480E+03 0.2500029E+03 0.2488433E+03 0.2476696E+03 + 0.2464817E+03 0.2452800E+03 0.2440648E+03 0.2428364E+03 0.2415953E+03 + 0.2403422E+03 0.2390774E+03 0.2378018E+03 0.2365159E+03 0.2352208E+03 + 0.2339172E+03 0.2326060E+03 0.2312879E+03 0.2299641E+03 0.2286353E+03 + 0.2273024E+03 0.2259665E+03 0.2246284E+03 0.2232889E+03 0.2219489E+03 + 0.2206090E+03 0.2192702E+03 0.2179331E+03 0.2165983E+03 0.2152664E+03 + 0.2139380E+03 0.2126136E+03 0.2112935E+03 0.2099784E+03 0.2086685E+03 + 0.2073641E+03 0.2060656E+03 0.2047731E+03 0.2034870E+03 0.2022074E+03 + 0.2009345E+03 0.1996683E+03 0.1984092E+03 0.1971571E+03 0.1959121E+03 + 0.1946743E+03 0.1934437E+03 0.1922204E+03 0.1910045E+03 0.1897958E+03 + 0.1885945E+03 0.1874005E+03 0.1862139E+03 0.1850345E+03 0.1838625E+03 + 0.1826977E+03 0.1815402E+03 0.1803900E+03 0.1792469E+03 0.1781110E+03 + 0.1769823E+03 0.1758607E+03 0.1747461E+03 0.1736385E+03 0.1725380E+03 + 0.1714444E+03 0.1703577E+03 0.1692779E+03 0.1682049E+03 0.1671387E+03 + 0.1660793E+03 0.1650265E+03 0.1639804E+03 0.1629410E+03 0.1619081E+03 + 0.1608818E+03 0.1598620E+03 0.1588486E+03 0.1578417E+03 0.1568412E+03 + 0.1558470E+03 0.1548591E+03 0.1538774E+03 0.1529020E+03 0.1519327E+03 + 0.1509696E+03 0.1500126E+03 0.1490617E+03 0.1481168E+03 0.1471779E+03 + 0.3040254E+03 0.3033041E+03 0.3025814E+03 0.3018573E+03 0.3011320E+03 + 0.3004055E+03 0.2996770E+03 0.2989473E+03 0.2982160E+03 0.2974827E+03 + 0.2967473E+03 0.2960102E+03 0.2952708E+03 0.2945291E+03 0.2937851E+03 + 0.2930385E+03 0.2922891E+03 0.2915372E+03 0.2907822E+03 0.2900242E+03 + 0.2892627E+03 0.2884984E+03 0.2877302E+03 0.2869583E+03 0.2861826E+03 + 0.2854026E+03 0.2846188E+03 0.2838302E+03 0.2830371E+03 0.2822392E+03 + 0.2814361E+03 0.2806277E+03 0.2798139E+03 0.2789942E+03 0.2781687E+03 + 0.2773365E+03 0.2764982E+03 0.2756527E+03 0.2748006E+03 0.2739408E+03 + 0.2730734E+03 0.2721979E+03 0.2713142E+03 0.2704218E+03 0.2695204E+03 + 0.2686099E+03 0.2676895E+03 0.2667592E+03 0.2658184E+03 0.2648671E+03 + 0.2639044E+03 0.2629306E+03 0.2619449E+03 0.2609471E+03 0.2599368E+03 + 0.2589135E+03 0.2578774E+03 0.2568277E+03 0.2557644E+03 0.2546872E+03 + 0.2535959E+03 0.2524904E+03 0.2513705E+03 0.2502362E+03 0.2490875E+03 + 0.2479244E+03 0.2467471E+03 0.2455557E+03 0.2443506E+03 0.2431320E+03 + 0.2419005E+03 0.2406564E+03 0.2394004E+03 0.2381331E+03 0.2368552E+03 + 0.2355674E+03 0.2342706E+03 0.2329656E+03 0.2316534E+03 0.2303347E+03 + 0.2290106E+03 0.2276820E+03 0.2263497E+03 0.2250147E+03 0.2236779E+03 + 0.2223400E+03 0.2210019E+03 0.2196645E+03 0.2183283E+03 0.2169940E+03 + 0.2156624E+03 0.2143340E+03 0.2130092E+03 0.2116887E+03 0.2103728E+03 + 0.2090619E+03 0.2077564E+03 0.2064565E+03 0.2051626E+03 0.2038750E+03 + 0.2025937E+03 0.2013190E+03 0.2000510E+03 0.1987900E+03 0.1975359E+03 + 0.1962888E+03 0.1950490E+03 0.1938163E+03 0.1925909E+03 0.1913728E+03 + 0.1901620E+03 0.1889585E+03 0.1877623E+03 0.1865735E+03 0.1853920E+03 + 0.1842178E+03 0.1830508E+03 0.1818911E+03 0.1807387E+03 0.1795935E+03 + 0.1784554E+03 0.1773245E+03 0.1762007E+03 0.1750840E+03 0.1739744E+03 + 0.1728717E+03 0.1717760E+03 0.1706872E+03 0.1696053E+03 0.1685302E+03 + 0.1674620E+03 0.1664005E+03 0.1653457E+03 0.1642976E+03 0.1632562E+03 + 0.1622213E+03 0.1611930E+03 0.1601712E+03 0.1591559E+03 0.1581470E+03 + 0.1571445E+03 0.1561484E+03 0.1551586E+03 0.1541751E+03 0.1531978E+03 + 0.1522266E+03 0.1512617E+03 0.1503028E+03 0.1493501E+03 0.1484034E+03 + 0.3045285E+03 0.3038120E+03 0.3030945E+03 0.3023757E+03 0.3016561E+03 + 0.3009348E+03 0.3002123E+03 0.2994883E+03 0.2987628E+03 0.2980355E+03 + 0.2973069E+03 0.2965761E+03 0.2958431E+03 0.2951085E+03 0.2943715E+03 + 0.2936319E+03 0.2928901E+03 0.2921460E+03 0.2913986E+03 0.2906486E+03 + 0.2898958E+03 0.2891397E+03 0.2883803E+03 0.2876176E+03 0.2868512E+03 + 0.2860809E+03 0.2853068E+03 0.2845284E+03 0.2837458E+03 0.2829586E+03 + 0.2821667E+03 0.2813699E+03 0.2805678E+03 0.2797603E+03 0.2789474E+03 + 0.2781286E+03 0.2773033E+03 0.2764721E+03 0.2756337E+03 0.2747889E+03 + 0.2739367E+03 0.2730769E+03 0.2722094E+03 0.2713337E+03 0.2704494E+03 + 0.2695565E+03 0.2686544E+03 0.2677427E+03 0.2668214E+03 0.2658898E+03 + 0.2649478E+03 0.2639948E+03 0.2630305E+03 0.2620546E+03 0.2610668E+03 + 0.2600666E+03 0.2590539E+03 0.2580282E+03 0.2569891E+03 0.2559365E+03 + 0.2548702E+03 0.2537898E+03 0.2526953E+03 0.2515863E+03 0.2504629E+03 + 0.2493250E+03 0.2481727E+03 0.2470061E+03 0.2458251E+03 0.2446302E+03 + 0.2434217E+03 0.2421998E+03 0.2409651E+03 0.2397180E+03 0.2384593E+03 + 0.2371895E+03 0.2359094E+03 0.2346198E+03 0.2333214E+03 0.2320152E+03 + 0.2307021E+03 0.2293830E+03 0.2280588E+03 0.2267304E+03 0.2253988E+03 + 0.2240649E+03 0.2227295E+03 0.2213934E+03 0.2200575E+03 0.2187225E+03 + 0.2173891E+03 0.2160579E+03 0.2147296E+03 0.2134047E+03 0.2120837E+03 + 0.2107671E+03 0.2094554E+03 0.2081488E+03 0.2068477E+03 0.2055524E+03 + 0.2042633E+03 0.2029803E+03 0.2017039E+03 0.2004342E+03 0.1991712E+03 + 0.1979152E+03 0.1966662E+03 0.1954243E+03 0.1941895E+03 0.1929620E+03 + 0.1917418E+03 0.1905288E+03 0.1893232E+03 0.1881248E+03 0.1869338E+03 + 0.1857501E+03 0.1845737E+03 0.1834045E+03 0.1822427E+03 0.1810881E+03 + 0.1799407E+03 0.1788005E+03 0.1776674E+03 0.1765415E+03 0.1754226E+03 + 0.1743108E+03 0.1732060E+03 0.1721082E+03 0.1710173E+03 0.1699333E+03 + 0.1688562E+03 0.1677859E+03 0.1667224E+03 0.1656656E+03 0.1646154E+03 + 0.1635720E+03 0.1625351E+03 0.1615048E+03 0.1604811E+03 0.1594638E+03 + 0.1584530E+03 0.1574485E+03 0.1564505E+03 0.1554588E+03 0.1544733E+03 + 0.1534941E+03 0.1525211E+03 0.1515543E+03 0.1505936E+03 0.1496390E+03 + 0.3050211E+03 0.3043095E+03 0.3035968E+03 0.3028830E+03 0.3021688E+03 + 0.3014527E+03 0.3007356E+03 0.3000173E+03 0.2992975E+03 0.2985759E+03 + 0.2978533E+03 0.2971288E+03 0.2964024E+03 0.2956741E+03 0.2949438E+03 + 0.2942113E+03 0.2934765E+03 0.2927394E+03 0.2919998E+03 0.2912575E+03 + 0.2905125E+03 0.2897643E+03 0.2890137E+03 0.2882596E+03 0.2875020E+03 + 0.2867410E+03 0.2859762E+03 0.2852076E+03 0.2844347E+03 0.2836580E+03 + 0.2828768E+03 0.2820909E+03 0.2813000E+03 0.2805042E+03 0.2797032E+03 + 0.2788968E+03 0.2780845E+03 0.2772661E+03 0.2764417E+03 0.2756104E+03 + 0.2747729E+03 0.2739280E+03 0.2730758E+03 0.2722160E+03 0.2713480E+03 + 0.2704721E+03 0.2695874E+03 0.2686936E+03 0.2677909E+03 0.2668781E+03 + 0.2659556E+03 0.2650227E+03 0.2640789E+03 0.2631243E+03 0.2621583E+03 + 0.2611804E+03 0.2601904E+03 0.2591878E+03 0.2581725E+03 0.2571440E+03 + 0.2561021E+03 0.2550465E+03 0.2539770E+03 0.2528933E+03 0.2517953E+03 + 0.2506828E+03 0.2495559E+03 0.2484144E+03 0.2472584E+03 0.2460881E+03 + 0.2449037E+03 0.2437052E+03 0.2424933E+03 0.2412681E+03 0.2400303E+03 + 0.2387803E+03 0.2375189E+03 0.2362466E+03 0.2349644E+03 0.2336730E+03 + 0.2323732E+03 0.2310659E+03 0.2297521E+03 0.2284326E+03 0.2271085E+03 + 0.2257806E+03 0.2244499E+03 0.2231172E+03 0.2217833E+03 0.2204492E+03 + 0.2191156E+03 0.2177831E+03 0.2164526E+03 0.2151245E+03 0.2137997E+03 + 0.2124784E+03 0.2111613E+03 0.2098488E+03 0.2085412E+03 0.2072390E+03 + 0.2059425E+03 0.2046518E+03 0.2033673E+03 0.2020893E+03 0.2008178E+03 + 0.1995529E+03 0.1982950E+03 0.1970440E+03 0.1958001E+03 0.1945633E+03 + 0.1933337E+03 0.1921113E+03 0.1908963E+03 0.1896884E+03 0.1884879E+03 + 0.1872947E+03 0.1861088E+03 0.1849302E+03 0.1837589E+03 0.1825949E+03 + 0.1814381E+03 0.1802885E+03 0.1791461E+03 0.1780109E+03 0.1768828E+03 + 0.1757618E+03 0.1746479E+03 0.1735410E+03 0.1724411E+03 0.1713481E+03 + 0.1702621E+03 0.1691828E+03 0.1681104E+03 0.1670449E+03 0.1659860E+03 + 0.1649338E+03 0.1638884E+03 0.1628495E+03 0.1618172E+03 0.1607915E+03 + 0.1597722E+03 0.1587595E+03 0.1577531E+03 0.1567531E+03 0.1557595E+03 + 0.1547721E+03 0.1537910E+03 0.1528161E+03 0.1518474E+03 0.1508849E+03 + 0.3055036E+03 0.3047968E+03 0.3040886E+03 0.3033801E+03 0.3026703E+03 + 0.3019595E+03 0.3012477E+03 0.3005348E+03 0.2998205E+03 0.2991047E+03 + 0.2983877E+03 0.2976689E+03 0.2969490E+03 0.2962270E+03 0.2955028E+03 + 0.2947769E+03 0.2940491E+03 0.2933188E+03 0.2925864E+03 0.2918516E+03 + 0.2911139E+03 0.2903739E+03 0.2896310E+03 0.2888849E+03 0.2881359E+03 + 0.2873835E+03 0.2866277E+03 0.2858683E+03 0.2851053E+03 0.2843383E+03 + 0.2835670E+03 0.2827915E+03 0.2820115E+03 0.2812268E+03 0.2804370E+03 + 0.2796423E+03 0.2788422E+03 0.2780365E+03 0.2772248E+03 0.2764073E+03 + 0.2755829E+03 0.2747525E+03 0.2739149E+03 0.2730701E+03 0.2722179E+03 + 0.2713579E+03 0.2704897E+03 0.2696132E+03 0.2687277E+03 0.2678334E+03 + 0.2669294E+03 0.2660157E+03 0.2650919E+03 0.2641576E+03 0.2632124E+03 + 0.2622559E+03 0.2612878E+03 0.2603077E+03 0.2593154E+03 0.2583104E+03 + 0.2572924E+03 0.2562611E+03 0.2552162E+03 0.2541575E+03 0.2530847E+03 + 0.2519975E+03 0.2508960E+03 0.2497800E+03 0.2486494E+03 0.2475043E+03 + 0.2463447E+03 0.2451707E+03 0.2439825E+03 0.2427807E+03 0.2415652E+03 + 0.2403369E+03 0.2390959E+03 0.2378431E+03 0.2365791E+03 0.2353045E+03 + 0.2340203E+03 0.2327272E+03 0.2314261E+03 0.2301179E+03 0.2288035E+03 + 0.2274839E+03 0.2261600E+03 0.2248327E+03 0.2235029E+03 0.2221716E+03 + 0.2208395E+03 0.2195075E+03 0.2181762E+03 0.2168464E+03 0.2155189E+03 + 0.2141941E+03 0.2128728E+03 0.2115553E+03 0.2102421E+03 0.2089337E+03 + 0.2076304E+03 0.2063326E+03 0.2050406E+03 0.2037547E+03 0.2024750E+03 + 0.2012017E+03 0.1999352E+03 0.1986753E+03 0.1974224E+03 0.1961765E+03 + 0.1949377E+03 0.1937060E+03 0.1924815E+03 0.1912643E+03 0.1900544E+03 + 0.1888517E+03 0.1876563E+03 0.1864682E+03 0.1852875E+03 0.1841140E+03 + 0.1829477E+03 0.1817888E+03 0.1806370E+03 0.1794925E+03 0.1783551E+03 + 0.1772249E+03 0.1761017E+03 0.1749857E+03 0.1738766E+03 0.1727746E+03 + 0.1716795E+03 0.1705914E+03 0.1695101E+03 0.1684356E+03 0.1673680E+03 + 0.1663071E+03 0.1652529E+03 0.1642054E+03 0.1631645E+03 0.1621302E+03 + 0.1611025E+03 0.1600813E+03 0.1590666E+03 0.1580583E+03 0.1570563E+03 + 0.1560608E+03 0.1550715E+03 0.1540885E+03 0.1531118E+03 0.1521412E+03 + 0.3059766E+03 0.3052743E+03 0.3045706E+03 0.3038666E+03 0.3031618E+03 + 0.3024558E+03 0.3017490E+03 0.3010413E+03 0.3003321E+03 0.2996221E+03 + 0.2989103E+03 0.2981974E+03 0.2974829E+03 0.2967669E+03 0.2960490E+03 + 0.2953295E+03 0.2946081E+03 0.2938846E+03 0.2931592E+03 0.2924310E+03 + 0.2917009E+03 0.2909683E+03 0.2902325E+03 0.2894947E+03 0.2887538E+03 + 0.2880096E+03 0.2872625E+03 0.2865118E+03 0.2857578E+03 0.2850000E+03 + 0.2842384E+03 0.2834728E+03 0.2827031E+03 0.2819288E+03 0.2811501E+03 + 0.2803664E+03 0.2795779E+03 0.2787841E+03 0.2779845E+03 0.2771796E+03 + 0.2763688E+03 0.2755513E+03 0.2747278E+03 0.2738975E+03 0.2730600E+03 + 0.2722154E+03 0.2713631E+03 0.2705026E+03 0.2696341E+03 0.2687570E+03 + 0.2678708E+03 0.2669757E+03 0.2660705E+03 0.2651558E+03 0.2642304E+03 + 0.2632945E+03 0.2623476E+03 0.2613892E+03 0.2604190E+03 0.2594367E+03 + 0.2584419E+03 0.2574343E+03 0.2564135E+03 0.2553792E+03 0.2543313E+03 + 0.2532693E+03 0.2521932E+03 0.2511026E+03 0.2499975E+03 0.2488779E+03 + 0.2477436E+03 0.2465947E+03 0.2454314E+03 0.2442537E+03 0.2430619E+03 + 0.2418565E+03 0.2406377E+03 0.2394060E+03 0.2381621E+03 0.2369064E+03 + 0.2356400E+03 0.2343633E+03 0.2330771E+03 0.2317825E+03 0.2304801E+03 + 0.2291712E+03 0.2278563E+03 0.2265367E+03 0.2252132E+03 0.2238866E+03 + 0.2225581E+03 0.2212282E+03 0.2198980E+03 0.2185681E+03 0.2172395E+03 + 0.2159125E+03 0.2145881E+03 0.2132667E+03 0.2119489E+03 0.2106352E+03 + 0.2093261E+03 0.2080218E+03 0.2067229E+03 0.2054297E+03 0.2041423E+03 + 0.2028610E+03 0.2015862E+03 0.2003178E+03 0.1990561E+03 0.1978013E+03 + 0.1965534E+03 0.1953126E+03 0.1940789E+03 0.1928523E+03 0.1916329E+03 + 0.1904209E+03 0.1892161E+03 0.1880185E+03 0.1868283E+03 0.1856453E+03 + 0.1844697E+03 0.1833013E+03 0.1821401E+03 0.1809862E+03 0.1798395E+03 + 0.1786999E+03 0.1775676E+03 0.1764423E+03 0.1753241E+03 0.1742129E+03 + 0.1731088E+03 0.1720116E+03 0.1709213E+03 0.1698380E+03 0.1687614E+03 + 0.1676917E+03 0.1666288E+03 0.1655726E+03 0.1645230E+03 0.1634801E+03 + 0.1624439E+03 0.1614142E+03 0.1603910E+03 0.1593743E+03 0.1583640E+03 + 0.1573602E+03 0.1563627E+03 0.1553715E+03 0.1543866E+03 0.1534079E+03 + 0.3064403E+03 0.3057421E+03 0.3050430E+03 0.3043433E+03 0.3036431E+03 + 0.3029418E+03 0.3022397E+03 0.3015370E+03 0.3008330E+03 0.3001282E+03 + 0.2994218E+03 0.2987141E+03 0.2980052E+03 0.2972948E+03 0.2965831E+03 + 0.2958697E+03 0.2951542E+03 0.2944371E+03 0.2937180E+03 0.2929968E+03 + 0.2922735E+03 0.2915477E+03 0.2908196E+03 0.2900892E+03 0.2893559E+03 + 0.2886198E+03 0.2878807E+03 0.2871384E+03 0.2863931E+03 0.2856443E+03 + 0.2848919E+03 0.2841356E+03 0.2833755E+03 0.2826114E+03 0.2818430E+03 + 0.2810699E+03 0.2802924E+03 0.2795099E+03 0.2787223E+03 0.2779291E+03 + 0.2771306E+03 0.2763264E+03 0.2755157E+03 0.2746991E+03 0.2738758E+03 + 0.2730454E+03 0.2722082E+03 0.2713635E+03 0.2705107E+03 0.2696500E+03 + 0.2687810E+03 0.2679030E+03 0.2670163E+03 0.2661200E+03 0.2652137E+03 + 0.2642977E+03 0.2633710E+03 0.2624333E+03 0.2614846E+03 0.2605242E+03 + 0.2595519E+03 0.2585671E+03 0.2575698E+03 0.2565595E+03 0.2555358E+03 + 0.2544986E+03 0.2534473E+03 0.2523821E+03 0.2513025E+03 0.2502084E+03 + 0.2490997E+03 0.2479763E+03 0.2468382E+03 0.2456855E+03 0.2445184E+03 + 0.2433371E+03 0.2421417E+03 0.2409328E+03 0.2397105E+03 0.2384757E+03 + 0.2372288E+03 0.2359705E+03 0.2347015E+03 0.2334226E+03 0.2321348E+03 + 0.2308387E+03 0.2295353E+03 0.2282257E+03 0.2269106E+03 0.2255912E+03 + 0.2242681E+03 0.2229426E+03 0.2216152E+03 0.2202871E+03 0.2189589E+03 + 0.2176314E+03 0.2163053E+03 0.2149814E+03 0.2136601E+03 0.2123422E+03 + 0.2110282E+03 0.2097184E+03 0.2084133E+03 0.2071134E+03 0.2058189E+03 + 0.2045301E+03 0.2032474E+03 0.2019709E+03 0.2007008E+03 0.1994374E+03 + 0.1981807E+03 0.1969309E+03 0.1956881E+03 0.1944523E+03 0.1932237E+03 + 0.1920023E+03 0.1907880E+03 0.1895811E+03 0.1883814E+03 0.1871890E+03 + 0.1860039E+03 0.1848260E+03 0.1836554E+03 0.1824921E+03 0.1813360E+03 + 0.1801871E+03 0.1790454E+03 0.1779109E+03 0.1767834E+03 0.1756631E+03 + 0.1745498E+03 0.1734436E+03 0.1723442E+03 0.1712519E+03 0.1701665E+03 + 0.1690879E+03 0.1680161E+03 0.1669511E+03 0.1658928E+03 0.1648413E+03 + 0.1637964E+03 0.1627581E+03 0.1617264E+03 0.1607012E+03 0.1596826E+03 + 0.1586704E+03 0.1576646E+03 0.1566651E+03 0.1556721E+03 0.1546852E+03 + 0.3068949E+03 0.3062008E+03 0.3055060E+03 0.3048105E+03 0.3041147E+03 + 0.3034179E+03 0.3027204E+03 0.3020226E+03 0.3013232E+03 0.3006235E+03 + 0.2999220E+03 0.2992198E+03 0.2985163E+03 0.2978111E+03 0.2971050E+03 + 0.2963975E+03 0.2956879E+03 0.2949770E+03 0.2942640E+03 0.2935495E+03 + 0.2928329E+03 0.2921136E+03 0.2913926E+03 0.2906690E+03 0.2899431E+03 + 0.2892147E+03 0.2884833E+03 0.2877492E+03 0.2870120E+03 0.2862716E+03 + 0.2855278E+03 0.2847807E+03 0.2840297E+03 0.2832754E+03 0.2825168E+03 + 0.2817538E+03 0.2809866E+03 0.2802149E+03 0.2794383E+03 0.2786566E+03 + 0.2778699E+03 0.2770778E+03 0.2762801E+03 0.2754761E+03 0.2746662E+03 + 0.2738499E+03 0.2730266E+03 0.2721966E+03 0.2713593E+03 0.2705142E+03 + 0.2696613E+03 0.2688002E+03 0.2679305E+03 0.2670518E+03 0.2661643E+03 + 0.2652667E+03 0.2643594E+03 0.2634418E+03 0.2625135E+03 0.2615742E+03 + 0.2606234E+03 0.2596609E+03 0.2586862E+03 0.2576991E+03 0.2566991E+03 + 0.2556859E+03 0.2546593E+03 0.2536188E+03 0.2525644E+03 0.2514957E+03 + 0.2504125E+03 0.2493148E+03 0.2482023E+03 0.2470751E+03 0.2459332E+03 + 0.2447768E+03 0.2436059E+03 0.2424207E+03 0.2412217E+03 0.2400093E+03 + 0.2387837E+03 0.2375458E+03 0.2362960E+03 0.2350351E+03 0.2337638E+03 + 0.2324830E+03 0.2311933E+03 0.2298960E+03 0.2285918E+03 0.2272816E+03 + 0.2259664E+03 0.2246473E+03 0.2233249E+03 0.2220005E+03 0.2206746E+03 + 0.2193482E+03 0.2180222E+03 0.2166972E+03 0.2153739E+03 0.2140530E+03 + 0.2127352E+03 0.2114208E+03 0.2101105E+03 0.2088047E+03 0.2075038E+03 + 0.2062082E+03 0.2049182E+03 0.2036340E+03 0.2023560E+03 0.2010843E+03 + 0.1998191E+03 0.1985605E+03 0.1973088E+03 0.1960641E+03 0.1948263E+03 + 0.1935956E+03 0.1923721E+03 0.1911558E+03 0.1899467E+03 0.1887449E+03 + 0.1875503E+03 0.1863630E+03 0.1851830E+03 0.1840102E+03 0.1828448E+03 + 0.1816865E+03 0.1805354E+03 0.1793916E+03 0.1782549E+03 0.1771253E+03 + 0.1760028E+03 0.1748874E+03 0.1737790E+03 0.1726776E+03 0.1715831E+03 + 0.1704956E+03 0.1694149E+03 0.1683411E+03 0.1672740E+03 0.1662137E+03 + 0.1651601E+03 0.1641132E+03 0.1630730E+03 0.1620392E+03 0.1610121E+03 + 0.1599915E+03 0.1589773E+03 0.1579696E+03 0.1569682E+03 0.1559732E+03 + 0.3073409E+03 0.3066503E+03 0.3059601E+03 0.3052687E+03 0.3045771E+03 + 0.3038846E+03 0.3031917E+03 0.3024984E+03 0.3018034E+03 0.3011083E+03 + 0.3004117E+03 0.2997146E+03 0.2990161E+03 0.2983166E+03 0.2976158E+03 + 0.2969134E+03 0.2962097E+03 0.2955046E+03 0.2947976E+03 0.2940891E+03 + 0.2933786E+03 0.2926663E+03 0.2919518E+03 0.2912349E+03 0.2905162E+03 + 0.2897948E+03 0.2890710E+03 0.2883445E+03 0.2876151E+03 0.2868829E+03 + 0.2861474E+03 0.2854089E+03 0.2846669E+03 0.2839212E+03 0.2831719E+03 + 0.2824188E+03 0.2816615E+03 0.2809000E+03 0.2801340E+03 0.2793632E+03 + 0.2785878E+03 0.2778074E+03 0.2770215E+03 0.2762300E+03 0.2754325E+03 + 0.2746294E+03 0.2738199E+03 0.2730036E+03 0.2721807E+03 0.2713508E+03 + 0.2705131E+03 0.2696678E+03 0.2688147E+03 0.2679531E+03 0.2670822E+03 + 0.2662030E+03 0.2653142E+03 0.2644157E+03 0.2635070E+03 0.2625878E+03 + 0.2616579E+03 0.2607167E+03 0.2597639E+03 0.2587991E+03 0.2578220E+03 + 0.2568322E+03 0.2558294E+03 0.2548133E+03 0.2537836E+03 0.2527399E+03 + 0.2516821E+03 0.2506098E+03 0.2495231E+03 0.2484216E+03 0.2473053E+03 + 0.2461744E+03 0.2450286E+03 0.2438683E+03 0.2426936E+03 0.2415047E+03 + 0.2403021E+03 0.2390862E+03 0.2378574E+03 0.2366163E+03 0.2353637E+03 + 0.2341003E+03 0.2328268E+03 0.2315441E+03 0.2302530E+03 0.2289544E+03 + 0.2276495E+03 0.2263391E+03 0.2250238E+03 0.2237051E+03 0.2223837E+03 + 0.2210604E+03 0.2197361E+03 0.2184117E+03 0.2170880E+03 0.2157656E+03 + 0.2144452E+03 0.2131275E+03 0.2118131E+03 0.2105025E+03 0.2091960E+03 + 0.2078943E+03 0.2065977E+03 0.2053064E+03 0.2040209E+03 0.2027414E+03 + 0.2014680E+03 0.2002012E+03 0.1989409E+03 0.1976873E+03 0.1964406E+03 + 0.1952008E+03 0.1939681E+03 0.1927426E+03 0.1915241E+03 0.1903129E+03 + 0.1891090E+03 0.1879123E+03 0.1867228E+03 0.1855406E+03 0.1843657E+03 + 0.1831980E+03 0.1820376E+03 0.1808844E+03 0.1797384E+03 0.1785995E+03 + 0.1774678E+03 0.1763431E+03 0.1752256E+03 0.1741151E+03 0.1730115E+03 + 0.1719150E+03 0.1708254E+03 0.1697426E+03 0.1686667E+03 0.1675976E+03 + 0.1665352E+03 0.1654796E+03 0.1644307E+03 0.1633884E+03 0.1623527E+03 + 0.1613236E+03 0.1603009E+03 0.1592848E+03 0.1582751E+03 0.1572718E+03 + 0.3077788E+03 0.3070919E+03 0.3064050E+03 0.3057179E+03 0.3050303E+03 + 0.3043423E+03 0.3036534E+03 0.3029641E+03 0.3022738E+03 0.3015832E+03 + 0.3008919E+03 0.3001991E+03 0.2995057E+03 0.2988110E+03 0.2981155E+03 + 0.2974183E+03 0.2967200E+03 0.2960205E+03 0.2953192E+03 0.2946166E+03 + 0.2939121E+03 0.2932062E+03 0.2924980E+03 0.2917876E+03 0.2910756E+03 + 0.2903608E+03 0.2896443E+03 0.2889249E+03 0.2882032E+03 0.2874787E+03 + 0.2867512E+03 0.2860208E+03 0.2852872E+03 0.2845502E+03 0.2838098E+03 + 0.2830657E+03 0.2823180E+03 0.2815663E+03 0.2808103E+03 0.2800498E+03 + 0.2792851E+03 0.2785156E+03 0.2777411E+03 0.2769613E+03 0.2761759E+03 + 0.2753854E+03 0.2745887E+03 0.2737859E+03 0.2729766E+03 0.2721607E+03 + 0.2713380E+03 0.2705076E+03 0.2696698E+03 0.2688242E+03 0.2679706E+03 + 0.2671082E+03 0.2662370E+03 0.2653568E+03 0.2644666E+03 0.2635669E+03 + 0.2626570E+03 0.2617360E+03 0.2608042E+03 0.2598610E+03 0.2589060E+03 + 0.2579389E+03 0.2569593E+03 0.2559668E+03 0.2549612E+03 0.2539420E+03 + 0.2529091E+03 0.2518621E+03 0.2508008E+03 0.2497249E+03 0.2486343E+03 + 0.2475291E+03 0.2464090E+03 0.2452740E+03 0.2441244E+03 0.2429602E+03 + 0.2417817E+03 0.2405891E+03 0.2393829E+03 0.2381635E+03 0.2369315E+03 + 0.2356875E+03 0.2344321E+03 0.2331663E+03 0.2318906E+03 0.2306061E+03 + 0.2293137E+03 0.2280142E+03 0.2267086E+03 0.2253979E+03 0.2240830E+03 + 0.2227649E+03 0.2214445E+03 0.2201226E+03 0.2188000E+03 0.2174778E+03 + 0.2161564E+03 0.2148368E+03 0.2135194E+03 0.2122050E+03 0.2108942E+03 + 0.2095873E+03 0.2082848E+03 0.2069872E+03 0.2056949E+03 0.2044081E+03 + 0.2031272E+03 0.2018523E+03 0.2005838E+03 0.1993217E+03 0.1980663E+03 + 0.1968177E+03 0.1955760E+03 0.1943413E+03 0.1931137E+03 0.1918932E+03 + 0.1906799E+03 0.1894738E+03 0.1882749E+03 0.1870833E+03 0.1858990E+03 + 0.1847219E+03 0.1835520E+03 0.1823895E+03 0.1812341E+03 0.1800859E+03 + 0.1789449E+03 0.1778110E+03 0.1766842E+03 0.1755645E+03 0.1744519E+03 + 0.1733462E+03 0.1722476E+03 0.1711558E+03 0.1700710E+03 0.1689930E+03 + 0.1679218E+03 0.1668574E+03 0.1657998E+03 0.1647488E+03 0.1637045E+03 + 0.1626668E+03 0.1616357E+03 0.1606111E+03 0.1595930E+03 0.1585814E+03 + 0.3082078E+03 0.3075247E+03 0.3068419E+03 0.3061585E+03 0.3054746E+03 + 0.3047906E+03 0.3041060E+03 0.3034208E+03 0.3027349E+03 0.3020488E+03 + 0.3013615E+03 0.3006735E+03 0.2999850E+03 0.2992951E+03 0.2986044E+03 + 0.2979124E+03 0.2972192E+03 0.2965251E+03 0.2958292E+03 0.2951323E+03 + 0.2944336E+03 0.2937333E+03 0.2930312E+03 0.2923275E+03 0.2916216E+03 + 0.2909135E+03 0.2902039E+03 0.2894915E+03 0.2887769E+03 0.2880595E+03 + 0.2873399E+03 0.2866169E+03 0.2858913E+03 0.2851627E+03 0.2844306E+03 + 0.2836957E+03 0.2829569E+03 0.2822144E+03 0.2814679E+03 0.2807174E+03 + 0.2799627E+03 0.2792036E+03 0.2784400E+03 0.2776714E+03 0.2768977E+03 + 0.2761186E+03 0.2753342E+03 0.2745441E+03 0.2737479E+03 0.2729453E+03 + 0.2721364E+03 0.2713207E+03 0.2704977E+03 0.2696673E+03 0.2688293E+03 + 0.2679833E+03 0.2671289E+03 0.2662659E+03 0.2653938E+03 0.2645125E+03 + 0.2636215E+03 0.2627200E+03 0.2618083E+03 0.2608859E+03 0.2599521E+03 + 0.2590068E+03 0.2580496E+03 0.2570801E+03 0.2560978E+03 0.2551026E+03 + 0.2540940E+03 0.2530717E+03 0.2520354E+03 0.2509849E+03 0.2499199E+03 + 0.2488404E+03 0.2477461E+03 0.2466369E+03 0.2455129E+03 0.2443740E+03 + 0.2432204E+03 0.2420523E+03 0.2408700E+03 0.2396735E+03 0.2384639E+03 + 0.2372411E+03 0.2360058E+03 0.2347590E+03 0.2335010E+03 0.2322328E+03 + 0.2309552E+03 0.2296691E+03 0.2283754E+03 0.2270750E+03 0.2257691E+03 + 0.2244583E+03 0.2231438E+03 0.2218265E+03 0.2205071E+03 0.2191868E+03 + 0.2178662E+03 0.2165461E+03 0.2152274E+03 0.2139106E+03 0.2125964E+03 + 0.2112854E+03 0.2099781E+03 0.2086751E+03 0.2073767E+03 0.2060833E+03 + 0.2047954E+03 0.2035131E+03 0.2022367E+03 0.2009666E+03 0.1997029E+03 + 0.1984457E+03 0.1971952E+03 0.1959516E+03 0.1947149E+03 0.1934853E+03 + 0.1922627E+03 0.1910473E+03 0.1898391E+03 0.1886381E+03 0.1874444E+03 + 0.1862579E+03 0.1850786E+03 0.1839066E+03 0.1827419E+03 0.1815843E+03 + 0.1804339E+03 0.1792908E+03 0.1781547E+03 0.1770258E+03 0.1759040E+03 + 0.1747892E+03 0.1736815E+03 0.1725807E+03 0.1714868E+03 0.1703999E+03 + 0.1693199E+03 0.1682466E+03 0.1671802E+03 0.1661205E+03 0.1650675E+03 + 0.1640212E+03 0.1629815E+03 0.1619484E+03 0.1609218E+03 0.1599017E+03 + 0.3086291E+03 0.3079499E+03 0.3072703E+03 0.3065905E+03 0.3059104E+03 + 0.3052306E+03 0.3045495E+03 0.3038688E+03 0.3031870E+03 0.3025047E+03 + 0.3018221E+03 0.3011383E+03 0.3004542E+03 0.2997690E+03 0.2990833E+03 + 0.2983961E+03 0.2977081E+03 0.2970188E+03 0.2963284E+03 0.2956366E+03 + 0.2949433E+03 0.2942489E+03 0.2935526E+03 0.2928550E+03 0.2921552E+03 + 0.2914533E+03 0.2907500E+03 0.2900444E+03 0.2893365E+03 0.2886263E+03 + 0.2879137E+03 0.2871983E+03 0.2864807E+03 0.2857596E+03 0.2850358E+03 + 0.2843089E+03 0.2835786E+03 0.2828449E+03 0.2821077E+03 0.2813666E+03 + 0.2806215E+03 0.2798724E+03 0.2791189E+03 0.2783609E+03 0.2775982E+03 + 0.2768303E+03 0.2760577E+03 0.2752796E+03 0.2744958E+03 0.2737060E+03 + 0.2729101E+03 0.2721080E+03 0.2712993E+03 0.2704834E+03 0.2696605E+03 + 0.2688297E+03 0.2679914E+03 0.2671451E+03 0.2662899E+03 0.2654260E+03 + 0.2645530E+03 0.2636702E+03 0.2627778E+03 0.2618753E+03 0.2609619E+03 + 0.2600375E+03 0.2591018E+03 0.2581543E+03 0.2571946E+03 0.2562225E+03 + 0.2552374E+03 0.2542392E+03 0.2532275E+03 0.2522019E+03 0.2511622E+03 + 0.2501084E+03 0.2490398E+03 0.2479564E+03 0.2468582E+03 0.2457451E+03 + 0.2446171E+03 0.2434742E+03 0.2423166E+03 0.2411446E+03 0.2399585E+03 + 0.2387584E+03 0.2375451E+03 0.2363190E+03 0.2350807E+03 0.2338309E+03 + 0.2325704E+03 0.2313000E+03 0.2300205E+03 0.2287330E+03 0.2274382E+03 + 0.2261371E+03 0.2248309E+03 0.2235203E+03 0.2222063E+03 0.2208899E+03 + 0.2195719E+03 0.2182532E+03 0.2169347E+03 0.2156170E+03 0.2143010E+03 + 0.2129872E+03 0.2116762E+03 0.2103688E+03 0.2090652E+03 0.2077661E+03 + 0.2064718E+03 0.2051828E+03 0.2038992E+03 0.2026215E+03 0.2013498E+03 + 0.2000844E+03 0.1988255E+03 0.1975732E+03 0.1963277E+03 0.1950891E+03 + 0.1938574E+03 0.1926328E+03 0.1914154E+03 0.1902050E+03 0.1890020E+03 + 0.1878061E+03 0.1866174E+03 0.1854360E+03 0.1842618E+03 0.1830949E+03 + 0.1819352E+03 0.1807827E+03 0.1796373E+03 0.1784991E+03 0.1773681E+03 + 0.1762441E+03 0.1751272E+03 0.1740173E+03 0.1729144E+03 0.1718185E+03 + 0.1707295E+03 0.1696474E+03 0.1685721E+03 0.1675036E+03 0.1664418E+03 + 0.1653868E+03 0.1643384E+03 0.1632967E+03 0.1622616E+03 0.1612331E+03 + 0.3090429E+03 0.3083672E+03 0.3076909E+03 0.3070149E+03 0.3063383E+03 + 0.3056617E+03 0.3049852E+03 0.3043076E+03 0.3036301E+03 0.3029518E+03 + 0.3022733E+03 0.3015938E+03 0.3009141E+03 0.3002333E+03 0.2995521E+03 + 0.2988696E+03 0.2981863E+03 0.2975021E+03 0.2968166E+03 0.2961301E+03 + 0.2954421E+03 0.2947531E+03 0.2940622E+03 0.2933703E+03 0.2926764E+03 + 0.2919808E+03 0.2912838E+03 0.2905842E+03 0.2898829E+03 0.2891794E+03 + 0.2884737E+03 0.2877654E+03 0.2870549E+03 0.2863414E+03 0.2856252E+03 + 0.2849063E+03 0.2841842E+03 0.2834587E+03 0.2827303E+03 0.2819985E+03 + 0.2812624E+03 0.2805227E+03 0.2797789E+03 0.2790310E+03 0.2782785E+03 + 0.2775217E+03 0.2767600E+03 0.2759932E+03 0.2752213E+03 0.2744437E+03 + 0.2736602E+03 0.2728711E+03 0.2720756E+03 0.2712738E+03 0.2704649E+03 + 0.2696492E+03 0.2688257E+03 0.2679949E+03 0.2671562E+03 0.2663091E+03 + 0.2654533E+03 0.2645884E+03 0.2637143E+03 0.2628306E+03 0.2619366E+03 + 0.2610323E+03 0.2601172E+03 0.2591909E+03 0.2582531E+03 0.2573033E+03 + 0.2563411E+03 0.2553663E+03 0.2543784E+03 0.2533771E+03 0.2523622E+03 + 0.2513333E+03 0.2502901E+03 0.2492324E+03 0.2481600E+03 0.2470728E+03 + 0.2459707E+03 0.2448536E+03 0.2437214E+03 0.2425746E+03 0.2414131E+03 + 0.2402371E+03 0.2390471E+03 0.2378435E+03 0.2366266E+03 0.2353972E+03 + 0.2341559E+03 0.2329034E+03 0.2316404E+03 0.2303679E+03 0.2290868E+03 + 0.2277979E+03 0.2265021E+03 0.2252006E+03 0.2238942E+03 0.2225839E+03 + 0.2212706E+03 0.2199553E+03 0.2186388E+03 0.2173220E+03 0.2160056E+03 + 0.2146905E+03 0.2133773E+03 0.2120666E+03 0.2107590E+03 0.2094552E+03 + 0.2081554E+03 0.2068603E+03 0.2055702E+03 0.2042855E+03 0.2030064E+03 + 0.2017333E+03 0.2004663E+03 0.1992057E+03 0.1979516E+03 0.1967043E+03 + 0.1954637E+03 0.1942301E+03 0.1930035E+03 0.1917840E+03 0.1905716E+03 + 0.1893664E+03 0.1881684E+03 0.1869776E+03 0.1857941E+03 0.1846177E+03 + 0.1834486E+03 0.1822867E+03 0.1811320E+03 0.1799846E+03 0.1788442E+03 + 0.1777110E+03 0.1765849E+03 0.1754658E+03 0.1743539E+03 0.1732489E+03 + 0.1721508E+03 0.1710597E+03 0.1699755E+03 0.1688981E+03 0.1678276E+03 + 0.1667638E+03 0.1657067E+03 0.1646563E+03 0.1636126E+03 0.1625755E+03 + 0.3094497E+03 0.3087765E+03 0.3081042E+03 0.3074310E+03 0.3067583E+03 + 0.3060850E+03 0.3054122E+03 0.3047383E+03 0.3040648E+03 0.3033904E+03 + 0.3027159E+03 0.3020405E+03 0.3013649E+03 0.3006886E+03 0.3000112E+03 + 0.2993336E+03 0.2986547E+03 0.2979753E+03 0.2972946E+03 0.2966130E+03 + 0.2959302E+03 0.2952462E+03 0.2945608E+03 0.2938742E+03 0.2931860E+03 + 0.2924962E+03 0.2918050E+03 0.2911116E+03 0.2904164E+03 0.2897193E+03 + 0.2890202E+03 0.2883186E+03 0.2876151E+03 0.2869088E+03 0.2862002E+03 + 0.2854886E+03 0.2847744E+03 0.2840572E+03 0.2833367E+03 0.2826131E+03 + 0.2818863E+03 0.2811555E+03 0.2804210E+03 0.2796826E+03 0.2789400E+03 + 0.2781934E+03 0.2774421E+03 0.2766862E+03 0.2759254E+03 0.2751593E+03 + 0.2743880E+03 0.2736109E+03 0.2728282E+03 0.2720394E+03 0.2712441E+03 + 0.2704423E+03 0.2696336E+03 0.2688174E+03 0.2679940E+03 0.2671628E+03 + 0.2663236E+03 0.2654757E+03 0.2646190E+03 0.2637534E+03 0.2628777E+03 + 0.2619926E+03 0.2610973E+03 0.2601913E+03 0.2592744E+03 0.2583459E+03 + 0.2574057E+03 0.2564537E+03 0.2554890E+03 0.2545113E+03 0.2535205E+03 + 0.2525161E+03 0.2514978E+03 0.2504654E+03 0.2494186E+03 0.2483571E+03 + 0.2472808E+03 0.2461897E+03 0.2450835E+03 0.2439623E+03 0.2428262E+03 + 0.2416752E+03 0.2405096E+03 0.2393298E+03 0.2381359E+03 0.2369287E+03 + 0.2357084E+03 0.2344758E+03 0.2332315E+03 0.2319763E+03 0.2307111E+03 + 0.2294366E+03 0.2281539E+03 0.2268638E+03 0.2255673E+03 0.2242654E+03 + 0.2229591E+03 0.2216492E+03 0.2203368E+03 0.2190228E+03 0.2177079E+03 + 0.2163931E+03 0.2150791E+03 0.2137666E+03 0.2124563E+03 0.2111488E+03 + 0.2098448E+03 0.2085446E+03 0.2072488E+03 0.2059578E+03 0.2046719E+03 + 0.2033916E+03 0.2021171E+03 0.2008485E+03 0.1995863E+03 0.1983305E+03 + 0.1970813E+03 0.1958389E+03 0.1946033E+03 0.1933748E+03 0.1921532E+03 + 0.1909388E+03 0.1897314E+03 0.1885313E+03 0.1873384E+03 0.1861527E+03 + 0.1849742E+03 0.1838030E+03 0.1826389E+03 0.1814821E+03 0.1803324E+03 + 0.1791899E+03 0.1780546E+03 0.1769263E+03 0.1758051E+03 0.1746910E+03 + 0.1735839E+03 0.1724837E+03 0.1713906E+03 0.1703042E+03 0.1692248E+03 + 0.1681522E+03 0.1670863E+03 0.1660272E+03 0.1649748E+03 0.1639291E+03 + 0.3098485E+03 0.3091789E+03 0.3085098E+03 0.3078398E+03 0.3071705E+03 + 0.3065005E+03 0.3058311E+03 0.3051610E+03 0.3044910E+03 0.3038206E+03 + 0.3031495E+03 0.3024784E+03 0.3018066E+03 0.3011346E+03 0.3004614E+03 + 0.2997882E+03 0.2991136E+03 0.2984388E+03 0.2977626E+03 0.2970858E+03 + 0.2964078E+03 0.2957289E+03 0.2950484E+03 0.2943672E+03 0.2936842E+03 + 0.2930000E+03 0.2923144E+03 0.2916265E+03 0.2909376E+03 0.2902467E+03 + 0.2895538E+03 0.2888588E+03 0.2881618E+03 0.2874625E+03 0.2867608E+03 + 0.2860563E+03 0.2853496E+03 0.2846400E+03 0.2839276E+03 0.2832120E+03 + 0.2824933E+03 0.2817711E+03 0.2810457E+03 0.2803165E+03 0.2795833E+03 + 0.2788463E+03 0.2781050E+03 0.2773594E+03 0.2766091E+03 0.2758541E+03 + 0.2750941E+03 0.2743286E+03 0.2735580E+03 0.2727816E+03 0.2719993E+03 + 0.2712106E+03 0.2704156E+03 0.2696140E+03 0.2688048E+03 0.2679885E+03 + 0.2671648E+03 0.2663332E+03 0.2654932E+03 0.2646446E+03 0.2637870E+03 + 0.2629201E+03 0.2620436E+03 0.2611569E+03 0.2602598E+03 0.2593521E+03 + 0.2584331E+03 0.2575025E+03 0.2565601E+03 0.2556052E+03 0.2546376E+03 + 0.2536571E+03 0.2526633E+03 0.2516558E+03 0.2506341E+03 0.2495981E+03 + 0.2485475E+03 0.2474822E+03 0.2464020E+03 0.2453068E+03 0.2441965E+03 + 0.2430712E+03 0.2419310E+03 0.2407759E+03 0.2396062E+03 0.2384226E+03 + 0.2372250E+03 0.2360140E+03 0.2347904E+03 0.2335546E+03 0.2323075E+03 + 0.2310498E+03 0.2297824E+03 0.2285061E+03 0.2272220E+03 0.2259308E+03 + 0.2246338E+03 0.2233316E+03 0.2220255E+03 0.2207163E+03 0.2194050E+03 + 0.2180923E+03 0.2167793E+03 0.2154666E+03 0.2141550E+03 0.2128453E+03 + 0.2115381E+03 0.2102339E+03 0.2089335E+03 0.2076371E+03 0.2063453E+03 + 0.2050585E+03 0.2037769E+03 0.2025010E+03 0.2012311E+03 0.1999673E+03 + 0.1987098E+03 0.1974588E+03 0.1962146E+03 0.1949771E+03 0.1937466E+03 + 0.1925230E+03 0.1913065E+03 0.1900971E+03 0.1888949E+03 0.1876998E+03 + 0.1865120E+03 0.1853314E+03 0.1841579E+03 0.1829918E+03 0.1818327E+03 + 0.1806809E+03 0.1795363E+03 0.1783988E+03 0.1772684E+03 0.1761451E+03 + 0.1750288E+03 0.1739196E+03 0.1728173E+03 0.1717220E+03 0.1706336E+03 + 0.1695521E+03 0.1684774E+03 0.1674095E+03 0.1663484E+03 0.1652939E+03 + 0.3102406E+03 0.3095744E+03 0.3089076E+03 0.3082416E+03 0.3075750E+03 + 0.3069088E+03 0.3062424E+03 0.3055762E+03 0.3049091E+03 0.3042425E+03 + 0.3035751E+03 0.3029078E+03 0.3022399E+03 0.3015717E+03 0.3009025E+03 + 0.3002334E+03 0.2995633E+03 0.2988926E+03 0.2982210E+03 0.2975490E+03 + 0.2968754E+03 0.2962010E+03 0.2955260E+03 0.2948492E+03 0.2941719E+03 + 0.2934926E+03 0.2928126E+03 0.2921302E+03 0.2914474E+03 0.2907619E+03 + 0.2900750E+03 0.2893863E+03 0.2886956E+03 0.2880028E+03 0.2873078E+03 + 0.2866104E+03 0.2859106E+03 0.2852084E+03 0.2845034E+03 0.2837957E+03 + 0.2830848E+03 0.2823710E+03 0.2816538E+03 0.2809333E+03 0.2802090E+03 + 0.2794812E+03 0.2787494E+03 0.2780136E+03 0.2772734E+03 0.2765288E+03 + 0.2757792E+03 0.2750252E+03 0.2742660E+03 0.2735015E+03 0.2727313E+03 + 0.2719552E+03 0.2711733E+03 0.2703850E+03 0.2695901E+03 0.2687881E+03 + 0.2679789E+03 0.2671627E+03 0.2663382E+03 0.2655062E+03 0.2646654E+03 + 0.2638159E+03 0.2629574E+03 0.2620890E+03 0.2612112E+03 0.2603230E+03 + 0.2594242E+03 0.2585144E+03 0.2575933E+03 0.2566607E+03 0.2557157E+03 + 0.2547582E+03 0.2537878E+03 0.2528042E+03 0.2518071E+03 0.2507961E+03 + 0.2497708E+03 0.2487314E+03 0.2476770E+03 0.2466078E+03 0.2455235E+03 + 0.2444242E+03 0.2433098E+03 0.2421803E+03 0.2410358E+03 0.2398769E+03 + 0.2387032E+03 0.2375155E+03 0.2363141E+03 0.2350996E+03 0.2338727E+03 + 0.2326339E+03 0.2313840E+03 0.2301239E+03 0.2288544E+03 0.2275765E+03 + 0.2262911E+03 0.2249990E+03 0.2237015E+03 0.2223994E+03 0.2210937E+03 + 0.2197852E+03 0.2184751E+03 0.2171640E+03 0.2158529E+03 0.2145425E+03 + 0.2132336E+03 0.2119268E+03 0.2106227E+03 0.2093221E+03 0.2080252E+03 + 0.2067327E+03 0.2054450E+03 0.2041624E+03 0.2028853E+03 0.2016139E+03 + 0.2003485E+03 0.1990895E+03 0.1978368E+03 0.1965907E+03 0.1953514E+03 + 0.1941189E+03 0.1928933E+03 0.1916748E+03 0.1904633E+03 0.1892590E+03 + 0.1880619E+03 0.1868719E+03 0.1856891E+03 0.1845136E+03 0.1833452E+03 + 0.1821841E+03 0.1810301E+03 0.1798833E+03 0.1787436E+03 0.1776111E+03 + 0.1764856E+03 0.1753673E+03 0.1742559E+03 0.1731515E+03 0.1720541E+03 + 0.1709637E+03 0.1698800E+03 0.1688033E+03 0.1677333E+03 0.1666701E+03 + 0.3106259E+03 0.3099627E+03 0.3092991E+03 0.3086358E+03 0.3079726E+03 + 0.3073096E+03 0.3066460E+03 0.3059833E+03 0.3053198E+03 0.3046565E+03 + 0.3039929E+03 0.3033293E+03 0.3026648E+03 0.3020003E+03 0.3013354E+03 + 0.3006698E+03 0.3000041E+03 0.2993374E+03 0.2986702E+03 0.2980021E+03 + 0.2973334E+03 0.2966637E+03 0.2959932E+03 0.2953214E+03 0.2946487E+03 + 0.2939748E+03 0.2932996E+03 0.2926230E+03 0.2919451E+03 0.2912656E+03 + 0.2905845E+03 0.2899016E+03 0.2892169E+03 0.2885303E+03 0.2878421E+03 + 0.2871511E+03 0.2864580E+03 0.2857626E+03 0.2850649E+03 0.2843646E+03 + 0.2836613E+03 0.2829551E+03 0.2822460E+03 0.2815337E+03 0.2808182E+03 + 0.2800990E+03 0.2793761E+03 0.2786495E+03 0.2779190E+03 0.2771843E+03 + 0.2764452E+03 0.2757017E+03 0.2749533E+03 0.2742000E+03 0.2734413E+03 + 0.2726774E+03 0.2719077E+03 0.2711321E+03 0.2703505E+03 0.2695624E+03 + 0.2687673E+03 0.2679653E+03 0.2671561E+03 0.2663392E+03 0.2655145E+03 + 0.2646816E+03 0.2638399E+03 0.2629893E+03 0.2621296E+03 0.2612602E+03 + 0.2603808E+03 0.2594909E+03 0.2585904E+03 0.2576786E+03 0.2567552E+03 + 0.2558199E+03 0.2548725E+03 0.2539124E+03 0.2529391E+03 0.2519524E+03 + 0.2509519E+03 0.2499374E+03 0.2489085E+03 0.2478650E+03 0.2468068E+03 + 0.2457337E+03 0.2446453E+03 0.2435419E+03 0.2424232E+03 0.2412895E+03 + 0.2401409E+03 0.2389777E+03 0.2378001E+03 0.2366085E+03 0.2354035E+03 + 0.2341855E+03 0.2329553E+03 0.2317135E+03 0.2304610E+03 0.2291987E+03 + 0.2279272E+03 0.2266477E+03 0.2253613E+03 0.2240685E+03 0.2227707E+03 + 0.2214688E+03 0.2201636E+03 0.2188561E+03 0.2175473E+03 0.2162380E+03 + 0.2149289E+03 0.2136209E+03 0.2123148E+03 0.2110110E+03 0.2097103E+03 + 0.2084132E+03 0.2071201E+03 0.2058316E+03 0.2045480E+03 0.2032697E+03 + 0.2019970E+03 0.2007302E+03 0.1994695E+03 0.1982151E+03 0.1969673E+03 + 0.1957261E+03 0.1944917E+03 0.1932642E+03 0.1920436E+03 0.1908301E+03 + 0.1896238E+03 0.1884245E+03 0.1872324E+03 0.1860475E+03 0.1848698E+03 + 0.1836993E+03 0.1825360E+03 0.1813799E+03 0.1802309E+03 0.1790891E+03 + 0.1779544E+03 0.1768269E+03 0.1757063E+03 0.1745928E+03 0.1734864E+03 + 0.1723869E+03 0.1712943E+03 0.1702086E+03 0.1691298E+03 0.1680578E+03 + 0.3110053E+03 0.3103439E+03 0.3096838E+03 0.3090231E+03 0.3083634E+03 + 0.3077029E+03 0.3070431E+03 0.3063829E+03 0.3057230E+03 0.3050628E+03 + 0.3044029E+03 0.3037424E+03 0.3030819E+03 0.3024209E+03 0.3017597E+03 + 0.3010978E+03 0.3004361E+03 0.2997735E+03 0.2991106E+03 0.2984465E+03 + 0.2977822E+03 0.2971168E+03 0.2964508E+03 0.2957836E+03 0.2951156E+03 + 0.2944466E+03 0.2937764E+03 0.2931049E+03 0.2924321E+03 0.2917581E+03 + 0.2910825E+03 0.2904052E+03 0.2897263E+03 0.2890457E+03 0.2883635E+03 + 0.2876791E+03 0.2869923E+03 0.2863036E+03 0.2856126E+03 0.2849189E+03 + 0.2842232E+03 0.2835243E+03 0.2828229E+03 0.2821186E+03 0.2814111E+03 + 0.2807004E+03 0.2799863E+03 0.2792686E+03 0.2785471E+03 0.2778219E+03 + 0.2770926E+03 0.2763587E+03 0.2756208E+03 0.2748782E+03 0.2741306E+03 + 0.2733780E+03 0.2726200E+03 0.2718565E+03 0.2710873E+03 0.2703121E+03 + 0.2695305E+03 0.2687421E+03 0.2679473E+03 0.2671452E+03 0.2663356E+03 + 0.2655183E+03 0.2646929E+03 0.2638592E+03 0.2630167E+03 0.2621653E+03 + 0.2613041E+03 0.2604333E+03 0.2595522E+03 0.2586606E+03 0.2577580E+03 + 0.2568443E+03 0.2559186E+03 0.2549808E+03 0.2540305E+03 0.2530673E+03 + 0.2520911E+03 0.2511014E+03 0.2500974E+03 0.2490793E+03 0.2480467E+03 + 0.2469993E+03 0.2459371E+03 0.2448598E+03 0.2437673E+03 0.2426597E+03 + 0.2415367E+03 0.2403988E+03 0.2392460E+03 0.2380785E+03 0.2368970E+03 + 0.2357016E+03 0.2344929E+03 0.2332715E+03 0.2320381E+03 0.2307935E+03 + 0.2295385E+03 0.2282739E+03 0.2270008E+03 0.2257200E+03 0.2244325E+03 + 0.2231392E+03 0.2218414E+03 0.2205397E+03 0.2192352E+03 0.2179289E+03 + 0.2166216E+03 0.2153141E+03 0.2140074E+03 0.2127020E+03 0.2113986E+03 + 0.2100981E+03 0.2088007E+03 0.2075072E+03 0.2062180E+03 0.2049336E+03 + 0.2036542E+03 0.2023802E+03 0.2011120E+03 0.1998499E+03 0.1985939E+03 + 0.1973443E+03 0.1961013E+03 0.1948650E+03 0.1936356E+03 0.1924131E+03 + 0.1911975E+03 0.1899891E+03 0.1887877E+03 0.1875936E+03 0.1864065E+03 + 0.1852267E+03 0.1840541E+03 0.1828886E+03 0.1817303E+03 0.1805792E+03 + 0.1794353E+03 0.1782985E+03 0.1771687E+03 0.1760461E+03 0.1749305E+03 + 0.1738219E+03 0.1727202E+03 0.1716256E+03 0.1705378E+03 0.1694569E+03 + 0.3113774E+03 0.3107196E+03 0.3100614E+03 0.3094043E+03 0.3087465E+03 + 0.3080897E+03 0.3074327E+03 0.3067760E+03 0.3061193E+03 0.3054621E+03 + 0.3048053E+03 0.3041483E+03 0.3034911E+03 0.3028333E+03 0.3021763E+03 + 0.3015179E+03 0.3008599E+03 0.3002011E+03 0.2995420E+03 0.2988820E+03 + 0.2982218E+03 0.2975608E+03 0.2968992E+03 0.2962363E+03 0.2955730E+03 + 0.2949084E+03 0.2942430E+03 0.2935764E+03 0.2929087E+03 0.2922396E+03 + 0.2915694E+03 0.2908976E+03 0.2902243E+03 0.2895494E+03 0.2888727E+03 + 0.2881942E+03 0.2875138E+03 0.2868316E+03 0.2861470E+03 0.2854602E+03 + 0.2847713E+03 0.2840799E+03 0.2833856E+03 0.2826887E+03 0.2819888E+03 + 0.2812863E+03 0.2805802E+03 0.2798709E+03 0.2791583E+03 0.2784420E+03 + 0.2777219E+03 0.2769977E+03 0.2762695E+03 0.2755369E+03 0.2747999E+03 + 0.2740579E+03 0.2733112E+03 0.2725591E+03 0.2718018E+03 0.2710388E+03 + 0.2702700E+03 0.2694948E+03 0.2687132E+03 0.2679253E+03 0.2671301E+03 + 0.2663277E+03 0.2655177E+03 0.2646999E+03 0.2638737E+03 0.2630393E+03 + 0.2621957E+03 0.2613431E+03 0.2604806E+03 0.2596082E+03 0.2587255E+03 + 0.2578321E+03 0.2569274E+03 0.2560111E+03 0.2550834E+03 0.2541430E+03 + 0.2531898E+03 0.2522237E+03 0.2512440E+03 0.2502507E+03 0.2492436E+03 + 0.2482218E+03 0.2471853E+03 0.2461340E+03 0.2450676E+03 0.2439862E+03 + 0.2428894E+03 0.2417775E+03 0.2406502E+03 0.2395080E+03 0.2383511E+03 + 0.2371796E+03 0.2359940E+03 0.2347947E+03 0.2335824E+03 0.2323578E+03 + 0.2311213E+03 0.2298739E+03 0.2286165E+03 0.2273500E+03 0.2260752E+03 + 0.2247932E+03 0.2235049E+03 0.2222113E+03 0.2209135E+03 0.2196123E+03 + 0.2183088E+03 0.2170037E+03 0.2156981E+03 0.2143927E+03 0.2130883E+03 + 0.2117856E+03 0.2104853E+03 0.2091879E+03 0.2078941E+03 0.2066044E+03 + 0.2053191E+03 0.2040388E+03 0.2027637E+03 0.2014942E+03 0.2002305E+03 + 0.1989730E+03 0.1977217E+03 0.1964770E+03 0.1952389E+03 0.1940075E+03 + 0.1927830E+03 0.1915655E+03 0.1903550E+03 0.1891516E+03 0.1879553E+03 + 0.1867662E+03 0.1855842E+03 0.1844094E+03 0.1832418E+03 0.1820814E+03 + 0.1809282E+03 0.1797821E+03 0.1786431E+03 0.1775112E+03 0.1763864E+03 + 0.1752687E+03 0.1741580E+03 0.1730543E+03 0.1719575E+03 0.1708676E+03 + 0.3117440E+03 0.3110881E+03 0.3104333E+03 0.3097787E+03 0.3091238E+03 + 0.3084697E+03 0.3078155E+03 0.3071615E+03 0.3065078E+03 0.3058542E+03 + 0.3052001E+03 0.3045467E+03 0.3038926E+03 0.3032388E+03 0.3025845E+03 + 0.3019302E+03 0.3012754E+03 0.3006205E+03 0.2999649E+03 0.2993093E+03 + 0.2986527E+03 0.2979958E+03 0.2973382E+03 0.2966800E+03 0.2960210E+03 + 0.2953604E+03 0.2947000E+03 0.2940380E+03 0.2933752E+03 0.2927109E+03 + 0.2920457E+03 0.2913790E+03 0.2907111E+03 0.2900416E+03 0.2893707E+03 + 0.2886978E+03 0.2880236E+03 0.2873472E+03 0.2866689E+03 0.2859886E+03 + 0.2853062E+03 0.2846214E+03 0.2839342E+03 0.2832444E+03 0.2825517E+03 + 0.2818567E+03 0.2811586E+03 0.2804576E+03 0.2797531E+03 0.2790452E+03 + 0.2783337E+03 0.2776189E+03 0.2769001E+03 0.2761771E+03 0.2754500E+03 + 0.2747184E+03 0.2739819E+03 0.2732410E+03 0.2724950E+03 0.2717436E+03 + 0.2709868E+03 0.2702241E+03 0.2694553E+03 0.2686803E+03 0.2678991E+03 + 0.2671109E+03 0.2663156E+03 0.2655128E+03 0.2647024E+03 0.2638839E+03 + 0.2630570E+03 0.2622213E+03 0.2613770E+03 0.2605229E+03 0.2596591E+03 + 0.2587851E+03 0.2579005E+03 0.2570052E+03 0.2560984E+03 0.2551798E+03 + 0.2542490E+03 0.2533061E+03 0.2523503E+03 0.2513809E+03 0.2503980E+03 + 0.2494012E+03 0.2483901E+03 0.2473647E+03 0.2463243E+03 0.2452689E+03 + 0.2441984E+03 0.2431127E+03 0.2420116E+03 0.2408954E+03 0.2397638E+03 + 0.2386173E+03 0.2374561E+03 0.2362805E+03 0.2350909E+03 0.2338879E+03 + 0.2326721E+03 0.2314441E+03 0.2302048E+03 0.2289548E+03 0.2276952E+03 + 0.2264268E+03 0.2251505E+03 0.2238675E+03 0.2225785E+03 0.2212848E+03 + 0.2199872E+03 0.2186867E+03 0.2173842E+03 0.2160806E+03 0.2147769E+03 + 0.2134737E+03 0.2121718E+03 0.2108719E+03 0.2095747E+03 0.2082807E+03 + 0.2069906E+03 0.2057047E+03 0.2044234E+03 0.2031472E+03 0.2018765E+03 + 0.2006115E+03 0.1993524E+03 0.1980995E+03 0.1968530E+03 0.1956131E+03 + 0.1943799E+03 0.1931535E+03 0.1919340E+03 0.1907215E+03 0.1895160E+03 + 0.1883177E+03 0.1871264E+03 0.1859424E+03 0.1847654E+03 0.1835957E+03 + 0.1824331E+03 0.1812777E+03 0.1801295E+03 0.1789884E+03 0.1778544E+03 + 0.1767275E+03 0.1756076E+03 0.1744948E+03 0.1733889E+03 0.1722900E+03 + 0.3121037E+03 0.3114512E+03 0.3107985E+03 0.3101461E+03 0.3094948E+03 + 0.3088430E+03 0.3081920E+03 0.3075406E+03 0.3068899E+03 0.3062391E+03 + 0.3055885E+03 0.3049375E+03 0.3042870E+03 0.3036365E+03 0.3029855E+03 + 0.3023349E+03 0.3016833E+03 0.3010320E+03 0.3003799E+03 0.2997280E+03 + 0.2990753E+03 0.2984222E+03 0.2977685E+03 0.2971144E+03 0.2964595E+03 + 0.2958038E+03 0.2951473E+03 0.2944900E+03 0.2938313E+03 0.2931720E+03 + 0.2925120E+03 0.2918502E+03 0.2911874E+03 0.2905230E+03 0.2898575E+03 + 0.2891901E+03 0.2885214E+03 0.2878508E+03 0.2871786E+03 0.2865045E+03 + 0.2858279E+03 0.2851498E+03 0.2844693E+03 0.2837866E+03 0.2831012E+03 + 0.2824131E+03 0.2817224E+03 0.2810289E+03 0.2803324E+03 0.2796328E+03 + 0.2789297E+03 0.2782234E+03 0.2775134E+03 0.2767995E+03 0.2760818E+03 + 0.2753599E+03 0.2746337E+03 0.2739031E+03 0.2731678E+03 0.2724274E+03 + 0.2716820E+03 0.2709312E+03 0.2701747E+03 0.2694123E+03 0.2686437E+03 + 0.2678692E+03 0.2670877E+03 0.2662993E+03 0.2655037E+03 0.2647005E+03 + 0.2638895E+03 0.2630703E+03 0.2622426E+03 0.2614059E+03 0.2605602E+03 + 0.2597046E+03 0.2588393E+03 0.2579637E+03 0.2570772E+03 0.2561795E+03 + 0.2552708E+03 0.2543497E+03 0.2534163E+03 0.2524702E+03 0.2515114E+03 + 0.2505391E+03 0.2495527E+03 0.2485523E+03 0.2475375E+03 0.2465079E+03 + 0.2454637E+03 0.2444042E+03 0.2433294E+03 0.2422393E+03 0.2411339E+03 + 0.2400133E+03 0.2388773E+03 0.2377265E+03 0.2365611E+03 0.2353814E+03 + 0.2341880E+03 0.2329812E+03 0.2317620E+03 0.2305309E+03 0.2292887E+03 + 0.2280362E+03 0.2267745E+03 0.2255043E+03 0.2242268E+03 0.2229429E+03 + 0.2216535E+03 0.2203598E+03 0.2190626E+03 0.2177629E+03 0.2164617E+03 + 0.2151598E+03 0.2138579E+03 0.2125571E+03 0.2112578E+03 0.2099609E+03 + 0.2086670E+03 0.2073765E+03 0.2060900E+03 0.2048080E+03 0.2035309E+03 + 0.2022590E+03 0.2009926E+03 0.1997321E+03 0.1984777E+03 0.1972295E+03 + 0.1959879E+03 0.1947528E+03 0.1935245E+03 0.1923031E+03 0.1910885E+03 + 0.1898810E+03 0.1886806E+03 0.1874873E+03 0.1863011E+03 0.1851221E+03 + 0.1839502E+03 0.1827855E+03 0.1816280E+03 0.1804776E+03 0.1793343E+03 + 0.1781982E+03 0.1770691E+03 0.1759471E+03 0.1748322E+03 0.1737242E+03 + 0.3124586E+03 0.3118080E+03 0.3111579E+03 0.3105085E+03 0.3098590E+03 + 0.3092102E+03 0.3085615E+03 0.3079134E+03 0.3072655E+03 0.3066171E+03 + 0.3059699E+03 0.3053219E+03 0.3046746E+03 0.3040268E+03 0.3033795E+03 + 0.3027314E+03 0.3020839E+03 0.3014356E+03 0.3007878E+03 0.3001389E+03 + 0.2994899E+03 0.2988406E+03 0.2981907E+03 0.2975405E+03 0.2968895E+03 + 0.2962381E+03 0.2955857E+03 0.2949327E+03 0.2942787E+03 0.2936238E+03 + 0.2929681E+03 0.2923113E+03 0.2916534E+03 0.2909940E+03 0.2903336E+03 + 0.2896715E+03 0.2890083E+03 0.2883431E+03 0.2876766E+03 0.2870083E+03 + 0.2863380E+03 0.2856660E+03 0.2849919E+03 0.2843154E+03 0.2836364E+03 + 0.2829557E+03 0.2822717E+03 0.2815858E+03 0.2808969E+03 0.2802049E+03 + 0.2795098E+03 0.2788117E+03 0.2781102E+03 0.2774052E+03 0.2766964E+03 + 0.2759838E+03 0.2752672E+03 0.2745464E+03 0.2738212E+03 0.2730913E+03 + 0.2723570E+03 0.2716171E+03 0.2708722E+03 0.2701218E+03 0.2693656E+03 + 0.2686034E+03 0.2678354E+03 0.2670606E+03 0.2662790E+03 0.2654903E+03 + 0.2646943E+03 0.2638908E+03 0.2630790E+03 0.2622589E+03 0.2614301E+03 + 0.2605925E+03 0.2597454E+03 0.2588885E+03 0.2580215E+03 0.2571438E+03 + 0.2562556E+03 0.2553557E+03 0.2544443E+03 0.2535207E+03 0.2525848E+03 + 0.2516357E+03 0.2506733E+03 0.2496977E+03 0.2487080E+03 0.2477039E+03 + 0.2466852E+03 0.2456517E+03 0.2446033E+03 0.2435395E+03 0.2424604E+03 + 0.2413660E+03 0.2402560E+03 0.2391310E+03 0.2379908E+03 0.2368356E+03 + 0.2356660E+03 0.2344823E+03 0.2332850E+03 0.2320747E+03 0.2308521E+03 + 0.2296178E+03 0.2283729E+03 0.2271181E+03 0.2258544E+03 0.2245827E+03 + 0.2233041E+03 0.2220195E+03 0.2207299E+03 0.2194362E+03 0.2181396E+03 + 0.2168410E+03 0.2155412E+03 0.2142410E+03 0.2129414E+03 0.2116430E+03 + 0.2103465E+03 0.2090528E+03 0.2077621E+03 0.2064752E+03 0.2051926E+03 + 0.2039146E+03 0.2026416E+03 0.2013741E+03 0.2001122E+03 0.1988562E+03 + 0.1976065E+03 0.1963631E+03 0.1951262E+03 0.1938960E+03 0.1926727E+03 + 0.1914562E+03 0.1902467E+03 0.1890442E+03 0.1878488E+03 0.1866605E+03 + 0.1854793E+03 0.1843053E+03 0.1831385E+03 0.1819788E+03 0.1808263E+03 + 0.1796809E+03 0.1785426E+03 0.1774114E+03 0.1762873E+03 0.1751702E+03 + 0.3128071E+03 0.3121589E+03 0.3115114E+03 0.3108642E+03 0.3102178E+03 + 0.3095710E+03 0.3089251E+03 0.3082799E+03 0.3076342E+03 0.3069896E+03 + 0.3063443E+03 0.3056997E+03 0.3050549E+03 0.3044106E+03 0.3037659E+03 + 0.3031212E+03 0.3024767E+03 0.3018320E+03 0.3011873E+03 0.3005420E+03 + 0.2998965E+03 0.2992505E+03 0.2986049E+03 0.2979580E+03 0.2973111E+03 + 0.2966635E+03 0.2960150E+03 0.2953665E+03 0.2947167E+03 0.2940664E+03 + 0.2934148E+03 0.2927626E+03 0.2921093E+03 0.2914551E+03 0.2907995E+03 + 0.2901423E+03 0.2894843E+03 0.2888244E+03 0.2881634E+03 0.2875005E+03 + 0.2868360E+03 0.2861699E+03 0.2855016E+03 0.2848315E+03 0.2841594E+03 + 0.2834851E+03 0.2828081E+03 0.2821289E+03 0.2814473E+03 0.2807625E+03 + 0.2800750E+03 0.2793848E+03 0.2786912E+03 0.2779944E+03 0.2772940E+03 + 0.2765905E+03 0.2758830E+03 0.2751715E+03 0.2744560E+03 0.2737361E+03 + 0.2730118E+03 0.2722828E+03 0.2715489E+03 0.2708099E+03 0.2700655E+03 + 0.2693154E+03 0.2685595E+03 0.2677978E+03 0.2670295E+03 0.2662547E+03 + 0.2654729E+03 0.2646840E+03 0.2638877E+03 0.2630832E+03 0.2622709E+03 + 0.2614498E+03 0.2606200E+03 0.2597811E+03 0.2589326E+03 0.2580739E+03 + 0.2572054E+03 0.2563258E+03 0.2554353E+03 0.2545333E+03 0.2536191E+03 + 0.2526929E+03 0.2517540E+03 0.2508020E+03 0.2498364E+03 0.2488571E+03 + 0.2478639E+03 0.2468560E+03 0.2458333E+03 0.2447957E+03 0.2437431E+03 + 0.2426750E+03 0.2415915E+03 0.2404926E+03 0.2393783E+03 0.2382486E+03 + 0.2371041E+03 0.2359446E+03 0.2347709E+03 0.2335831E+03 0.2323820E+03 + 0.2311681E+03 0.2299423E+03 0.2287052E+03 0.2274576E+03 0.2262006E+03 + 0.2249351E+03 0.2236620E+03 0.2223825E+03 0.2210973E+03 0.2198076E+03 + 0.2185144E+03 0.2172186E+03 0.2159210E+03 0.2146228E+03 0.2133246E+03 + 0.2120272E+03 0.2107315E+03 0.2094380E+03 0.2081474E+03 0.2068602E+03 + 0.2055770E+03 0.2042982E+03 0.2030243E+03 0.2017556E+03 0.2004924E+03 + 0.1992350E+03 0.1979837E+03 0.1967386E+03 0.1955000E+03 0.1942680E+03 + 0.1930427E+03 0.1918243E+03 0.1906128E+03 0.1894083E+03 0.1882108E+03 + 0.1870204E+03 0.1858372E+03 0.1846611E+03 0.1834921E+03 0.1823303E+03 + 0.1811756E+03 0.1800281E+03 0.1788877E+03 0.1777543E+03 0.1766281E+03 + 0.3131504E+03 0.3125046E+03 0.3118590E+03 0.3112147E+03 0.3105700E+03 + 0.3099263E+03 0.3092831E+03 0.3086396E+03 0.3079973E+03 0.3073546E+03 + 0.3067126E+03 0.3060706E+03 0.3054288E+03 0.3047875E+03 0.3041456E+03 + 0.3035043E+03 0.3028625E+03 0.3022212E+03 0.3015793E+03 0.3009377E+03 + 0.3002956E+03 0.2996530E+03 0.2990109E+03 0.2983677E+03 0.2977245E+03 + 0.2970807E+03 0.2964365E+03 0.2957914E+03 0.2951460E+03 0.2944995E+03 + 0.2938525E+03 0.2932048E+03 0.2925558E+03 0.2919060E+03 0.2912550E+03 + 0.2906030E+03 0.2899500E+03 0.2892951E+03 0.2886395E+03 0.2879818E+03 + 0.2873231E+03 0.2866624E+03 0.2859998E+03 0.2853359E+03 0.2846699E+03 + 0.2840015E+03 0.2833312E+03 0.2826585E+03 0.2819833E+03 0.2813060E+03 + 0.2806261E+03 0.2799431E+03 0.2792573E+03 0.2785683E+03 0.2778763E+03 + 0.2771809E+03 0.2764820E+03 0.2757794E+03 0.2750730E+03 0.2743626E+03 + 0.2736482E+03 0.2729292E+03 0.2722058E+03 0.2714776E+03 0.2707443E+03 + 0.2700058E+03 0.2692617E+03 0.2685121E+03 0.2677566E+03 0.2669948E+03 + 0.2662265E+03 0.2654515E+03 0.2646694E+03 0.2638802E+03 0.2630831E+03 + 0.2622781E+03 0.2614651E+03 0.2606429E+03 0.2598118E+03 0.2589716E+03 + 0.2581216E+03 0.2572614E+03 0.2563911E+03 0.2555093E+03 0.2546165E+03 + 0.2537119E+03 0.2527954E+03 0.2518661E+03 0.2509243E+03 0.2499692E+03 + 0.2490002E+03 0.2480173E+03 0.2470203E+03 0.2460085E+03 0.2449818E+03 + 0.2439400E+03 0.2428830E+03 0.2418104E+03 0.2407225E+03 0.2396191E+03 + 0.2385003E+03 0.2373663E+03 0.2362171E+03 0.2350536E+03 0.2338756E+03 + 0.2326840E+03 0.2314791E+03 0.2302617E+03 0.2290327E+03 0.2277927E+03 + 0.2265428E+03 0.2252838E+03 0.2240166E+03 0.2227423E+03 0.2214619E+03 + 0.2201764E+03 0.2188868E+03 0.2175941E+03 0.2162993E+03 0.2150031E+03 + 0.2137066E+03 0.2124105E+03 0.2111156E+03 0.2098226E+03 0.2085321E+03 + 0.2072448E+03 0.2059612E+03 0.2046818E+03 0.2034070E+03 0.2021372E+03 + 0.2008728E+03 0.1996141E+03 0.1983612E+03 0.1971146E+03 0.1958743E+03 + 0.1946405E+03 0.1934133E+03 0.1921930E+03 0.1909795E+03 0.1897730E+03 + 0.1885734E+03 0.1873810E+03 0.1861957E+03 0.1850174E+03 0.1838464E+03 + 0.1826824E+03 0.1815256E+03 0.1803759E+03 0.1792334E+03 0.1780979E+03 + 0.3134879E+03 0.3128444E+03 0.3122015E+03 0.3115587E+03 0.3109171E+03 + 0.3102758E+03 0.3096345E+03 0.3089943E+03 0.3083537E+03 0.3077141E+03 + 0.3070745E+03 0.3064355E+03 0.3057964E+03 0.3051576E+03 0.3045187E+03 + 0.3038800E+03 0.3032418E+03 0.3026031E+03 0.3019646E+03 0.3013264E+03 + 0.3006873E+03 0.3000485E+03 0.2994093E+03 0.2987702E+03 0.2981299E+03 + 0.2974900E+03 0.2968494E+03 0.2962082E+03 0.2955669E+03 0.2949243E+03 + 0.2942814E+03 0.2936377E+03 0.2929928E+03 0.2923480E+03 0.2917013E+03 + 0.2910540E+03 0.2904054E+03 0.2897557E+03 0.2891048E+03 0.2884525E+03 + 0.2877991E+03 0.2871436E+03 0.2864869E+03 0.2858284E+03 0.2851682E+03 + 0.2845058E+03 0.2838417E+03 0.2831756E+03 0.2825071E+03 0.2818364E+03 + 0.2811631E+03 0.2804872E+03 0.2798087E+03 0.2791274E+03 0.2784431E+03 + 0.2777556E+03 0.2770651E+03 0.2763710E+03 0.2756734E+03 0.2749721E+03 + 0.2742668E+03 0.2735575E+03 0.2728439E+03 0.2721259E+03 0.2714032E+03 + 0.2706757E+03 0.2699431E+03 0.2692049E+03 0.2684613E+03 0.2677117E+03 + 0.2669563E+03 0.2661946E+03 0.2654263E+03 0.2646510E+03 0.2638688E+03 + 0.2630788E+03 0.2622809E+03 0.2614755E+03 0.2606611E+03 0.2598381E+03 + 0.2590059E+03 0.2581643E+03 0.2573126E+03 0.2564506E+03 0.2555780E+03 + 0.2546943E+03 0.2537990E+03 0.2528921E+03 0.2519729E+03 0.2510407E+03 + 0.2500956E+03 0.2491371E+03 0.2481647E+03 0.2471781E+03 0.2461770E+03 + 0.2451614E+03 0.2441305E+03 0.2430844E+03 0.2420230E+03 0.2409462E+03 + 0.2398536E+03 0.2387456E+03 0.2376223E+03 0.2364838E+03 0.2353303E+03 + 0.2341624E+03 0.2329803E+03 0.2317847E+03 0.2305762E+03 0.2293555E+03 + 0.2281235E+03 0.2268808E+03 0.2256286E+03 0.2243676E+03 0.2230990E+03 + 0.2218237E+03 0.2205427E+03 0.2192570E+03 0.2179678E+03 0.2166758E+03 + 0.2153820E+03 0.2140874E+03 0.2127927E+03 0.2114989E+03 0.2102066E+03 + 0.2089164E+03 0.2076292E+03 0.2063453E+03 0.2050654E+03 0.2037898E+03 + 0.2025191E+03 0.2012536E+03 0.1999935E+03 0.1987393E+03 0.1974910E+03 + 0.1962490E+03 0.1950135E+03 0.1937845E+03 0.1925623E+03 0.1913468E+03 + 0.1901383E+03 0.1889368E+03 0.1877423E+03 0.1865548E+03 0.1853745E+03 + 0.1842013E+03 0.1830352E+03 0.1818763E+03 0.1807245E+03 0.1795798E+03 + 0.3138205E+03 0.3131791E+03 0.3125380E+03 0.3118984E+03 0.3112584E+03 + 0.3106193E+03 0.3099809E+03 0.3093425E+03 0.3087050E+03 0.3080672E+03 + 0.3074305E+03 0.3067943E+03 0.3061576E+03 0.3055215E+03 0.3048855E+03 + 0.3042497E+03 0.3036142E+03 0.3029786E+03 0.3023435E+03 0.3017075E+03 + 0.3010721E+03 0.3004362E+03 0.2998004E+03 0.2991643E+03 0.2985278E+03 + 0.2978913E+03 0.2972543E+03 0.2966171E+03 0.2959790E+03 0.2953407E+03 + 0.2947018E+03 0.2940620E+03 0.2934217E+03 0.2927804E+03 0.2921385E+03 + 0.2914957E+03 0.2908515E+03 0.2902067E+03 0.2895603E+03 0.2889127E+03 + 0.2882644E+03 0.2876142E+03 0.2869630E+03 0.2863098E+03 0.2856549E+03 + 0.2849984E+03 0.2843405E+03 0.2836804E+03 0.2830181E+03 0.2823534E+03 + 0.2816867E+03 0.2810179E+03 0.2803465E+03 0.2796724E+03 0.2789953E+03 + 0.2783156E+03 0.2776328E+03 0.2769467E+03 0.2762573E+03 0.2755647E+03 + 0.2748683E+03 0.2741682E+03 0.2734639E+03 0.2727558E+03 0.2720428E+03 + 0.2713256E+03 0.2706035E+03 0.2698766E+03 0.2691444E+03 0.2684067E+03 + 0.2676637E+03 0.2669141E+03 0.2661589E+03 0.2653971E+03 0.2646284E+03 + 0.2638532E+03 0.2630704E+03 0.2622798E+03 0.2614815E+03 0.2606749E+03 + 0.2598593E+03 0.2590353E+03 0.2582016E+03 0.2573585E+03 0.2565049E+03 + 0.2556413E+03 0.2547664E+03 0.2538806E+03 0.2529831E+03 0.2520732E+03 + 0.2511510E+03 0.2502160E+03 0.2492675E+03 0.2483056E+03 0.2473297E+03 + 0.2463392E+03 0.2453342E+03 0.2443144E+03 0.2432793E+03 0.2422289E+03 + 0.2411630E+03 0.2400815E+03 0.2389844E+03 0.2378719E+03 0.2367440E+03 + 0.2356009E+03 0.2344432E+03 0.2332709E+03 0.2320849E+03 0.2308854E+03 + 0.2296734E+03 0.2284494E+03 0.2272144E+03 0.2259693E+03 0.2247149E+03 + 0.2234522E+03 0.2221822E+03 0.2209061E+03 0.2196247E+03 0.2183391E+03 + 0.2170502E+03 0.2157591E+03 0.2144666E+03 0.2131737E+03 0.2118811E+03 + 0.2105897E+03 0.2093000E+03 0.2080130E+03 0.2067290E+03 0.2054486E+03 + 0.2041725E+03 0.2029009E+03 0.2016343E+03 0.2003730E+03 0.1991174E+03 + 0.1978677E+03 0.1966241E+03 0.1953868E+03 0.1941561E+03 0.1929320E+03 + 0.1917146E+03 0.1905041E+03 0.1893006E+03 0.1881040E+03 0.1869145E+03 + 0.1857321E+03 0.1845568E+03 0.1833886E+03 0.1822276E+03 0.1810736E+03 + 0.3141481E+03 0.3135089E+03 0.3128702E+03 0.3122318E+03 0.3115943E+03 + 0.3109576E+03 0.3103210E+03 0.3096855E+03 0.3090501E+03 0.3084149E+03 + 0.3077809E+03 0.3071463E+03 0.3065129E+03 0.3058790E+03 0.3052459E+03 + 0.3046131E+03 0.3039799E+03 0.3033476E+03 0.3027147E+03 0.3020822E+03 + 0.3014498E+03 0.3008171E+03 0.3001846E+03 0.2995515E+03 0.2989186E+03 + 0.2982850E+03 0.2976519E+03 0.2970179E+03 0.2963835E+03 0.2957490E+03 + 0.2951137E+03 0.2944779E+03 0.2938414E+03 0.2932043E+03 0.2925666E+03 + 0.2919277E+03 0.2912882E+03 0.2906477E+03 0.2900061E+03 0.2893637E+03 + 0.2887196E+03 0.2880746E+03 0.2874283E+03 0.2867802E+03 0.2861312E+03 + 0.2854802E+03 0.2848279E+03 0.2841734E+03 0.2835168E+03 0.2828586E+03 + 0.2821984E+03 0.2815357E+03 0.2808711E+03 0.2802035E+03 0.2795338E+03 + 0.2788613E+03 0.2781858E+03 0.2775075E+03 0.2768262E+03 0.2761416E+03 + 0.2754535E+03 0.2747619E+03 0.2740666E+03 0.2733676E+03 0.2726645E+03 + 0.2719570E+03 0.2712451E+03 0.2705285E+03 0.2698069E+03 0.2690807E+03 + 0.2683490E+03 0.2676117E+03 0.2668689E+03 0.2661196E+03 0.2653641E+03 + 0.2646022E+03 0.2638336E+03 0.2630577E+03 0.2622743E+03 0.2614831E+03 + 0.2606840E+03 0.2598763E+03 0.2590599E+03 0.2582345E+03 0.2573994E+03 + 0.2565545E+03 0.2556993E+03 0.2548335E+03 0.2539567E+03 0.2530683E+03 + 0.2521680E+03 0.2512555E+03 0.2503304E+03 0.2493923E+03 0.2484403E+03 + 0.2474749E+03 0.2464952E+03 0.2455009E+03 0.2444917E+03 0.2434677E+03 + 0.2424282E+03 0.2413733E+03 0.2403028E+03 0.2392169E+03 0.2381152E+03 + 0.2369979E+03 0.2358655E+03 0.2347180E+03 0.2335558E+03 0.2323794E+03 + 0.2311892E+03 0.2299861E+03 0.2287706E+03 0.2275435E+03 0.2263057E+03 + 0.2250582E+03 0.2238018E+03 0.2225375E+03 0.2212665E+03 0.2199896E+03 + 0.2187080E+03 0.2174226E+03 0.2161344E+03 0.2148443E+03 0.2135533E+03 + 0.2122622E+03 0.2109718E+03 0.2096830E+03 0.2083962E+03 0.2071122E+03 + 0.2058317E+03 0.2045550E+03 0.2032826E+03 0.2020151E+03 0.2007527E+03 + 0.1994958E+03 0.1982446E+03 0.1969995E+03 0.1957606E+03 0.1945281E+03 + 0.1933021E+03 0.1920829E+03 0.1908705E+03 0.1896649E+03 0.1884664E+03 + 0.1872748E+03 0.1860903E+03 0.1849129E+03 0.1837426E+03 0.1825794E+03 + 0.3144706E+03 0.3138331E+03 0.3131963E+03 0.3125606E+03 0.3119251E+03 + 0.3112902E+03 0.3106564E+03 0.3100224E+03 0.3093898E+03 0.3087573E+03 + 0.3081248E+03 0.3074932E+03 0.3068618E+03 0.3062308E+03 0.3056004E+03 + 0.3049701E+03 0.3043398E+03 0.3037099E+03 0.3030800E+03 0.3024505E+03 + 0.3018207E+03 0.3011914E+03 0.3005616E+03 0.2999321E+03 0.2993021E+03 + 0.2986717E+03 0.2980417E+03 0.2974110E+03 0.2967805E+03 0.2961492E+03 + 0.2955176E+03 0.2948860E+03 0.2942530E+03 0.2936200E+03 0.2929861E+03 + 0.2923513E+03 0.2917163E+03 0.2910798E+03 0.2904427E+03 0.2898046E+03 + 0.2891653E+03 0.2885251E+03 0.2878833E+03 0.2872405E+03 0.2865965E+03 + 0.2859507E+03 0.2853036E+03 0.2846546E+03 0.2840040E+03 0.2833520E+03 + 0.2826975E+03 0.2820411E+03 0.2813824E+03 0.2807218E+03 0.2800587E+03 + 0.2793931E+03 0.2787245E+03 0.2780539E+03 0.2773799E+03 0.2767032E+03 + 0.2760232E+03 0.2753399E+03 0.2746530E+03 0.2739628E+03 0.2732686E+03 + 0.2725705E+03 0.2718682E+03 0.2711616E+03 0.2704505E+03 0.2697345E+03 + 0.2690138E+03 0.2682878E+03 0.2675565E+03 0.2668196E+03 0.2660768E+03 + 0.2653275E+03 0.2645721E+03 0.2638102E+03 0.2630411E+03 0.2622646E+03 + 0.2614806E+03 0.2606888E+03 0.2598887E+03 0.2590800E+03 0.2582625E+03 + 0.2574352E+03 0.2565990E+03 0.2557523E+03 0.2548953E+03 0.2540272E+03 + 0.2531480E+03 0.2522572E+03 0.2513542E+03 0.2504388E+03 0.2495106E+03 + 0.2485692E+03 0.2476138E+03 0.2466446E+03 0.2456611E+03 0.2446627E+03 + 0.2436495E+03 0.2426210E+03 0.2415772E+03 0.2405177E+03 0.2394427E+03 + 0.2383519E+03 0.2372456E+03 0.2361237E+03 0.2349866E+03 0.2338347E+03 + 0.2326682E+03 0.2314875E+03 0.2302935E+03 0.2290867E+03 0.2278678E+03 + 0.2266378E+03 0.2253974E+03 0.2241476E+03 0.2228893E+03 0.2216237E+03 + 0.2203517E+03 0.2190744E+03 0.2177927E+03 0.2165077E+03 0.2152203E+03 + 0.2139315E+03 0.2126421E+03 0.2113531E+03 0.2100650E+03 0.2087788E+03 + 0.2074951E+03 0.2062144E+03 0.2049373E+03 0.2036643E+03 0.2023959E+03 + 0.2011325E+03 0.1998744E+03 0.1986218E+03 0.1973752E+03 0.1961347E+03 + 0.1949005E+03 0.1936728E+03 0.1924517E+03 0.1912374E+03 0.1900299E+03 + 0.1888293E+03 0.1876357E+03 0.1864491E+03 0.1852696E+03 0.1840972E+03 + 0.3147881E+03 0.3141526E+03 0.3135178E+03 0.3128837E+03 0.3122507E+03 + 0.3116180E+03 0.3109859E+03 0.3103548E+03 0.3097237E+03 0.3090932E+03 + 0.3084637E+03 0.3078343E+03 0.3072055E+03 0.3065770E+03 0.3059487E+03 + 0.3053212E+03 0.3046935E+03 0.3040662E+03 0.3034393E+03 0.3028120E+03 + 0.3021855E+03 0.3015584E+03 0.3009320E+03 0.3003055E+03 0.2996783E+03 + 0.2990516E+03 0.2984244E+03 0.2977974E+03 0.2971699E+03 0.2965420E+03 + 0.2959142E+03 0.2952855E+03 0.2946565E+03 0.2940271E+03 0.2933971E+03 + 0.2927666E+03 0.2921353E+03 0.2915032E+03 0.2908705E+03 0.2902363E+03 + 0.2896019E+03 0.2889659E+03 0.2883290E+03 0.2876911E+03 0.2870517E+03 + 0.2864109E+03 0.2857691E+03 0.2851255E+03 0.2844804E+03 0.2838337E+03 + 0.2831848E+03 0.2825345E+03 0.2818820E+03 0.2812275E+03 0.2805711E+03 + 0.2799117E+03 0.2792504E+03 0.2785864E+03 0.2779198E+03 0.2772503E+03 + 0.2765779E+03 0.2759024E+03 0.2752236E+03 0.2745418E+03 0.2738563E+03 + 0.2731671E+03 0.2724738E+03 0.2717768E+03 0.2710755E+03 0.2703697E+03 + 0.2696591E+03 0.2689436E+03 0.2682235E+03 0.2674980E+03 0.2667671E+03 + 0.2660302E+03 0.2652872E+03 0.2645382E+03 0.2637829E+03 0.2630205E+03 + 0.2622509E+03 0.2614739E+03 0.2606894E+03 0.2598966E+03 0.2590955E+03 + 0.2582857E+03 0.2574669E+03 0.2566382E+03 0.2558000E+03 0.2549516E+03 + 0.2540925E+03 0.2532223E+03 0.2523406E+03 0.2514471E+03 0.2505415E+03 + 0.2496231E+03 0.2486916E+03 0.2477468E+03 0.2467878E+03 0.2458147E+03 + 0.2448273E+03 0.2438248E+03 0.2428074E+03 0.2417745E+03 0.2407261E+03 + 0.2396620E+03 0.2385822E+03 0.2374868E+03 0.2363757E+03 0.2352493E+03 + 0.2341076E+03 0.2329511E+03 0.2317803E+03 0.2305956E+03 0.2293977E+03 + 0.2281874E+03 0.2269653E+03 0.2257323E+03 0.2244894E+03 0.2232375E+03 + 0.2219776E+03 0.2207108E+03 0.2194380E+03 0.2181604E+03 0.2168789E+03 + 0.2155944E+03 0.2143081E+03 0.2130207E+03 0.2117331E+03 0.2104462E+03 + 0.2091607E+03 0.2078773E+03 0.2065966E+03 0.2053194E+03 0.2040459E+03 + 0.2027767E+03 0.2015124E+03 0.2002531E+03 0.1989993E+03 0.1977512E+03 + 0.1965092E+03 0.1952733E+03 0.1940439E+03 0.1928209E+03 0.1916047E+03 + 0.1903953E+03 0.1891927E+03 0.1879971E+03 0.1868085E+03 0.1856269E+03 + 0.3151007E+03 0.3144673E+03 0.3138347E+03 0.3132028E+03 0.3125714E+03 + 0.3119409E+03 0.3113111E+03 0.3106812E+03 0.3100530E+03 0.3094247E+03 + 0.3087971E+03 0.3081703E+03 0.3075434E+03 0.3069172E+03 0.3062919E+03 + 0.3056663E+03 0.3050415E+03 0.3044165E+03 0.3037917E+03 0.3031677E+03 + 0.3025434E+03 0.3019198E+03 0.3012957E+03 0.3006718E+03 0.3000481E+03 + 0.2994242E+03 0.2988004E+03 0.2981764E+03 0.2975519E+03 0.2969279E+03 + 0.2963029E+03 0.2956778E+03 0.2950528E+03 0.2944266E+03 0.2938003E+03 + 0.2931736E+03 0.2925460E+03 0.2919182E+03 0.2912891E+03 0.2906595E+03 + 0.2900292E+03 0.2893975E+03 0.2887652E+03 0.2881318E+03 0.2874969E+03 + 0.2868615E+03 0.2862242E+03 0.2855857E+03 0.2849460E+03 0.2843044E+03 + 0.2836612E+03 0.2830165E+03 0.2823699E+03 0.2817213E+03 0.2810705E+03 + 0.2804181E+03 0.2797630E+03 0.2791058E+03 0.2784460E+03 0.2777836E+03 + 0.2771183E+03 0.2764504E+03 0.2757795E+03 0.2751054E+03 0.2744279E+03 + 0.2737471E+03 0.2730625E+03 0.2723746E+03 0.2716824E+03 0.2709861E+03 + 0.2702856E+03 0.2695806E+03 0.2688709E+03 0.2681561E+03 0.2674362E+03 + 0.2667112E+03 0.2659804E+03 0.2652436E+03 0.2645008E+03 0.2637519E+03 + 0.2629960E+03 0.2622332E+03 0.2614631E+03 0.2606855E+03 0.2599002E+03 + 0.2591066E+03 0.2583044E+03 0.2574934E+03 0.2566730E+03 0.2558430E+03 + 0.2550029E+03 0.2541524E+03 0.2532912E+03 0.2524186E+03 0.2515345E+03 + 0.2506384E+03 0.2497297E+03 0.2488083E+03 0.2478732E+03 0.2469248E+03 + 0.2459623E+03 0.2449852E+03 0.2439938E+03 0.2429871E+03 0.2419653E+03 + 0.2409280E+03 0.2398749E+03 0.2388061E+03 0.2377216E+03 0.2366215E+03 + 0.2355056E+03 0.2343744E+03 0.2332283E+03 0.2320673E+03 0.2308922E+03 + 0.2297035E+03 0.2285019E+03 0.2272880E+03 0.2260628E+03 0.2248271E+03 + 0.2235818E+03 0.2223280E+03 0.2210668E+03 0.2197989E+03 0.2185256E+03 + 0.2172478E+03 0.2159666E+03 0.2146830E+03 0.2133978E+03 0.2121120E+03 + 0.2108264E+03 0.2095418E+03 0.2082589E+03 0.2069785E+03 0.2057011E+03 + 0.2044272E+03 0.2031575E+03 0.2018922E+03 0.2006320E+03 0.1993769E+03 + 0.1981275E+03 0.1968840E+03 0.1956465E+03 0.1944154E+03 0.1931907E+03 + 0.1919726E+03 0.1907613E+03 0.1895567E+03 0.1883591E+03 0.1871685E+03 + 0.3154095E+03 0.3147774E+03 0.3141463E+03 0.3135166E+03 0.3128871E+03 + 0.3122584E+03 0.3116304E+03 0.3110033E+03 0.3103764E+03 0.3097506E+03 + 0.3091255E+03 0.3085001E+03 0.3078756E+03 0.3072524E+03 0.3066284E+03 + 0.3060059E+03 0.3053832E+03 0.3047609E+03 0.3041389E+03 0.3035172E+03 + 0.3028957E+03 0.3022744E+03 0.3016532E+03 0.3010323E+03 0.3004113E+03 + 0.2997904E+03 0.2991697E+03 0.2985485E+03 0.2979274E+03 0.2973063E+03 + 0.2966844E+03 0.2960628E+03 0.2954408E+03 0.2948187E+03 0.2941957E+03 + 0.2935725E+03 0.2929489E+03 0.2923246E+03 0.2916996E+03 0.2910741E+03 + 0.2904475E+03 0.2898203E+03 0.2891926E+03 0.2885631E+03 0.2879331E+03 + 0.2873020E+03 0.2866693E+03 0.2860358E+03 0.2854011E+03 0.2847645E+03 + 0.2841266E+03 0.2834874E+03 0.2828465E+03 0.2822034E+03 0.2815588E+03 + 0.2809121E+03 0.2802632E+03 0.2796124E+03 0.2789592E+03 0.2783034E+03 + 0.2776452E+03 0.2769845E+03 0.2763208E+03 0.2756541E+03 0.2749846E+03 + 0.2743118E+03 0.2736357E+03 0.2729561E+03 0.2722728E+03 0.2715856E+03 + 0.2708944E+03 0.2701988E+03 0.2694991E+03 0.2687947E+03 0.2680858E+03 + 0.2673714E+03 0.2666519E+03 0.2659272E+03 0.2651965E+03 0.2644598E+03 + 0.2637170E+03 0.2629676E+03 0.2622116E+03 0.2614482E+03 0.2606779E+03 + 0.2598996E+03 0.2591133E+03 0.2583186E+03 0.2575153E+03 0.2567029E+03 + 0.2558810E+03 0.2550495E+03 0.2542074E+03 0.2533550E+03 0.2524914E+03 + 0.2516164E+03 0.2507296E+03 0.2498306E+03 0.2489188E+03 0.2479942E+03 + 0.2470556E+03 0.2461037E+03 0.2451372E+03 0.2441562E+03 0.2431605E+03 + 0.2421495E+03 0.2411232E+03 0.2400812E+03 0.2390234E+03 0.2379499E+03 + 0.2368607E+03 0.2357557E+03 0.2346352E+03 0.2334993E+03 0.2323485E+03 + 0.2311832E+03 0.2300039E+03 0.2288113E+03 0.2276060E+03 0.2263887E+03 + 0.2251606E+03 0.2239223E+03 0.2226750E+03 0.2214194E+03 0.2201567E+03 + 0.2188881E+03 0.2176144E+03 0.2163367E+03 0.2150560E+03 0.2137733E+03 + 0.2124895E+03 0.2112054E+03 0.2099220E+03 0.2086398E+03 0.2073598E+03 + 0.2060824E+03 0.2048083E+03 0.2035381E+03 0.2022721E+03 0.2010109E+03 + 0.1997548E+03 0.1985041E+03 0.1972591E+03 0.1960201E+03 0.1947873E+03 + 0.1935609E+03 0.1923410E+03 0.1911278E+03 0.1899213E+03 0.1887217E+03 + 0.3157130E+03 0.3150834E+03 0.3144542E+03 0.3138255E+03 0.3131980E+03 + 0.3125716E+03 0.3119454E+03 0.3113199E+03 0.3106958E+03 0.3100717E+03 + 0.3094480E+03 0.3088256E+03 0.3082034E+03 0.3075814E+03 0.3069606E+03 + 0.3063394E+03 0.3057195E+03 0.3050998E+03 0.3044800E+03 0.3038611E+03 + 0.3032421E+03 0.3026230E+03 0.3020051E+03 0.3013864E+03 0.3007679E+03 + 0.3001503E+03 0.2995319E+03 0.2989139E+03 0.2982960E+03 0.2976775E+03 + 0.2970594E+03 0.2964408E+03 0.2958221E+03 0.2952031E+03 0.2945836E+03 + 0.2939640E+03 0.2933439E+03 0.2927231E+03 0.2921021E+03 0.2914801E+03 + 0.2908577E+03 0.2902348E+03 0.2896105E+03 0.2889857E+03 0.2883603E+03 + 0.2877330E+03 0.2871052E+03 0.2864765E+03 0.2858466E+03 0.2852146E+03 + 0.2845821E+03 0.2839478E+03 0.2833122E+03 0.2826746E+03 0.2820356E+03 + 0.2813945E+03 0.2807517E+03 0.2801068E+03 0.2794598E+03 0.2788106E+03 + 0.2781588E+03 0.2775050E+03 0.2768482E+03 0.2761890E+03 0.2755269E+03 + 0.2748616E+03 0.2741934E+03 0.2735219E+03 0.2728470E+03 0.2721683E+03 + 0.2714861E+03 0.2708000E+03 0.2701095E+03 0.2694148E+03 0.2687157E+03 + 0.2680120E+03 0.2673034E+03 0.2665895E+03 0.2658704E+03 0.2651461E+03 + 0.2644153E+03 0.2636785E+03 0.2629357E+03 0.2621861E+03 0.2614295E+03 + 0.2606660E+03 0.2598948E+03 0.2591157E+03 0.2583283E+03 0.2575327E+03 + 0.2567282E+03 0.2559142E+03 0.2550906E+03 0.2542573E+03 0.2534134E+03 + 0.2525587E+03 0.2516927E+03 0.2508154E+03 0.2499256E+03 0.2490238E+03 + 0.2481087E+03 0.2471807E+03 0.2462386E+03 0.2452830E+03 0.2443125E+03 + 0.2433275E+03 0.2423275E+03 0.2413119E+03 0.2402809E+03 0.2392343E+03 + 0.2381719E+03 0.2370936E+03 0.2359994E+03 0.2348896E+03 0.2337643E+03 + 0.2326238E+03 0.2314684E+03 0.2302988E+03 0.2291154E+03 0.2279189E+03 + 0.2267100E+03 0.2254897E+03 0.2242586E+03 0.2230179E+03 0.2217685E+03 + 0.2205115E+03 0.2192477E+03 0.2179784E+03 0.2167045E+03 0.2154271E+03 + 0.2141471E+03 0.2128655E+03 0.2115833E+03 0.2103011E+03 0.2090199E+03 + 0.2077404E+03 0.2064633E+03 0.2051891E+03 0.2039185E+03 0.2026519E+03 + 0.2013899E+03 0.2001327E+03 0.1988808E+03 0.1976345E+03 0.1963940E+03 + 0.1951596E+03 0.1939315E+03 0.1927098E+03 0.1914948E+03 0.1902864E+03 + 0.3160123E+03 0.3153843E+03 0.3147570E+03 0.3141306E+03 0.3135045E+03 + 0.3128797E+03 0.3122556E+03 0.3116322E+03 0.3110094E+03 0.3103876E+03 + 0.3097663E+03 0.3091454E+03 0.3085257E+03 0.3079062E+03 0.3072867E+03 + 0.3066685E+03 0.3060503E+03 0.3054329E+03 0.3048157E+03 0.3041989E+03 + 0.3035821E+03 0.3029664E+03 0.3023499E+03 0.3017346E+03 0.3011190E+03 + 0.3005036E+03 0.2998883E+03 0.2992732E+03 0.2986578E+03 0.2980425E+03 + 0.2974273E+03 0.2968117E+03 0.2961964E+03 0.2955803E+03 0.2949644E+03 + 0.2943481E+03 0.2937313E+03 0.2931143E+03 0.2924967E+03 0.2918784E+03 + 0.2912599E+03 0.2906405E+03 0.2900204E+03 0.2893999E+03 0.2887782E+03 + 0.2881554E+03 0.2875325E+03 0.2869079E+03 0.2862822E+03 0.2856557E+03 + 0.2850273E+03 0.2843982E+03 0.2837674E+03 0.2831351E+03 0.2825017E+03 + 0.2818661E+03 0.2812288E+03 0.2805897E+03 0.2799486E+03 0.2793055E+03 + 0.2786603E+03 0.2780127E+03 0.2773627E+03 0.2767102E+03 0.2760550E+03 + 0.2753972E+03 0.2747365E+03 0.2740726E+03 0.2734057E+03 0.2727354E+03 + 0.2720614E+03 0.2713839E+03 0.2707026E+03 0.2700173E+03 0.2693279E+03 + 0.2686339E+03 0.2679355E+03 0.2672324E+03 0.2665242E+03 0.2658106E+03 + 0.2650917E+03 0.2643676E+03 0.2636367E+03 0.2629001E+03 0.2621570E+03 + 0.2614069E+03 0.2606502E+03 0.2598860E+03 0.2591140E+03 0.2583341E+03 + 0.2575455E+03 0.2567487E+03 0.2559427E+03 0.2551273E+03 0.2543020E+03 + 0.2534667E+03 0.2526208E+03 0.2517638E+03 0.2508954E+03 0.2500151E+03 + 0.2491227E+03 0.2482177E+03 0.2472994E+03 0.2463678E+03 0.2454220E+03 + 0.2444625E+03 0.2434880E+03 0.2424988E+03 0.2414942E+03 0.2404743E+03 + 0.2394388E+03 0.2383874E+03 0.2373199E+03 0.2362368E+03 0.2351378E+03 + 0.2340231E+03 0.2328931E+03 0.2317478E+03 0.2305880E+03 0.2294141E+03 + 0.2282267E+03 0.2270264E+03 0.2258141E+03 0.2245906E+03 0.2233569E+03 + 0.2221140E+03 0.2208627E+03 0.2196043E+03 0.2183396E+03 0.2170699E+03 + 0.2157960E+03 0.2145190E+03 0.2132400E+03 0.2119597E+03 0.2106792E+03 + 0.2093991E+03 0.2081204E+03 0.2068436E+03 0.2055695E+03 0.2042987E+03 + 0.2030316E+03 0.2017688E+03 0.2005107E+03 0.1992577E+03 0.1980101E+03 + 0.1967682E+03 0.1955323E+03 0.1943025E+03 0.1930791E+03 0.1918622E+03 + 0.3163077E+03 0.3156807E+03 0.3150552E+03 0.3144307E+03 0.3138067E+03 + 0.3131835E+03 0.3125612E+03 0.3119397E+03 0.3113191E+03 0.3106985E+03 + 0.3100795E+03 0.3094609E+03 0.3088427E+03 0.3082252E+03 0.3076084E+03 + 0.3069920E+03 0.3063760E+03 0.3057608E+03 0.3051458E+03 0.3045313E+03 + 0.3039175E+03 0.3033031E+03 0.3026901E+03 0.3020770E+03 0.3014637E+03 + 0.3008512E+03 0.3002383E+03 0.2996259E+03 0.2990135E+03 0.2984009E+03 + 0.2977886E+03 0.2971762E+03 0.2965635E+03 0.2959512E+03 0.2953382E+03 + 0.2947248E+03 0.2941117E+03 0.2934978E+03 0.2928837E+03 0.2922693E+03 + 0.2916541E+03 0.2910384E+03 0.2904225E+03 0.2898054E+03 0.2891876E+03 + 0.2885696E+03 0.2879503E+03 0.2873296E+03 0.2867089E+03 0.2860867E+03 + 0.2854632E+03 0.2848386E+03 0.2842126E+03 0.2835854E+03 0.2829572E+03 + 0.2823264E+03 0.2816948E+03 0.2810613E+03 0.2804259E+03 0.2797885E+03 + 0.2791497E+03 0.2785082E+03 0.2778645E+03 0.2772186E+03 0.2765702E+03 + 0.2759193E+03 0.2752656E+03 0.2746091E+03 0.2739497E+03 0.2732873E+03 + 0.2726213E+03 0.2719521E+03 0.2712796E+03 0.2706029E+03 0.2699225E+03 + 0.2692381E+03 0.2685496E+03 0.2678561E+03 0.2671585E+03 0.2664557E+03 + 0.2657478E+03 0.2650345E+03 0.2643160E+03 0.2635914E+03 0.2628611E+03 + 0.2621242E+03 0.2613806E+03 0.2606305E+03 0.2598730E+03 0.2591081E+03 + 0.2583354E+03 0.2575544E+03 0.2567647E+03 0.2559668E+03 0.2551592E+03 + 0.2543421E+03 0.2535153E+03 0.2526777E+03 0.2518295E+03 0.2509701E+03 + 0.2500991E+03 0.2492160E+03 0.2483207E+03 0.2474125E+03 0.2464907E+03 + 0.2455555E+03 0.2446059E+03 0.2436424E+03 0.2426637E+03 0.2416701E+03 + 0.2406611E+03 0.2396364E+03 0.2385961E+03 0.2375400E+03 0.2364677E+03 + 0.2353796E+03 0.2342757E+03 0.2331562E+03 0.2320213E+03 0.2308716E+03 + 0.2297073E+03 0.2285292E+03 0.2273378E+03 0.2261338E+03 0.2249183E+03 + 0.2236918E+03 0.2224556E+03 0.2212106E+03 0.2199577E+03 0.2186980E+03 + 0.2174327E+03 0.2161627E+03 0.2148890E+03 0.2136127E+03 0.2123347E+03 + 0.2110559E+03 0.2097773E+03 0.2084995E+03 0.2072233E+03 0.2059494E+03 + 0.2046785E+03 0.2034111E+03 0.2021477E+03 0.2008887E+03 0.1996347E+03 + 0.1983859E+03 0.1971427E+03 0.1959053E+03 0.1946739E+03 0.1934488E+03 + 0.3165989E+03 0.3159736E+03 0.3153493E+03 0.3147262E+03 0.3141041E+03 + 0.3134830E+03 0.3128623E+03 0.3122425E+03 0.3116233E+03 0.3110055E+03 + 0.3103882E+03 0.3097708E+03 0.3091550E+03 0.3085395E+03 0.3079247E+03 + 0.3073105E+03 0.3066969E+03 0.3060834E+03 0.3054710E+03 0.3048587E+03 + 0.3042465E+03 0.3036353E+03 0.3030241E+03 0.3024133E+03 0.3018029E+03 + 0.3011926E+03 0.3005826E+03 0.2999726E+03 0.2993629E+03 0.2987535E+03 + 0.2981440E+03 0.2975340E+03 0.2969245E+03 0.2963148E+03 0.2957047E+03 + 0.2950950E+03 0.2944847E+03 0.2938741E+03 0.2932637E+03 0.2926523E+03 + 0.2920406E+03 0.2914289E+03 0.2908161E+03 0.2902028E+03 0.2895892E+03 + 0.2889748E+03 0.2883593E+03 0.2877437E+03 0.2871267E+03 0.2865085E+03 + 0.2858894E+03 0.2852697E+03 0.2846482E+03 0.2840257E+03 0.2834025E+03 + 0.2827771E+03 0.2821504E+03 0.2815222E+03 0.2808922E+03 0.2802603E+03 + 0.2796271E+03 0.2789917E+03 0.2783541E+03 0.2777145E+03 0.2770725E+03 + 0.2764282E+03 0.2757813E+03 0.2751319E+03 0.2744795E+03 0.2738244E+03 + 0.2731665E+03 0.2725052E+03 0.2718405E+03 0.2711725E+03 0.2705007E+03 + 0.2698250E+03 0.2691456E+03 0.2684620E+03 0.2677742E+03 0.2670813E+03 + 0.2663843E+03 0.2656818E+03 0.2649742E+03 0.2642614E+03 0.2635430E+03 + 0.2628185E+03 0.2620879E+03 0.2613507E+03 0.2606070E+03 0.2598563E+03 + 0.2590982E+03 0.2583325E+03 0.2575589E+03 0.2567767E+03 0.2559860E+03 + 0.2551864E+03 0.2543773E+03 0.2535586E+03 0.2527296E+03 0.2518901E+03 + 0.2510393E+03 0.2501776E+03 0.2493039E+03 0.2484182E+03 0.2475194E+03 + 0.2466078E+03 0.2456826E+03 0.2447436E+03 0.2437905E+03 0.2428226E+03 + 0.2418396E+03 0.2408415E+03 0.2398279E+03 0.2387986E+03 0.2377534E+03 + 0.2366922E+03 0.2356151E+03 0.2345220E+03 0.2334132E+03 0.2322889E+03 + 0.2311492E+03 0.2299949E+03 0.2288262E+03 0.2276439E+03 0.2264486E+03 + 0.2252412E+03 0.2240224E+03 0.2227932E+03 0.2215547E+03 0.2203077E+03 + 0.2190534E+03 0.2177928E+03 0.2165269E+03 0.2152569E+03 0.2139836E+03 + 0.2127081E+03 0.2114314E+03 0.2101543E+03 0.2088776E+03 0.2076022E+03 + 0.2063288E+03 0.2050579E+03 0.2037903E+03 0.2025264E+03 0.2012668E+03 + 0.2000118E+03 0.1987619E+03 0.1975174E+03 0.1962786E+03 0.1950457E+03 + 0.3168859E+03 0.3162622E+03 0.3156398E+03 0.3150183E+03 0.3143974E+03 + 0.3137777E+03 0.3131589E+03 0.3125410E+03 0.3119236E+03 0.3113070E+03 + 0.3106920E+03 0.3100770E+03 0.3094625E+03 0.3088487E+03 0.3082362E+03 + 0.3076240E+03 0.3070121E+03 0.3064012E+03 0.3057904E+03 0.3051803E+03 + 0.3045711E+03 0.3039615E+03 0.3033528E+03 0.3027445E+03 0.3021361E+03 + 0.3015287E+03 0.3009211E+03 0.3003135E+03 0.2997066E+03 0.2990996E+03 + 0.2984925E+03 0.2978856E+03 0.2972786E+03 0.2966721E+03 0.2960652E+03 + 0.2954580E+03 0.2948509E+03 0.2942438E+03 0.2936362E+03 0.2930281E+03 + 0.2924203E+03 0.2918114E+03 0.2912024E+03 0.2905932E+03 0.2899828E+03 + 0.2893718E+03 0.2887609E+03 0.2881486E+03 0.2875354E+03 0.2869218E+03 + 0.2863074E+03 0.2856916E+03 0.2850750E+03 0.2844570E+03 0.2838379E+03 + 0.2832174E+03 0.2825958E+03 0.2819729E+03 0.2813481E+03 0.2807217E+03 + 0.2800937E+03 0.2794638E+03 0.2788322E+03 0.2781986E+03 0.2775627E+03 + 0.2769245E+03 0.2762842E+03 0.2756415E+03 0.2749962E+03 0.2743481E+03 + 0.2736973E+03 0.2730435E+03 0.2723868E+03 0.2717267E+03 0.2710629E+03 + 0.2703958E+03 0.2697253E+03 0.2690504E+03 0.2683719E+03 0.2676891E+03 + 0.2670016E+03 0.2663095E+03 0.2656128E+03 0.2649109E+03 0.2642034E+03 + 0.2634911E+03 0.2627725E+03 0.2620482E+03 0.2613172E+03 0.2605799E+03 + 0.2598357E+03 0.2590844E+03 0.2583256E+03 0.2575591E+03 0.2567842E+03 + 0.2560010E+03 0.2552090E+03 0.2544078E+03 0.2535972E+03 0.2527765E+03 + 0.2519455E+03 0.2511038E+03 0.2502506E+03 0.2493862E+03 0.2485097E+03 + 0.2476209E+03 0.2467189E+03 0.2458038E+03 0.2448750E+03 0.2439321E+03 + 0.2429749E+03 0.2420027E+03 0.2410155E+03 0.2400128E+03 0.2389944E+03 + 0.2379604E+03 0.2369103E+03 0.2358441E+03 0.2347620E+03 0.2336640E+03 + 0.2325502E+03 0.2314209E+03 0.2302766E+03 0.2291177E+03 0.2279447E+03 + 0.2267584E+03 0.2255594E+03 0.2243485E+03 0.2231268E+03 0.2218950E+03 + 0.2206543E+03 0.2194055E+03 0.2181500E+03 0.2168885E+03 0.2156224E+03 + 0.2143524E+03 0.2130798E+03 0.2118053E+03 0.2105300E+03 0.2092548E+03 + 0.2079803E+03 0.2067075E+03 0.2054369E+03 0.2041692E+03 0.2029050E+03 + 0.2016447E+03 0.2003889E+03 0.1991380E+03 0.1978923E+03 0.1966521E+03 + 0.3171682E+03 0.3165469E+03 0.3159259E+03 0.3153057E+03 0.3146868E+03 + 0.3140685E+03 0.3134512E+03 0.3128349E+03 0.3122197E+03 0.3116051E+03 + 0.3109906E+03 0.3103778E+03 0.3097657E+03 0.3091538E+03 0.3085429E+03 + 0.3079328E+03 0.3073231E+03 0.3067139E+03 0.3061053E+03 0.3054974E+03 + 0.3048898E+03 0.3042831E+03 0.3036761E+03 0.3030698E+03 0.3024645E+03 + 0.3018586E+03 0.3012536E+03 0.3006491E+03 0.3000442E+03 0.2994397E+03 + 0.2988357E+03 0.2982311E+03 0.2976269E+03 0.2970231E+03 0.2964190E+03 + 0.2958149E+03 0.2952108E+03 0.2946064E+03 0.2940020E+03 0.2933973E+03 + 0.2927923E+03 0.2921869E+03 0.2915817E+03 0.2909752E+03 0.2903686E+03 + 0.2897618E+03 0.2891539E+03 0.2885454E+03 0.2879367E+03 0.2873269E+03 + 0.2867163E+03 0.2861048E+03 0.2854924E+03 0.2848788E+03 0.2842644E+03 + 0.2836483E+03 0.2830313E+03 0.2824134E+03 0.2817935E+03 0.2811723E+03 + 0.2805497E+03 0.2799250E+03 0.2792994E+03 0.2786713E+03 0.2780411E+03 + 0.2774091E+03 0.2767749E+03 0.2761385E+03 0.2754998E+03 0.2748585E+03 + 0.2742147E+03 0.2735680E+03 0.2729185E+03 0.2722659E+03 0.2716104E+03 + 0.2709513E+03 0.2702887E+03 0.2696228E+03 0.2689531E+03 0.2682792E+03 + 0.2676013E+03 0.2669192E+03 0.2662322E+03 0.2655406E+03 0.2648446E+03 + 0.2641426E+03 0.2634358E+03 0.2627233E+03 0.2620047E+03 0.2612803E+03 + 0.2605491E+03 0.2598113E+03 0.2590666E+03 0.2583147E+03 0.2575552E+03 + 0.2567874E+03 0.2560116E+03 0.2552272E+03 0.2544340E+03 0.2536310E+03 + 0.2528186E+03 0.2519959E+03 0.2511627E+03 0.2503187E+03 0.2494632E+03 + 0.2485959E+03 0.2477164E+03 0.2468243E+03 0.2459191E+03 0.2450003E+03 + 0.2440679E+03 0.2431209E+03 0.2421595E+03 0.2411830E+03 0.2401912E+03 + 0.2391840E+03 0.2381608E+03 0.2371218E+03 0.2360667E+03 0.2349956E+03 + 0.2339084E+03 0.2328053E+03 0.2316866E+03 0.2305525E+03 0.2294036E+03 + 0.2282402E+03 0.2270629E+03 0.2258727E+03 0.2246700E+03 0.2234559E+03 + 0.2222312E+03 0.2209971E+03 0.2197543E+03 0.2185041E+03 0.2172474E+03 + 0.2159854E+03 0.2147192E+03 0.2134496E+03 0.2121777E+03 0.2109044E+03 + 0.2096308E+03 0.2083575E+03 0.2070854E+03 0.2058153E+03 0.2045476E+03 + 0.2032832E+03 0.2020225E+03 0.2007660E+03 0.1995142E+03 0.1982673E+03 + 0.3174477E+03 0.3168271E+03 0.3162078E+03 0.3155891E+03 0.3149721E+03 + 0.3143554E+03 0.3137397E+03 0.3131248E+03 0.3125110E+03 0.3118983E+03 + 0.3112863E+03 0.3106743E+03 0.3100641E+03 0.3094543E+03 0.3088452E+03 + 0.3082367E+03 0.3076290E+03 0.3070221E+03 0.3064149E+03 0.3058093E+03 + 0.3052039E+03 0.3045989E+03 0.3039946E+03 0.3033908E+03 0.3027870E+03 + 0.3021839E+03 0.3015811E+03 0.3009783E+03 0.3003763E+03 0.2997744E+03 + 0.2991724E+03 0.2985709E+03 0.2979697E+03 0.2973681E+03 0.2967668E+03 + 0.2961657E+03 0.2955642E+03 0.2949627E+03 0.2943612E+03 0.2937595E+03 + 0.2931577E+03 0.2925557E+03 0.2919530E+03 0.2913504E+03 0.2907477E+03 + 0.2901437E+03 0.2895394E+03 0.2889350E+03 0.2883296E+03 0.2877237E+03 + 0.2871168E+03 0.2865095E+03 0.2859012E+03 0.2852918E+03 0.2846818E+03 + 0.2840701E+03 0.2834576E+03 0.2828446E+03 0.2822292E+03 0.2816130E+03 + 0.2809954E+03 0.2803761E+03 0.2797553E+03 0.2791329E+03 0.2785083E+03 + 0.2778821E+03 0.2772539E+03 0.2766236E+03 0.2759910E+03 0.2753563E+03 + 0.2747190E+03 0.2740791E+03 0.2734366E+03 0.2727914E+03 0.2721433E+03 + 0.2714918E+03 0.2708371E+03 0.2701794E+03 0.2695178E+03 0.2688528E+03 + 0.2681840E+03 0.2675110E+03 0.2668336E+03 0.2661522E+03 0.2654658E+03 + 0.2647749E+03 0.2640789E+03 0.2633774E+03 0.2626706E+03 0.2619580E+03 + 0.2612394E+03 0.2605148E+03 0.2597832E+03 0.2590450E+03 0.2582998E+03 + 0.2575472E+03 0.2567866E+03 0.2560180E+03 0.2552410E+03 0.2544552E+03 + 0.2536602E+03 0.2528558E+03 0.2520415E+03 0.2512167E+03 0.2503813E+03 + 0.2495347E+03 0.2486766E+03 0.2478064E+03 0.2469239E+03 0.2460284E+03 + 0.2451200E+03 0.2441973E+03 0.2432610E+03 0.2423100E+03 0.2413443E+03 + 0.2403634E+03 0.2393669E+03 0.2383550E+03 0.2373269E+03 0.2362829E+03 + 0.2352228E+03 0.2341465E+03 0.2330543E+03 0.2319462E+03 0.2308226E+03 + 0.2296836E+03 0.2285300E+03 0.2273622E+03 0.2261809E+03 0.2249867E+03 + 0.2237806E+03 0.2225633E+03 0.2213360E+03 0.2200996E+03 0.2188550E+03 + 0.2176035E+03 0.2163459E+03 0.2150836E+03 0.2138173E+03 0.2125483E+03 + 0.2112774E+03 0.2100056E+03 0.2087337E+03 0.2074626E+03 0.2061930E+03 + 0.2049257E+03 0.2036612E+03 0.2024001E+03 0.2011431E+03 0.1998904E+03 + 0.3177231E+03 0.3171039E+03 0.3164858E+03 0.3158689E+03 0.3152529E+03 + 0.3146383E+03 0.3140239E+03 0.3134109E+03 0.3127985E+03 0.3121872E+03 + 0.3115768E+03 0.3109674E+03 0.3103580E+03 0.3097498E+03 0.3091430E+03 + 0.3085363E+03 0.3079302E+03 0.3073249E+03 0.3067206E+03 0.3061164E+03 + 0.3055128E+03 0.3049101E+03 0.3043076E+03 0.3037058E+03 0.3031046E+03 + 0.3025036E+03 0.3019026E+03 0.3013027E+03 0.3007028E+03 0.3001031E+03 + 0.2995040E+03 0.2989050E+03 0.2983059E+03 0.2977071E+03 0.2971085E+03 + 0.2965099E+03 0.2959113E+03 0.2953129E+03 0.2947139E+03 0.2941154E+03 + 0.2935165E+03 0.2929173E+03 0.2923183E+03 0.2917186E+03 0.2911186E+03 + 0.2905183E+03 0.2899178E+03 0.2893167E+03 0.2887149E+03 0.2881127E+03 + 0.2875098E+03 0.2869060E+03 0.2863017E+03 0.2856966E+03 0.2850905E+03 + 0.2844833E+03 0.2838752E+03 0.2832661E+03 0.2826556E+03 0.2820441E+03 + 0.2814312E+03 0.2808169E+03 0.2802012E+03 0.2795840E+03 0.2789648E+03 + 0.2783440E+03 0.2777214E+03 0.2770970E+03 0.2764704E+03 0.2758416E+03 + 0.2752108E+03 0.2745775E+03 0.2739417E+03 0.2733035E+03 0.2726621E+03 + 0.2720182E+03 0.2713712E+03 0.2707211E+03 0.2700677E+03 0.2694108E+03 + 0.2687503E+03 0.2680861E+03 0.2674181E+03 0.2667457E+03 0.2660692E+03 + 0.2653883E+03 0.2647021E+03 0.2640118E+03 0.2633158E+03 0.2626146E+03 + 0.2619080E+03 0.2611954E+03 0.2604769E+03 0.2597516E+03 0.2590199E+03 + 0.2582812E+03 0.2575352E+03 0.2567816E+03 0.2560201E+03 0.2552505E+03 + 0.2544722E+03 0.2536849E+03 0.2528884E+03 0.2520821E+03 0.2512659E+03 + 0.2504389E+03 0.2496011E+03 0.2487519E+03 0.2478911E+03 0.2470180E+03 + 0.2461321E+03 0.2452331E+03 0.2443211E+03 0.2433947E+03 0.2424543E+03 + 0.2414993E+03 0.2405291E+03 0.2395435E+03 0.2385425E+03 0.2375255E+03 + 0.2364926E+03 0.2354435E+03 0.2343783E+03 0.2332970E+03 0.2321997E+03 + 0.2310864E+03 0.2299579E+03 0.2288143E+03 0.2276561E+03 0.2264839E+03 + 0.2252986E+03 0.2241006E+03 0.2228912E+03 0.2216709E+03 0.2204411E+03 + 0.2192026E+03 0.2179564E+03 0.2167037E+03 0.2154455E+03 0.2141830E+03 + 0.2129170E+03 0.2116487E+03 0.2103790E+03 0.2091087E+03 0.2078388E+03 + 0.2065700E+03 0.2053031E+03 0.2040387E+03 0.2027775E+03 0.2015199E+03 + 0.3179943E+03 0.3173770E+03 0.3167603E+03 0.3161448E+03 0.3155302E+03 + 0.3149166E+03 0.3143040E+03 0.3136926E+03 0.3130822E+03 0.3124723E+03 + 0.3118633E+03 0.3112552E+03 0.3106482E+03 0.3100416E+03 0.3094358E+03 + 0.3088313E+03 0.3082275E+03 0.3076238E+03 0.3070206E+03 0.3064189E+03 + 0.3058176E+03 0.3052163E+03 0.3046164E+03 0.3040167E+03 0.3034169E+03 + 0.3028186E+03 0.3022201E+03 0.3016216E+03 0.3010242E+03 0.3004270E+03 + 0.2998297E+03 0.2992331E+03 0.2986370E+03 0.2980403E+03 0.2974441E+03 + 0.2968485E+03 0.2962524E+03 0.2956566E+03 0.2950606E+03 0.2944646E+03 + 0.2938686E+03 0.2932730E+03 0.2926766E+03 0.2920798E+03 0.2914832E+03 + 0.2908863E+03 0.2902887E+03 0.2896909E+03 0.2890928E+03 0.2884942E+03 + 0.2878949E+03 0.2872947E+03 0.2866944E+03 0.2860928E+03 0.2854907E+03 + 0.2848881E+03 0.2842839E+03 0.2836790E+03 0.2830730E+03 0.2824658E+03 + 0.2818578E+03 0.2812480E+03 0.2806374E+03 0.2800250E+03 0.2794109E+03 + 0.2787955E+03 0.2781782E+03 0.2775596E+03 0.2769384E+03 0.2763155E+03 + 0.2756908E+03 0.2750636E+03 0.2744342E+03 0.2738024E+03 0.2731680E+03 + 0.2725311E+03 0.2718914E+03 0.2712484E+03 0.2706027E+03 0.2699538E+03 + 0.2693014E+03 0.2686456E+03 0.2679859E+03 0.2673225E+03 0.2666553E+03 + 0.2659835E+03 0.2653078E+03 0.2646271E+03 0.2639418E+03 0.2632516E+03 + 0.2625558E+03 0.2618549E+03 0.2611481E+03 0.2604354E+03 0.2597165E+03 + 0.2589910E+03 0.2582589E+03 0.2575197E+03 0.2567727E+03 0.2560182E+03 + 0.2552557E+03 0.2544849E+03 0.2537052E+03 0.2529164E+03 0.2521181E+03 + 0.2513099E+03 0.2504916E+03 0.2496624E+03 0.2488222E+03 0.2479702E+03 + 0.2471065E+03 0.2462301E+03 0.2453413E+03 0.2444388E+03 0.2435227E+03 + 0.2425927E+03 0.2416480E+03 0.2406885E+03 0.2397139E+03 0.2387237E+03 + 0.2377178E+03 0.2366959E+03 0.2356579E+03 0.2346037E+03 0.2335334E+03 + 0.2324468E+03 0.2313444E+03 0.2302262E+03 0.2290928E+03 0.2279444E+03 + 0.2267817E+03 0.2256053E+03 0.2244159E+03 0.2232145E+03 0.2220018E+03 + 0.2207787E+03 0.2195466E+03 0.2183062E+03 0.2170586E+03 0.2158050E+03 + 0.2145463E+03 0.2132838E+03 0.2120184E+03 0.2107510E+03 0.2094826E+03 + 0.2082141E+03 0.2069463E+03 0.2056800E+03 0.2044159E+03 0.2031546E+03 + 0.3182625E+03 0.3176460E+03 0.3170309E+03 0.3164169E+03 0.3158037E+03 + 0.3151916E+03 0.3145804E+03 0.3139705E+03 0.3133615E+03 0.3127534E+03 + 0.3121458E+03 0.3115393E+03 0.3109337E+03 0.3103293E+03 0.3097254E+03 + 0.3091220E+03 0.3085197E+03 0.3079180E+03 0.3073174E+03 0.3067166E+03 + 0.3061174E+03 0.3055185E+03 0.3049198E+03 0.3043221E+03 0.3037248E+03 + 0.3031279E+03 0.3025316E+03 0.3019357E+03 0.3013401E+03 0.3007452E+03 + 0.3001506E+03 0.2995562E+03 0.2989620E+03 0.2983683E+03 0.2977749E+03 + 0.2971811E+03 0.2965879E+03 0.2959946E+03 0.2954012E+03 0.2948079E+03 + 0.2942150E+03 0.2936214E+03 0.2930280E+03 0.2924348E+03 0.2918411E+03 + 0.2912469E+03 0.2906529E+03 0.2900585E+03 0.2894633E+03 0.2888681E+03 + 0.2882723E+03 0.2876761E+03 0.2870789E+03 0.2864814E+03 0.2858831E+03 + 0.2852842E+03 0.2846841E+03 0.2840833E+03 0.2834812E+03 0.2828784E+03 + 0.2822751E+03 0.2816699E+03 0.2810639E+03 0.2804561E+03 0.2798471E+03 + 0.2792367E+03 0.2786245E+03 0.2780109E+03 0.2773955E+03 0.2767783E+03 + 0.2761593E+03 0.2755379E+03 0.2749147E+03 0.2742891E+03 0.2736612E+03 + 0.2730308E+03 0.2723978E+03 0.2717622E+03 0.2711237E+03 0.2704818E+03 + 0.2698375E+03 0.2691897E+03 0.2685382E+03 0.2678835E+03 0.2672246E+03 + 0.2665622E+03 0.2658955E+03 0.2652242E+03 0.2645491E+03 0.2638690E+03 + 0.2631840E+03 0.2624940E+03 0.2617985E+03 0.2610975E+03 0.2603906E+03 + 0.2596778E+03 0.2589586E+03 0.2582328E+03 0.2574999E+03 0.2567598E+03 + 0.2560123E+03 0.2552568E+03 0.2544932E+03 0.2537211E+03 0.2529399E+03 + 0.2521495E+03 0.2513495E+03 0.2505392E+03 0.2497184E+03 0.2488871E+03 + 0.2480440E+03 0.2471894E+03 0.2463226E+03 0.2454431E+03 0.2445507E+03 + 0.2436448E+03 0.2427246E+03 0.2417906E+03 0.2408417E+03 0.2398777E+03 + 0.2388984E+03 0.2379035E+03 0.2368927E+03 0.2358657E+03 0.2348227E+03 + 0.2337632E+03 0.2326877E+03 0.2315961E+03 0.2304886E+03 0.2293653E+03 + 0.2282270E+03 0.2270739E+03 0.2259067E+03 0.2247262E+03 0.2235331E+03 + 0.2223281E+03 0.2211125E+03 0.2198869E+03 0.2186525E+03 0.2174103E+03 + 0.2161616E+03 0.2149072E+03 0.2136484E+03 0.2123860E+03 0.2111213E+03 + 0.2098550E+03 0.2085881E+03 0.2073215E+03 0.2060560E+03 0.2047924E+03 + 0.3185270E+03 0.3179120E+03 0.3172978E+03 0.3166854E+03 0.3160738E+03 + 0.3154631E+03 0.3148531E+03 0.3142444E+03 0.3136367E+03 0.3130298E+03 + 0.3124246E+03 0.3118196E+03 0.3112155E+03 0.3106120E+03 0.3100097E+03 + 0.3094087E+03 0.3088081E+03 0.3082080E+03 0.3076091E+03 0.3070104E+03 + 0.3064126E+03 0.3058153E+03 0.3052188E+03 0.3046230E+03 0.3040275E+03 + 0.3034329E+03 0.3028388E+03 0.3022449E+03 0.3016516E+03 0.3010586E+03 + 0.3004659E+03 0.2998740E+03 0.2992821E+03 0.2986906E+03 0.2980991E+03 + 0.2975082E+03 0.2969174E+03 0.2963266E+03 0.2957361E+03 0.2951455E+03 + 0.2945546E+03 0.2939645E+03 0.2933739E+03 0.2927831E+03 0.2921923E+03 + 0.2916016E+03 0.2910105E+03 0.2904188E+03 0.2898272E+03 0.2892352E+03 + 0.2886427E+03 0.2880497E+03 0.2874563E+03 0.2868624E+03 0.2862676E+03 + 0.2856723E+03 0.2850766E+03 0.2844794E+03 0.2838816E+03 0.2832831E+03 + 0.2826834E+03 0.2820827E+03 0.2814810E+03 0.2808779E+03 0.2802736E+03 + 0.2796680E+03 0.2790607E+03 0.2784523E+03 0.2778423E+03 0.2772303E+03 + 0.2766169E+03 0.2760011E+03 0.2753836E+03 0.2747639E+03 0.2741423E+03 + 0.2735184E+03 0.2728917E+03 0.2722627E+03 0.2716313E+03 0.2709965E+03 + 0.2703594E+03 0.2697191E+03 0.2690757E+03 0.2684286E+03 0.2677782E+03 + 0.2671244E+03 0.2664663E+03 0.2658047E+03 0.2651385E+03 0.2644684E+03 + 0.2637935E+03 0.2631134E+03 0.2624290E+03 0.2617391E+03 0.2610437E+03 + 0.2603426E+03 0.2596358E+03 0.2589225E+03 0.2582032E+03 0.2574767E+03 + 0.2567432E+03 0.2560024E+03 0.2552539E+03 0.2544973E+03 0.2537325E+03 + 0.2529590E+03 0.2521763E+03 0.2513840E+03 0.2505819E+03 0.2497697E+03 + 0.2489467E+03 0.2481127E+03 0.2472671E+03 0.2464095E+03 0.2455395E+03 + 0.2446567E+03 0.2437606E+03 0.2428509E+03 0.2419271E+03 0.2409886E+03 + 0.2400352E+03 0.2390669E+03 0.2380828E+03 0.2370830E+03 0.2360672E+03 + 0.2350351E+03 0.2339868E+03 0.2329223E+03 0.2318416E+03 0.2307445E+03 + 0.2296320E+03 0.2285037E+03 0.2273605E+03 0.2262029E+03 0.2250314E+03 + 0.2238468E+03 0.2226500E+03 0.2214418E+03 0.2202232E+03 0.2189952E+03 + 0.2177588E+03 0.2165152E+03 0.2152655E+03 0.2140106E+03 0.2127517E+03 + 0.2114898E+03 0.2102259E+03 0.2089609E+03 0.2076958E+03 0.2064312E+03 + 0.3187878E+03 0.3181745E+03 0.3175619E+03 0.3169501E+03 0.3163396E+03 + 0.3157304E+03 0.3151222E+03 0.3145148E+03 0.3139087E+03 0.3133034E+03 + 0.3126990E+03 0.3120958E+03 0.3114934E+03 0.3108917E+03 0.3102911E+03 + 0.3096909E+03 0.3090922E+03 0.3084939E+03 0.3078962E+03 0.3072992E+03 + 0.3067038E+03 0.3061082E+03 0.3055135E+03 0.3049196E+03 0.3043263E+03 + 0.3037331E+03 0.3031406E+03 0.3025493E+03 0.3019579E+03 0.3013667E+03 + 0.3007765E+03 0.3001868E+03 0.2995969E+03 0.2990078E+03 0.2984185E+03 + 0.2978299E+03 0.2972413E+03 0.2966533E+03 0.2960650E+03 0.2954769E+03 + 0.2948891E+03 0.2943015E+03 0.2937131E+03 0.2931256E+03 0.2925376E+03 + 0.2919493E+03 0.2913611E+03 0.2907729E+03 0.2901845E+03 0.2895953E+03 + 0.2890060E+03 0.2884164E+03 0.2878266E+03 0.2872356E+03 0.2866443E+03 + 0.2860530E+03 0.2854608E+03 0.2848673E+03 0.2842737E+03 0.2836788E+03 + 0.2830834E+03 0.2824870E+03 0.2818893E+03 0.2812910E+03 0.2806909E+03 + 0.2800901E+03 0.2794873E+03 0.2788839E+03 0.2782789E+03 0.2776721E+03 + 0.2770635E+03 0.2764534E+03 0.2758414E+03 0.2752275E+03 0.2746118E+03 + 0.2739938E+03 0.2733734E+03 0.2727509E+03 0.2721257E+03 0.2714983E+03 + 0.2708682E+03 0.2702346E+03 0.2695987E+03 0.2689593E+03 0.2683171E+03 + 0.2676710E+03 0.2670214E+03 0.2663685E+03 0.2657113E+03 0.2650502E+03 + 0.2643845E+03 0.2637151E+03 0.2630404E+03 0.2623610E+03 0.2616768E+03 + 0.2609868E+03 0.2602915E+03 0.2595905E+03 0.2588833E+03 0.2581698E+03 + 0.2574499E+03 0.2567228E+03 0.2559886E+03 0.2552470E+03 0.2544974E+03 + 0.2537397E+03 0.2529736E+03 0.2521986E+03 0.2514142E+03 0.2506202E+03 + 0.2498161E+03 0.2490016E+03 0.2481761E+03 0.2473394E+03 0.2464910E+03 + 0.2456303E+03 0.2447572E+03 0.2438710E+03 0.2429709E+03 0.2420573E+03 + 0.2411294E+03 0.2401868E+03 0.2392290E+03 0.2382558E+03 0.2372670E+03 + 0.2362621E+03 0.2352412E+03 0.2342040E+03 0.2331505E+03 0.2320804E+03 + 0.2309944E+03 0.2298923E+03 0.2287747E+03 0.2276415E+03 0.2264935E+03 + 0.2253314E+03 0.2241557E+03 0.2229672E+03 0.2217668E+03 0.2205555E+03 + 0.2193342E+03 0.2181039E+03 0.2168658E+03 0.2156209E+03 0.2143703E+03 + 0.2131152E+03 0.2118564E+03 0.2105951E+03 0.2093323E+03 0.2080688E+03 + 0.3190461E+03 0.3184332E+03 0.3178218E+03 0.3172119E+03 0.3166027E+03 + 0.3159946E+03 0.3153873E+03 0.3147815E+03 0.3141768E+03 0.3135729E+03 + 0.3129699E+03 0.3123680E+03 0.3117667E+03 0.3111672E+03 0.3105679E+03 + 0.3099693E+03 0.3093719E+03 0.3087757E+03 0.3081794E+03 0.3075843E+03 + 0.3069904E+03 0.3063967E+03 0.3058038E+03 0.3052112E+03 0.3046196E+03 + 0.3040291E+03 0.3034381E+03 0.3028485E+03 0.3022594E+03 0.3016707E+03 + 0.3010822E+03 0.3004943E+03 0.2999067E+03 0.2993194E+03 0.2987329E+03 + 0.2981466E+03 0.2975602E+03 0.2969742E+03 0.2963887E+03 0.2958031E+03 + 0.2952177E+03 0.2946321E+03 0.2940472E+03 0.2934615E+03 0.2928764E+03 + 0.2922915E+03 0.2917061E+03 0.2911204E+03 0.2905345E+03 0.2899490E+03 + 0.2893628E+03 0.2887762E+03 0.2881894E+03 0.2876021E+03 0.2870145E+03 + 0.2864262E+03 0.2858373E+03 0.2852480E+03 0.2846578E+03 0.2840668E+03 + 0.2834753E+03 0.2828830E+03 0.2822892E+03 0.2816949E+03 0.2810995E+03 + 0.2805031E+03 0.2799051E+03 0.2793059E+03 0.2787056E+03 0.2781036E+03 + 0.2775004E+03 0.2768952E+03 0.2762887E+03 0.2756803E+03 0.2750702E+03 + 0.2744578E+03 0.2738435E+03 0.2732270E+03 0.2726080E+03 0.2719871E+03 + 0.2713633E+03 0.2707368E+03 0.2701081E+03 0.2694761E+03 0.2688411E+03 + 0.2682029E+03 0.2675617E+03 0.2669164E+03 0.2662679E+03 0.2656154E+03 + 0.2649591E+03 0.2642989E+03 0.2636337E+03 0.2629645E+03 0.2622905E+03 + 0.2616111E+03 0.2609269E+03 0.2602374E+03 0.2595417E+03 0.2588406E+03 + 0.2581332E+03 0.2574194E+03 0.2566988E+03 0.2559711E+03 0.2552361E+03 + 0.2544935E+03 0.2537429E+03 0.2529840E+03 0.2522163E+03 0.2514396E+03 + 0.2506537E+03 0.2498577E+03 0.2490515E+03 0.2482345E+03 0.2474066E+03 + 0.2465671E+03 0.2457157E+03 0.2448519E+03 0.2439752E+03 0.2430854E+03 + 0.2421819E+03 0.2412641E+03 0.2403319E+03 0.2393847E+03 0.2384224E+03 + 0.2374445E+03 0.2364507E+03 0.2354408E+03 0.2344148E+03 0.2333721E+03 + 0.2323133E+03 0.2312382E+03 0.2301468E+03 0.2290395E+03 0.2279167E+03 + 0.2267786E+03 0.2256260E+03 0.2244594E+03 0.2232795E+03 0.2220873E+03 + 0.2208835E+03 0.2196692E+03 0.2184454E+03 0.2172131E+03 0.2159734E+03 + 0.2147275E+03 0.2134763E+03 0.2122210E+03 0.2109627E+03 0.2097022E+03 + 0.3193003E+03 0.3186888E+03 0.3180786E+03 0.3174695E+03 0.3168615E+03 + 0.3162549E+03 0.3156494E+03 0.3150446E+03 0.3144410E+03 0.3138389E+03 + 0.3132371E+03 0.3126365E+03 0.3120369E+03 0.3114385E+03 0.3108409E+03 + 0.3102442E+03 0.3096482E+03 0.3090529E+03 0.3084586E+03 0.3078654E+03 + 0.3072729E+03 0.3066806E+03 0.3060892E+03 0.3054993E+03 0.3049089E+03 + 0.3043201E+03 0.3037317E+03 0.3031434E+03 0.3025561E+03 0.3019691E+03 + 0.3013830E+03 0.3007970E+03 0.3002115E+03 0.2996267E+03 0.2990420E+03 + 0.2984576E+03 0.2978739E+03 0.2972900E+03 0.2967067E+03 0.2961234E+03 + 0.2955406E+03 0.2949577E+03 0.2943749E+03 0.2937923E+03 0.2932098E+03 + 0.2926268E+03 0.2920445E+03 0.2914619E+03 0.2908790E+03 0.2902960E+03 + 0.2897128E+03 0.2891297E+03 0.2885459E+03 0.2879616E+03 0.2873770E+03 + 0.2867922E+03 0.2862070E+03 0.2856207E+03 0.2850342E+03 0.2844471E+03 + 0.2838593E+03 0.2832707E+03 0.2826810E+03 0.2820907E+03 0.2814993E+03 + 0.2809070E+03 0.2803135E+03 0.2797190E+03 0.2791231E+03 0.2785256E+03 + 0.2779274E+03 0.2773272E+03 0.2767259E+03 0.2761227E+03 0.2755180E+03 + 0.2749110E+03 0.2743023E+03 0.2736918E+03 0.2730788E+03 0.2724638E+03 + 0.2718463E+03 0.2712267E+03 0.2706043E+03 0.2699794E+03 0.2693515E+03 + 0.2687207E+03 0.2680869E+03 0.2674496E+03 0.2668094E+03 0.2661649E+03 + 0.2655174E+03 0.2648654E+03 0.2642101E+03 0.2635503E+03 0.2628857E+03 + 0.2622170E+03 0.2615430E+03 0.2608640E+03 0.2601798E+03 0.2594901E+03 + 0.2587947E+03 0.2580930E+03 0.2573855E+03 0.2566712E+03 0.2559499E+03 + 0.2552215E+03 0.2544856E+03 0.2537420E+03 0.2529902E+03 0.2522300E+03 + 0.2514608E+03 0.2506823E+03 0.2498944E+03 0.2490963E+03 0.2482880E+03 + 0.2474687E+03 0.2466380E+03 0.2457957E+03 0.2449414E+03 0.2440741E+03 + 0.2431940E+03 0.2423003E+03 0.2413928E+03 0.2404710E+03 0.2395344E+03 + 0.2385828E+03 0.2376157E+03 0.2366329E+03 0.2356340E+03 0.2346189E+03 + 0.2335875E+03 0.2325398E+03 0.2314757E+03 0.2303951E+03 0.2292983E+03 + 0.2281859E+03 0.2270580E+03 0.2259151E+03 0.2247578E+03 0.2235869E+03 + 0.2224030E+03 0.2212072E+03 0.2200002E+03 0.2187831E+03 0.2175569E+03 + 0.2163228E+03 0.2150818E+03 0.2138350E+03 0.2125834E+03 0.2113282E+03 + 0.3195515E+03 0.3189412E+03 0.3183321E+03 0.3177245E+03 0.3171178E+03 + 0.3165120E+03 0.3159077E+03 0.3153046E+03 0.3147021E+03 0.3141010E+03 + 0.3135009E+03 0.3129019E+03 0.3123036E+03 0.3117065E+03 0.3111101E+03 + 0.3105146E+03 0.3099203E+03 0.3093270E+03 0.3087339E+03 0.3081422E+03 + 0.3075513E+03 0.3069609E+03 0.3063715E+03 0.3057821E+03 0.3051945E+03 + 0.3046072E+03 0.3040201E+03 0.3034340E+03 0.3028485E+03 0.3022633E+03 + 0.3016790E+03 0.3010952E+03 0.3005120E+03 0.2999285E+03 0.2993460E+03 + 0.2987641E+03 0.2981820E+03 0.2976008E+03 0.2970198E+03 0.2964388E+03 + 0.2958580E+03 0.2952775E+03 0.2946973E+03 0.2941172E+03 0.2935371E+03 + 0.2929572E+03 0.2923773E+03 0.2917969E+03 0.2912169E+03 0.2906372E+03 + 0.2900567E+03 0.2894759E+03 0.2888953E+03 0.2883146E+03 0.2877332E+03 + 0.2871513E+03 0.2865693E+03 0.2859866E+03 0.2854036E+03 0.2848200E+03 + 0.2842356E+03 0.2836508E+03 0.2830651E+03 0.2824783E+03 0.2818912E+03 + 0.2813026E+03 0.2807136E+03 0.2801232E+03 0.2795316E+03 0.2789389E+03 + 0.2783452E+03 0.2777497E+03 0.2771530E+03 0.2765549E+03 0.2759553E+03 + 0.2753538E+03 0.2747505E+03 0.2741454E+03 0.2735381E+03 0.2729290E+03 + 0.2723177E+03 0.2717043E+03 0.2710880E+03 0.2704698E+03 0.2698488E+03 + 0.2692249E+03 0.2685984E+03 0.2679685E+03 0.2673358E+03 0.2666993E+03 + 0.2660602E+03 0.2654167E+03 0.2647698E+03 0.2641187E+03 0.2634639E+03 + 0.2628044E+03 0.2621402E+03 0.2614719E+03 0.2607981E+03 0.2601193E+03 + 0.2594354E+03 0.2587456E+03 0.2580499E+03 0.2573482E+03 0.2566400E+03 + 0.2559251E+03 0.2552032E+03 0.2544740E+03 0.2537372E+03 0.2529924E+03 + 0.2522393E+03 0.2514776E+03 0.2507068E+03 0.2499266E+03 0.2491367E+03 + 0.2483364E+03 0.2475256E+03 0.2467037E+03 0.2458704E+03 0.2450251E+03 + 0.2441672E+03 0.2432969E+03 0.2424132E+03 0.2415157E+03 0.2406040E+03 + 0.2396779E+03 0.2387369E+03 0.2377806E+03 0.2368087E+03 0.2358208E+03 + 0.2348168E+03 0.2337966E+03 0.2327599E+03 0.2317066E+03 0.2306370E+03 + 0.2295511E+03 0.2284493E+03 0.2273315E+03 0.2261987E+03 0.2250509E+03 + 0.2238892E+03 0.2227140E+03 0.2215263E+03 0.2203269E+03 0.2191169E+03 + 0.2178972E+03 0.2166689E+03 0.2154331E+03 0.2141910E+03 0.2129435E+03 + 0.3197993E+03 0.3191903E+03 0.3185823E+03 0.3179757E+03 0.3173701E+03 + 0.3167660E+03 0.3161627E+03 0.3155605E+03 0.3149597E+03 0.3143598E+03 + 0.3137607E+03 0.3131629E+03 0.3125663E+03 0.3119706E+03 0.3113759E+03 + 0.3107817E+03 0.3101886E+03 0.3095967E+03 0.3090057E+03 0.3084149E+03 + 0.3078254E+03 0.3072368E+03 0.3066491E+03 0.3060614E+03 0.3054754E+03 + 0.3048897E+03 0.3043047E+03 0.3037200E+03 0.3031365E+03 0.3025534E+03 + 0.3019707E+03 0.3013887E+03 0.3008071E+03 0.3002264E+03 0.2996454E+03 + 0.2990653E+03 0.2984859E+03 0.2979066E+03 0.2973275E+03 0.2967488E+03 + 0.2961705E+03 0.2955923E+03 0.2950144E+03 0.2944368E+03 0.2938591E+03 + 0.2932815E+03 0.2927037E+03 0.2921268E+03 0.2915492E+03 0.2909717E+03 + 0.2903942E+03 0.2898168E+03 0.2892388E+03 0.2886607E+03 0.2880823E+03 + 0.2875038E+03 0.2869248E+03 0.2863456E+03 0.2857657E+03 0.2851854E+03 + 0.2846047E+03 0.2840230E+03 0.2834411E+03 0.2828582E+03 0.2822747E+03 + 0.2816902E+03 0.2811049E+03 0.2805188E+03 0.2799316E+03 0.2793430E+03 + 0.2787540E+03 0.2781631E+03 0.2775710E+03 0.2769777E+03 0.2763827E+03 + 0.2757864E+03 0.2751881E+03 0.2745881E+03 0.2739866E+03 0.2733832E+03 + 0.2727775E+03 0.2721700E+03 0.2715599E+03 0.2709481E+03 0.2703331E+03 + 0.2697164E+03 0.2690963E+03 0.2684739E+03 0.2678482E+03 0.2672196E+03 + 0.2665881E+03 0.2659526E+03 0.2653140E+03 0.2646714E+03 0.2640254E+03 + 0.2633746E+03 0.2627204E+03 0.2620616E+03 0.2613978E+03 0.2607295E+03 + 0.2600560E+03 0.2593774E+03 0.2586933E+03 0.2580035E+03 0.2573074E+03 + 0.2566055E+03 0.2558968E+03 0.2551812E+03 0.2544585E+03 0.2537284E+03 + 0.2529906E+03 0.2522447E+03 0.2514900E+03 0.2507266E+03 0.2499542E+03 + 0.2491722E+03 0.2483802E+03 0.2475779E+03 0.2467644E+03 0.2459398E+03 + 0.2451035E+03 0.2442551E+03 0.2433941E+03 0.2425199E+03 0.2416325E+03 + 0.2407309E+03 0.2398154E+03 0.2388848E+03 0.2379392E+03 0.2369781E+03 + 0.2360012E+03 0.2350083E+03 0.2339991E+03 0.2329734E+03 0.2319312E+03 + 0.2308726E+03 0.2297977E+03 0.2287064E+03 0.2275993E+03 0.2264764E+03 + 0.2253385E+03 0.2241861E+03 0.2230199E+03 0.2218407E+03 0.2206493E+03 + 0.2194466E+03 0.2182337E+03 0.2170116E+03 0.2157814E+03 0.2145442E+03 + 0.3200440E+03 0.3194363E+03 0.3188294E+03 0.3182239E+03 0.3176196E+03 + 0.3170165E+03 0.3164142E+03 0.3158132E+03 0.3152135E+03 0.3146149E+03 + 0.3140175E+03 0.3134208E+03 0.3128253E+03 0.3122308E+03 0.3116376E+03 + 0.3110449E+03 0.3104532E+03 0.3098625E+03 0.3092728E+03 0.3086845E+03 + 0.3080963E+03 0.3075090E+03 0.3069227E+03 0.3063373E+03 0.3057524E+03 + 0.3051679E+03 0.3045846E+03 0.3040023E+03 0.3034203E+03 0.3028387E+03 + 0.3022580E+03 0.3016780E+03 0.3010983E+03 0.3005187E+03 0.2999407E+03 + 0.2993625E+03 0.2987845E+03 0.2982075E+03 0.2976305E+03 0.2970539E+03 + 0.2964777E+03 0.2959018E+03 0.2953263E+03 0.2947506E+03 0.2941754E+03 + 0.2936006E+03 0.2930254E+03 0.2924505E+03 0.2918756E+03 0.2913011E+03 + 0.2907262E+03 0.2901510E+03 0.2895759E+03 0.2890007E+03 0.2884254E+03 + 0.2878501E+03 0.2872738E+03 0.2866976E+03 0.2861211E+03 0.2855441E+03 + 0.2849664E+03 0.2843884E+03 0.2838102E+03 0.2832304E+03 0.2826509E+03 + 0.2820701E+03 0.2814885E+03 0.2809063E+03 0.2803232E+03 0.2797390E+03 + 0.2791537E+03 0.2785674E+03 0.2779795E+03 0.2773909E+03 0.2768006E+03 + 0.2762089E+03 0.2756158E+03 0.2750211E+03 0.2744247E+03 0.2738265E+03 + 0.2732265E+03 0.2726247E+03 0.2720204E+03 0.2714145E+03 0.2708061E+03 + 0.2701954E+03 0.2695820E+03 0.2689663E+03 0.2683476E+03 0.2677261E+03 + 0.2671015E+03 0.2664740E+03 0.2658430E+03 0.2652088E+03 0.2645706E+03 + 0.2639292E+03 0.2632837E+03 0.2626336E+03 0.2619798E+03 0.2613212E+03 + 0.2606580E+03 0.2599901E+03 0.2593166E+03 0.2586378E+03 0.2579539E+03 + 0.2572637E+03 0.2565674E+03 0.2558649E+03 0.2551556E+03 0.2544393E+03 + 0.2537159E+03 0.2529851E+03 0.2522458E+03 0.2514986E+03 0.2507427E+03 + 0.2499778E+03 0.2492034E+03 0.2484193E+03 0.2476251E+03 0.2468201E+03 + 0.2460042E+03 0.2451767E+03 0.2443376E+03 0.2434859E+03 0.2426215E+03 + 0.2417438E+03 0.2408523E+03 0.2399467E+03 0.2390268E+03 0.2380915E+03 + 0.2371413E+03 0.2361753E+03 0.2351934E+03 0.2341951E+03 0.2331806E+03 + 0.2321496E+03 0.2311021E+03 0.2300381E+03 0.2289575E+03 0.2278610E+03 + 0.2267485E+03 0.2256205E+03 0.2244778E+03 0.2233208E+03 0.2221503E+03 + 0.2209671E+03 0.2197720E+03 0.2185663E+03 0.2173507E+03 0.2161263E+03 + 0.3202856E+03 0.3196789E+03 0.3190735E+03 0.3184689E+03 0.3178657E+03 + 0.3172638E+03 0.3166631E+03 0.3160629E+03 0.3154644E+03 0.3148669E+03 + 0.3142706E+03 0.3136752E+03 0.3130813E+03 0.3124879E+03 0.3118958E+03 + 0.3113049E+03 0.3107148E+03 0.3101251E+03 0.3095367E+03 0.3089495E+03 + 0.3083633E+03 0.3077775E+03 0.3071926E+03 0.3066083E+03 0.3060253E+03 + 0.3054427E+03 0.3048611E+03 0.3042798E+03 0.3037000E+03 0.3031199E+03 + 0.3025408E+03 0.3019626E+03 0.3013848E+03 0.3008074E+03 0.3002305E+03 + 0.2996545E+03 0.2990788E+03 0.2985036E+03 0.2979285E+03 0.2973542E+03 + 0.2967804E+03 0.2962062E+03 0.2956327E+03 0.2950598E+03 0.2944867E+03 + 0.2939139E+03 0.2933413E+03 0.2927689E+03 0.2921967E+03 0.2916241E+03 + 0.2910518E+03 0.2904798E+03 0.2899074E+03 0.2893348E+03 0.2887622E+03 + 0.2881893E+03 0.2876165E+03 0.2870435E+03 0.2864697E+03 0.2858957E+03 + 0.2853216E+03 0.2847472E+03 0.2841714E+03 0.2835958E+03 0.2830193E+03 + 0.2824424E+03 0.2818643E+03 0.2812861E+03 0.2807065E+03 0.2801266E+03 + 0.2795453E+03 0.2789631E+03 0.2783796E+03 0.2777952E+03 0.2772093E+03 + 0.2766226E+03 0.2760340E+03 0.2754442E+03 0.2748528E+03 0.2742599E+03 + 0.2736650E+03 0.2730686E+03 0.2724700E+03 0.2718698E+03 0.2712672E+03 + 0.2706625E+03 0.2700555E+03 0.2694461E+03 0.2688339E+03 0.2682195E+03 + 0.2676018E+03 0.2669815E+03 0.2663579E+03 0.2657315E+03 0.2651014E+03 + 0.2644680E+03 0.2638307E+03 0.2631897E+03 0.2625448E+03 0.2618955E+03 + 0.2612421E+03 0.2605835E+03 0.2599207E+03 0.2592529E+03 0.2585796E+03 + 0.2579010E+03 0.2572166E+03 0.2565262E+03 0.2558297E+03 0.2551267E+03 + 0.2544165E+03 0.2536996E+03 0.2529754E+03 0.2522431E+03 0.2515029E+03 + 0.2507542E+03 0.2499968E+03 0.2492301E+03 0.2484538E+03 0.2476676E+03 + 0.2468710E+03 0.2460636E+03 0.2452450E+03 0.2444146E+03 0.2435722E+03 + 0.2427170E+03 0.2418490E+03 0.2409676E+03 0.2400722E+03 0.2391624E+03 + 0.2382379E+03 0.2372983E+03 0.2363430E+03 0.2353720E+03 0.2343849E+03 + 0.2333816E+03 0.2323617E+03 0.2313251E+03 0.2302720E+03 0.2292025E+03 + 0.2281164E+03 0.2270145E+03 0.2258969E+03 0.2247639E+03 0.2236163E+03 + 0.2224548E+03 0.2212801E+03 0.2200930E+03 0.2188947E+03 0.2176859E+03 + 0.3205251E+03 0.3199188E+03 0.3193144E+03 0.3187111E+03 0.3181088E+03 + 0.3175078E+03 0.3169078E+03 0.3163096E+03 0.3157119E+03 0.3151158E+03 + 0.3145205E+03 0.3139266E+03 0.3133334E+03 0.3127418E+03 0.3121510E+03 + 0.3115609E+03 0.3109721E+03 0.3103846E+03 0.3097975E+03 0.3092114E+03 + 0.3086263E+03 0.3080421E+03 0.3074590E+03 0.3068762E+03 0.3062945E+03 + 0.3057133E+03 0.3051334E+03 0.3045541E+03 0.3039749E+03 0.3033968E+03 + 0.3028199E+03 0.3022431E+03 0.3016670E+03 0.3010917E+03 0.3005168E+03 + 0.2999421E+03 0.2993681E+03 0.2987951E+03 0.2982223E+03 0.2976497E+03 + 0.2970778E+03 0.2965062E+03 0.2959347E+03 0.2953636E+03 0.2947929E+03 + 0.2942224E+03 0.2936522E+03 0.2930818E+03 0.2925119E+03 0.2919421E+03 + 0.2913725E+03 0.2908026E+03 0.2902327E+03 0.2896631E+03 0.2890932E+03 + 0.2885231E+03 0.2879529E+03 0.2873826E+03 0.2868122E+03 0.2862412E+03 + 0.2856698E+03 0.2850983E+03 0.2845263E+03 0.2839539E+03 0.2833806E+03 + 0.2828076E+03 0.2822328E+03 0.2816582E+03 0.2810824E+03 0.2805060E+03 + 0.2799288E+03 0.2793505E+03 0.2787712E+03 0.2781912E+03 0.2776096E+03 + 0.2770269E+03 0.2764432E+03 0.2758579E+03 0.2752713E+03 0.2746832E+03 + 0.2740935E+03 0.2735023E+03 0.2729090E+03 0.2723142E+03 0.2717171E+03 + 0.2711185E+03 0.2705172E+03 0.2699140E+03 0.2693081E+03 0.2687002E+03 + 0.2680891E+03 0.2674758E+03 0.2668592E+03 0.2662402E+03 0.2656176E+03 + 0.2649919E+03 0.2643628E+03 0.2637302E+03 0.2630937E+03 0.2624532E+03 + 0.2618090E+03 0.2611600E+03 0.2605069E+03 0.2598488E+03 0.2591863E+03 + 0.2585183E+03 0.2578452E+03 0.2571663E+03 0.2564818E+03 0.2557911E+03 + 0.2550941E+03 0.2543903E+03 0.2536796E+03 0.2529620E+03 0.2522364E+03 + 0.2515032E+03 0.2507617E+03 0.2500112E+03 0.2492521E+03 0.2484836E+03 + 0.2477053E+03 0.2469169E+03 0.2461179E+03 0.2453079E+03 0.2444865E+03 + 0.2436531E+03 0.2428076E+03 0.2419491E+03 0.2410772E+03 0.2401917E+03 + 0.2392922E+03 0.2383781E+03 0.2374490E+03 0.2365045E+03 0.2355444E+03 + 0.2345683E+03 0.2335761E+03 0.2325671E+03 0.2315417E+03 0.2304997E+03 + 0.2294411E+03 0.2283660E+03 0.2272745E+03 0.2261672E+03 0.2250444E+03 + 0.2239065E+03 0.2227542E+03 0.2215883E+03 0.2204095E+03 0.2192188E+03 + 0.3207607E+03 0.3201557E+03 0.3195525E+03 0.3189500E+03 0.3183489E+03 + 0.3177490E+03 0.3171505E+03 0.3165531E+03 0.3159566E+03 0.3153612E+03 + 0.3147674E+03 0.3141744E+03 0.3135829E+03 0.3129921E+03 0.3124026E+03 + 0.3118138E+03 0.3112263E+03 0.3106400E+03 0.3100540E+03 0.3094699E+03 + 0.3088856E+03 0.3083029E+03 0.3077212E+03 0.3071402E+03 0.3065598E+03 + 0.3059802E+03 0.3054013E+03 0.3048240E+03 0.3042468E+03 0.3036700E+03 + 0.3030945E+03 0.3025199E+03 0.3019453E+03 0.3013715E+03 0.3007983E+03 + 0.3002261E+03 0.2996541E+03 0.2990821E+03 0.2985112E+03 0.2979411E+03 + 0.2973706E+03 0.2968008E+03 0.2962316E+03 0.2956628E+03 0.2950941E+03 + 0.2945258E+03 0.2939576E+03 0.2933899E+03 0.2928222E+03 0.2922545E+03 + 0.2916872E+03 0.2911198E+03 0.2905528E+03 0.2899855E+03 0.2894182E+03 + 0.2888508E+03 0.2882836E+03 0.2877159E+03 0.2871480E+03 0.2865800E+03 + 0.2860121E+03 0.2854436E+03 0.2848746E+03 0.2843050E+03 0.2837356E+03 + 0.2831650E+03 0.2825944E+03 0.2820229E+03 0.2814507E+03 0.2808777E+03 + 0.2803046E+03 0.2797299E+03 0.2791548E+03 0.2785786E+03 0.2780013E+03 + 0.2774228E+03 0.2768435E+03 0.2762629E+03 0.2756806E+03 0.2750974E+03 + 0.2745125E+03 0.2739262E+03 0.2733380E+03 0.2727484E+03 0.2721567E+03 + 0.2715634E+03 0.2709677E+03 0.2703705E+03 0.2697706E+03 0.2691689E+03 + 0.2685641E+03 0.2679576E+03 0.2673476E+03 0.2667354E+03 0.2661201E+03 + 0.2655018E+03 0.2648803E+03 0.2642556E+03 0.2636274E+03 0.2629951E+03 + 0.2623595E+03 0.2617195E+03 0.2610757E+03 0.2604273E+03 0.2597747E+03 + 0.2591169E+03 0.2584542E+03 0.2577863E+03 0.2571131E+03 0.2564341E+03 + 0.2557494E+03 0.2550582E+03 0.2543605E+03 0.2536561E+03 0.2529447E+03 + 0.2522260E+03 0.2514995E+03 0.2507650E+03 0.2500217E+03 0.2492699E+03 + 0.2485090E+03 0.2477389E+03 0.2469582E+03 0.2461673E+03 0.2453660E+03 + 0.2445530E+03 0.2437287E+03 0.2428922E+03 0.2420432E+03 0.2411811E+03 + 0.2403057E+03 0.2394160E+03 0.2385123E+03 0.2375936E+03 0.2366599E+03 + 0.2357106E+03 0.2347455E+03 0.2337640E+03 0.2327663E+03 0.2317520E+03 + 0.2307210E+03 0.2296735E+03 0.2286093E+03 0.2275287E+03 0.2264317E+03 + 0.2253191E+03 0.2241911E+03 0.2230483E+03 0.2218915E+03 0.2207213E+03 + 0.3209937E+03 0.3203900E+03 0.3197874E+03 0.3191863E+03 0.3185862E+03 + 0.3179874E+03 0.3173896E+03 0.3167934E+03 0.3161978E+03 0.3156042E+03 + 0.3150111E+03 0.3144196E+03 0.3138293E+03 0.3132395E+03 0.3126512E+03 + 0.3120635E+03 0.3114771E+03 0.3108918E+03 0.3103073E+03 0.3097245E+03 + 0.3091418E+03 0.3085606E+03 0.3079797E+03 0.3074003E+03 0.3068215E+03 + 0.3062435E+03 0.3056663E+03 0.3050896E+03 0.3045139E+03 0.3039396E+03 + 0.3033653E+03 0.3027919E+03 0.3022190E+03 0.3016474E+03 0.3010759E+03 + 0.3005049E+03 0.2999347E+03 0.2993651E+03 0.2987961E+03 0.2982270E+03 + 0.2976591E+03 0.2970912E+03 0.2965240E+03 0.2959569E+03 0.2953902E+03 + 0.2948244E+03 0.2942582E+03 0.2936927E+03 0.2931270E+03 0.2925618E+03 + 0.2919971E+03 0.2914319E+03 0.2908672E+03 0.2903023E+03 0.2897377E+03 + 0.2891729E+03 0.2886080E+03 0.2880428E+03 0.2874785E+03 0.2869130E+03 + 0.2863475E+03 0.2857819E+03 0.2852160E+03 0.2846500E+03 0.2840831E+03 + 0.2835160E+03 0.2829489E+03 0.2823804E+03 0.2818120E+03 0.2812426E+03 + 0.2806727E+03 0.2801018E+03 0.2795304E+03 0.2789580E+03 0.2783849E+03 + 0.2778105E+03 0.2772352E+03 0.2766584E+03 0.2760811E+03 0.2755020E+03 + 0.2749219E+03 0.2743401E+03 0.2737570E+03 0.2731722E+03 0.2725858E+03 + 0.2719976E+03 0.2714079E+03 0.2708159E+03 0.2702218E+03 0.2696260E+03 + 0.2690274E+03 0.2684271E+03 0.2678235E+03 0.2672182E+03 0.2666095E+03 + 0.2659983E+03 0.2653840E+03 0.2647666E+03 0.2641462E+03 0.2635220E+03 + 0.2628945E+03 0.2622632E+03 0.2616280E+03 0.2609890E+03 0.2603452E+03 + 0.2596974E+03 0.2590447E+03 0.2583870E+03 0.2577249E+03 0.2570569E+03 + 0.2563835E+03 0.2557042E+03 0.2550190E+03 0.2543275E+03 0.2536291E+03 + 0.2529241E+03 0.2522118E+03 0.2514921E+03 0.2507640E+03 0.2500281E+03 + 0.2492837E+03 0.2485302E+03 0.2477675E+03 0.2469950E+03 0.2462124E+03 + 0.2454192E+03 0.2446150E+03 0.2437993E+03 0.2429719E+03 0.2421322E+03 + 0.2412796E+03 0.2404137E+03 0.2395341E+03 0.2386404E+03 0.2377321E+03 + 0.2368089E+03 0.2358703E+03 0.2349160E+03 0.2339456E+03 0.2329590E+03 + 0.2319559E+03 0.2309361E+03 0.2298997E+03 0.2288464E+03 0.2277764E+03 + 0.2266904E+03 0.2255880E+03 0.2244701E+03 0.2233371E+03 0.2221895E+03 + 0.3212245E+03 0.3206209E+03 0.3200195E+03 0.3194191E+03 0.3188203E+03 + 0.3182223E+03 0.3176261E+03 0.3170307E+03 0.3164363E+03 0.3158435E+03 + 0.3152517E+03 0.3146616E+03 0.3140718E+03 0.3134836E+03 0.3128961E+03 + 0.3123103E+03 0.3117250E+03 0.3111405E+03 0.3105576E+03 0.3099755E+03 + 0.3093945E+03 0.3088144E+03 0.3082354E+03 0.3076567E+03 0.3070795E+03 + 0.3065031E+03 0.3059272E+03 0.3053525E+03 0.3047778E+03 0.3042047E+03 + 0.3036325E+03 0.3030608E+03 0.3024893E+03 0.3019189E+03 0.3013494E+03 + 0.3007802E+03 0.3002115E+03 0.2996437E+03 0.2990763E+03 0.2985096E+03 + 0.2979430E+03 0.2973769E+03 0.2968118E+03 0.2962468E+03 0.2956822E+03 + 0.2951180E+03 0.2945542E+03 0.2939908E+03 0.2934274E+03 0.2928642E+03 + 0.2923012E+03 0.2917389E+03 0.2911766E+03 0.2906139E+03 0.2900518E+03 + 0.2894894E+03 0.2889272E+03 0.2883647E+03 0.2878025E+03 0.2872399E+03 + 0.2866775E+03 0.2861149E+03 0.2855516E+03 0.2849881E+03 0.2844244E+03 + 0.2838607E+03 0.2832962E+03 0.2827315E+03 0.2821661E+03 0.2816002E+03 + 0.2810334E+03 0.2804666E+03 0.2798983E+03 0.2793299E+03 0.2787603E+03 + 0.2781900E+03 0.2776186E+03 0.2770463E+03 0.2764730E+03 0.2758979E+03 + 0.2753224E+03 0.2747451E+03 0.2741668E+03 0.2735866E+03 0.2730054E+03 + 0.2724219E+03 0.2718374E+03 0.2712508E+03 0.2706624E+03 0.2700722E+03 + 0.2694793E+03 0.2688849E+03 0.2682875E+03 0.2676885E+03 0.2670861E+03 + 0.2664819E+03 0.2658744E+03 0.2652641E+03 0.2646510E+03 0.2640345E+03 + 0.2634149E+03 0.2627915E+03 0.2621648E+03 0.2615341E+03 0.2608994E+03 + 0.2602607E+03 0.2596175E+03 0.2589699E+03 0.2583175E+03 0.2576602E+03 + 0.2569980E+03 0.2563297E+03 0.2556560E+03 0.2549769E+03 0.2542910E+03 + 0.2535986E+03 0.2528998E+03 0.2521940E+03 0.2514806E+03 0.2507594E+03 + 0.2500305E+03 0.2492933E+03 0.2485472E+03 0.2477920E+03 0.2470273E+03 + 0.2462524E+03 0.2454674E+03 0.2446717E+03 0.2438650E+03 0.2430463E+03 + 0.2422156E+03 0.2413725E+03 0.2405160E+03 0.2396465E+03 0.2387627E+03 + 0.2378647E+03 0.2369520E+03 0.2360240E+03 0.2350805E+03 0.2341212E+03 + 0.2331456E+03 0.2321534E+03 0.2311447E+03 0.2301193E+03 0.2290771E+03 + 0.2280183E+03 0.2269427E+03 0.2258511E+03 0.2247434E+03 0.2236202E+03 + 0.3214514E+03 0.3208495E+03 0.3202490E+03 0.3196495E+03 0.3190518E+03 + 0.3184547E+03 0.3178591E+03 0.3172652E+03 0.3166719E+03 0.3160800E+03 + 0.3154895E+03 0.3149002E+03 0.3143118E+03 0.3137245E+03 0.3131385E+03 + 0.3125535E+03 0.3119696E+03 0.3113864E+03 0.3108044E+03 0.3102235E+03 + 0.3096438E+03 0.3090647E+03 0.3084873E+03 0.3079100E+03 0.3073340E+03 + 0.3067586E+03 0.3061844E+03 0.3056113E+03 0.3050386E+03 0.3044662E+03 + 0.3038952E+03 0.3033253E+03 0.3027558E+03 0.3021869E+03 0.3016184E+03 + 0.3010509E+03 0.3004844E+03 0.2999181E+03 0.2993523E+03 0.2987871E+03 + 0.2982229E+03 0.2976585E+03 0.2970951E+03 0.2965322E+03 0.2959695E+03 + 0.2954073E+03 0.2948451E+03 0.2942838E+03 0.2937226E+03 0.2931618E+03 + 0.2926010E+03 0.2920405E+03 0.2914801E+03 0.2909204E+03 0.2903606E+03 + 0.2898004E+03 0.2892406E+03 0.2886811E+03 0.2881213E+03 0.2875612E+03 + 0.2870013E+03 0.2864410E+03 0.2858811E+03 0.2853207E+03 0.2847598E+03 + 0.2841984E+03 0.2836375E+03 0.2830756E+03 0.2825135E+03 0.2819511E+03 + 0.2813875E+03 0.2808238E+03 0.2802592E+03 0.2796943E+03 0.2791284E+03 + 0.2785620E+03 0.2779942E+03 0.2774258E+03 0.2768562E+03 0.2762859E+03 + 0.2757143E+03 0.2751417E+03 0.2745676E+03 0.2739919E+03 0.2734154E+03 + 0.2728367E+03 0.2722572E+03 0.2716757E+03 0.2710925E+03 0.2705074E+03 + 0.2699206E+03 0.2693317E+03 0.2687401E+03 0.2681472E+03 0.2675509E+03 + 0.2669531E+03 0.2663521E+03 0.2657488E+03 0.2651425E+03 0.2645333E+03 + 0.2639211E+03 0.2633053E+03 0.2626867E+03 0.2620641E+03 0.2614378E+03 + 0.2608079E+03 0.2601737E+03 0.2595356E+03 0.2588925E+03 0.2582451E+03 + 0.2575929E+03 0.2569356E+03 0.2562729E+03 0.2556051E+03 0.2549310E+03 + 0.2542512E+03 0.2535649E+03 0.2528721E+03 0.2521725E+03 0.2514659E+03 + 0.2507512E+03 0.2500290E+03 0.2492988E+03 0.2485600E+03 0.2478122E+03 + 0.2470548E+03 0.2462880E+03 0.2455112E+03 0.2447234E+03 0.2439252E+03 + 0.2431154E+03 0.2422937E+03 0.2414595E+03 0.2406130E+03 0.2397529E+03 + 0.2388792E+03 0.2379914E+03 0.2370890E+03 0.2361716E+03 0.2352387E+03 + 0.2342902E+03 0.2333255E+03 0.2323446E+03 0.2313469E+03 0.2303326E+03 + 0.2293015E+03 0.2282537E+03 0.2271892E+03 0.2261080E+03 0.2250108E+03 + 0.3216765E+03 0.3210758E+03 0.3204755E+03 0.3198774E+03 0.3192802E+03 + 0.3186845E+03 0.3180895E+03 0.3174969E+03 0.3169049E+03 0.3163135E+03 + 0.3157242E+03 0.3151358E+03 0.3145483E+03 0.3139623E+03 0.3133773E+03 + 0.3127934E+03 0.3122105E+03 0.3116291E+03 0.3110482E+03 0.3104684E+03 + 0.3098897E+03 0.3093121E+03 0.3087353E+03 0.3081602E+03 0.3075853E+03 + 0.3070115E+03 0.3064383E+03 0.3058663E+03 0.3052953E+03 0.3047247E+03 + 0.3041551E+03 0.3035860E+03 0.3030181E+03 0.3024510E+03 0.3018843E+03 + 0.3013182E+03 0.3007532E+03 0.3001885E+03 0.2996246E+03 0.2990610E+03 + 0.2984980E+03 0.2979362E+03 0.2973742E+03 0.2968130E+03 0.2962522E+03 + 0.2956917E+03 0.2951318E+03 0.2945725E+03 0.2940132E+03 0.2934542E+03 + 0.2928959E+03 0.2923378E+03 0.2917794E+03 0.2912215E+03 0.2906636E+03 + 0.2901065E+03 0.2895490E+03 0.2889914E+03 0.2884341E+03 0.2878767E+03 + 0.2873196E+03 0.2867620E+03 0.2862043E+03 0.2856466E+03 0.2850888E+03 + 0.2845309E+03 0.2839722E+03 0.2834134E+03 0.2828546E+03 0.2822947E+03 + 0.2817349E+03 0.2811742E+03 0.2806132E+03 0.2800513E+03 0.2794893E+03 + 0.2789262E+03 0.2783621E+03 0.2777978E+03 0.2772321E+03 0.2766657E+03 + 0.2760980E+03 0.2755295E+03 0.2749597E+03 0.2743887E+03 0.2738164E+03 + 0.2732427E+03 0.2726677E+03 0.2720910E+03 0.2715128E+03 0.2709326E+03 + 0.2703511E+03 0.2697674E+03 0.2691817E+03 0.2685943E+03 0.2680044E+03 + 0.2674124E+03 0.2668180E+03 0.2662210E+03 0.2656214E+03 0.2650190E+03 + 0.2644138E+03 0.2638053E+03 0.2631941E+03 0.2625793E+03 0.2619610E+03 + 0.2613394E+03 0.2607137E+03 0.2600843E+03 0.2594505E+03 0.2588128E+03 + 0.2581701E+03 0.2575230E+03 0.2568708E+03 0.2562135E+03 0.2555509E+03 + 0.2548824E+03 0.2542085E+03 0.2535281E+03 0.2528410E+03 0.2521475E+03 + 0.2514474E+03 0.2507391E+03 0.2500237E+03 0.2493003E+03 0.2485687E+03 + 0.2478278E+03 0.2470782E+03 0.2463190E+03 0.2455502E+03 0.2447709E+03 + 0.2439808E+03 0.2431796E+03 0.2423670E+03 0.2415419E+03 0.2407044E+03 + 0.2398542E+03 0.2389901E+03 0.2381122E+03 0.2372200E+03 0.2363130E+03 + 0.2353908E+03 0.2344530E+03 0.2334992E+03 0.2325294E+03 0.2315429E+03 + 0.2305397E+03 0.2295197E+03 0.2284830E+03 0.2274294E+03 0.2263591E+03 + 0.3218990E+03 0.3212989E+03 0.3207000E+03 0.3201022E+03 0.3195060E+03 + 0.3189113E+03 0.3183179E+03 0.3177255E+03 0.3171341E+03 0.3165443E+03 + 0.3159558E+03 0.3153684E+03 0.3147823E+03 0.3141973E+03 0.3136135E+03 + 0.3130304E+03 0.3124487E+03 0.3118680E+03 0.3112885E+03 0.3107103E+03 + 0.3101331E+03 0.3095563E+03 0.3089808E+03 0.3084063E+03 0.3078330E+03 + 0.3072605E+03 0.3066886E+03 0.3061179E+03 0.3055482E+03 0.3049788E+03 + 0.3044109E+03 0.3038435E+03 0.3032767E+03 0.3027108E+03 0.3021460E+03 + 0.3015817E+03 0.3010179E+03 0.3004548E+03 0.2998923E+03 0.2993309E+03 + 0.2987696E+03 0.2982090E+03 0.2976491E+03 0.2970896E+03 0.2965308E+03 + 0.2959722E+03 0.2954141E+03 0.2948565E+03 0.2942995E+03 0.2937425E+03 + 0.2931858E+03 0.2926297E+03 0.2920736E+03 0.2915182E+03 0.2909623E+03 + 0.2904070E+03 0.2898520E+03 0.2892971E+03 0.2887421E+03 0.2881870E+03 + 0.2876322E+03 0.2870773E+03 0.2865223E+03 0.2859673E+03 0.2854121E+03 + 0.2848563E+03 0.2843008E+03 0.2837451E+03 0.2831887E+03 0.2826324E+03 + 0.2820754E+03 0.2815181E+03 0.2809604E+03 0.2804017E+03 0.2798429E+03 + 0.2792831E+03 0.2787231E+03 0.2781618E+03 0.2776000E+03 0.2770372E+03 + 0.2764738E+03 0.2759091E+03 0.2753431E+03 0.2747768E+03 0.2742083E+03 + 0.2736393E+03 0.2730685E+03 0.2724969E+03 0.2719236E+03 0.2713484E+03 + 0.2707718E+03 0.2701933E+03 0.2696131E+03 0.2690308E+03 0.2684467E+03 + 0.2678605E+03 0.2672717E+03 0.2666812E+03 0.2660879E+03 0.2654918E+03 + 0.2648936E+03 0.2642921E+03 0.2636880E+03 0.2630804E+03 0.2624700E+03 + 0.2618561E+03 0.2612384E+03 0.2606175E+03 0.2599925E+03 0.2593634E+03 + 0.2587302E+03 0.2580925E+03 0.2574502E+03 0.2568029E+03 0.2561510E+03 + 0.2554939E+03 0.2548310E+03 0.2541622E+03 0.2534878E+03 0.2528065E+03 + 0.2521193E+03 0.2514252E+03 0.2507234E+03 0.2500145E+03 0.2492980E+03 + 0.2485730E+03 0.2478395E+03 0.2470974E+03 0.2463458E+03 0.2455847E+03 + 0.2448133E+03 0.2440315E+03 0.2432388E+03 0.2424346E+03 0.2416186E+03 + 0.2407903E+03 0.2399494E+03 0.2390952E+03 0.2382273E+03 0.2373452E+03 + 0.2364485E+03 0.2355368E+03 0.2346097E+03 0.2336668E+03 0.2327078E+03 + 0.2317324E+03 0.2307403E+03 0.2297314E+03 0.2287058E+03 0.2276632E+03 + 0.3221185E+03 0.3215196E+03 0.3209214E+03 0.3203247E+03 0.3197292E+03 + 0.3191355E+03 0.3185429E+03 0.3179514E+03 0.3173614E+03 0.3167725E+03 + 0.3161847E+03 0.3155985E+03 0.3150135E+03 0.3144294E+03 0.3138463E+03 + 0.3132643E+03 0.3126837E+03 0.3121044E+03 0.3115259E+03 0.3109488E+03 + 0.3103725E+03 0.3097974E+03 0.3092233E+03 0.3086495E+03 0.3080773E+03 + 0.3075059E+03 0.3069358E+03 0.3063665E+03 0.3057979E+03 0.3052302E+03 + 0.3046634E+03 0.3040975E+03 0.3035322E+03 0.3029680E+03 0.3024041E+03 + 0.3018411E+03 0.3012791E+03 0.3007178E+03 0.3001568E+03 0.2995963E+03 + 0.2990375E+03 0.2984783E+03 0.2979197E+03 0.2973618E+03 0.2968051E+03 + 0.2962482E+03 0.2956920E+03 0.2951363E+03 0.2945809E+03 0.2940260E+03 + 0.2934716E+03 0.2929171E+03 0.2923633E+03 0.2918095E+03 0.2912563E+03 + 0.2907034E+03 0.2901501E+03 0.2895974E+03 0.2890445E+03 0.2884922E+03 + 0.2879397E+03 0.2873872E+03 0.2868344E+03 0.2862820E+03 0.2857296E+03 + 0.2851767E+03 0.2846240E+03 0.2840704E+03 0.2835175E+03 0.2829638E+03 + 0.2824096E+03 0.2818555E+03 0.2813006E+03 0.2807454E+03 0.2801894E+03 + 0.2796336E+03 0.2790764E+03 0.2785189E+03 0.2779610E+03 0.2774016E+03 + 0.2768417E+03 0.2762808E+03 0.2757191E+03 0.2751563E+03 0.2745925E+03 + 0.2740276E+03 0.2734614E+03 0.2728939E+03 0.2723250E+03 0.2717546E+03 + 0.2711830E+03 0.2706093E+03 0.2700343E+03 0.2694572E+03 0.2688786E+03 + 0.2682978E+03 0.2677148E+03 0.2671300E+03 0.2665427E+03 0.2659532E+03 + 0.2653611E+03 0.2647662E+03 0.2641689E+03 0.2635684E+03 0.2629654E+03 + 0.2623587E+03 0.2617488E+03 0.2611358E+03 0.2605188E+03 0.2598985E+03 + 0.2592739E+03 0.2586453E+03 0.2580125E+03 0.2573751E+03 0.2567329E+03 + 0.2560860E+03 0.2554337E+03 0.2547764E+03 0.2541131E+03 0.2534443E+03 + 0.2527691E+03 0.2520875E+03 0.2513997E+03 0.2507041E+03 0.2500018E+03 + 0.2492920E+03 0.2485735E+03 0.2478473E+03 0.2471124E+03 0.2463684E+03 + 0.2456146E+03 0.2448512E+03 0.2440774E+03 0.2432932E+03 0.2424976E+03 + 0.2416906E+03 0.2408713E+03 0.2400395E+03 0.2391949E+03 0.2383366E+03 + 0.2374645E+03 0.2365780E+03 0.2356766E+03 0.2347602E+03 0.2338281E+03 + 0.2328800E+03 0.2319156E+03 0.2309347E+03 0.2299370E+03 0.2289223E+03 + 0.3223362E+03 0.3217372E+03 0.3211405E+03 0.3205443E+03 0.3199502E+03 + 0.3193571E+03 0.3187653E+03 0.3181750E+03 0.3175855E+03 0.3169979E+03 + 0.3164109E+03 0.3158253E+03 0.3152415E+03 0.3146585E+03 0.3140765E+03 + 0.3134954E+03 0.3129160E+03 0.3123375E+03 0.3117603E+03 0.3111839E+03 + 0.3106090E+03 0.3100350E+03 0.3094619E+03 0.3088900E+03 0.3083192E+03 + 0.3077487E+03 0.3071794E+03 0.3066113E+03 0.3060443E+03 0.3054778E+03 + 0.3049119E+03 0.3043474E+03 0.3037838E+03 0.3032206E+03 0.3026589E+03 + 0.3020971E+03 0.3015365E+03 0.3009766E+03 0.3004174E+03 0.2998589E+03 + 0.2993008E+03 0.2987432E+03 0.2981867E+03 0.2976306E+03 0.2970753E+03 + 0.2965202E+03 0.2959657E+03 0.2954117E+03 0.2948584E+03 0.2943051E+03 + 0.2937524E+03 0.2932003E+03 0.2926483E+03 0.2920965E+03 0.2915453E+03 + 0.2909941E+03 0.2904434E+03 0.2898929E+03 0.2893422E+03 0.2887920E+03 + 0.2882417E+03 0.2876918E+03 0.2871417E+03 0.2865916E+03 0.2860413E+03 + 0.2854912E+03 0.2849410E+03 0.2843908E+03 0.2838399E+03 0.2832889E+03 + 0.2827383E+03 0.2821865E+03 0.2816349E+03 0.2810826E+03 0.2805299E+03 + 0.2799769E+03 0.2794231E+03 0.2788690E+03 0.2783141E+03 0.2777587E+03 + 0.2772020E+03 0.2766451E+03 0.2760873E+03 0.2755282E+03 0.2749684E+03 + 0.2744073E+03 0.2738457E+03 0.2732825E+03 0.2727177E+03 0.2721519E+03 + 0.2715847E+03 0.2710160E+03 0.2704458E+03 0.2698737E+03 0.2693004E+03 + 0.2687246E+03 0.2681475E+03 0.2675680E+03 0.2669865E+03 0.2664029E+03 + 0.2658167E+03 0.2652283E+03 0.2646375E+03 0.2640436E+03 0.2634474E+03 + 0.2628477E+03 0.2622454E+03 0.2616399E+03 0.2610307E+03 0.2604182E+03 + 0.2598021E+03 0.2591820E+03 0.2585580E+03 0.2579299E+03 0.2572974E+03 + 0.2566601E+03 0.2560183E+03 0.2553712E+03 0.2547188E+03 0.2540611E+03 + 0.2533976E+03 0.2527286E+03 0.2520525E+03 0.2513706E+03 0.2506813E+03 + 0.2499854E+03 0.2492821E+03 0.2485704E+03 0.2478510E+03 0.2471233E+03 + 0.2463863E+03 0.2456403E+03 0.2448847E+03 0.2441190E+03 0.2433427E+03 + 0.2425558E+03 0.2417572E+03 0.2409468E+03 0.2401242E+03 0.2392889E+03 + 0.2384403E+03 0.2375781E+03 0.2367017E+03 0.2358107E+03 0.2349046E+03 + 0.2339832E+03 0.2330459E+03 0.2320925E+03 0.2311226E+03 0.2301361E+03 + 0.3225504E+03 0.3219531E+03 0.3213569E+03 0.3207617E+03 0.3201681E+03 + 0.3195757E+03 0.3189850E+03 0.3183953E+03 0.3178072E+03 0.3172203E+03 + 0.3166344E+03 0.3160499E+03 0.3154668E+03 0.3148845E+03 0.3143039E+03 + 0.3137240E+03 0.3131454E+03 0.3125680E+03 0.3119919E+03 0.3114165E+03 + 0.3108429E+03 0.3102697E+03 0.3096978E+03 0.3091273E+03 0.3085569E+03 + 0.3079882E+03 0.3074200E+03 0.3068529E+03 0.3062871E+03 0.3057220E+03 + 0.3051579E+03 0.3045946E+03 0.3040319E+03 0.3034702E+03 0.3029097E+03 + 0.3023496E+03 0.3017906E+03 0.3012318E+03 0.3006742E+03 0.3001172E+03 + 0.2995608E+03 0.2990045E+03 0.2984497E+03 0.2978953E+03 0.2973416E+03 + 0.2967881E+03 0.2962354E+03 0.2956831E+03 0.2951314E+03 0.2945801E+03 + 0.2940292E+03 0.2934785E+03 0.2929286E+03 0.2923792E+03 0.2918297E+03 + 0.2912804E+03 0.2907319E+03 0.2901833E+03 0.2896352E+03 0.2890872E+03 + 0.2885392E+03 0.2879911E+03 0.2874433E+03 0.2868960E+03 0.2863481E+03 + 0.2858003E+03 0.2852524E+03 0.2847043E+03 0.2841565E+03 0.2836086E+03 + 0.2830601E+03 0.2825117E+03 0.2819627E+03 0.2814134E+03 0.2808639E+03 + 0.2803135E+03 0.2797636E+03 0.2792122E+03 0.2786610E+03 0.2781086E+03 + 0.2775556E+03 0.2770021E+03 0.2764477E+03 0.2758925E+03 0.2753367E+03 + 0.2747794E+03 0.2742213E+03 0.2736621E+03 0.2731020E+03 0.2725407E+03 + 0.2719775E+03 0.2714136E+03 0.2708478E+03 0.2702808E+03 0.2697122E+03 + 0.2691416E+03 0.2685697E+03 0.2679951E+03 0.2674194E+03 0.2668415E+03 + 0.2662612E+03 0.2656789E+03 0.2650942E+03 0.2645066E+03 0.2639168E+03 + 0.2633242E+03 0.2627287E+03 0.2621301E+03 0.2615286E+03 0.2609240E+03 + 0.2603154E+03 0.2597034E+03 0.2590882E+03 0.2584684E+03 0.2578449E+03 + 0.2572169E+03 0.2565845E+03 0.2559474E+03 0.2553056E+03 0.2546584E+03 + 0.2540063E+03 0.2533481E+03 0.2526845E+03 0.2520145E+03 0.2513384E+03 + 0.2506554E+03 0.2499654E+03 0.2492686E+03 0.2485634E+03 0.2478510E+03 + 0.2471302E+03 0.2464003E+03 0.2456618E+03 0.2449137E+03 0.2441557E+03 + 0.2433876E+03 0.2426087E+03 0.2418189E+03 0.2410174E+03 0.2402037E+03 + 0.2393776E+03 0.2385386E+03 0.2376860E+03 0.2368195E+03 0.2359389E+03 + 0.2350433E+03 0.2341323E+03 0.2332057E+03 0.2322630E+03 0.2313042E+03 + 0.3227627E+03 0.3221658E+03 0.3215702E+03 0.3209764E+03 0.3203833E+03 + 0.3197926E+03 0.3192024E+03 0.3186134E+03 0.3180262E+03 0.3174403E+03 + 0.3168553E+03 0.3162713E+03 0.3156891E+03 0.3151082E+03 0.3145285E+03 + 0.3139496E+03 0.3133720E+03 0.3127957E+03 0.3122205E+03 0.3116463E+03 + 0.3110732E+03 0.3105013E+03 0.3099308E+03 0.3093607E+03 0.3087922E+03 + 0.3082245E+03 0.3076580E+03 0.3070920E+03 0.3065268E+03 0.3059630E+03 + 0.3054000E+03 0.3048383E+03 0.3042768E+03 0.3037165E+03 0.3031570E+03 + 0.3025987E+03 0.3020406E+03 0.3014839E+03 0.3009271E+03 0.3003714E+03 + 0.2998168E+03 0.2992627E+03 0.2987091E+03 0.2981560E+03 0.2976037E+03 + 0.2970522E+03 0.2965011E+03 0.2959503E+03 0.2954003E+03 0.2948506E+03 + 0.2943019E+03 0.2937531E+03 0.2932049E+03 0.2926573E+03 0.2921097E+03 + 0.2915629E+03 0.2910159E+03 0.2904692E+03 0.2899230E+03 0.2893770E+03 + 0.2888315E+03 0.2882856E+03 0.2877402E+03 0.2871945E+03 0.2866493E+03 + 0.2861039E+03 0.2855590E+03 0.2850133E+03 0.2844680E+03 0.2839220E+03 + 0.2833768E+03 0.2828308E+03 0.2822845E+03 0.2817384E+03 0.2811916E+03 + 0.2806445E+03 0.2800968E+03 0.2795490E+03 0.2790007E+03 0.2784517E+03 + 0.2779023E+03 0.2773520E+03 0.2768011E+03 0.2762498E+03 0.2756969E+03 + 0.2751437E+03 0.2745898E+03 0.2740342E+03 0.2734781E+03 0.2729206E+03 + 0.2723622E+03 0.2718023E+03 0.2712411E+03 0.2706787E+03 0.2701146E+03 + 0.2695492E+03 0.2689819E+03 0.2684128E+03 0.2678423E+03 0.2672697E+03 + 0.2666947E+03 0.2661182E+03 0.2655392E+03 0.2649579E+03 0.2643745E+03 + 0.2637880E+03 0.2631992E+03 0.2626079E+03 0.2620132E+03 0.2614155E+03 + 0.2608145E+03 0.2602106E+03 0.2596029E+03 0.2589916E+03 0.2583766E+03 + 0.2577576E+03 0.2571341E+03 0.2565065E+03 0.2558745E+03 0.2552374E+03 + 0.2545955E+03 0.2539483E+03 0.2532957E+03 0.2526375E+03 0.2519732E+03 + 0.2513027E+03 0.2506258E+03 0.2499420E+03 0.2492515E+03 0.2485528E+03 + 0.2478470E+03 0.2471331E+03 0.2464102E+03 0.2456790E+03 0.2449384E+03 + 0.2441881E+03 0.2434277E+03 0.2426573E+03 0.2418756E+03 0.2410828E+03 + 0.2402780E+03 0.2394611E+03 0.2386313E+03 0.2377884E+03 0.2369317E+03 + 0.2360609E+03 0.2351756E+03 0.2342751E+03 0.2333593E+03 0.2324276E+03 + 0.3229725E+03 0.3223766E+03 0.3217819E+03 0.3211890E+03 0.3205965E+03 + 0.3200063E+03 0.3194170E+03 0.3188288E+03 0.3182428E+03 0.3176576E+03 + 0.3170738E+03 0.3164905E+03 0.3159093E+03 0.3153295E+03 0.3147503E+03 + 0.3141725E+03 0.3135957E+03 0.3130205E+03 0.3124462E+03 0.3118732E+03 + 0.3113012E+03 0.3107301E+03 0.3101604E+03 0.3095919E+03 0.3090241E+03 + 0.3084576E+03 0.3078922E+03 0.3073275E+03 0.3067638E+03 0.3062010E+03 + 0.3056392E+03 0.3050783E+03 0.3045184E+03 0.3039594E+03 0.3034013E+03 + 0.3028439E+03 0.3022875E+03 0.3017320E+03 0.3011772E+03 0.3006229E+03 + 0.3000693E+03 0.2995164E+03 0.2989646E+03 0.2984132E+03 0.2978621E+03 + 0.2973123E+03 0.2967627E+03 0.2962137E+03 0.2956656E+03 0.2951173E+03 + 0.2945702E+03 0.2940235E+03 0.2934772E+03 0.2929312E+03 0.2923853E+03 + 0.2918402E+03 0.2912954E+03 0.2907508E+03 0.2902067E+03 0.2896626E+03 + 0.2891187E+03 0.2885753E+03 0.2880321E+03 0.2874892E+03 0.2869458E+03 + 0.2864024E+03 0.2858597E+03 0.2853167E+03 0.2847738E+03 0.2842308E+03 + 0.2836877E+03 0.2831441E+03 0.2826009E+03 0.2820570E+03 0.2815132E+03 + 0.2809693E+03 0.2804241E+03 0.2798796E+03 0.2793338E+03 0.2787886E+03 + 0.2782420E+03 0.2776950E+03 0.2771478E+03 0.2765993E+03 0.2760503E+03 + 0.2755009E+03 0.2749500E+03 0.2743987E+03 0.2738462E+03 0.2732928E+03 + 0.2727385E+03 0.2721827E+03 0.2716259E+03 0.2710678E+03 0.2705081E+03 + 0.2699475E+03 0.2693848E+03 0.2688207E+03 0.2682550E+03 0.2676877E+03 + 0.2671183E+03 0.2665471E+03 0.2659737E+03 0.2653984E+03 0.2648207E+03 + 0.2642403E+03 0.2636579E+03 0.2630727E+03 0.2624847E+03 0.2618940E+03 + 0.2613005E+03 0.2607039E+03 0.2601035E+03 0.2594999E+03 0.2588932E+03 + 0.2582822E+03 0.2576676E+03 0.2570491E+03 0.2564263E+03 0.2557987E+03 + 0.2551665E+03 0.2545298E+03 0.2538876E+03 0.2532407E+03 0.2525874E+03 + 0.2519291E+03 0.2512639E+03 0.2505930E+03 0.2499151E+03 0.2492308E+03 + 0.2485385E+03 0.2478393E+03 0.2471319E+03 0.2464162E+03 0.2456921E+03 + 0.2449587E+03 0.2442162E+03 0.2434637E+03 0.2427010E+03 0.2419278E+03 + 0.2411431E+03 0.2403473E+03 0.2395393E+03 0.2387186E+03 0.2378852E+03 + 0.2370382E+03 0.2361775E+03 0.2353022E+03 0.2344120E+03 0.2335067E+03 + 0.3231807E+03 0.3225849E+03 0.3219903E+03 0.3213983E+03 0.3208076E+03 + 0.3202176E+03 0.3196290E+03 0.3190419E+03 0.3184569E+03 0.3178724E+03 + 0.3172890E+03 0.3167075E+03 0.3161264E+03 0.3155473E+03 0.3149695E+03 + 0.3143927E+03 0.3138169E+03 0.3132425E+03 0.3126695E+03 0.3120970E+03 + 0.3115264E+03 0.3109565E+03 0.3103877E+03 0.3098198E+03 0.3092533E+03 + 0.3086880E+03 0.3081235E+03 0.3075601E+03 0.3069975E+03 0.3064362E+03 + 0.3058757E+03 0.3053157E+03 0.3047570E+03 0.3041991E+03 0.3036425E+03 + 0.3030865E+03 0.3025311E+03 0.3019767E+03 0.3014229E+03 0.3008703E+03 + 0.3003184E+03 0.2997671E+03 0.2992162E+03 0.2986665E+03 0.2981171E+03 + 0.2975689E+03 0.2970205E+03 0.2964733E+03 0.2959268E+03 0.2953803E+03 + 0.2948347E+03 0.2942892E+03 0.2937447E+03 0.2932007E+03 0.2926570E+03 + 0.2921136E+03 0.2915706E+03 0.2910277E+03 0.2904857E+03 0.2899439E+03 + 0.2894019E+03 0.2888605E+03 0.2883192E+03 0.2877780E+03 0.2872369E+03 + 0.2866966E+03 0.2861557E+03 0.2856153E+03 0.2850742E+03 0.2845335E+03 + 0.2839930E+03 0.2834525E+03 0.2829113E+03 0.2823705E+03 0.2818292E+03 + 0.2812876E+03 0.2807460E+03 0.2802038E+03 0.2796617E+03 0.2791187E+03 + 0.2785752E+03 0.2780318E+03 0.2774872E+03 0.2769426E+03 0.2763970E+03 + 0.2758504E+03 0.2753035E+03 0.2747557E+03 0.2742069E+03 0.2736573E+03 + 0.2731067E+03 0.2725551E+03 0.2720026E+03 0.2714482E+03 0.2708932E+03 + 0.2703367E+03 0.2697788E+03 0.2692197E+03 0.2686584E+03 0.2680958E+03 + 0.2675316E+03 0.2669656E+03 0.2663973E+03 0.2658278E+03 0.2652555E+03 + 0.2646812E+03 0.2641049E+03 0.2635255E+03 0.2629444E+03 0.2623603E+03 + 0.2617735E+03 0.2611834E+03 0.2605907E+03 0.2599948E+03 0.2593954E+03 + 0.2587926E+03 0.2581861E+03 0.2575761E+03 0.2569617E+03 0.2563431E+03 + 0.2557205E+03 0.2550935E+03 0.2544613E+03 0.2538243E+03 0.2531820E+03 + 0.2525347E+03 0.2518816E+03 0.2512224E+03 0.2505571E+03 0.2498852E+03 + 0.2492068E+03 0.2485207E+03 0.2478279E+03 0.2471270E+03 0.2464183E+03 + 0.2457013E+03 0.2449750E+03 0.2442399E+03 0.2434950E+03 0.2427405E+03 + 0.2419750E+03 0.2411991E+03 0.2404116E+03 0.2396123E+03 0.2388008E+03 + 0.2379767E+03 0.2371395E+03 0.2362881E+03 0.2354230E+03 0.2345431E+03 + 0.3233855E+03 0.3227918E+03 0.3221982E+03 0.3216064E+03 0.3210159E+03 + 0.3204271E+03 0.3198392E+03 0.3192526E+03 0.3186677E+03 0.3180848E+03 + 0.3175022E+03 0.3169214E+03 0.3163412E+03 0.3157629E+03 0.3151861E+03 + 0.3146104E+03 0.3140353E+03 0.3134621E+03 0.3128900E+03 0.3123187E+03 + 0.3117485E+03 0.3111797E+03 0.3106123E+03 0.3100453E+03 0.3094799E+03 + 0.3089153E+03 0.3083520E+03 0.3077894E+03 0.3072279E+03 0.3066678E+03 + 0.3061087E+03 0.3055501E+03 0.3049924E+03 0.3044359E+03 0.3038799E+03 + 0.3033255E+03 0.3027713E+03 0.3022184E+03 0.3016656E+03 0.3011147E+03 + 0.3005640E+03 0.3000141E+03 0.2994647E+03 0.2989163E+03 0.2983683E+03 + 0.2978214E+03 0.2972750E+03 0.2967294E+03 0.2961839E+03 0.2956390E+03 + 0.2950954E+03 0.2945518E+03 0.2940088E+03 0.2934661E+03 0.2929242E+03 + 0.2923826E+03 0.2918414E+03 0.2913007E+03 0.2907602E+03 0.2902200E+03 + 0.2896803E+03 0.2891412E+03 0.2886018E+03 0.2880629E+03 0.2875237E+03 + 0.2869852E+03 0.2864467E+03 0.2859084E+03 0.2853700E+03 0.2848319E+03 + 0.2842934E+03 0.2837548E+03 0.2832166E+03 0.2826781E+03 0.2821393E+03 + 0.2816010E+03 0.2810616E+03 0.2805226E+03 0.2799829E+03 0.2794424E+03 + 0.2789025E+03 0.2783615E+03 0.2778203E+03 0.2772786E+03 0.2767364E+03 + 0.2761932E+03 0.2756497E+03 0.2751053E+03 0.2745603E+03 0.2740143E+03 + 0.2734671E+03 0.2729198E+03 0.2723708E+03 0.2718208E+03 0.2712701E+03 + 0.2707175E+03 0.2701641E+03 0.2696092E+03 0.2690526E+03 0.2684952E+03 + 0.2679356E+03 0.2673741E+03 0.2668116E+03 0.2662471E+03 0.2656801E+03 + 0.2651115E+03 0.2645407E+03 0.2639675E+03 0.2633922E+03 0.2628141E+03 + 0.2622338E+03 0.2616506E+03 0.2610650E+03 0.2604758E+03 0.2598838E+03 + 0.2592883E+03 0.2586899E+03 0.2580876E+03 0.2574818E+03 0.2568720E+03 + 0.2562580E+03 0.2556402E+03 0.2550175E+03 0.2543901E+03 0.2537585E+03 + 0.2531212E+03 0.2524790E+03 0.2518311E+03 0.2511774E+03 0.2505176E+03 + 0.2498519E+03 0.2491793E+03 0.2484998E+03 0.2478130E+03 0.2471185E+03 + 0.2464167E+03 0.2457065E+03 0.2449873E+03 0.2442594E+03 0.2435220E+03 + 0.2427749E+03 0.2420178E+03 0.2412499E+03 0.2404708E+03 0.2396803E+03 + 0.2388778E+03 0.2380628E+03 0.2372348E+03 0.2363935E+03 0.2355381E+03 + 0.3235891E+03 0.3229945E+03 0.3224026E+03 0.3218117E+03 0.3212220E+03 + 0.3206332E+03 0.3200469E+03 0.3194610E+03 0.3188771E+03 0.3182941E+03 + 0.3177130E+03 0.3171330E+03 0.3165537E+03 0.3159766E+03 0.3154004E+03 + 0.3148253E+03 0.3142512E+03 0.3136791E+03 0.3131078E+03 0.3125372E+03 + 0.3119684E+03 0.3114005E+03 0.3108335E+03 0.3102682E+03 0.3097034E+03 + 0.3091401E+03 0.3085774E+03 0.3080161E+03 0.3074559E+03 0.3068965E+03 + 0.3063385E+03 0.3057814E+03 0.3052247E+03 0.3046695E+03 0.3041145E+03 + 0.3035612E+03 0.3030086E+03 0.3024567E+03 0.3019058E+03 0.3013554E+03 + 0.3008060E+03 0.3002575E+03 0.2997099E+03 0.2991625E+03 0.2986162E+03 + 0.2980706E+03 0.2975253E+03 0.2969811E+03 0.2964378E+03 0.2958943E+03 + 0.2953519E+03 0.2948102E+03 0.2942690E+03 0.2937280E+03 0.2931875E+03 + 0.2926476E+03 0.2921082E+03 0.2915693E+03 0.2910308E+03 0.2904926E+03 + 0.2899543E+03 0.2894168E+03 0.2888797E+03 0.2883429E+03 0.2878062E+03 + 0.2872696E+03 0.2867329E+03 0.2861965E+03 0.2856606E+03 0.2851249E+03 + 0.2845885E+03 0.2840527E+03 0.2835166E+03 0.2829804E+03 0.2824445E+03 + 0.2819080E+03 0.2813717E+03 0.2808351E+03 0.2802981E+03 0.2797610E+03 + 0.2792232E+03 0.2786855E+03 0.2781473E+03 0.2776086E+03 0.2770696E+03 + 0.2765296E+03 0.2759893E+03 0.2754485E+03 0.2749064E+03 0.2743640E+03 + 0.2738210E+03 0.2732767E+03 0.2727317E+03 0.2721857E+03 0.2716383E+03 + 0.2710903E+03 0.2705408E+03 0.2699901E+03 0.2694385E+03 0.2688850E+03 + 0.2683303E+03 0.2677740E+03 0.2672160E+03 0.2666562E+03 0.2660949E+03 + 0.2655316E+03 0.2649659E+03 0.2643984E+03 0.2638292E+03 0.2632568E+03 + 0.2626828E+03 0.2621061E+03 0.2615264E+03 0.2609439E+03 0.2603591E+03 + 0.2597711E+03 0.2591798E+03 0.2585852E+03 0.2579871E+03 0.2573857E+03 + 0.2567800E+03 0.2561707E+03 0.2555570E+03 0.2549390E+03 0.2543171E+03 + 0.2536897E+03 0.2530577E+03 0.2524207E+03 0.2517780E+03 0.2511297E+03 + 0.2504755E+03 0.2498152E+03 0.2491485E+03 0.2484752E+03 0.2477946E+03 + 0.2471065E+03 0.2464109E+03 0.2457074E+03 0.2449957E+03 0.2442749E+03 + 0.2435449E+03 0.2428054E+03 0.2420560E+03 0.2412961E+03 0.2405253E+03 + 0.2397434E+03 0.2389498E+03 0.2381437E+03 0.2373250E+03 0.2364930E+03 + 0.3237905E+03 0.3231973E+03 0.3226050E+03 0.3220146E+03 0.3214252E+03 + 0.3208380E+03 0.3202515E+03 0.3196671E+03 0.3190841E+03 0.3185019E+03 + 0.3179211E+03 0.3173418E+03 0.3167639E+03 0.3161870E+03 0.3156116E+03 + 0.3150375E+03 0.3144648E+03 0.3138929E+03 0.3133227E+03 0.3127534E+03 + 0.3121852E+03 0.3116182E+03 0.3110524E+03 0.3104879E+03 0.3099247E+03 + 0.3093619E+03 0.3088006E+03 0.3082404E+03 0.3076808E+03 0.3071225E+03 + 0.3065654E+03 0.3060092E+03 0.3054542E+03 0.3048996E+03 0.3043466E+03 + 0.3037939E+03 0.3032422E+03 0.3026915E+03 0.3021423E+03 0.3015932E+03 + 0.3010448E+03 0.3004978E+03 0.2999514E+03 0.2994056E+03 0.2988607E+03 + 0.2983164E+03 0.2977723E+03 0.2972299E+03 0.2966876E+03 0.2961462E+03 + 0.2956051E+03 0.2950647E+03 0.2945247E+03 0.2939858E+03 0.2934471E+03 + 0.2929089E+03 0.2923711E+03 0.2918336E+03 0.2912970E+03 0.2907606E+03 + 0.2902248E+03 0.2896887E+03 0.2891535E+03 0.2886180E+03 0.2880834E+03 + 0.2875490E+03 0.2870146E+03 0.2864804E+03 0.2859466E+03 0.2854124E+03 + 0.2848786E+03 0.2843448E+03 0.2838116E+03 0.2832779E+03 0.2827438E+03 + 0.2822104E+03 0.2816761E+03 0.2811422E+03 0.2806081E+03 0.2800734E+03 + 0.2795388E+03 0.2790038E+03 0.2784680E+03 0.2779326E+03 0.2773963E+03 + 0.2768594E+03 0.2763225E+03 0.2757845E+03 0.2752460E+03 0.2747072E+03 + 0.2741672E+03 0.2736262E+03 0.2730854E+03 0.2725427E+03 0.2719998E+03 + 0.2714554E+03 0.2709097E+03 0.2703632E+03 0.2698155E+03 0.2692662E+03 + 0.2687161E+03 0.2681644E+03 0.2676111E+03 0.2670562E+03 0.2664998E+03 + 0.2659413E+03 0.2653811E+03 0.2648193E+03 0.2642549E+03 0.2636887E+03 + 0.2631204E+03 0.2625495E+03 0.2619764E+03 0.2614005E+03 0.2608219E+03 + 0.2602405E+03 0.2596563E+03 0.2590689E+03 0.2584785E+03 0.2578845E+03 + 0.2572871E+03 0.2566859E+03 0.2560809E+03 0.2554717E+03 0.2548587E+03 + 0.2542408E+03 0.2536186E+03 0.2529915E+03 0.2523592E+03 0.2517219E+03 + 0.2510792E+03 0.2504304E+03 0.2497757E+03 0.2491146E+03 0.2484471E+03 + 0.2477730E+03 0.2470912E+03 0.2464021E+03 0.2457049E+03 0.2449999E+03 + 0.2442861E+03 0.2435634E+03 0.2428315E+03 0.2420898E+03 0.2413378E+03 + 0.2405753E+03 0.2398016E+03 0.2390165E+03 0.2382194E+03 0.2374098E+03 + 0.3239862E+03 0.3233954E+03 0.3228044E+03 0.3222159E+03 0.3216272E+03 + 0.3210397E+03 0.3204544E+03 0.3198711E+03 0.3192885E+03 0.3187070E+03 + 0.3181269E+03 0.3175490E+03 0.3169716E+03 0.3163958E+03 0.3158212E+03 + 0.3152476E+03 0.3146757E+03 0.3141045E+03 0.3135350E+03 0.3129670E+03 + 0.3123997E+03 0.3118340E+03 0.3112688E+03 0.3107053E+03 0.3101425E+03 + 0.3095811E+03 0.3090207E+03 0.3084614E+03 0.3079033E+03 0.3073459E+03 + 0.3067896E+03 0.3062345E+03 0.3056802E+03 0.3051274E+03 0.3045753E+03 + 0.3040238E+03 0.3034734E+03 0.3029238E+03 0.3023754E+03 0.3018278E+03 + 0.3012812E+03 0.3007350E+03 0.3001895E+03 0.2996451E+03 0.2991014E+03 + 0.2985587E+03 0.2980164E+03 0.2974745E+03 0.2969339E+03 0.2963938E+03 + 0.2958549E+03 0.2953160E+03 0.2947773E+03 0.2942396E+03 0.2937025E+03 + 0.2931659E+03 0.2926302E+03 0.2920946E+03 0.2915591E+03 0.2910244E+03 + 0.2904902E+03 0.2899564E+03 0.2894231E+03 0.2888898E+03 0.2883567E+03 + 0.2878239E+03 0.2872916E+03 0.2867596E+03 0.2862280E+03 0.2856961E+03 + 0.2851645E+03 0.2846324E+03 0.2841013E+03 0.2835695E+03 0.2830385E+03 + 0.2825069E+03 0.2819755E+03 0.2814440E+03 0.2809120E+03 0.2803803E+03 + 0.2798483E+03 0.2793159E+03 0.2787833E+03 0.2782502E+03 0.2777169E+03 + 0.2771835E+03 0.2766489E+03 0.2761143E+03 0.2755793E+03 0.2750432E+03 + 0.2745066E+03 0.2739697E+03 0.2734313E+03 0.2728929E+03 0.2723533E+03 + 0.2718122E+03 0.2712708E+03 0.2707283E+03 0.2701844E+03 0.2696394E+03 + 0.2690936E+03 0.2685459E+03 0.2679973E+03 0.2674471E+03 0.2668952E+03 + 0.2663417E+03 0.2657867E+03 0.2652297E+03 0.2646708E+03 0.2641101E+03 + 0.2635473E+03 0.2629821E+03 0.2624146E+03 0.2618449E+03 0.2612727E+03 + 0.2606978E+03 0.2601204E+03 0.2595400E+03 0.2589565E+03 0.2583699E+03 + 0.2577798E+03 0.2571868E+03 0.2565897E+03 0.2559891E+03 0.2553844E+03 + 0.2547755E+03 0.2541622E+03 0.2535452E+03 0.2529226E+03 0.2522955E+03 + 0.2516632E+03 0.2510254E+03 0.2503823E+03 0.2497332E+03 0.2490775E+03 + 0.2484160E+03 0.2477475E+03 0.2470721E+03 0.2463894E+03 0.2456987E+03 + 0.2450005E+03 0.2442936E+03 0.2435781E+03 0.2428534E+03 0.2421189E+03 + 0.2413750E+03 0.2406205E+03 0.2398550E+03 0.2390783E+03 0.2382901E+03 + 0.8999999E+10 0.3235944E+03 0.3230036E+03 0.3224138E+03 0.3218258E+03 + 0.3212402E+03 0.3206551E+03 0.3200728E+03 0.3194904E+03 0.3189099E+03 + 0.3183304E+03 0.3177533E+03 0.3171769E+03 0.3166019E+03 0.3160278E+03 + 0.3154553E+03 0.3148843E+03 0.3143137E+03 0.3137451E+03 0.3131777E+03 + 0.3126116E+03 0.3120465E+03 0.3114825E+03 0.3109200E+03 0.3103581E+03 + 0.3097976E+03 0.3092384E+03 0.3086801E+03 0.3081228E+03 0.3075665E+03 + 0.3070114E+03 0.3064568E+03 0.3059038E+03 0.3053517E+03 0.3048009E+03 + 0.3042506E+03 0.3037017E+03 0.3031530E+03 0.3026057E+03 0.3020590E+03 + 0.3015135E+03 0.3009688E+03 0.3004250E+03 0.2998817E+03 0.2993394E+03 + 0.2987978E+03 0.2982567E+03 0.2977169E+03 0.2971775E+03 0.2966385E+03 + 0.2961002E+03 0.2955630E+03 0.2950264E+03 0.2944904E+03 0.2939549E+03 + 0.2934197E+03 0.2928851E+03 0.2923514E+03 0.2918179E+03 0.2912847E+03 + 0.2907519E+03 0.2902196E+03 0.2896882E+03 0.2891567E+03 0.2886256E+03 + 0.2880951E+03 0.2875647E+03 0.2870341E+03 0.2865043E+03 0.2859745E+03 + 0.2854452E+03 0.2849158E+03 0.2843865E+03 0.2838575E+03 0.2833277E+03 + 0.2827988E+03 0.2822700E+03 0.2817405E+03 0.2812114E+03 0.2806819E+03 + 0.2801522E+03 0.2796225E+03 0.2790925E+03 0.2785622E+03 0.2780318E+03 + 0.2775007E+03 0.2769696E+03 0.2764379E+03 0.2759055E+03 0.2753729E+03 + 0.2748393E+03 0.2743055E+03 0.2737708E+03 0.2732358E+03 0.2726994E+03 + 0.2721623E+03 0.2716245E+03 0.2710855E+03 0.2705460E+03 0.2700049E+03 + 0.2694627E+03 0.2689194E+03 0.2683751E+03 0.2678292E+03 0.2672820E+03 + 0.2667331E+03 0.2661830E+03 0.2656306E+03 0.2650768E+03 0.2645213E+03 + 0.2639634E+03 0.2634040E+03 0.2628425E+03 0.2622787E+03 0.2617124E+03 + 0.2611437E+03 0.2605720E+03 0.2599983E+03 0.2594216E+03 0.2588419E+03 + 0.2582596E+03 0.2576734E+03 0.2570842E+03 0.2564913E+03 0.2558949E+03 + 0.2552945E+03 0.2546901E+03 0.2540820E+03 0.2534687E+03 0.2528513E+03 + 0.2522289E+03 0.2516016E+03 0.2509692E+03 0.2503311E+03 0.2496874E+03 + 0.2490377E+03 0.2483819E+03 0.2477190E+03 0.2470497E+03 0.2463729E+03 + 0.2456890E+03 0.2449973E+03 0.2442971E+03 0.2435887E+03 0.2428711E+03 + 0.2421444E+03 0.2414080E+03 0.2406610E+03 0.2399039E+03 0.2391356E+03 + 0.8999999E+10 0.3237857E+03 0.3231994E+03 0.3226109E+03 0.3220236E+03 + 0.3214381E+03 0.3208542E+03 0.3202716E+03 0.3196906E+03 0.3191102E+03 + 0.3185320E+03 0.3179554E+03 0.3173794E+03 0.3168052E+03 0.3162325E+03 + 0.3156605E+03 0.3150904E+03 0.3145209E+03 0.3139529E+03 0.3133861E+03 + 0.3128206E+03 0.3122565E+03 0.3116935E+03 0.3111319E+03 0.3105708E+03 + 0.3100115E+03 0.3094526E+03 0.3088955E+03 0.3083392E+03 0.3077841E+03 + 0.3072302E+03 0.3066770E+03 0.3061249E+03 0.3055735E+03 0.3050235E+03 + 0.3044745E+03 0.3039267E+03 0.3033792E+03 0.3028329E+03 0.3022880E+03 + 0.3017431E+03 0.3011995E+03 0.3006567E+03 0.3001151E+03 0.2995738E+03 + 0.2990334E+03 0.2984940E+03 0.2979548E+03 0.2974172E+03 0.2968799E+03 + 0.2963434E+03 0.2958068E+03 0.2952715E+03 0.2947367E+03 0.2942032E+03 + 0.2936696E+03 0.2931364E+03 0.2926039E+03 0.2920719E+03 0.2915409E+03 + 0.2910099E+03 0.2904796E+03 0.2899493E+03 0.2894198E+03 0.2888906E+03 + 0.2883616E+03 0.2878332E+03 0.2873049E+03 0.2867766E+03 0.2862487E+03 + 0.2857211E+03 0.2851938E+03 0.2846667E+03 0.2841396E+03 0.2836129E+03 + 0.2830858E+03 0.2825588E+03 0.2820320E+03 0.2815049E+03 0.2809780E+03 + 0.2804512E+03 0.2799237E+03 0.2793964E+03 0.2788689E+03 0.2783406E+03 + 0.2778128E+03 0.2772842E+03 0.2767552E+03 0.2762260E+03 0.2756962E+03 + 0.2751658E+03 0.2746351E+03 0.2741036E+03 0.2735716E+03 0.2730390E+03 + 0.2725052E+03 0.2719709E+03 0.2714358E+03 0.2708995E+03 0.2703623E+03 + 0.2698243E+03 0.2692850E+03 0.2687446E+03 0.2682027E+03 0.2676599E+03 + 0.2671156E+03 0.2665698E+03 0.2660225E+03 0.2654737E+03 0.2649226E+03 + 0.2643703E+03 0.2638162E+03 0.2632598E+03 0.2627011E+03 0.2621407E+03 + 0.2615779E+03 0.2610129E+03 0.2604452E+03 0.2598749E+03 0.2593017E+03 + 0.2587260E+03 0.2581470E+03 0.2575647E+03 0.2569798E+03 0.2563909E+03 + 0.2557986E+03 0.2552029E+03 0.2546027E+03 0.2539985E+03 0.2533903E+03 + 0.2527774E+03 0.2521600E+03 0.2515376E+03 0.2509100E+03 0.2502775E+03 + 0.2496389E+03 0.2489945E+03 0.2483443E+03 0.2476872E+03 0.2470239E+03 + 0.2463536E+03 0.2456756E+03 0.2449905E+03 0.2442969E+03 0.2435954E+03 + 0.2428849E+03 0.2421654E+03 0.2414364E+03 0.2406974E+03 0.2399481E+03 + 0.8999999E+10 0.8999999E+10 0.3233897E+03 0.3228040E+03 0.3222179E+03 + 0.3216338E+03 0.3210503E+03 0.3204682E+03 0.3198882E+03 0.3193093E+03 + 0.3187312E+03 0.3181553E+03 0.3175802E+03 0.3170066E+03 0.3164343E+03 + 0.3158631E+03 0.3152934E+03 0.3147251E+03 0.3141585E+03 0.3135926E+03 + 0.3130279E+03 0.3124643E+03 0.3119025E+03 0.3113410E+03 0.3107811E+03 + 0.3102225E+03 0.3096650E+03 0.3091086E+03 0.3085531E+03 0.3079992E+03 + 0.3074461E+03 0.3068938E+03 0.3063430E+03 0.3057928E+03 0.3052437E+03 + 0.3046957E+03 0.3041487E+03 0.3036024E+03 0.3030576E+03 0.3025135E+03 + 0.3019702E+03 0.3014271E+03 0.3008857E+03 0.3003451E+03 0.2998052E+03 + 0.2992663E+03 0.2987280E+03 0.2981906E+03 0.2976534E+03 0.2971175E+03 + 0.2965822E+03 0.2960478E+03 0.2955135E+03 0.2949803E+03 0.2944477E+03 + 0.2939160E+03 0.2933844E+03 0.2928534E+03 0.2923228E+03 0.2917934E+03 + 0.2912639E+03 0.2907352E+03 0.2902066E+03 0.2896790E+03 0.2891515E+03 + 0.2886239E+03 0.2880973E+03 0.2875709E+03 0.2870447E+03 0.2865190E+03 + 0.2859935E+03 0.2854676E+03 0.2849423E+03 0.2844177E+03 0.2838929E+03 + 0.2833680E+03 0.2828434E+03 0.2823185E+03 0.2817939E+03 0.2812695E+03 + 0.2807444E+03 0.2802199E+03 0.2796946E+03 0.2791696E+03 0.2786444E+03 + 0.2781187E+03 0.2775929E+03 0.2770670E+03 0.2765404E+03 0.2760136E+03 + 0.2754865E+03 0.2749585E+03 0.2744300E+03 0.2739014E+03 0.2733717E+03 + 0.2728413E+03 0.2723105E+03 0.2717789E+03 0.2712459E+03 0.2707126E+03 + 0.2701783E+03 0.2696426E+03 0.2691061E+03 0.2685688E+03 0.2680297E+03 + 0.2674898E+03 0.2669482E+03 0.2664055E+03 0.2658610E+03 0.2653151E+03 + 0.2647676E+03 0.2642182E+03 0.2636667E+03 0.2631140E+03 0.2625584E+03 + 0.2620013E+03 0.2614420E+03 0.2608803E+03 0.2603159E+03 0.2597494E+03 + 0.2591798E+03 0.2586078E+03 0.2580328E+03 0.2574547E+03 0.2568734E+03 + 0.2562887E+03 0.2557005E+03 0.2551085E+03 0.2545127E+03 0.2539133E+03 + 0.2533094E+03 0.2527012E+03 0.2520885E+03 0.2514708E+03 0.2508484E+03 + 0.2502205E+03 0.2495875E+03 0.2489485E+03 0.2483036E+03 0.2476526E+03 + 0.2469949E+03 0.2463305E+03 0.2456588E+03 0.2449800E+03 0.2442931E+03 + 0.2435982E+03 0.2428949E+03 0.2421823E+03 0.2414605E+03 0.2407294E+03 + 0.8999999E+10 0.8999999E+10 0.8999999E+10 0.3230028E+03 0.3224122E+03 + 0.3218277E+03 0.3212447E+03 0.3206636E+03 0.3200836E+03 0.3195050E+03 + 0.3189283E+03 0.3183529E+03 0.3177787E+03 0.3172054E+03 0.3166344E+03 + 0.3160642E+03 0.3154950E+03 0.3149272E+03 0.3143609E+03 0.3137963E+03 + 0.3132323E+03 0.3126699E+03 0.3121087E+03 0.3115485E+03 0.3109892E+03 + 0.3104314E+03 0.3098745E+03 0.3093192E+03 0.3087646E+03 0.3082115E+03 + 0.3076593E+03 0.3071082E+03 0.3065584E+03 0.3060093E+03 0.3054613E+03 + 0.3049145E+03 0.3043682E+03 0.3038229E+03 0.3032789E+03 0.3027357E+03 + 0.3021938E+03 0.3016526E+03 0.3011121E+03 0.3005720E+03 0.3000333E+03 + 0.2994954E+03 0.2989587E+03 0.2984222E+03 0.2978870E+03 0.2973521E+03 + 0.2968178E+03 0.2962849E+03 0.2957524E+03 0.2952206E+03 0.2946889E+03 + 0.2941585E+03 0.2936282E+03 0.2930994E+03 0.2925704E+03 0.2920423E+03 + 0.2915141E+03 0.2909870E+03 0.2904604E+03 0.2899343E+03 0.2894084E+03 + 0.2888829E+03 0.2883580E+03 0.2878331E+03 0.2873086E+03 0.2867843E+03 + 0.2862611E+03 0.2857375E+03 0.2852144E+03 0.2846913E+03 0.2841681E+03 + 0.2836456E+03 0.2831229E+03 0.2826006E+03 0.2820778E+03 0.2815556E+03 + 0.2810333E+03 0.2805105E+03 0.2799879E+03 0.2794655E+03 0.2789425E+03 + 0.2784196E+03 0.2778965E+03 0.2773729E+03 0.2768492E+03 0.2763250E+03 + 0.2758006E+03 0.2752756E+03 0.2747506E+03 0.2742243E+03 0.2736980E+03 + 0.2731712E+03 0.2726433E+03 0.2721147E+03 0.2715858E+03 0.2710557E+03 + 0.2705247E+03 0.2699934E+03 0.2694605E+03 0.2689266E+03 0.2683918E+03 + 0.2678558E+03 0.2673187E+03 0.2667798E+03 0.2662396E+03 0.2656986E+03 + 0.2651553E+03 0.2646107E+03 0.2640648E+03 0.2635168E+03 0.2629666E+03 + 0.2624149E+03 0.2618612E+03 0.2613049E+03 0.2607465E+03 0.2601858E+03 + 0.2596227E+03 0.2590568E+03 0.2584883E+03 0.2579167E+03 0.2573423E+03 + 0.2567653E+03 0.2561843E+03 0.2556001E+03 0.2550124E+03 0.2544214E+03 + 0.2538258E+03 0.2532262E+03 0.2526227E+03 0.2520145E+03 0.2514017E+03 + 0.2507840E+03 0.2501615E+03 0.2495332E+03 0.2488999E+03 0.2482601E+03 + 0.2476148E+03 0.2469631E+03 0.2463042E+03 0.2456385E+03 0.2449661E+03 + 0.2442856E+03 0.2435974E+03 0.2429006E+03 0.2421952E+03 0.2414808E+03 + 0.8999999E+10 0.8999999E+10 0.8999999E+10 0.8999999E+10 0.3226006E+03 + 0.3220179E+03 0.3214376E+03 0.3208557E+03 0.3202767E+03 0.3196991E+03 + 0.3191229E+03 0.3185481E+03 0.3179749E+03 0.3174029E+03 0.3168318E+03 + 0.3162621E+03 0.3156940E+03 0.3151273E+03 0.3145618E+03 0.3139975E+03 + 0.3134343E+03 0.3128728E+03 0.3123120E+03 0.3117529E+03 0.3111947E+03 + 0.3106381E+03 0.3100822E+03 0.3095270E+03 0.3089738E+03 0.3084216E+03 + 0.3078701E+03 0.3073200E+03 0.3067706E+03 0.3062231E+03 0.3056758E+03 + 0.3051302E+03 0.3045849E+03 0.3040409E+03 0.3034977E+03 0.3029555E+03 + 0.3024144E+03 0.3018744E+03 0.3013350E+03 0.3007968E+03 0.3002589E+03 + 0.2997223E+03 0.2991865E+03 0.2986513E+03 0.2981169E+03 0.2975835E+03 + 0.2970509E+03 0.2965189E+03 0.2959874E+03 0.2954569E+03 0.2949273E+03 + 0.2943982E+03 0.2938691E+03 0.2933411E+03 0.2928138E+03 0.2922874E+03 + 0.2917611E+03 0.2912354E+03 0.2907102E+03 0.2901853E+03 0.2896611E+03 + 0.2891372E+03 0.2886144E+03 0.2880912E+03 0.2875688E+03 0.2870462E+03 + 0.2865241E+03 0.2860025E+03 0.2854813E+03 0.2849604E+03 0.2844395E+03 + 0.2839189E+03 0.2833982E+03 0.2828773E+03 0.2823575E+03 0.2818372E+03 + 0.2813168E+03 0.2807967E+03 0.2802765E+03 0.2797560E+03 0.2792357E+03 + 0.2787154E+03 0.2781944E+03 0.2776737E+03 0.2771523E+03 0.2766307E+03 + 0.2761093E+03 0.2755871E+03 0.2750645E+03 0.2745415E+03 0.2740181E+03 + 0.2734941E+03 0.2729694E+03 0.2724445E+03 0.2719185E+03 0.2713918E+03 + 0.2708646E+03 0.2703363E+03 0.2698069E+03 0.2692770E+03 0.2687460E+03 + 0.2682139E+03 0.2676806E+03 0.2671465E+03 0.2666106E+03 0.2660732E+03 + 0.2655347E+03 0.2649950E+03 0.2644532E+03 0.2639097E+03 0.2633649E+03 + 0.2628183E+03 0.2622693E+03 0.2617185E+03 0.2611659E+03 0.2606109E+03 + 0.2600537E+03 0.2594940E+03 0.2589317E+03 0.2583670E+03 0.2577991E+03 + 0.2572287E+03 0.2566551E+03 0.2560782E+03 0.2554980E+03 0.2549141E+03 + 0.2543269E+03 0.2537360E+03 0.2531409E+03 0.2525417E+03 0.2519383E+03 + 0.2513298E+03 0.2507173E+03 0.2500993E+03 0.2494767E+03 0.2488478E+03 + 0.2482139E+03 0.2475738E+03 0.2469276E+03 0.2462746E+03 0.2456152E+03 + 0.2449487E+03 0.2442744E+03 0.2435925E+03 0.2429027E+03 0.2422042E+03 + 0.8999999E+10 0.8999999E+10 0.8999999E+10 0.8999999E+10 0.8999999E+10 + 0.3222098E+03 0.3216255E+03 0.3210467E+03 0.3204680E+03 0.3198916E+03 + 0.3193160E+03 0.3187419E+03 0.3181684E+03 0.3175975E+03 0.3170271E+03 + 0.3164586E+03 0.3158910E+03 0.3153254E+03 0.3147602E+03 0.3141969E+03 + 0.3136345E+03 0.3130734E+03 0.3125137E+03 0.3119552E+03 0.3113979E+03 + 0.3108418E+03 0.3102867E+03 0.3097330E+03 0.3091802E+03 0.3086289E+03 + 0.3080784E+03 0.3075292E+03 0.3069812E+03 0.3064339E+03 0.3058876E+03 + 0.3053432E+03 0.3047990E+03 0.3042560E+03 0.3037139E+03 0.3031725E+03 + 0.3026324E+03 0.3020932E+03 0.3015551E+03 0.3010179E+03 0.3004817E+03 + 0.2999460E+03 0.2994110E+03 0.2988772E+03 0.2983440E+03 0.2978121E+03 + 0.2972803E+03 0.2967499E+03 0.2962194E+03 0.2956901E+03 0.2951619E+03 + 0.2946341E+03 0.2941069E+03 0.2935804E+03 0.2930541E+03 0.2925289E+03 + 0.2920042E+03 0.2914802E+03 0.2909564E+03 0.2904332E+03 0.2899105E+03 + 0.2893884E+03 0.2888665E+03 0.2883455E+03 0.2878247E+03 0.2873041E+03 + 0.2867840E+03 0.2862639E+03 0.2857441E+03 0.2852249E+03 0.2847059E+03 + 0.2841876E+03 0.2836688E+03 0.2831507E+03 0.2826320E+03 0.2821139E+03 + 0.2815959E+03 0.2810776E+03 0.2805594E+03 0.2800417E+03 0.2795236E+03 + 0.2790051E+03 0.2784874E+03 0.2779686E+03 0.2774499E+03 0.2769313E+03 + 0.2764122E+03 0.2758926E+03 0.2753730E+03 0.2748528E+03 0.2743322E+03 + 0.2738112E+03 0.2732897E+03 0.2727676E+03 0.2722447E+03 0.2717218E+03 + 0.2711973E+03 0.2706725E+03 0.2701471E+03 0.2696204E+03 0.2690927E+03 + 0.2685646E+03 0.2680352E+03 0.2675049E+03 0.2669727E+03 0.2664397E+03 + 0.2659059E+03 0.2653701E+03 0.2648329E+03 0.2642942E+03 0.2637541E+03 + 0.2632123E+03 0.2626685E+03 0.2621228E+03 0.2615754E+03 0.2610259E+03 + 0.2604742E+03 0.2599202E+03 0.2593639E+03 0.2588051E+03 0.2582438E+03 + 0.2576797E+03 0.2571129E+03 0.2565429E+03 0.2559700E+03 0.2553937E+03 + 0.2548140E+03 0.2542309E+03 0.2536441E+03 0.2530535E+03 0.2524585E+03 + 0.2518596E+03 0.2512561E+03 0.2506479E+03 0.2500353E+03 0.2494167E+03 + 0.2487936E+03 0.2481647E+03 0.2475300E+03 0.2468892E+03 0.2462420E+03 + 0.2455885E+03 0.2449279E+03 0.2442599E+03 0.2435844E+03 0.2429011E+03 + 0.8999999E+10 0.8999999E+10 0.8999999E+10 0.8999999E+10 0.8999999E+10 + 0.3223920E+03 0.3218184E+03 0.3212359E+03 0.3206581E+03 0.3200815E+03 + 0.3195058E+03 0.3189323E+03 0.3183611E+03 0.3177897E+03 0.3172209E+03 + 0.3166523E+03 0.3160858E+03 0.3155206E+03 0.3149567E+03 0.3143935E+03 + 0.3138326E+03 0.3132721E+03 0.3127131E+03 0.3121553E+03 0.3115984E+03 + 0.3110437E+03 0.3104893E+03 0.3099363E+03 0.3093847E+03 0.3088338E+03 + 0.3082841E+03 0.3077359E+03 0.3071886E+03 0.3066425E+03 0.3060970E+03 + 0.3055532E+03 0.3050099E+03 0.3044685E+03 0.3039274E+03 0.3033873E+03 + 0.3028481E+03 0.3023096E+03 0.3017724E+03 0.3012364E+03 0.3007011E+03 + 0.3001665E+03 0.2996330E+03 0.2991002E+03 0.2985684E+03 0.2980371E+03 + 0.2975068E+03 0.2969777E+03 0.2964486E+03 0.2959206E+03 0.2953932E+03 + 0.2948666E+03 0.2943412E+03 0.2938159E+03 0.2932915E+03 0.2927674E+03 + 0.2922436E+03 0.2917210E+03 0.2911990E+03 0.2906777E+03 0.2901565E+03 + 0.2896359E+03 0.2891154E+03 0.2885959E+03 0.2880764E+03 0.2875577E+03 + 0.2870395E+03 0.2865211E+03 0.2860036E+03 0.2854859E+03 0.2849688E+03 + 0.2844519E+03 0.2839352E+03 0.2834187E+03 0.2829025E+03 0.2823863E+03 + 0.2818700E+03 0.2813543E+03 0.2808386E+03 0.2803225E+03 0.2798068E+03 + 0.2792908E+03 0.2787749E+03 0.2782591E+03 0.2777428E+03 0.2772259E+03 + 0.2767097E+03 0.2761928E+03 0.2756756E+03 0.2751584E+03 0.2746409E+03 + 0.2741223E+03 0.2736036E+03 0.2730847E+03 0.2725649E+03 0.2720446E+03 + 0.2715237E+03 0.2710022E+03 0.2704799E+03 0.2699566E+03 0.2694329E+03 + 0.2689081E+03 0.2683822E+03 0.2678554E+03 0.2673278E+03 0.2667988E+03 + 0.2662684E+03 0.2657370E+03 0.2652043E+03 0.2646701E+03 0.2641343E+03 + 0.2635968E+03 0.2630582E+03 0.2625177E+03 0.2619752E+03 0.2614311E+03 + 0.2608845E+03 0.2603360E+03 0.2597857E+03 0.2592325E+03 0.2586771E+03 + 0.2581192E+03 0.2575585E+03 0.2569956E+03 0.2564294E+03 0.2558603E+03 + 0.2552879E+03 0.2547122E+03 0.2541329E+03 0.2535500E+03 0.2529638E+03 + 0.2523733E+03 0.2517785E+03 0.2511796E+03 0.2505762E+03 0.2499677E+03 + 0.2493548E+03 0.2487364E+03 0.2481127E+03 0.2474834E+03 0.2468478E+03 + 0.2462065E+03 0.2455585E+03 0.2449039E+03 0.2442420E+03 0.2435727E+03 + 0.8999999E+10 0.8999999E+10 0.8999999E+10 0.8999999E+10 0.8999999E+10 + 0.8999999E+10 0.3219957E+03 0.3214211E+03 0.3208443E+03 0.3202687E+03 + 0.3196947E+03 0.3191218E+03 0.3185506E+03 0.3179805E+03 0.3174117E+03 + 0.3168443E+03 0.3162787E+03 0.3157137E+03 0.3151507E+03 0.3145882E+03 + 0.3140279E+03 0.3134680E+03 0.3129100E+03 0.3123530E+03 0.3117970E+03 + 0.3112428E+03 0.3106894E+03 0.3101374E+03 0.3095866E+03 0.3090367E+03 + 0.3084883E+03 0.3079402E+03 0.3073940E+03 0.3068483E+03 0.3063043E+03 + 0.3057611E+03 0.3052188E+03 0.3046780E+03 0.3041378E+03 0.3035990E+03 + 0.3030611E+03 0.3025239E+03 0.3019873E+03 0.3014520E+03 0.3009177E+03 + 0.3003843E+03 0.2998524E+03 0.2993205E+03 0.2987896E+03 0.2982596E+03 + 0.2977302E+03 0.2972022E+03 0.2966748E+03 0.2961481E+03 0.2956219E+03 + 0.2950964E+03 0.2945718E+03 0.2940479E+03 0.2935250E+03 0.2930023E+03 + 0.2924807E+03 0.2919591E+03 0.2914380E+03 0.2909180E+03 0.2903985E+03 + 0.2898795E+03 0.2893608E+03 0.2888427E+03 0.2883250E+03 0.2878075E+03 + 0.2872910E+03 0.2867743E+03 0.2862586E+03 0.2857429E+03 0.2852274E+03 + 0.2847122E+03 0.2841974E+03 0.2836828E+03 0.2831684E+03 0.2826542E+03 + 0.2821405E+03 0.2816261E+03 0.2811125E+03 0.2805988E+03 0.2800851E+03 + 0.2795711E+03 0.2790578E+03 0.2785440E+03 0.2780298E+03 0.2775163E+03 + 0.2770021E+03 0.2764874E+03 0.2759734E+03 0.2754585E+03 0.2749431E+03 + 0.2744278E+03 0.2739119E+03 0.2733956E+03 0.2728787E+03 0.2723618E+03 + 0.2718438E+03 0.2713252E+03 0.2708062E+03 0.2702864E+03 0.2697661E+03 + 0.2692446E+03 0.2687223E+03 0.2681992E+03 0.2676752E+03 0.2671496E+03 + 0.2666234E+03 0.2660962E+03 0.2655674E+03 0.2650373E+03 0.2645060E+03 + 0.2639732E+03 0.2634391E+03 0.2629030E+03 0.2623654E+03 0.2618262E+03 + 0.2612849E+03 0.2607416E+03 0.2601963E+03 0.2596490E+03 0.2590991E+03 + 0.2585475E+03 0.2579931E+03 0.2574361E+03 0.2568767E+03 0.2563139E+03 + 0.2557484E+03 0.2551798E+03 0.2546082E+03 0.2540330E+03 0.2534542E+03 + 0.2528719E+03 0.2522857E+03 0.2516955E+03 0.2511006E+03 0.2505020E+03 + 0.2498985E+03 0.2492900E+03 0.2486766E+03 0.2480581E+03 0.2474336E+03 + 0.2468038E+03 0.2461678E+03 0.2455257E+03 0.2448767E+03 0.2442207E+03 + 0.8999999E+10 0.8999999E+10 0.8999999E+10 0.8999999E+10 0.8999999E+10 + 0.8999999E+10 0.8999999E+10 0.3216098E+03 0.3210316E+03 0.3204551E+03 + 0.3198815E+03 0.3193090E+03 0.3187384E+03 0.3181698E+03 0.3176014E+03 + 0.3170342E+03 0.3164689E+03 0.3159052E+03 0.3153423E+03 0.3147809E+03 + 0.3142211E+03 0.3136623E+03 0.3131050E+03 0.3125486E+03 0.3119938E+03 + 0.3114399E+03 0.3108871E+03 0.3103359E+03 0.3097860E+03 0.3092370E+03 + 0.3086890E+03 0.3081424E+03 0.3075968E+03 0.3070524E+03 0.3065092E+03 + 0.3059666E+03 0.3054252E+03 0.3048851E+03 0.3043462E+03 0.3038076E+03 + 0.3032712E+03 0.3027348E+03 0.3021996E+03 0.3016654E+03 0.3011318E+03 + 0.3005995E+03 0.3000680E+03 0.2995380E+03 0.2990082E+03 0.2984794E+03 + 0.2979513E+03 0.2974238E+03 0.2968976E+03 0.2963721E+03 0.2958473E+03 + 0.2953235E+03 0.2947998E+03 0.2942771E+03 0.2937551E+03 0.2932341E+03 + 0.2927137E+03 0.2921937E+03 0.2916741E+03 0.2911553E+03 0.2906373E+03 + 0.2901192E+03 0.2896024E+03 0.2890860E+03 0.2885699E+03 0.2880543E+03 + 0.2875389E+03 0.2870239E+03 0.2865094E+03 0.2859953E+03 0.2854819E+03 + 0.2849686E+03 0.2844557E+03 0.2839431E+03 0.2834303E+03 0.2829178E+03 + 0.2824058E+03 0.2818940E+03 0.2813818E+03 0.2808704E+03 0.2803591E+03 + 0.2798475E+03 0.2793358E+03 0.2788243E+03 0.2783129E+03 0.2778011E+03 + 0.2772891E+03 0.2767775E+03 0.2762652E+03 0.2757530E+03 0.2752407E+03 + 0.2747277E+03 0.2742143E+03 0.2737008E+03 0.2731870E+03 0.2726726E+03 + 0.2721575E+03 0.2716425E+03 0.2711263E+03 0.2706094E+03 0.2700920E+03 + 0.2695742E+03 0.2690556E+03 0.2685357E+03 0.2680150E+03 0.2674936E+03 + 0.2669713E+03 0.2664474E+03 0.2659225E+03 0.2653969E+03 0.2648696E+03 + 0.2643409E+03 0.2638110E+03 0.2632797E+03 0.2627468E+03 0.2622119E+03 + 0.2616756E+03 0.2611375E+03 0.2605975E+03 0.2600553E+03 0.2595112E+03 + 0.2589649E+03 0.2584164E+03 0.2578654E+03 0.2573119E+03 0.2567557E+03 + 0.2561970E+03 0.2556352E+03 0.2550704E+03 0.2545025E+03 0.2539311E+03 + 0.2533563E+03 0.2527778E+03 0.2521961E+03 0.2516101E+03 0.2510200E+03 + 0.2504253E+03 0.2498265E+03 0.2492232E+03 0.2486143E+03 0.2480006E+03 + 0.2473815E+03 0.2467567E+03 0.2461262E+03 0.2454895E+03 0.2448461E+03 + 0.9601257E+03 0.8999999E+10 0.8999999E+10 0.8999999E+10 0.8999999E+10 + 0.8999999E+10 0.8999999E+10 0.3217826E+03 0.3212120E+03 0.3206398E+03 + 0.3200671E+03 0.3194944E+03 0.3189249E+03 0.3183556E+03 0.3177885E+03 + 0.3172225E+03 0.3166573E+03 0.3160941E+03 0.3155325E+03 0.3149719E+03 + 0.3144120E+03 0.3138543E+03 0.3132976E+03 0.3127422E+03 0.3121874E+03 + 0.3116346E+03 0.3110828E+03 0.3105323E+03 0.3099831E+03 0.3094348E+03 + 0.3088878E+03 0.3083420E+03 0.3077973E+03 0.3072536E+03 0.3067110E+03 + 0.3061696E+03 0.3056293E+03 0.3050899E+03 0.3045518E+03 0.3040143E+03 + 0.3034784E+03 0.3029431E+03 0.3024090E+03 0.3018759E+03 0.3013437E+03 + 0.3008123E+03 0.3002818E+03 0.2997523E+03 0.2992235E+03 0.2986957E+03 + 0.2981691E+03 0.2976432E+03 0.2971177E+03 0.2965934E+03 0.2960695E+03 + 0.2955470E+03 0.2950248E+03 0.2945035E+03 0.2939828E+03 0.2934625E+03 + 0.2929433E+03 0.2924248E+03 0.2919068E+03 0.2913894E+03 0.2908727E+03 + 0.2903564E+03 0.2898404E+03 0.2893255E+03 0.2888107E+03 0.2882969E+03 + 0.2877831E+03 0.2872701E+03 0.2867572E+03 0.2862443E+03 0.2857328E+03 + 0.2852211E+03 0.2847098E+03 0.2841987E+03 0.2836882E+03 0.2831778E+03 + 0.2826672E+03 0.2821569E+03 0.2816476E+03 0.2811378E+03 0.2806280E+03 + 0.2801187E+03 0.2796093E+03 0.2790996E+03 0.2785904E+03 0.2780812E+03 + 0.2775717E+03 0.2770617E+03 0.2765526E+03 0.2760425E+03 0.2755322E+03 + 0.2750219E+03 0.2745116E+03 0.2740007E+03 0.2734893E+03 0.2729778E+03 + 0.2724658E+03 0.2719531E+03 0.2714400E+03 0.2709267E+03 0.2704124E+03 + 0.2698973E+03 0.2693819E+03 0.2688656E+03 0.2683485E+03 0.2678302E+03 + 0.2673114E+03 0.2667914E+03 0.2662707E+03 0.2657482E+03 0.2652249E+03 + 0.2647006E+03 0.2641750E+03 0.2636478E+03 0.2631192E+03 0.2625889E+03 + 0.2620574E+03 0.2615239E+03 0.2609890E+03 0.2604521E+03 0.2599131E+03 + 0.2593724E+03 0.2588292E+03 0.2582837E+03 0.2577361E+03 0.2571862E+03 + 0.2566334E+03 0.2560779E+03 0.2555198E+03 0.2549586E+03 0.2543944E+03 + 0.2538272E+03 0.2532566E+03 0.2526821E+03 0.2521042E+03 0.2515225E+03 + 0.2509366E+03 0.2503468E+03 0.2497522E+03 0.2491533E+03 0.2485495E+03 + 0.2479407E+03 0.2473265E+03 0.2467070E+03 0.2460818E+03 0.2454503E+03 diff --git a/src/wrf/dbz.py b/src/wrf/dbz.py index bb9f64d..dd30da4 100755 --- a/src/wrf/dbz.py +++ b/src/wrf/dbz.py @@ -1,10 +1,10 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) -import numpy as n +import numpy as np #from .extension import computedbz,computetk -from .extension import computedbz, _tk +from .extension import _dbz, _tk from .constants import Constants from .util import extract_vars from .metadecorators import copy_and_set_metadata @@ -39,7 +39,7 @@ def get_dbz(wrfnc, timeidx=0, method="cat", snowvars = extract_vars(wrfnc, timeidx, "QSNOW", method, squeeze, cache, meta=False) except KeyError: - qs = n.zeros(qv.shape, "float") + qs = np.zeros(qv.shape, qv.dtype) else: qs = snowvars["QSNOW"] @@ -47,28 +47,20 @@ def get_dbz(wrfnc, timeidx=0, method="cat", graupvars = extract_vars(wrfnc, timeidx, "QGRAUP", method, squeeze, cache, meta=False) except KeyError: - qg = n.zeros(qv.shape, "float") + qg = np.zeros(qv.shape, qv.dtype) else: qg = graupvars["QGRAUP"] - # If qsnow is all 0, set sn0 to 1 - sn0 = 0 - if (n.any(qs != 0)): - sn0 = 1 - full_t = t + Constants.T_BASE full_p = p + pb tk = _tk(full_p, full_t) - ivarint = 0 - if do_varint: - ivarint = 1 - - iliqskin = 0 - if do_liqskin: - iliqskin = 1 + # If qsnow is not all 0, set sn0 to 1 + sn0 = 1 if qs.any() else 0 + ivarint = 1 if do_varint else 0 + iliqskin = 1 if do_liqskin else 0 - return computedbz(full_p,tk,qv,qr,qs,qg,sn0,ivarint,iliqskin) + return _dbz(full_p, tk, qv, qr, qs, qg, sn0, ivarint, iliqskin) @copy_and_set_metadata(copy_varname="T", name="max_dbz", @@ -79,8 +71,7 @@ def get_dbz(wrfnc, timeidx=0, method="cat", def get_max_dbz(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, meta=True, do_varint=False, do_liqskin=False): - return n.amax(get_dbz(wrfnc, timeidx, method, - squeeze, cache, meta, - do_varint, do_liqskin), + return np.amax(get_dbz(wrfnc, timeidx, method, squeeze, cache, meta, + do_varint, do_liqskin), axis=-3) diff --git a/src/wrf/decorators.py b/src/wrf/decorators.py index 56d3723..bde6102 100644 --- a/src/wrf/decorators.py +++ b/src/wrf/decorators.py @@ -8,8 +8,8 @@ import numpy as np import numpy.ma as ma from .units import do_conversion, check_units -from .util import (iter_left_indexes, viewitems, viewvalues, from_args, - npvalues, py3range, combine_dims, isstr) +from .util import iter_left_indexes, from_args, npvalues, combine_dims +from .py3compat import viewitems, viewvalues, py3range, isstr from .config import xarray_enabled from .constants import Constants @@ -351,38 +351,6 @@ def left_iter_nocopy(ref_var_expected_dims, return func_wrapper -# Only flip the input arguments, but flip the result -def flip_vertical(argidxs=None, argkeys=None, flip_result=True): - @wrapt.decorator - def func_wrapper(wrapped, instance, args, kwargs): - - _argidxs = argidxs if argidxs is not None else () - _argkeys = argkeys if argkeys is not None else () - - # Slice the args if applicable - new_args = [np.ascontiguousarray(arg[...,::-1,:,:]) - if i in _argidxs else arg - for i,arg in enumerate(args)] - - # Slice the kwargs if applicable - new_kargs = {key:np.ascontiguousarray(kwarg[...,::-1,:,:]) - if key in _argkeys else kwarg - for key,kwarg in viewitems(kwargs)} - - - result = wrapped(*args, **kwargs) - - if flip_result: - if isinstance(result, np.ndarray): - return np.ascontiguousarray(result[...,::-1,:,:]) - else: - # Sequence - return [np.ascontiguousarray(arr[...,::-1,:,:]) - for arr in result] - - return result - - return func_wrapper def handle_casting(ref_idx=0, arg_idxs=None, karg_names=None, alg_dtype=np.float64, @@ -397,7 +365,7 @@ def handle_casting(ref_idx=0, arg_idxs=None, karg_names=None, _karg_names = karg_names if karg_names is not None else () # Handle output views if applicable - _outkeys = [outviews] if isstr(outviews) else _outviews + _outkeys = [outviews] if isstr(outviews) else outviews _outviews = from_args(wrapped, _outkeys, *args, **kwargs) has_outview = False @@ -425,7 +393,7 @@ def handle_casting(ref_idx=0, arg_idxs=None, karg_names=None, if result.dtype == orig_type: return result return result.astype(orig_type) - else: # got back a sequence of arrays + elif isinstance(result, Iterable): # got back a sequence of arrays return tuple(arr.astype(orig_type) if arr.dtype != orig_type else arr for arr in result) @@ -458,7 +426,7 @@ def handle_extract_transpose(do_transpose=True, outviews="outview"): def func_wrapper(wrapped, instance, args, kwargs): # Handle output views if applicable - _outkeys = [outviews] if isstr(outviews) else _outviews + _outkeys = [outviews] if isstr(outviews) else outviews _outviews = from_args(wrapped, _outkeys, *args, **kwargs) has_outview = False @@ -490,13 +458,37 @@ def handle_extract_transpose(do_transpose=True, outviews="outview"): return func_wrapper -def check_args(refvaridx, refvarndim, rightdims): +def check_args(refvaridx, refvarndim, rightdims, stagger=None, + refstagdim=None): + """ + + refvaridx - reference variable to check for presence of left dimensions + refvarndim - the number of dimensions for the references variable + expected by the fortran routine + rightdims - the expected number of right dimensions for each argument + stagger - the dimension which is staggered for each argument. Use + None to indicate no staggering. + refstagdim - If the reference variable is staggered, indicate the dim that + is staggered + """ @wrapt.decorator def func_wrapper(wrapped, instance, args, kwargs): refvar = args[refvaridx] extra_dims = refvar.ndim - refvarndim - ref_right_sizes = refvar.shape[extra_dims:] + + # Always use unstaggered as the basis of comparison + if refstagdim is not None: + _refshape = list(refvar.shape) + _refshape[refstagdim] -= 1 + _refshape = tuple(_refshape) + else: + _refshape = refvar.shape + + if stagger is None: + _stagger = [None]*len(rightdims) + else: + _stagger = stagger for i,ndim in enumerate(rightdims): if ndim is None: @@ -513,9 +505,20 @@ def check_args(refvaridx, refvarndim, rightdims): var.ndim, right_var_ndims + extra_dims)) + # Add 1 to the reference staggered dim index before doing the check + if _stagger[i] is not None: + ref_shape = list(_refshape) + ref_shape[_stagger[i]] += 1 + ref_shape = tuple(ref_shape) + else: + ref_shape = _refshape + + ref_right_sizes = ref_shape[extra_dims:] + # Check that right dimensions are lined up if (var.shape[-right_var_ndims:] != ref_right_sizes[-right_var_ndims:]): + raise ValueError("invalid shape for argument " "{} (got {}, expected {})".format(i, var.shape[-right_var_ndims:], @@ -524,6 +527,8 @@ def check_args(refvaridx, refvarndim, rightdims): return wrapped(*args, **kwargs) return func_wrapper + + diff --git a/src/wrf/extension.py b/src/wrf/extension.py index cbdd0c5..03e6858 100755 --- a/src/wrf/extension.py +++ b/src/wrf/extension.py @@ -4,30 +4,36 @@ from __future__ import (absolute_import, division, print_function, import numpy as np from .constants import Constants -from .psadlookup import get_lookup_tables +#from .psadlookup import get_lookup_tables # Old way -from ._wrfext import (f_interpz3d, f_interp2dxy,f_interp1d, - f_computeslp, f_computetk, f_computetd, f_computerh, - f_computeabsvort,f_computepvo, f_computeeth, - f_computeuvmet, - f_computeomega, f_computetv, f_computewetbulb, - f_computesrh, f_computeuh, f_computepw, f_computedbz, - f_lltoij, f_ijtoll, f_converteta, f_computectt, - f_monotonic, f_filter2d, f_vintrp) -from ._wrfcape import f_computecape +#from ._wrfext import (f_interpz3d, f_interp2dxy,f_interp1d, +# f_computeslp, f_computetk, f_computetd, f_computerh, +# f_computeabsvort,f_computepvo, f_computeeth, +# f_computeuvmet, +# f_computeomega, f_computetv, f_computewetbulb, +# f_computesrh, f_computeuh, f_computepw, f_computedbz, +# f_lltoij, f_ijtoll, f_converteta, f_computectt, +# f_monotonic, f_filter2d, f_vintrp) +#from ._wrfcape import f_computecape # New way from ._wrffortran import (dcomputetk, dinterp3dz, dinterp2dxy, dinterp1d, dcomputeseaprs, dfilter2d, dcomputerh, dcomputeuvmet, - dcomputetd) + dcomputetd, dcapecalc3d, dcloudfrac, wrfcttcalc, + calcdbz, dcalrelhl, dcalcuh, dcomputepv, + dcomputeabsvort, dlltoij, dijtoll, deqthecalc, + omgcalc, virtual_temp, wetbulbcalc, dcomputepw, + wrf_monotonic, wrf_vintrp) from .decorators import (handle_left_iter, handle_casting, handle_extract_transpose) from .decorators import (left_iter_nocopy, check_args) -from .util import py3range, combine_dims, _npbytes_to_str -from .uvdecorator import uvmet_left_iter_nocopy +from .util import combine_dims, npbytes_to_str, psafilepath +from .py3compat import py3range +from .specialdec import (uvmet_left_iter_nocopy, cape_left_iter, + cloudfrac_left_iter) -__all__ = [] +#__all__ = [] # __all__ += ["FortranException", "computeslp", "computetk", "computetd", # "computerh", "computeavo", "computepvo", "computeeth", # "computeuvmet","computeomega", "computetv", "computesrh", @@ -37,7 +43,13 @@ __all__ = [] # "computevertcross"] # __all__ += ["", ""] -class FortranException(Exception): +class FortranError(Exception): + def __init__(self, message=None): + self._msg = message + + def __str__(self): + return self._msg + def __call__(self, message): raise self.__class__(message) @@ -233,7 +245,7 @@ def _slp(z, t, p, q, outview=None): errmsg=errmsg) if int(errstat) != 0: - raise RuntimeError("".join(_npbytes_to_str(errmsg)).strip()) + raise FortranError("".join(npbytes_to_str(errmsg)).strip()) return result @@ -321,47 +333,113 @@ def _rh(qv, q, t, outview=None): return result -@handle_left_iter(3,0, ignore_args=(6,7)) +#@handle_left_iter(3,0, ignore_args=(6,7)) +#@handle_casting(arg_idxs=(0,1,2,3,4,5)) +#@handle_extract_transpose() +#def computeavo(u, v, msfu, msfv, msfm, cor, dx, dy): +# result = f_computeabsvort(u, +# v, +# msfu, +# msfv, +# msfm, +# cor, +# dx, +# dy) +# +# return result + +# Note: combining the -3 and -2 dimensions from u, then the -1 dimension +# from v +@check_args(0, 3, (3,3,2,2,2,2), stagger=(-1,-2,-1,-2,None,None), + refstagdim=-1) +@left_iter_nocopy(3, combine_dims([(0, (-3,-2)), + (1, (-1,))]), + ref_var_idx=0, ignore_args=(6,7)) @handle_casting(arg_idxs=(0,1,2,3,4,5)) @handle_extract_transpose() -def computeavo(u, v, msfu, msfv, msfm, cor, dx, dy): - result = f_computeabsvort(u, - v, - msfu, - msfv, - msfm, - cor, - dx, - dy) +def _avo(u, v, msfu, msfv, msfm, cor, dx, dy, outview=None): + if outview is None: + outshape = (v.shape[0],) + u.shape[1:] + outview = np.empty(outshape, np.float64, order="F") + + result = dcomputeabsvort(outview, + u, + v, + msfu, + msfv, + msfm, + cor, + dx, + dy) return result -@handle_left_iter(3,2, ignore_args=(8,9)) +#@handle_left_iter(3,2, ignore_args=(8,9)) +#@handle_casting(arg_idxs=(0,1,2,3,4,5,6,7)) +#@handle_extract_transpose() +#def computepvo(u, v, theta, prs, msfu, msfv, msfm, cor, dx, dy): +# +# result = f_computepvo(u, +# v, +# theta, +# prs, +# msfu, +# msfv, +# msfm, +# cor, +# dx, +# dy) +# +# return result + +@check_args(0, 3, (3,3,3,3,2,2,2,2), stagger=(-1,-2,None,None,-1,-2,None, + None), + refstagdim=-1) +@left_iter_nocopy(3, 3, ref_var_idx=2, ignore_args=(8,9)) @handle_casting(arg_idxs=(0,1,2,3,4,5,6,7)) @handle_extract_transpose() -def computepvo(u, v, theta, prs, msfu, msfv, msfm, cor, dx, dy): - - result = f_computepvo(u, - v, - theta, - prs, - msfu, - msfv, - msfm, - cor, - dx, - dy) +def _pvo(u, v, theta, prs, msfu, msfv, msfm, cor, dx, dy, outview=None): + if outview is None: + outview = np.empty_like(prs) + + result = dcomputepv(outview, + u, + v, + theta, + prs, + msfu, + msfv, + msfm, + cor, + dx, + dy) return result -@handle_left_iter(3,0) +#@handle_left_iter(3,0) +#@handle_casting(arg_idxs=(0,1,2)) +#@handle_extract_transpose() +#def computeeth(qv, tk, p): +# +# result = f_computeeth(qv, +# tk, +# p) +# +# return result + + +@check_args(0, 3, (3,3,3)) +@left_iter_nocopy(3, 3, ref_var_idx=0) @handle_casting(arg_idxs=(0,1,2)) @handle_extract_transpose() -def computeeth(qv, tk, p): +def _eth(qv, tk, p, outview=None): + if outview is None: + outview = np.empty_like(qv) - result = f_computeeth(qv, - tk, - p) + result = deqthecalc(qv, + tk, + p, + outview) return result @@ -399,7 +477,6 @@ def computeeth(qv, tk, p): # # return np.squeeze(result) -# uvmet_left_iter needs to determine if the variable has missing values @uvmet_left_iter_nocopy() @handle_casting(arg_idxs=(0,1,2,3)) @handle_extract_transpose() @@ -432,109 +509,249 @@ def _uvmet(u, v, lat, lon, cen_long, cone, isstag=0, has_missing=False, return result -@handle_left_iter(3,0) +#@handle_left_iter(3,0) +#@handle_casting(arg_idxs=(0,1,2,3)) +#@handle_extract_transpose() +#def computeomega(qv, tk, w, p): +# +# result = f_computeomega(qv, +# tk, +# w, +# p) +# +# return result + +@check_args(0, 3, (3,3,3,3)) +@left_iter_nocopy(3, 3, ref_var_idx=0) @handle_casting(arg_idxs=(0,1,2,3)) @handle_extract_transpose() -def computeomega(qv, tk, w, p): +def _omega(qv, tk, w, p, outview=None): + if outview is None: + outview = np.empty_like(qv) - result = f_computeomega(qv, - tk, - w, - p) + result = omgcalc(qv, + tk, + w, + p, + outview) return result -@handle_left_iter(3,0) +#@handle_left_iter(3,0) +#@handle_casting(arg_idxs=(0,1)) +#@handle_extract_transpose() +#def computetv(tk, qv): +# result = f_computetv(tk, +# qv) +# +# return result + + +@check_args(0, 3, (3,3)) +@left_iter_nocopy(3, 3, ref_var_idx=0) @handle_casting(arg_idxs=(0,1)) @handle_extract_transpose() -def computetv(tk, qv): - result = f_computetv(tk, - qv) +def _tv(tk, qv, outview=None): + if outview is None: + outview = np.empty_like(tk) + + result = virtual_temp(tk, + qv, + outview) return result -@handle_left_iter(3,0) +#@handle_left_iter(3,0) +#@handle_casting(arg_idxs=(0,1,2)) +#@handle_extract_transpose() +#def computewetbulb(p, tk, qv): +# PSADITHTE, PSADIPRS, PSADITMK = get_lookup_tables() +# PSADITMK = PSADITMK.T +# +# result = f_computewetbulb(p, +# tk, +# qv, +# PSADITHTE, +# PSADIPRS, +# PSADITMK, +# FortranError()) +# +# return result + + +@check_args(0, 3, (3,3,3)) +@left_iter_nocopy(3, 3, ref_var_idx=0, ignore_args=(3,)) @handle_casting(arg_idxs=(0,1,2)) @handle_extract_transpose() -def computewetbulb(p, tk, qv): - PSADITHTE, PSADIPRS, PSADITMK = get_lookup_tables() - PSADITMK = PSADITMK.T +def _wetbulb(p, tk, qv, psafile=psafilepath(), outview=None): + if outview is None: + outview = np.empty_like(p) - result = f_computewetbulb(p, - tk, - qv, - PSADITHTE, - PSADIPRS, - PSADITMK, - FortranException()) + errstat = np.array(0) + errmsg = np.zeros(Constants.ERRLEN, "c") + + result = wetbulbcalc(p, + tk, + qv, + outview, + psafile, + errstat, + errmsg) + + if int(errstat) != 0: + raise FortranError("".join(npbytes_to_str(errmsg)).strip()) return result -@handle_left_iter(3,0, ignore_args=(4,)) +#@handle_left_iter(3,0, ignore_args=(4,)) +#@handle_casting(arg_idxs=(0,1,2,3)) +#@handle_extract_transpose() +#def computesrh(u, v, z, ter, top): +# +# result = f_computesrh(u, +# v, +# z, +# ter, +# top) +# +# return result + +@check_args(0, 3, (3,3,3,2)) +@left_iter_nocopy(3, 2, ref_var_idx=0, ignore_args=(4,)) @handle_casting(arg_idxs=(0,1,2,3)) @handle_extract_transpose() -def computesrh(u, v, z, ter, top): - - result = f_computesrh(u, +def _srhel(u, v, z, ter, top, outview=None): + if outview is None: + outview = np.empty_like(ter) + + result = dcalrelhl(u, v, z, ter, - top) + top, + outview) return result -@handle_left_iter(3,2, ignore_args=(5,6,7,8)) +#@handle_left_iter(3,2, ignore_args=(5,6,7,8)) +#@handle_casting(arg_idxs=(0,1,2,3,4)) +#@handle_extract_transpose() +#def computeuh(zp, mapfct, u, v, wstag, dx, dy, bottom, top): +# +# tem1 = np.zeros((u.shape[0], u.shape[1], u.shape[2]), np.float64, +# order="F") +# tem2 = np.zeros((u.shape[0], u.shape[1], u.shape[2]), np.float64, +# order="F") +# +# result = f_computeuh(zp, +# mapfct, +# dx, +# dy, +# bottom, +# top, +# u, +# v, +# wstag, +# tem1, +# tem2) +# +# return result + +@check_args(2, 3, (3,2,3,3,3), stagger=(-3,None,None,None,-3)) +@left_iter_nocopy(3, 2, ref_var_idx=2, ignore_args=(5,6,7,8)) @handle_casting(arg_idxs=(0,1,2,3,4)) @handle_extract_transpose() -def computeuh(zp, mapfct, u, v, wstag, dx, dy, bottom, top): - +def _udhel(zstag, mapfct, u, v, wstag, dx, dy, bottom, top, outview=None): + if outview is None: + outview = np.empty_like(mapfct) + tem1 = np.zeros((u.shape[0], u.shape[1], u.shape[2]), np.float64, order="F") tem2 = np.zeros((u.shape[0], u.shape[1], u.shape[2]), np.float64, order="F") - result = f_computeuh(zp, - mapfct, - dx, - dy, - bottom, - top, - u, - v, - wstag, - tem1, - tem2) + result = dcalcuh(zstag, + mapfct, + dx, + dy, + bottom, + top, + u, + v, + wstag, + outview, + tem1, + tem2) return result -@handle_left_iter(3,0) +#@handle_left_iter(3,0) +#@handle_casting(arg_idxs=(0,1,2,3)) +#@handle_extract_transpose() +#def computepw(p, tv, qv, ht): +# +# zdiff = np.zeros((p.shape[0], p.shape[1]), np.float64, order="F") +# result = f_computepw(p, +# tv, +# qv, +# ht, +# zdiff) +# +# return result + + +@check_args(0, 3, (3,3,3,3), stagger=(None, None, None, -3)) +@left_iter_nocopy(3, 2, ref_var_idx=0) @handle_casting(arg_idxs=(0,1,2,3)) @handle_extract_transpose() -def computepw(p, tv, qv, ht): - - zdiff = np.zeros((p.shape[0], p.shape[1]), np.float64, order="F") - result = f_computepw(p, - tv, - qv, - ht, - zdiff) +def _pw(p, tv, qv, ht, outview=None): + + if outview is None: + outview = np.empty(p.shape[0:2], p.dtype, order="F") + + result = dcomputepw(p, + tv, + qv, + ht, + outview) return result -@handle_left_iter(3,0, ignore_args=(6,7,8)) +#@handle_left_iter(3,0, ignore_args=(6,7,8)) +#@handle_casting(arg_idxs=(0,1,2,3,4,5)) +#@handle_extract_transpose() +#def computedbz(p, tk, qv, qr, qs, qg, sn0, ivarint, iliqskin): +# +# result = f_computedbz(p, +# tk, +# qv, +# qr, +# qs, +# qg, +# sn0, +# ivarint, +# iliqskin) +# +# return result + +@check_args(0, 3, (3,3,3,3,3,3)) +@left_iter_nocopy(3, 3, ref_var_idx=0, ignore_args=(6,7,8)) @handle_casting(arg_idxs=(0,1,2,3,4,5)) @handle_extract_transpose() -def computedbz(p, tk, qv, qr, qs, qg, sn0, ivarint, iliqskin): - - result = f_computedbz(p, - tk, - qv, - qr, - qs, - qg, - sn0, - ivarint, - iliqskin) +def _dbz(p, tk, qv, qr, qs, qg, sn0, ivarint, iliqskin, outview=None): + if outview is None: + outview = np.empty_like(p) + + result = calcdbz(p, + tk, + qv, + qr, + qs, + qg, + sn0, + ivarint, + iliqskin, + outview) return result @@ -544,126 +761,272 @@ def computedbz(p, tk, qv, qr, qs, qg, sn0, ivarint, iliqskin): # Then flip the final result. The copy is unavoidable, but at least it is # only happening once, not every time. -@handle_left_iter(3,0,ignore_args=(6,7,8)) -@handle_casting(arg_idxs=(0,1,2,3,4,5)) -@handle_extract_transpose() -def computecape(p_hpa, tk, qv, ht, ter, sfp, missing, i3dflag, ter_follow): - flip_cape = np.zeros(p_hpa.shape[0:3], np.float64, order="F") - flip_cin = np.zeros(p_hpa.shape[0:3], np.float64, order="F") - PSADITHTE, PSADIPRS, PSADITMK = get_lookup_tables() - PSADITMK = PSADITMK.T - - # The fortran routine needs pressure to be ascending in z-direction, - # along with tk,qv,and ht. - # The extra mumbo-jumbo is so that the view created by numpy is fortran - # contiguous. 'ascontiguousarray' only works in C ordering, hence the - # extra transposes. Note, this is probably making a copy - flip_p = np.ascontiguousarray(p_hpa[:,:,::-1].T).T - flip_tk = np.ascontiguousarray(tk[:,:,::-1].T).T - flip_qv = np.ascontiguousarray(qv[:,:,::-1].T).T - flip_ht = np.ascontiguousarray(ht[:,:,::-1].T).T - - f_computecape(flip_p, - flip_tk, - flip_qv, - flip_ht, - ter, - sfp, - flip_cape, - flip_cin, - PSADITHTE, - PSADIPRS, - PSADITMK, - missing, - i3dflag, - ter_follow, - FortranException()) - - # Need to flip the vertical back to decending pressure with height. - cape = np.ascontiguousarray(flip_cape[:,:,::-1].T).T - cin = np.ascontiguousarray(flip_cin[:,:,::-1].T).T - - return (cape, cin) - -def computeij(map_proj, truelat1, truelat2, stdlon, - lat1, lon1, pole_lat, pole_lon, - knowni, knownj, dx, latinc, loninc, lat, lon): - - result = f_lltoij(map_proj, - truelat1, - truelat2, - stdlon, - lat1, - lon1, - pole_lat, - pole_lon, - knowni, - knownj, - dx, - latinc, - loninc, - lat, - lon, - FortranException()) +# @handle_left_iter(3,0,ignore_args=(6,7,8)) +# @handle_casting(arg_idxs=(0,1,2,3,4,5)) +# @handle_extract_transpose() +# def computecape(p_hpa, tk, qv, ht, ter, sfp, missing, i3dflag, ter_follow): +# flip_cape = np.zeros(p_hpa.shape[0:3], np.float64, order="F") +# flip_cin = np.zeros(p_hpa.shape[0:3], np.float64, order="F") +# PSADITHTE, PSADIPRS, PSADITMK = get_lookup_tables() +# PSADITMK = PSADITMK.T +# +# # The fortran routine needs pressure to be ascending in z-direction, +# # along with tk,qv,and ht. +# # The extra mumbo-jumbo is so that the view created by numpy is fortran +# # contiguous. 'ascontiguousarray' only works in C ordering, hence the +# # extra transposes. Note, this is probably making a copy +# flip_p = np.ascontiguousarray(p_hpa[:,:,::-1].T).T +# flip_tk = np.ascontiguousarray(tk[:,:,::-1].T).T +# flip_qv = np.ascontiguousarray(qv[:,:,::-1].T).T +# flip_ht = np.ascontiguousarray(ht[:,:,::-1].T).T +# +# f_computecape(flip_p, +# flip_tk, +# flip_qv, +# flip_ht, +# ter, +# sfp, +# flip_cape, +# flip_cin, +# PSADITHTE, +# PSADIPRS, +# PSADITMK, +# missing, +# i3dflag, +# ter_follow, +# FortranException()) +# +# # Need to flip the vertical back to decending pressure with height. +# cape = np.ascontiguousarray(flip_cape[:,:,::-1].T).T +# cin = np.ascontiguousarray(flip_cin[:,:,::-1].T).T +# +# return (cape, cin) + +@check_args(0, 3, (3,3,3,3,2,2)) +@cape_left_iter() +@handle_casting(arg_idxs=(0,1,2,3,4,5), outviews=("capeview", "cinview")) +@handle_extract_transpose(outviews=("capeview", "cinview")) +def _cape(p_hpa, tk, qv, ht, ter, sfp, missing, i3dflag, ter_follow, + psafile=psafilepath(), capeview=None, cinview=None): + + if capeview is None: + capeview = np.zeros(p_hpa.shape[0:3], p_hpa.dtype, order="F") + + if cinview is None: + cinview = np.zeros(p_hpa.shape[0:3], p_hpa.dtype, order="F") + + errstat = np.array(0) + errmsg = np.zeros(Constants.ERRLEN, "c") + + # note that p_hpa, tk, qv, and ht have the vertical flipped + result = dcapecalc3d(p_hpa, + tk, + qv, + ht, + ter, + sfp, + capeview, + cinview, + missing, + i3dflag, + ter_follow, + psafile, + errstat, + errmsg) + + if int(errstat) != 0: + raise FortranError("".join(npbytes_to_str(errmsg)).strip()) return result -def computell(map_proj, truelat1, truelat2, stdlon, lat1, lon1, - pole_lat, pole_lon, knowni, knownj, dx, latinc, - loninc, i, j): - - result = f_ijtoll(map_proj, - truelat1, - truelat2, - stdlon, - lat1, - lon1, - pole_lat, - pole_lon, - knowni, - knownj, - dx, - latinc, - loninc, - i, - j, - FortranException()) +@check_args(0, 3, (3,3)) +@cloudfrac_left_iter() +@handle_casting(arg_idxs=(0, 1), outviews=("lowview", "medview", "highview")) +@handle_extract_transpose(outviews=("lowview", "medview", "hightview")) +def _cloudfrac(p, rh, lowview=None, medview=None, highview=None): + + if lowview is None: + lowview = np.zeros(p.shape[0:2], p.dtype, order="F") + + if medview is None: + medview = np.zeros(p.shape[0:2], p.dtype, order="F") + + if highview is None: + highview = np.zeros(p.shape[0:2], p.dtype, order="F") + + result = dcloudfrac(p, + rh, + lowview, + medview, + highview) return result -@handle_left_iter(3,0, ignore_args=(3,)) -@handle_casting(arg_idxs=(0,1,2)) -@handle_extract_transpose() -def computeeta(full_t, znu, psfc, ptop): - pcalc = np.zeros(full_t.shape, np.float64, order="F") - mean_t = np.zeros(full_t.shape, np.float64, order="F") - temp_t = np.zeros(full_t.shape, np.float64, order="F") - - result = f_converteta(full_t, - znu, - psfc, - ptop, - pcalc, - mean_t, - temp_t) + +#def computeij(map_proj, truelat1, truelat2, stdlon, +# lat1, lon1, pole_lat, pole_lon, +# knowni, knownj, dx, latinc, loninc, lat, lon): +# +# result = f_lltoij(map_proj, +# truelat1, +# truelat2, +# stdlon, +# lat1, +# lon1, +# pole_lat, +# pole_lon, +# knowni, +# knownj, +# dx, +# latinc, +# loninc, +# lat, +# lon, +# FortranError()) +# +# return result + +#def computell(map_proj, truelat1, truelat2, stdlon, lat1, lon1, +# pole_lat, pole_lon, knowni, knownj, dx, latinc, +# loninc, i, j): +# +# result = f_ijtoll(map_proj, +# truelat1, +# truelat2, +# stdlon, +# lat1, +# lon1, +# pole_lat, +# pole_lon, +# knowni, +# knownj, +# dx, +# latinc, +# loninc, +# i, +# j, +# FortranError()) +# +# return result + +def _lltoxy(map_proj, truelat1, truelat2, stdlon, + lat1, lon1, pole_lat, pole_lon, + known_x, known_y, dx, dy, latinc, loninc, lat, lon): + + errstat = np.array(0) + errmsg = np.zeros(Constants.ERRLEN, "c") + + result = dlltoij(map_proj, + truelat1, + truelat2, + stdlon, + lat1, + lon1, + pole_lat, + pole_lon, + known_x, + known_y, + dx, + dy, + latinc, + loninc, + lat, + lon, + errstat, + errmsg) + + if int(errstat) != 0: + raise FortranError("".join(npbytes_to_str(errmsg)).strip()) return result -@handle_left_iter(3,0,ignore_args=(7,)) + +def _xytoll(map_proj, truelat1, truelat2, stdlon, lat1, lon1, + pole_lat, pole_lon, known_x, known_y, dx, dy, latinc, + loninc, x, y): + + errstat = np.array(0) + errmsg = np.zeros(Constants.ERRLEN, "c") + + result = dijtoll(map_proj, + truelat1, + truelat2, + stdlon, + lat1, + lon1, + pole_lat, + pole_lon, + known_x, + known_y, + dx, + dy, + latinc, + loninc, + x, + y, + errstat, + errmsg) + + if int(errstat) != 0: + raise FortranError("".join(npbytes_to_str(errmsg)).strip()) + + return result + + +#@handle_left_iter(3,0, ignore_args=(3,)) +#@handle_casting(arg_idxs=(0,1,2)) +#@handle_extract_transpose() +#def computeeta(full_t, znu, psfc, ptop): +# pcalc = np.zeros(full_t.shape, np.float64, order="F") +# mean_t = np.zeros(full_t.shape, np.float64, order="F") +# temp_t = np.zeros(full_t.shape, np.float64, order="F") +# +# result = f_converteta(full_t, +# znu, +# psfc, +# ptop, +# pcalc, +# mean_t, +# temp_t) +# +# return result + +#@handle_left_iter(3,0,ignore_args=(7,)) +#@handle_casting(arg_idxs=(0,1,2,3,4,5,6)) +#@handle_extract_transpose() +#def computectt(p_hpa, tk, qice, qcld, qv, ght, ter, haveqci): +# result = f_computectt(p_hpa, +# tk, +# qice, +# qcld, +# qv, +# ght, +# ter, +# haveqci) +# +# return result + +@check_args(0, 3, (3,3,3,3,3,3,2)) +@left_iter_nocopy(3, 2, ref_var_idx=0, ignore_args=(7,)) @handle_casting(arg_idxs=(0,1,2,3,4,5,6)) @handle_extract_transpose() -def computectt(p_hpa, tk, qice, qcld, qv, ght, ter, haveqci): - result = f_computectt(p_hpa, - tk, - qice, - qcld, - qv, - ght, - ter, - haveqci) +def _ctt(p_hpa, tk, qice, qcld, qv, ght, ter, haveqci, outview=None): + if outview is None: + outview = np.empty_like(ter) + + result = wrfcttcalc(p_hpa, + tk, + qice, + qcld, + qv, + ght, + ter, + outview, + haveqci) return result + # @handle_left_iter(2,0,ignore_args=(1,)) # @handle_casting(arg_idxs=(0,)) # @handle_extract_transpose() @@ -717,41 +1080,107 @@ def _smooth2d(field, passes, outview=None): # array. It's only modifying the existing array. return outview -@handle_left_iter(3,0,ignore_args=(3,4,5)) +#@handle_left_iter(3,0,ignore_args=(3,4,5)) +#@handle_casting(arg_idxs=(0,1,2)) +#@handle_extract_transpose() +#def monotonic(var, lvprs, coriolis, idir, delta, icorsw): +# result = f_monotonic(var, +# lvprs, +# coriolis, +# idir, +# delta, +# icorsw) +# +# return result + + +@check_args(0, 3, (3,3,2)) +@left_iter_nocopy(3, 3, ref_var_idx=0, ignore_args=(3,4,5)) @handle_casting(arg_idxs=(0,1,2)) @handle_extract_transpose() -def monotonic(var, lvprs, coriolis, idir, delta, icorsw): - result = f_monotonic(var, - lvprs, - coriolis, - idir, - delta, - icorsw) +def _monotonic(var, lvprs, coriolis, idir, delta, icorsw, outview=None): + # If icorsw is not 0, then the input variable might get modified by the + # fortran routine. We don't want this, so make a copy and pass that on. + var = var.copy(order="A") if icorsw != 0 else var + + if outview is None: + outview = np.empty_like(var) + + result = wrf_monotonic(outview, + var, + lvprs, + coriolis, + idir, + delta, + icorsw) return result -@handle_left_iter(3,0,ignore_args=(9,10,11,12,13,14)) +#@handle_left_iter(3,0,ignore_args=(9,10,11,12,13,14)) +#@handle_casting(arg_idxs=(0,1,2,3,4,5,6,7,8,9)) +#@handle_extract_transpose() +#def vintrp(field, pres, tk, qvp, ght, terrain, sfp, smsfp, +# vcarray, interp_levels, icase, extrap, vcor, logp, +# missing): +# +# result = f_vintrp(field, +# pres, +# tk, +# qvp, +# ght, +# terrain, +# sfp, +# smsfp, +# vcarray, +# interp_levels, +# icase, +# extrap, +# vcor, +# logp, +# missing) +# +# return result + + +# Output shape is interp_levels.shape + field.shape[-2:] +@check_args(0, 3, (3,3,3,3,3,2,2,2,3)) +@left_iter_nocopy(3, combine_dims([(9, (-1,)), + (0, (-2,-1))]), + ref_var_idx=0, ignore_args=(9,10,11,12,13,14)) @handle_casting(arg_idxs=(0,1,2,3,4,5,6,7,8,9)) @handle_extract_transpose() -def vintrp(field, pres, tk, qvp, ght, terrain, sfp, smsfp, - vcarray, interp_levels, icase, extrap, vcor, logp, - missing): - - result = f_vintrp(field, - pres, - tk, - qvp, - ght, - terrain, - sfp, - smsfp, - vcarray, - interp_levels, - icase, - extrap, - vcor, - logp, - missing) +def _vintrp(field, pres, tk, qvp, ght, terrain, sfp, smsfp, + vcarray, interp_levels, icase, extrap, vcor, logp, + missing, outview=None): + + if outview is None: + outdims = field.shape[0:2] + interp_levels.shape + outview = np.empty(outdims, field.dtype, order="F") + + errstat = np.array(0) + errmsg = np.zeros(Constants.ERRLEN, "c") + + result = wrf_vintrp(field, + outview, + pres, + tk, + qvp, + ght, + terrain, + sfp, + smsfp, + vcarray, + interp_levels, + icase, + extrap, + vcor, + logp, + missing, + errstat, + errmsg) + + if int(errstat) != 0: + raise FortranError("".join(npbytes_to_str(errmsg)).strip()) return result diff --git a/src/wrf/helicity.py b/src/wrf/helicity.py index ce461c3..dcb3dff 100755 --- a/src/wrf/helicity.py +++ b/src/wrf/helicity.py @@ -3,7 +3,7 @@ from __future__ import (absolute_import, division, print_function, from .constants import Constants -from .extension import computesrh, computeuh +from .extension import _srhel, _udhel from .destag import destagger from .util import extract_vars, extract_global_attrs, either from .metadecorators import copy_and_set_metadata @@ -44,7 +44,7 @@ def get_srh(wrfnc, timeidx=0, method="cat", squeeze=True, v1 = v[...,::-1,:,:] z1 = z[...,::-1,:,:] - srh = computesrh(u1, v1, z1, ter, top) + srh = _srhel(u1, v1, z1, ter, top) return srh @@ -80,7 +80,7 @@ def get_uh(wrfnc, timeidx=0, method="cat", squeeze=True, zp = ph + phb - uh = computeuh(zp, mapfct, u, v, wstag, dx, dy, bottom, top) + uh = _udhel(zp, mapfct, u, v, wstag, dx, dy, bottom, top) return uh diff --git a/src/wrf/interp.py b/src/wrf/interp.py index b410447..13abb1e 100755 --- a/src/wrf/interp.py +++ b/src/wrf/interp.py @@ -9,7 +9,7 @@ import numpy.ma as ma # computeinterpline) from .extension import (_interpz3d, _interp2dxy, _interp1d, _vertcross, - _interpline, _smooth2d, monotonic, vintrp) + _interpline, _smooth2d, _monotonic, _vintrp) from .metadecorators import set_interp_metadata from .util import extract_vars, is_staggered @@ -51,7 +51,7 @@ def interplevel(field3d, z, desiredlev, missing=Constants.DEFAULT_FILL, Returns ------- - out : 'xarray.DataArray` or `numpy.ndarray` + `xarray.DataArray` or `numpy.ndarray` Returns the interpolated variable. If xarray is enabled and the meta parameter is True, then the result will be an `xarray.DataArray` object. Otherwise, the result will be a @@ -70,7 +70,7 @@ def vertcross(field3d, z, missing=Constants.DEFAULT_FILL, include_latlon=False, cache=None, meta=True): """Return the vertical cross section for a 3D field, interpolated - to a verical plane defined by a horizontal line. + to a vertical plane defined by a horizontal line. The horizontal line is defined by either including the `pivot_point` and `angle` parameters, or the `start_point` and @@ -123,7 +123,7 @@ def vertcross(field3d, z, missing=Constants.DEFAULT_FILL, Returns ------- - out : 'xarray.DataArray` or `numpy.ndarray` + `xarray.DataArray` or `numpy.ndarray` Returns the interpolated variable. If xarray is enabled and the meta parameter is True, then the result will be an `xarray.DataArray` object. Otherwise, the result will be a @@ -195,7 +195,7 @@ def interpline(field2d, pivot_point=None, Returns ------- - out : 'xarray.DataArray` or `numpy.ndarray` + `xarray.DataArray` or `numpy.ndarray` Returns the interpolated variable. If xarray is enabled and the meta parameter is True, then the result will be an `xarray.DataArray` object. Otherwise, the result will be a @@ -227,16 +227,15 @@ def vinterp(wrfnc, field, vert_coord, interp_levels, extrapolate=False, field2d : `xarray.DataArray` or `numpy.ndarray` A two-dimensional field. - vert_coord : {"pressure", "pres", "p", "ght_msl", - "ght_agl", "theta", "th", "theta-e", - "thetae", "eth"} + vert_coord : {'pressure', 'pres', 'p', 'ght_msl', 'ght_agl', 'theta', 'th', 'theta-e', 'thetae', 'eth'} A string indicating the vertical coordinate type to interpolate to. + Valid strings are: - * "pressure", "pres", "p": pressure [hPa] - * "ght_msl": grid point height msl [km] - * "ght_agl": grid point height agl [km] - * "theta", "th": potential temperature [K] - * "theta-e", "thetae", "eth": equivalent potential temperature [K] + * 'pressure', 'pres', 'p': pressure [hPa] + * 'ght_msl': grid point height msl [km] + * 'ght_agl': grid point height agl [km] + * 'theta', 'th': potential temperature [K] + * 'theta-e', 'thetae', 'eth': equivalent potential temperature [K] interp_levels : sequence A 1D sequence of vertical levels to interpolate to. @@ -244,8 +243,7 @@ def vinterp(wrfnc, field, vert_coord, interp_levels, extrapolate=False, extrapolate : {True, False}, optional Set to True to extrapolate values below ground. Default is False. - field_type : {"none", "pressure", "pres", "p", "z", "tc", "tk", "theta", - "th", "theta-e", "thetae", "eth", "ght"}, optional + field_type : {'none', 'pressure', 'pres', 'p', 'z', 'tc', 'tk', 'theta', 'th', 'theta-e', 'thetae', 'eth', 'ght'}, optional The type of field. Default is None. log_p : {True, False} @@ -280,7 +278,7 @@ def vinterp(wrfnc, field, vert_coord, interp_levels, extrapolate=False, Returns ------- - out : 'xarray.DataArray` or `numpy.ndarray` + `xarray.DataArray` or `numpy.ndarray` Returns the interpolated variable. If xarray is enabled and the meta parameter is True, then the result will be an `xarray.DataArray` object. Otherwise, the result will be a @@ -314,9 +312,9 @@ def vinterp(wrfnc, field, vert_coord, interp_levels, extrapolate=False, "eth" : 6} # These constants match what's in the fortran code. - rgas = 287.04 #J/K/kg - ussalr = .0065 # deg C per m, avg lapse rate - sclht = rgas*256./9.81 + rgas = Constants.RD#287.04 #J/K/kg + ussalr = Constants.USSALR#.0065 # deg C per m, avg lapse rate + sclht = Constants.SCLHT #rgas*256./9.81 # interp_levels might be a list or tuple, make a numpy array if not isinstance(interp_levels, np.ndarray): @@ -390,7 +388,7 @@ def vinterp(wrfnc, field, vert_coord, interp_levels, extrapolate=False, p_hpa = p * ConversionFactors.PA_TO_HPA - vcord_array = monotonic(t, p_hpa, coriolis, idir, delta, icorsw) + vcord_array = _monotonic(t, p_hpa, coriolis, idir, delta, icorsw) # We only extrapolate temperature fields below ground # if we are interpolating to pressure or height vertical surfaces. @@ -407,7 +405,7 @@ def vinterp(wrfnc, field, vert_coord, interp_levels, extrapolate=False, p_hpa = p * ConversionFactors.PA_TO_HPA - vcord_array = monotonic(eth, p_hpa, coriolis, idir, delta, icorsw) + vcord_array = _monotonic(eth, p_hpa, coriolis, idir, delta, icorsw) # We only extrapolate temperature fields below ground if we are # interpolating to pressure or height vertical surfaces icase = 0 @@ -424,9 +422,9 @@ def vinterp(wrfnc, field, vert_coord, interp_levels, extrapolate=False, "same value used when extracting the 'field' " "variable.") - res = vintrp(field, p, tk, qv, ght, terht, sfp, smsfp, - vcord_array, interp_levels, - icase, extrap, vcor, log_p_int, missing) + res = _vintrp(field, p, tk, qv, ght, terht, sfp, smsfp, + vcord_array, interp_levels, + icase, extrap, vcor, log_p_int, missing) return ma.masked_values(res, missing) diff --git a/src/wrf/interputils.py b/src/wrf/interputils.py index abd157f..a9b9e56 100644 --- a/src/wrf/interputils.py +++ b/src/wrf/interputils.py @@ -6,7 +6,7 @@ from math import floor, ceil import numpy as np from .extension import _interp2dxy -from .util import py3range +from .py3compat import py3range def to_positive_idxs(shape, coord): diff --git a/src/wrf/latlon.py b/src/wrf/latlon.py index b33d95c..641936e 100755 --- a/src/wrf/latlon.py +++ b/src/wrf/latlon.py @@ -1,8 +1,8 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) -from .util import (extract_vars) -from .latlonutils import (_lat_varname, _lon_varname, ll_to_ij, ij_to_ll) +from .util import extract_vars +from .latlonutils import (_lat_varname, _lon_varname, _ll_to_xy, _xy_to_ll) from .metadecorators import set_latlon_metadata @@ -28,19 +28,22 @@ def get_lon(wrfnc, timeidx=0, method="cat", squeeze=True, return lon_var[varname] -# TODO: Rename these! -@set_latlon_metadata(ij=True) -def get_ij(wrfnc, latitude, longitude, timeidx=0, - stagger=None, method="cat", squeeze=True, cache=None, meta=True): - return ll_to_ij(wrfnc, latitude, longitude, timeidx, stagger, - method, squeeze, cache) - - -@set_latlon_metadata(ij=False) -def get_ll(wrfnc, i, j, timeidx=0, - stagger=None, method="cat", squeeze=True, cache=None, meta=True): - return ij_to_ll(wrfnc, i, j, timeidx, stagger, - method, squeeze, cache) +# Can either use wrfnc as a single file or sequence, or provide +# projection parameters (which don't allow for moving domains) +@set_latlon_metadata(xy=True) +def ll_to_xy(latitude, longitude, wrfnc=None, timeidx=0, + stagger=None, method="cat", squeeze=True, cache=None, meta=True, + **projparms): + return _ll_to_xy(latitude, longitude, wrfnc, timeidx, stagger, + method, squeeze, cache, **projparams) + + +@set_latlon_metadata(xy=False) +def xy_to_ll(x, y, wrfnc=None, timeidx=0, + stagger=None, method="cat", squeeze=True, cache=None, meta=True, + **projparms): + return _xy_to_ll(x, y, wrfnc, timeidx, stagger, + method, squeeze, cache, **projparams) \ No newline at end of file diff --git a/src/wrf/latlonutils.py b/src/wrf/latlonutils.py index 2950000..febf60e 100644 --- a/src/wrf/latlonutils.py +++ b/src/wrf/latlonutils.py @@ -6,11 +6,11 @@ from collections import Iterable import numpy as np from .constants import Constants -from .extension import computeij, computell +from .extension import _lltoxy, _xytoll from .util import (extract_vars, extract_global_attrs, - either, _is_moving_domain, _is_multi_time_req, - iter_left_indexes, _is_mapping, _is_multi_file, - viewkeys) + either, is_moving_domain, is_multi_time_req, + iter_left_indexes, is_mapping, is_multi_file) +from .py3compat import viewkeys, viewitems def _lat_varname(wrfnc, stagger): if stagger is None or stagger.lower() == "m": @@ -64,15 +64,15 @@ def _get_proj_params(wrfnc, timeidx, stagger, method, squeeze, cache): lat_timeidx = timeidx - is_moving = _is_moving_domain(wrfnc, latvar=latvar, lonvar=lonvar) + is_moving = is_moving_domain(wrfnc, latvar=latvar, lonvar=lonvar) # Only need one file and one time if the domain is not moving if not is_moving: - if _is_multi_time_req(timeidx): + if is_multi_time_req(timeidx): lat_timeidx = 0 - if _is_multi_file(wrfnc): - if not _is_mapping(wrfnc): + if is_multi_file(wrfnc): + if not is_mapping(wrfnc): wrfnc = next(iter(wrfnc)) # only need one file else: wrfnc = wrfnc[next(iter(viewkeys(wrfnc)))] @@ -84,23 +84,95 @@ def _get_proj_params(wrfnc, timeidx, stagger, method, squeeze, cache): xlon = extract_vars(wrfnc, lat_timeidx, (lonvar,), method, squeeze, cache, meta=False)[lonvar] - ref_lat = np.ravel(xlat[...,0,0]) - ref_lon = np.ravel(xlon[...,0,0]) + ref_lat = np.ravel(xlat[..., 0, 0]) + ref_lon = np.ravel(xlon[..., 0, 0]) # Note: fortran index - known_i = 1.0 - known_j = 1.0 + known_x = 1.0 + known_y = 1.0 return (map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon, - pole_lat, pole_lon, known_i, known_j, dx, latinc, loninc) + pole_lat, pole_lon, known_x, known_y, dx, dy, latinc, loninc) + + +def _dict_keys_to_upper(d): + return {key.upper(): val for key, val in viewitems(d)} + +# known_x and known_y are 0-based +def _kwarg_proj_params(projparams): + projparams = _dict_keys_to_upper(projparams) + + map_proj = projparams.get("MAP_PROJ"), + truelat1 = projparams.get("TRUELAT1"), + truelat2 = projparams.get("TRUELAT2"), + stdlon = projparams.get("STDLON"), + ref_lat = projparams.get("REF_LAT"), + ref_lon = projparams.get("REF_LON"), + pole_lat = projparams.get("POLE_LAT", 90.0), + pole_lon = projparams.get("POLE_LON", 0.0), + known_x = projparams.get("KNOWN_X"), # Use 0-based + known_y = projparams.get("KNOWN_Y"), # Use 0-based + dx = projparams.get("DX"), + dy = projparams.get("DY"), + latinc = projparams.get("LATINC"), + loninc = projparams.get("LONINC") + + # Sanity checks + # Required args for all projections + for name, var in viewitems({"MAP_PROJ" : map_proj, + "STDLON" : stdlon, + "REF_LAT" : ref_lat, + "REF_LON" : ref_lon, + "KNOWN_X" : known_x, + "KNOWN_Y" : known_y, + "DX" : dx}): + if var is None: + raise ValueError("'{}' argument required".format(name)) + + # Fortran wants 1-based indexing + known_x = known_x + 1 + known_y = known_y + 1 + + if map_proj in (1, 2, 3): + if truelat1 is None: + raise ValueError("'TRUELAT1' argument required") + else: + if truelat1 is None: + truelat1 = 0.0 + + # Map projection 6 (lat lon) required latinc, loninc, and dy + if map_proj == 6: + if latinc is None: + raise ValueError("'LATINC' argument required") + + if loninc is None: + raise ValueError("'LONINC' argument required") + + if dy is None: + raise ValueError("'DY' argument required") + else: + latinc = 0.0 + loninc = 0.0 + dy = 0.0 + return (map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon, pole_lat, + pole_lon, known_x, known_y, dx, dy, latinc, loninc) -def ll_to_ij(wrfnc, latitude, longitude, timeidx=0, - stagger=None, method="cat", squeeze=True, cache=None): + +# Will return 0-based indexes +def _ll_to_xy(latitude, longitude, wrfnc=None, timeidx=0, + stagger=None, method="cat", squeeze=True, cache=None, + **projparms): - (map_proj,truelat1,truelat2,stdlon,ref_lat,ref_lon, - pole_lat,pole_lon,known_i,known_j,dx,latinc, - loninc) = _get_proj_params(wrfnc, timeidx, stagger, method, squeeze, cache) + if wrfnc is not None: + (map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon, + pole_lat, pole_lon, known_x, known_y, dx, dy, latinc, + loninc) = _get_proj_params(wrfnc, timeidx, stagger, method, squeeze, + cache) + else: + (map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon, + pole_lat, pole_lon, known_x, known_y, dx, dy, latinc, + loninc) = _kwarg_proj_params(**projparams) if isinstance(latitude, Iterable): lats = np.asarray(latitude) @@ -116,7 +188,6 @@ def ll_to_ij(wrfnc, latitude, longitude, timeidx=0, raise ValueError("'latitude' and 'longitude' " "must be the same length") - if ref_lat.size == 1: outdim = [lats.size, 2] extra_dims = [outdim[0]] @@ -125,7 +196,7 @@ def ll_to_ij(wrfnc, latitude, longitude, timeidx=0, outdim = [lats.size, ref_lat.size, 2] extra_dims = outdim[0:2] - res = np.empty(outdim, np.float64) + result = np.empty(outdim, np.float64) for left_idxs in iter_left_indexes(extra_dims): left_and_slice_idxs = left_idxs + (slice(None), ) @@ -140,55 +211,70 @@ def ll_to_ij(wrfnc, latitude, longitude, timeidx=0, lat = lats[left_idxs[0]] lon = lons[left_idxs[0]] - ij = computeij(map_proj, truelat1, truelat2, stdlon, + xy = _lltoxy(map_proj, truelat1, truelat2, stdlon, ref_lat_val, ref_lon_val, pole_lat, pole_lon, - known_i, known_j, dx, latinc, loninc, + known_x, known_y, dx, dy, latinc, loninc, lat, lon) - res[left_and_slice_idxs] = ij[:] + result[left_and_slice_idxs] = xy[:] else: - res = computeij(map_proj, truelat1, truelat2, stdlon, + result = _lltoxy(map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon, pole_lat, pole_lon, - known_i, known_j, dx, latinc, loninc, + known_x, known_y, dx, dy, latinc, loninc, latitude, longitude) + # Make indexes 0-based + result = result - 1 + if squeeze: - res = res.squeeze() + result = result.squeeze() - return res + return result -def ij_to_ll(wrfnc, i, j, timeidx=0, - stagger=None, method="cat", squeeze=True, cache=None): - - (map_proj,truelat1,truelat2,stdlon,ref_lat,ref_lon, - pole_lat,pole_lon,known_i,known_j,dx,latinc, - loninc) = _get_proj_params(wrfnc, timeidx, stagger, method, squeeze, cache) +# X and Y should be 0-based +def _xy_to_ll(x, y, wrfnc=None, timeidx=0, stagger=None, + method="cat", squeeze=True, cache=None, **projparams): + + if wrfnc is not None: + (map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon, + pole_lat, pole_lon, known_x, known_y, dx, dy, latinc, + loninc) = _get_proj_params(wrfnc, timeidx, stagger, method, squeeze, + cache) + else: + (map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon, + pole_lat, pole_lon, known_x, known_y, dx, dy, latinc, + loninc) = _kwarg_proj_params(**projparams) + - if isinstance(i, Iterable): - i_arr = np.asarray(i) - j_arr = np.asarray(j) + if isinstance(x, Iterable): + x_arr = np.asarray(x) + y_arr = np.asarray(y) + + # Convert 0-based x, y to 1-based + x_arr = x_arr + 1 + y_arr = y_arr + 1 - if i_arr.ndim > 1: - i_arr = i_arr.ravel() + if x_arr.ndim > 1: + x_arr = x_arr.ravel() - if j_arr.ndim > 1: - j_arr = j_arr.ravel() + if y_arr.ndim > 1: + y_arr = y_arr.ravel() - if (i_arr.size != j_arr.size): - raise ValueError("'i' and 'j' " + if (x_arr.size != y_arr.size): + raise ValueError("'x' and 'y' " "must be the same length") if ref_lat.size == 1: - outdim = [i_arr.size, 2] + outdim = [x_arr.size, 2] extra_dims = [outdim[0]] else: # Moving domain will have moving ref_lats/ref_lons - outdim = [i_arr.size, ref_lat.size, 2] + outdim = [x_arr.size, ref_lat.size, 2] extra_dims = outdim[0:2] - res = np.empty(outdim, np.float64) + result = np.empty(outdim, np.float64) for left_idxs in iter_left_indexes(extra_dims): left_and_slice_idxs = left_idxs + (slice(None), ) @@ -200,28 +286,25 @@ def ij_to_ll(wrfnc, i, j, timeidx=0, ref_lat_val = ref_lat[left_idxs[-1]] ref_lon_val = ref_lon[left_idxs[-1]] - i_val = i_arr[left_idxs[0]] - j_val = j_arr[left_idxs[0]] + x_val = x_arr[left_idxs[0]] + y_val = y_arr[left_idxs[0]] - ll = computell(map_proj, truelat1, truelat2, - stdlon, ref_lat_val, ref_lon_val, - pole_lat, pole_lon, known_i, known_j, - dx, latinc, loninc, - i_val, j_val) + ll = _xytoll(map_proj, truelat1, truelat2, stdlon, ref_lat_val, + ref_lon_val, pole_lat, pole_lon, known_x, known_y, + dx, dy, latinc, loninc, x_val, y_val) - res[left_and_slice_idxs] = ll[:] + result[left_and_slice_idxs] = ll[:] else: - i_val = i - j_val = j + # Convert 0-based to 1-based for Fortran + x_val = x + 1 + y_val = y + 1 - res = computell(map_proj, truelat1, truelat2, - stdlon, ref_lat, ref_lon, - pole_lat, pole_lon, known_i, known_j, - dx, latinc, loninc, - i_val, j_val) + result = _xytoll(map_proj, truelat1, truelat2, stdlon, ref_lat, ref_lon, + pole_lat, pole_lon, known_x, known_y, dx, dy, latinc, + loninc, x_val, y_val) if squeeze: - res = res.squeeze() + result = result.squeeze() - return res \ No newline at end of file + return result diff --git a/src/wrf/metadecorators.py b/src/wrf/metadecorators.py index 0f1eed6..29f4a2e 100644 --- a/src/wrf/metadecorators.py +++ b/src/wrf/metadecorators.py @@ -7,12 +7,11 @@ import numpy as np import numpy.ma as ma from .extension import _interpline -from .util import (viewkeys, viewitems, extract_vars, - combine_with, either, from_args, arg_location, +from .util import (extract_vars, combine_with, either, from_args, arg_location, is_coordvar, latlon_coordvars, CoordPair, npvalues, - py3range, ucode, from_var, iter_left_indexes) + from_var, iter_left_indexes) +from .py3compat import viewkeys, viewitems, py3range, ucode from .interputils import get_xy_z_params, get_xy -from .latlonutils import ij_to_ll, ll_to_ij from .config import xarray_enabled if xarray_enabled(): @@ -231,10 +230,102 @@ def set_wind_metadata(copy_varname, name, description, return func_wrapper -def set_latlon_metadata(ij=False): +def set_cape_metadata(is2d): @wrapt.decorator def func_wrapper(wrapped, instance, args, kwargs): + do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"] + + if do_meta is None: + do_meta = True + + if not xarray_enabled() or not do_meta: + return wrapped(*args, **kwargs) + + argvars = from_args(wrapped, ("wrfnc", "timeidx", "method", "squeeze", + "cache", "missing"), + *args, **kwargs) + wrfnc = argvars["wrfnc"] + timeidx = argvars["timeidx"] + method = argvars["method"] + squeeze = argvars["squeeze"] + cache = argvars["cache"] + missing = argvars["missing"] + if cache is None: + cache = {} + + _copy_varname = "P" + copy_var = extract_vars(wrfnc, timeidx, _copy_varname, method, squeeze, + cache, meta=True)[_copy_varname] + + # Make a copy so we don't modify a user supplied cache + new_cache = dict(cache) + new_cache[_copy_varname] = copy_var + + # Don't modify the original args/kargs. The args need to be a list + # so it can be modified. + new_args, cache_argloc = arg_location(wrapped, "cache", args, kwargs) + new_args[cache_argloc] = new_cache + + result = wrapped(*new_args) + + outcoords = OrderedDict() + outattrs = OrderedDict() + outattrs.update(copy_var.attrs) + outdimnames = [None] * result.ndim + + if is2d: + # Right dims + outdimnames[-2:] = copy_var.dims[-2:] + # Left dims + outdimnames[1:-2] = copy_var.dims[0:-3] + outdimnames[0] = "mcape_mcin_lcl_lfc" + outattrs["description"] = "mcape ; mcin ; lcl ; lfc" + outattrs["MemoryOrder"] = "XY" + outattrs["units"] = "J/kg ; J/kg ; m ; m" + outname = "cape_2d" + else: + # Right dims + outdimnames[-3:] = copy_var.dims[-3:] + # Left dims + outdimnames[1:-3] = copy_var.dims[0:-3] + outdimnames[0] = "cape_cin" + outattrs["description"] = "cape; cin" + outattrs["units"] = "J kg-1 ; J kg-1" + outattrs["MemoryOrder"] = "XYZ" + outname = "cape_3d" + + outattrs["_FillValue"] = missing + outattrs["missing_value"] = missing + + + # xarray doesn't line up coordinate dimensions based on + # names, it just remembers the index it originally mapped to. + # So, need to rebuild the XLAT, XLONG, coordinates again since the + # leftmost index changed. + + for key,dataarray in viewitems(copy_var.coords): + if is_coordvar(key): + outcoords[key] = dataarray.dims, npvalues(dataarray) + elif key == "XTIME": + outcoords[key] = dataarray.dims, npvalues(dataarray) + elif key == "Time": + outcoords[key] = npvalues(dataarray) + + if is2d: + outcoords["mcape_mcin_lcl_lfc"] = ["mcape", "mcin", "lcl", "lfc"] + else: + outcoords["cape_cin"] = ["cape", "cin"] + + + return DataArray(result, name=outname, coords=outcoords, + dims=outdimnames, attrs=outattrs) + return func_wrapper + + +def set_cloudfrac_metadata(): + @wrapt.decorator + def func_wrapper(wrapped, instance, args, kwargs): do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"] if do_meta is None: @@ -243,22 +334,100 @@ def set_latlon_metadata(ij=False): if not xarray_enabled() or not do_meta: return wrapped(*args, **kwargs) - res = wrapped(*args, **kwargs) + argvars = from_args(wrapped, ("wrfnc", "timeidx", "method", "squeeze", + "cache"), + *args, **kwargs) + wrfnc = argvars["wrfnc"] + timeidx = argvars["timeidx"] + method = argvars["method"] + squeeze = argvars["squeeze"] + cache = argvars["cache"] + if cache is None: + cache = {} + + _copy_varname = "P" + copy_var = extract_vars(wrfnc, timeidx, _copy_varname, method, squeeze, + cache, meta=True)[_copy_varname] + + # Make a copy so we don't modify a user supplied cache + new_cache = dict(cache) + new_cache[_copy_varname] = copy_var + + # Don't modify the original args/kargs. The args need to be a list + # so it can be modified. + new_args, cache_argloc = arg_location(wrapped, "cache", args, kwargs) + new_args[cache_argloc] = new_cache + + result = wrapped(*new_args) + + outcoords = OrderedDict() + outattrs = OrderedDict() + outattrs.update(copy_var.attrs) + outdimnames = [None] * result.ndim + + # Right dims + outdimnames[-2:] = copy_var.dims[-2:] + # Left dims + outdimnames[1:-2] = copy_var.dims[0:-3] + outdimnames[0] = "low_med_high" + outattrs["description"] = "low, med, high clouds" + outattrs["MemoryOrder"] = "XY" + outattrs["units"] = "%" + outname = "cloudfrac" + + # xarray doesn't line up coordinate dimensions based on + # names, it just remembers the index it originally mapped to. + # So, need to rebuild the XLAT, XLONG, coordinates again since the + # leftmost index changed. + + for key,dataarray in viewitems(copy_var.coords): + if is_coordvar(key): + outcoords[key] = dataarray.dims, npvalues(dataarray) + elif key == "XTIME": + outcoords[key] = dataarray.dims, npvalues(dataarray) + elif key == "Time": + outcoords[key] = npvalues(dataarray) + + outcoords["low_med_high"] = ["low", "med", "high"] + + return DataArray(result, name=outname, coords=outcoords, + dims=outdimnames, attrs=outattrs) + + return func_wrapper + +def set_latlon_metadata(xy=False): + @wrapt.decorator + def func_wrapper(wrapped, instance, args, kwargs): + + do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"] + + if do_meta is None: + do_meta = True + + if not xarray_enabled() or not do_meta: + return wrapped(*args, **kwargs) + + # Set squeeze to False. Squeeze will be handled in here + new_args, squeeze_argloc = arg_location(wrapped, "squeeze", args, + kwargs) + new_args[squeeze_argloc] = False + + result = wrapped(*new_args) # Want to preserve the input coordinate pair in metadata - if res.ndim == 1: - res = res[np.newaxis, :] + if result.ndim == 1: + result = result[np.newaxis, :] - argnames = ["i", "j"] if not ij else ["latitude", "longitude"] + argnames = ["x", "y"] if not xy else ["latitude", "longitude"] argnames.append("squeeze") - outname = "latlon" if not ij else "ij" + outname = "latlon" if not xy else "xy" - if res.ndim == 2: - dimnames = (["ij", "lat_lon"] if not ij - else ["latlon", "i_j"]) + if result.ndim == 2: + dimnames = (["xy", "lat_lon"] if not xy + else ["latlon", "x_y"]) else: - dimnames = (["ij", "domain", "lat_lon"] if not ij - else ["latlon", "domain", "i_j"]) + dimnames = (["xy", "domain", "lat_lon"] if not xy + else ["latlon", "domain", "x_y"]) argvars = from_args(wrapped, argnames, *args, **kwargs) @@ -271,15 +440,15 @@ def set_latlon_metadata(ij=False): coords = {} if not ij: - coords["coord_pair"] = (dimnames[0], [CoordPair(i=x[0], j=x[1]) + coords["coord_pair"] = (dimnames[0], [CoordPair(x=x[0], y=x[1]) for x in zip(arr1, arr2)]) coords[dimnames[-1]] = ["lat", "lon"] else: coords["coord_pair"] = (dimnames[0], [CoordPair(lat=x[0], lon=x[1]) for x in zip(arr1, arr2)]) - coords[dimnames[-1]] = ["i", "j"] + coords[dimnames[-1]] = ["x", "y"] - da = DataArray(res, name=outname, dims=dimnames, coords=coords) + da = DataArray(result, name=outname, dims=dimnames, coords=coords) if squeeze: da = da.squeeze() @@ -642,12 +811,11 @@ def _set_line_meta(wrapped, instance, args, kwargs): lats = _interpline(latcoord, xy) lons = _interpline(loncoord, xy) - outcoords["xy_loc"] = ("xy", - np.asarray(tuple( + outcoords["xy_loc"] = np.asarray(tuple( CoordPair(x=xy[i,0], y=xy[i,1], lat=lats[i], lon=lons[i]) for i in py3range(xy.shape[-2]))) - ) + else: extra_dims = latcoord.shape[0:-2] @@ -919,11 +1087,21 @@ def set_interp_metadata(interp_type): return func_wrapper -def set_alg_metadata(alg_ndims, right_dimnames=None, - refvarndims=None, - refvarname=None, missingarg=None, - insert_dimnames=None, +def set_alg_metadata(alg_ndims, refvarname, + refvarndims=None, missingarg=None, + stagdim=None, stagsubvar=None, units=None, description=None, squeeze=False): + """ + alg_ndims: number of dimensions returned by the algorithm + refvarndims: number of right dimensions for the refernce var, used + when the result has less dimensions than reference + refvarname: argument name for the reference variable + missingarg: argument name for the missing value + stagdim: staggered dimension in reference + stagsubvar: the variable to use to supply the staggered dimension name + + + """ @wrapt.decorator def func_wrapper(wrapped, instance, args, kwargs): @@ -980,14 +1158,19 @@ def set_alg_metadata(alg_ndims, right_dimnames=None, else: refvar = None + if stagsubvar is not None: + stagvar = from_args(wrapped, (stagsubvar,), + *args, **kwargs)[stagsubvar] + else: + stagvar = None + if isinstance(refvar, DataArray): - # If right dims are provided, use them first - if right_dimnames is not None: - outdims[-alg_ndims:] = right_dimnames[-alg_ndims:] - else: - # Copy the right dims - outdims[-alg_ndims:] = refvar.dims[-alg_ndims:] + # Copy the right dims + outdims[-alg_ndims:] = refvar.dims[-alg_ndims:] + + # Use the stagsubvar if applicable + outdims[stagdim] = stagvar.dims[stagdim] # Left dims if refvarndims is None: @@ -1001,7 +1184,8 @@ def set_alg_metadata(alg_ndims, right_dimnames=None, outdims[idx] = refvar.dims[idx] else: continue - # When reference and result aren't exactly aligned (slp,uvmet) + # When reference and result aren't exactly aligned (slp) + # (reference is 3D, result is 2D) else: ref_extra = refvar.ndim - refvarndims ref_left_dimnames = refvar.dims[0:ref_extra] @@ -1012,13 +1196,8 @@ def set_alg_metadata(alg_ndims, right_dimnames=None, outdims[idx] = dimname else: continute - - if insert_dimnames is not None: - for pair in insert_dimnames: - outdims.insert(pair[0], pair[1]) - out = DataArray(result, name=outname, dims=outdims, - attrs=outattrs) + out = DataArray(result, name=outname, dims=outdims, attrs=outattrs) if squeeze: return out.squeeze() @@ -1063,11 +1242,127 @@ def set_uvmet_alg_metadata(units="mps", description="earth rotated u,v"): # Left dims come from u-var outdims[1:-2] = uvar.dims[0:-2] - # Left-most is always u_v - outdims[0] = "u_v" + # Left-most is always u_v + outdims[0] = "u_v" + outcoords = {} + outcoords["u_v"] = ["u", "v"] - out = DataArray(result, name=outname, dims=outdims, - attrs=outattrs) + out = DataArray(result, name=outname, dims=outdims, coords=outcoords, + attrs=outattrs) + + return out + + return func_wrapper + +def set_cape_alg_metadata(is2d): + + @wrapt.decorator + def func_wrapper(wrapped, instance, args, kwargs): + do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"] + + if do_meta is None: + do_meta = True + + if not xarray_enabled() or not do_meta: + return wrapped(*args, **kwargs) + + result = wrapped(*args, **kwargs) + + # Default dimension names + outdims = ["dim_{}".format(i) for i in py3range(result.ndim)] + + outattrs = OrderedDict() + + if is2d: + outname = "cape_2d" + outattrs["description"] = "mcape ; mcin ; lcl ; lfc" + outattrs["units"] = "J/kg ; J/kg ; m ; m" + outattrs["MemoryOrder"] = "XY" + else: + outname = "cape_3d" + outattrs["description"] = "cape; cin" + outattrs["units"] = "J kg-1 ; J kg-1" + outattrs["MemoryOrder"] = "XYZ" + + + argvals = from_args(wrapped, ("p_hpa","missing"), *args, **kwargs) + p = argvals["p_hpa"] + missing = argvals["missing"] + + if isinstance(p, DataArray): + if is2d: + # Right dims + outdims[-2:] = p.dims[-2:] + # Left dims + outdims[1:-2] = p.dims[0:-3] + + else: + # Right dims + outdims[-3:] = p.dims[-3:] + # Left dims + outdims[1:-3] = p.dims[0:-3] + + outcoords = {} + # Left-most is always cape_cin or cape_cin_lcl_lfc + if is2d: + outdims[0] = "cape_cin_lcl_lfc" + outcoords["cape_cin_lcl_lfc"] = ["cape", "cin", "lcl", "lfc"] + else: + outdims[0] = "cape_cin" + outcoords["cape_cin"] = ["cape", "cin"] + + outattrs["_FillValue"] = missing + outattrs["missing_value"] = missing + + out = DataArray(result, name=outname, dims=outdims, coords=outcoords, + attrs=outattrs) + + return out + + return func_wrapper + + +def set_cloudfrac_alg_metadata(): + + @wrapt.decorator + def func_wrapper(wrapped, instance, args, kwargs): + do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"] + + if do_meta is None: + do_meta = True + + if not xarray_enabled() or not do_meta: + return wrapped(*args, **kwargs) + + result = wrapped(*args, **kwargs) + + # Default dimension names + outdims = ["dim_{}".format(i) for i in py3range(result.ndim)] + + outattrs = OrderedDict() + + outname = "cloudfrac" + outattrs["description"] = "low, med, high clouds" + outattrs["units"] = "%" + outattrs["MemoryOrder"] = "XY" + + + argvals = from_args(wrapped, "p", *args, **kwargs)["p"] + + if isinstance(p, DataArray): + # Right dims + outdims[-2:] = p.dims[-2:] + # Left dims + outdims[1:-2] = p.dims[0:-3] + + + outcoords = {} + # Left-most is always cape_cin or cape_cin_lcl_lfc + outdims[0] = "low_med_high" + outcoords["low_med_high"] = ["low", "med", "high"] + + out = DataArray(result, name=outname, dims=outdims, coords=outcoords, + attrs=outattrs) return out diff --git a/src/wrf/omega.py b/src/wrf/omega.py index 6da289f..5f90192 100755 --- a/src/wrf/omega.py +++ b/src/wrf/omega.py @@ -4,7 +4,7 @@ from __future__ import (absolute_import, division, print_function, from .constants import Constants from .destag import destagger #from .extension import computeomega,computetk -from .extension import computeomega, _tk +from .extension import _omega, _tk from .util import extract_vars from .metadecorators import copy_and_set_metadata @@ -28,7 +28,7 @@ def get_omega(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, full_p = p + pb tk = _tk(full_p, full_t) - omega = computeomega(qv,tk,wa,full_p) + omega = _omega(qv, tk, wa, full_p) return omega \ No newline at end of file diff --git a/src/wrf/pw.py b/src/wrf/pw.py index d7c5c6b..b4e3e80 100755 --- a/src/wrf/pw.py +++ b/src/wrf/pw.py @@ -2,7 +2,7 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) #from .extension import computepw,computetv,computetk -from .extension import computepw,computetv, _tk +from .extension import _pw, _tv, _tk from .constants import Constants from .util import extract_vars from .metadecorators import copy_and_set_metadata @@ -32,9 +32,9 @@ def get_pw(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, full_t = t + Constants.T_BASE tk = _tk(full_p, full_t) - tv = computetv(tk, qv) + tv = _tv(tk, qv) - return computepw(full_p, tv, qv, ht) + return _pw(full_p, tv, qv, ht) diff --git a/src/wrf/py3compat.py b/src/wrf/py3compat.py new file mode 100644 index 0000000..f14af6a --- /dev/null +++ b/src/wrf/py3compat.py @@ -0,0 +1,55 @@ +from sys import version_info + +# Dictionary python 2-3 compatibility stuff +def viewitems(d): + func = getattr(d, "viewitems", None) + if func is None: + func = d.items + return func() + + +def viewkeys(d): + func = getattr(d, "viewkeys", None) + if func is None: + func = d.keys + return func() + + +def viewvalues(d): + func = getattr(d, "viewvalues", None) + if func is None: + func = d.values + return func() + +def isstr(s): + try: + return isinstance(s, basestring) + except NameError: + return isinstance(s, str) + + +# Python 2 rounding behavior +def _round2(x, d=0): + p = 10 ** d + return float(floor((x * p) + copysign(0.5, x)))/p + + +def py2round(x, d=0): + if version_info >= (3,): + return _round2(x, d) + + return round(x, d) + + +def py3range(*args): + if version_info >= (3,): + return range(*args) + + return xrange(*args) + + +def ucode(*args, **kwargs): + if version_info >= (3, ): + return str(*args, **kwargs) + + return unicode(*args, **kwargs) \ No newline at end of file diff --git a/src/wrf/routines.py b/src/wrf/routines.py index b738863..598eb5b 100644 --- a/src/wrf/routines.py +++ b/src/wrf/routines.py @@ -1,7 +1,7 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) -from .util import _get_iterable, is_standard_wrf_var, extract_vars, viewkeys +from .util import get_iterable, is_standard_wrf_var, extract_vars, viewkeys from .cape import get_2dcape, get_3dcape from .ctt import get_ctt from .dbz import get_dbz, get_max_dbz @@ -22,6 +22,7 @@ from .vorticity import get_avo, get_pvo from .wind import (get_destag_wspd_wdir, get_destag_wspd_wdir10, get_u_destag, get_v_destag, get_w_destag) from .times import get_times +from .cloudfrac import get_cloudfrac # func is the function to call. kargs are required arguments that should @@ -65,7 +66,8 @@ _FUNC_MAP = {"cape2d" : get_2dcape, "wspd_wdir10" : get_destag_wspd_wdir10, "wspd_wdir_uvmet" : get_uvmet_wspd_wdir, "wspd_wdir_uvmet10" : get_uvmet10_wspd_wdir, - "ctt" : get_ctt + "ctt" : get_ctt, + "cloudfrac" : get_cloudfrac } _VALID_KARGS = {"cape2d" : ["missing"], @@ -108,6 +110,7 @@ _VALID_KARGS = {"cape2d" : ["missing"], "wspd_wdir_uvmet" : ["units"], "wspd_wdir_uvmet10" : ["units"], "ctt" : [], + "cloudfrac" : [], "default" : [] } @@ -171,6 +174,8 @@ def getvar(wrfnc, varname, timeidx=0, +--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+ | ctt | Cloud Top Temperature | C | | +--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+ + | cloudfrac | Cloud Fraction | % | | + +--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+ | dbz | Reflectivity | dBz | do_variant: Set to True to enable variant calculation. Default is False. | | | | | do_liqskin : Set to True to enable liquid skin calculation. Default is False. | +--------------------+---------------------------------------------------------------+---------------------+-----------------------------------------------------------------------------------------------+ @@ -270,15 +275,15 @@ def getvar(wrfnc, varname, timeidx=0, Returns ------- - out : 'xarray.DataArray` or `numpy.ndarray` - Returns the specififed diagnostics output. If xarray is enabled and + `xarray.DataArray` or `numpy.ndarray` + Returns the specified diagnostics output. If xarray is enabled and the meta parameter is True, then the result will be an `xarray.DataArray` object. Otherwise, the result will be a `numpy.ndarray` object with no metadata. """ - wrfnc = _get_iterable(wrfnc) + wrfnc = get_iterable(wrfnc) if is_standard_wrf_var(wrfnc, varname): return extract_vars(wrfnc, timeidx, varname, diff --git a/src/wrf/specialdec.py b/src/wrf/specialdec.py new file mode 100644 index 0000000..474d20d --- /dev/null +++ b/src/wrf/specialdec.py @@ -0,0 +1,489 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import numpy as np + +import wrapt + +#from .destag import destagger +from .util import iter_left_indexes, npvalues +from .py3compat import py3range +from .config import xarray_enabled +from .constants import Constants + +if xarray_enabled(): + from xarray import DataArray + + +# def uvmet_left_iter(): +# """Decorator to handle iterating over leftmost dimensions when using +# multiple files and/or multiple times with the uvmet product. +# +# """ +# @wrapt.decorator +# def func_wrapper(wrapped, instance, args, kwargs): +# u = args[0] +# v = args[1] +# lat = args[2] +# lon = args[3] +# cen_long = args[4] +# cone = args[5] +# +# if u.ndim == lat.ndim: +# num_right_dims = 2 +# is_3d = False +# else: +# num_right_dims = 3 +# is_3d = True +# +# is_stag = False +# if ((u.shape[-1] != lat.shape[-1]) or +# (u.shape[-2] != lat.shape[-2])): +# is_stag = True +# +# if is_3d: +# extra_dim_num = u.ndim - 3 +# else: +# extra_dim_num = u.ndim - 2 +# +# if is_stag: +# u = destagger(u,-1) +# v = destagger(v,-2) +# +# # No special left side iteration, return the function result +# if (extra_dim_num == 0): +# return wrapped(u, v, lat, lon, cen_long, cone) +# +# # Start by getting the left-most 'extra' dims +# outdims = u.shape[0:extra_dim_num] +# extra_dims = list(outdims) # Copy the left-most dims for iteration +# +# # Append the right-most dimensions +# outdims += [2] # For u/v components +# +# #outdims += [u.shape[x] for x in py3range(-num_right_dims,0,1)] +# outdims += list(u.shape[-num_right_dims:]) +# +# output = np.empty(outdims, u.dtype) +# +# for left_idxs in iter_left_indexes(extra_dims): +# # Make the left indexes plus a single slice object +# # The single slice will handle all the dimensions to +# # the right (e.g. [1,1,:]) +# left_and_slice_idxs = tuple([x for x in left_idxs] + [slice(None)]) +# +# new_u = u[left_and_slice_idxs] +# new_v = v[left_and_slice_idxs] +# new_lat = lat[left_and_slice_idxs] +# new_lon = lon[left_and_slice_idxs] +# +# # Call the numerical routine +# result = wrapped(new_u, new_v, new_lat, new_lon, cen_long, cone) +# +# # Note: The 2D version will return a 3D array with a 1 length +# # dimension. Numpy is unable to broadcast this without +# # sqeezing first. +# result = np.squeeze(result) +# +# output[left_and_slice_idxs] = result[:] +# +# return output +# +# return func_wrapper + +def _move_dim_to_left(arr, dimidx): + + if isinstance(arr, np.ma.MaskedArray): + has_missing = True + missing = result.fill_value + + shape = list(arr.shape) + move_dim_size = shape.pop(dimidx) + + output_dims = [move_dim_size] + shape + + output = np.empty(output_dims, arr.dtype) + + if dimidx < 0: + right_ndim = -dimidx + else: + right_ndim = arr.ndim - dimidx + + rightdims = [slice(None)] * right_ndim + + for i in py3range(move_dim_size): + rightdims[0] = i + outidxs = (Ellipsis,) + tuple(rightdims) + output[i,:] = outview_array[outidxs] + + if has_missing: + output = np.ma.masked_values(output, missing) + + return output + + +def uvmet_left_iter_nocopy(alg_dtype=np.float64): + """Decorator to handle iterating over leftmost dimensions when using + multiple files and/or multiple times with the uvmet product. + + """ + @wrapt.decorator + def func_wrapper(wrapped, instance, args, kwargs): + u = args[0] + v = args[1] + lat = args[2] + lon = args[3] + cen_long = args[4] + cone = args[5] + + orig_dtype = u.dtype + + lat_lon_fixed = False + if lat.ndim == 2: + lat_lon_fixed = True + + if lon.ndim == 2 and not lat_lon_fixed: + raise ValueError("'lat' and 'lon' shape mismatch") + + num_left_dims_u = u.ndim - 2 + num_left_dims_lat = lat.ndim - 2 + + if (num_left_dims_lat > num_left_dims_u): + raise ValueError("number of 'lat' dimensions is greater than 'u'") + + if lat_lon_fixed: + mode = 0 # fixed lat/lon + else: + if num_left_dims_u == num_left_dims_lat: + mode = 1 # lat/lon same as u + else: + mode = 2 # probably 3D with 2D lat/lon plus Time + + has_missing = False + u_arr = u + if isinstance(u, DataArray): + u_arr = npvalues(u) + + v_arr = v + if isinstance(v, DataArray): + v_arr = npvalues(v) + + umissing = Constants.DEFAULT_FILL + if isinstance(u_arr, np.ma.MaskedArray): + has_missing = True + umissing = u_arr.fill_value + + vmissing = Constants.DEFAULT_FILL + if isinstance(v_arr, np.ma.MaskedArray): + has_missing = True + vmissing = v_arr.fill_value + + uvmetmissing = umissing + + is_stag = 0 + if (u.shape[-1] != lat.shape[-1] or u.shape[-2] != lat.shape[-2]): + is_stag = 1 + # Sanity check + if (v.shape[-1] == lat.shape[-1] or v.shape[-2] == lat.shape[-2]): + raise ValueError("u is staggered but v is not") + + if (v.shape[-1] != lat.shape[-1] or v.shape[-2] != lat.shape[-2]): + is_stag = 1 + # Sanity check + if (u.shape[-1] == lat.shape[-1] or u.shape[-2] == lat.shape[-2]): + raise ValueError("v is staggered but u is not") + + + + # No special left side iteration, return the function result + if (num_left_dims_u == 0): + return wrapped(u, v, lat, lon, cen_long, cone, isstag=is_stag, + has_missing=has_missing, umissing=umissing, + vmissing=vmissing, uvmetmissing=uvmetmissing) + + # Initial output is time,nz,2,ny,nx to create contiguous views + outdims = u.shape[0:num_left_dims_u] + extra_dims = tuple(outdims) # Copy the left-most dims for iteration + + outdims += (2,) + + outdims += lat.shape[-2:] + + outview_array = np.empty(outdims, alg_dtype) + + # Final Output moves the u_v dimension to left side + output_dims = (2,) + output_dims += extra_dims + output_dims += lat.shape[-2:] + output = np.empty(output_dims, orig_dtype) + + for left_idxs in iter_left_indexes(extra_dims): + left_and_slice_idxs = left_idxs + (slice(None),) + + if mode == 0: + lat_left_and_slice = (slice(None),) + elif mode == 1: + lat_left_and_slice = left_and_slice_idxs + elif mode == 2: + # Only need the left-most + lat_left_and_slice = tuple(left_idx + for left_idx in left_idxs[0:num_left_dims_lat]) + + u_output_idxs = (0,) + left_idxs + (slice(None),) + v_output_idxs = (1,) + left_idxs + (slice(None),) + u_view_idxs = left_idxs + (0, slice(None)) + v_view_idxs = left_idxs + (1, slice(None)) + + + new_u = u[left_and_slice_idxs] + new_v = v[left_and_slice_idxs] + new_lat = lat[lat_left_and_slice] + new_lon = lon[lat_left_and_slice] + outview = outview_array[left_and_slice_idxs] + + # Call the numerical routine + result = wrapped(new_u, new_v, new_lat, new_lon, cen_long, cone, + isstag=is_stag, has_missing=has_missing, + umissing=umissing, vmissing=vmissing, + uvmetmissing=uvmetmissing, outview=outview) + + # Make sure the result is the same data as what got passed in + # Can delete this once everything works + if (result.__array_interface__["data"][0] != + outview.__array_interface__["data"][0]): + raise RuntimeError("output array was copied") + + output[u_output_idxs] = ( + outview_array[u_view_idxs].astype(orig_dtype)) + output[v_output_idxs] = ( + outview_array[v_view_idxs].astype(orig_dtype)) + + if has_missing: + output = np.ma.masked_values(output, uvmetmissing) + + return output + + return func_wrapper + + + +def cape_left_iter(alg_dtype=np.float64): + """Decorator to handle iterating over leftmost dimensions when using + multiple files and/or multiple times with the cape product. + + + """ + @wrapt.decorator + def func_wrapper(wrapped, instance, args, kwargs): + # The cape calculations use an ascending vertical pressure coordinate + + new_args = list(args) + new_kwargs = dict(kwargs) + + p_hpa = args[0] + tk = args[1] + qv = args[2] + ht = args[3] + ter = args[4] + sfp = args[5] + missing = args[6] + i3dflag = args[7] + ter_follow = args[8] + + is2d = False if i3dflag != 0 else True + + # Need to order in ascending pressure order + flip = False + bot_idxs = (0,) * p_hpa.ndim + top_idxs = list(bot_idxs) + top_idxs[-3] = -1 + top_idxs = tuple(top_idxs) + + if p_hpa[bot_idxs] > p_hpa[top_idxs]: + flip = True + p_hpa = np.ascontiguousarray(p_hpa[...,::-1,:,:]) + tk = np.ascontiguousarray(tk[...,::-1,:,:]) + qv = np.ascontiguousarray(qv[...,::-1,:,:]) + ht = np.ascontiguousarray(ht[...,::-1,:,:]) + new_args[0] = p_hpa + new_args[1] = tk + new_args[2] = qv + new_args[3] = ht + + num_left_dims = p_hpa.ndim - 3 + orig_dtype = p_hpa.dtype + + # No special left side iteration, build the output from the cape,cin + # result + if (num_left_dims == 0): + cape, cin = wrapped(*new_args, **new_kwargs) + + output_dims = (2,) + output_dims += p_hpa.shape[-3:] + output = np.empty(output_dims, orig_dtype) + + if flip and not is2d: + output[0,:] = cape[::-1,:,:] + output[1,:] = cin[::-1,:,:] + else: + output[0,:] = cape[:] + output[1,:] = cin[:] + + return output + + + # Initial output is ...,cape_cin,nz,ny,nx to create contiguous views + outdims = p_hpa.shape[0:num_left_dims] + extra_dims = tuple(outdims) # Copy the left-most dims for iteration + + outdims += (2,) # cape_cin + + outdims += p_hpa.shape[-3:] + + outview_array = np.empty(outdims, alg_dtype) + + # Create the output array where the leftmost dim is the product type + output_dims = (2,) + output_dims += extra_dims + output_dims += p_hpa.shape[-3:] + output = np.empty(output_dims, orig_dtype) + + for left_idxs in iter_left_indexes(extra_dims): + left_and_slice_idxs = left_idxs + (slice(None),) + cape_idxs = left_idxs + (0, slice(None)) + cin_idxs = left_idxs + (1, slice(None)) + + cape_output_idxs = (0,) + left_idxs + (slice(None),) + cin_output_idxs = (1,) + left_idxs + (slice(None),) + view_cape_reverse_idxs = left_idxs + (0, slice(None,None,-1), + slice(None)) + view_cin_reverse_idxs = left_idxs + (1, slice(None,None,-1), + slice(None)) + + new_args[0] = p_hpa[left_and_slice_idxs] + new_args[1] = tk[left_and_slice_idxs] + new_args[2] = qv[left_and_slice_idxs] + new_args[3] = ht[left_and_slice_idxs] + new_args[4] = ter[left_and_slice_idxs] + new_args[5] = sfp[left_and_slice_idxs] + capeview = outview_array[cape_idxs] + cinview = outview_array[cin_idxs] + + # Call the numerical routine + new_kwargs["capeview"] = capeview + new_kwargs["cinview"] = cinview + + cape, cin = wrapped(*new_args, **new_kwargs) + + # Make sure the result is the same data as what got passed in + # Can delete this once everything works + if (cape.__array_interface__["data"][0] != + capeview.__array_interface__["data"][0]): + raise RuntimeError("output array was copied") + + + if flip and not is2d: + output[cape_output_idxs] = ( + outview_array[view_cape_reverse_idxs].astype(orig_dtype)) + output[cin_output_idxs] = ( + outview_array[view_cin_reverse_idxs].astype(orig_dtype)) + else: + output[cape_output_idxs] = ( + outview_array[cape_idxs].astype(orig_dtype)) + output[cin_output_idxs] = ( + outview_array[cin_idxs].astype(orig_dtype)) + + return output + + return func_wrapper + +def cloudfrac_left_iter(alg_dtype=np.float64): + """Decorator to handle iterating over leftmost dimensions when using + multiple files and/or multiple times with the cloudfrac product. + + + """ + @wrapt.decorator + def func_wrapper(wrapped, instance, args, kwargs): + # The cape calculations use an ascending vertical pressure coordinate + new_args = list(args) + new_kwargs = dict(kwargs) + + p = args[0] + rh = args[1] + + num_left_dims = p.ndim - 3 + orig_dtype = p.dtype + + # No special left side iteration, build the output from the cape,cin + # result + if (num_left_dims == 0): + low, med, high = wrapped(*new_args, **new_kwargs) + + output_dims = (3,) + output_dims += p.shape[-2:] + output = np.empty(output_dims, orig_dtype) + + output[0,:] = low[:] + output[1,:] = med[:] + output[2,:] = high[:] + + return output + + + # Initial output is ...,cape_cin,nz,ny,nx to create contiguous views + outdims = p.shape[0:num_left_dims] + extra_dims = tuple(outdims) # Copy the left-most dims for iteration + + outdims += (3,) # low_mid_high + + outdims += p.shape[-2:] + + outview_array = np.empty(outdims, alg_dtype) + + # Create the output array where the leftmost dim is the cloud type + output_dims = (3,) + output_dims += extra_dims + output_dims += p.shape[-2:] + output = np.empty(output_dims, orig_dtype) + + for left_idxs in iter_left_indexes(extra_dims): + left_and_slice_idxs = left_idxs + (slice(None),) + low_idxs = left_idxs + (0, slice(None)) + med_idxs = left_idxs + (1, slice(None)) + high_idxs = left_idxs + (2, slice(None)) + + low_output_idxs = (0,) + left_idxs + (slice(None),) + med_output_idxs = (1,) + left_idxs + (slice(None),) + high_output_idxs = (2,) + left_idxs + (slice(None),) + + new_args[0] = p[left_and_slice_idxs] + new_args[1] = rh[left_and_slice_idxs] + + lowview = outview_array[low_idxs] + medview = outview_array[med_idxs] + highview = outview_array[high_idxs] + + new_kwargs["lowview"] = lowview + new_kwargs["medview"] = medview + new_kwargs["highview"] = highview + + low, med, high = wrapped(*new_args, **new_kwargs) + + # Make sure the result is the same data as what got passed in + # Can delete this once everything works + if (low.__array_interface__["data"][0] != + lowview.__array_interface__["data"][0]): + raise RuntimeError("output array was copied") + + output[low_output_idxs] = ( + outview_array[low_idxs].astype(orig_dtype)) + output[med_output_idxs] = ( + outview_array[med_idxs].astype(orig_dtype)) + output[high_output_idxs] = ( + outview_array[high_idxs].astype(orig_dtype)) + + return output + + return func_wrapper + diff --git a/src/wrf/temp.py b/src/wrf/temp.py index 28da822..7b8e2c0 100755 --- a/src/wrf/temp.py +++ b/src/wrf/temp.py @@ -3,7 +3,7 @@ from __future__ import (absolute_import, division, print_function, from .constants import Constants #from .extension import computetk, computeeth, computetv, computewetbulb -from .extension import _tk, computeeth, computetv, computewetbulb +from .extension import _tk, _eth, _tv, _wetbulb from .decorators import convert_units from .metadecorators import copy_and_set_metadata from .util import extract_vars @@ -65,7 +65,7 @@ def get_eth(wrfnc, timeidx=0, method="cat", squeeze=True, full_p = p + pb tk = _tk(full_p, full_t) - eth = computeeth(qv, tk, full_p) + eth = _eth(qv, tk, full_p) return eth @@ -90,7 +90,7 @@ def get_tv(wrfnc, timeidx=0, method="cat", squeeze=True, full_p = p + pb tk = _tk(full_p, full_t) - tv = computetv(tk,qv) + tv = _tv(tk, qv) return tv @@ -114,7 +114,7 @@ def get_tw(wrfnc, timeidx=0, method="cat", squeeze=True, full_p = p + pb tk = _tk(full_p, full_t) - tw = computewetbulb(full_p,tk,qv) + tw = _wetbulb(full_p, tk, qv) return tw diff --git a/src/wrf/units.py b/src/wrf/units.py index 1738b10..f21628a 100755 --- a/src/wrf/units.py +++ b/src/wrf/units.py @@ -22,7 +22,7 @@ def _apply_conv_fact(var, vartype, var_unit, dest_unit): def _to_celsius(var, var_unit): if var_unit == "k": - return var - Constants.TCK0 + return var - Constants.CELKEL elif var_unit == "f": return (var - 32.0) * (5.0/9.0) diff --git a/src/wrf/util.py b/src/wrf/util.py index 383213b..4a70020 100644 --- a/src/wrf/util.py +++ b/src/wrf/util.py @@ -1,6 +1,7 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) +import os from sys import version_info from copy import copy from collections import Iterable, Mapping, OrderedDict @@ -26,20 +27,13 @@ import numpy.ma as ma from .config import xarray_enabled from .projection import getproj, NullProjection from .constants import Constants, ALL_TIMES - +from .py3compat import (viewitems, viewkeys, viewvalues, isstr, py2round, + py3range, ucode) if xarray_enabled(): from xarray import DataArray from pandas import NaT -__all__ = ["extract_vars", "extract_global_attrs", "extract_dim", - "combine_files", "is_standard_wrf_var", "extract_times", - "iter_left_indexes", "get_left_indexes", "get_right_slices", - "is_staggered", "get_proj_params", "viewitems", "viewkeys", - "viewvalues", "py2round", "py3range", "combine_with", "either", - "from_args", "arg_location", "args_to_list", "npvalues", - "CoordPair"] - _COORD_PAIR_MAP = {"XLAT" : ("XLAT", "XLONG"), "XLONG" : ("XLAT", "XLONG"), @@ -63,25 +57,25 @@ _LON_COORDS = ("XLONG", "XLONG_M", "XLONG_U","XLONG_V", "CLONG") _TIME_COORD_VARS = ("XTIME",) -def _is_time_coord_var(varname): +def is_time_coord_var(varname): return varname in _TIME_COORD_VARS -def _get_coord_pairs(varname): +def get_coord_pairs(varname): return _COORD_PAIR_MAP[varname] -def _is_multi_time_req(timeidx): +def is_multi_time_req(timeidx): return timeidx is None -def _is_multi_file(wrfnc): +def is_multi_file(wrfnc): return (isinstance(wrfnc, Iterable) and not isstr(wrfnc)) -def _has_time_coord(wrfnc): +def has_time_coord(wrfnc): return "XTIME" in wrfnc.variables -def _is_mapping(wrfnc): +def is_mapping(wrfnc): return isinstance(wrfnc, Mapping) def _generator_copy(gen): @@ -159,12 +153,12 @@ class IterWrapper(Iterable): return obj_copy.__iter__() -def _get_iterable(wrfseq): +def get_iterable(wrfseq): """Returns a resetable iterable object.""" - if not _is_multi_file(wrfseq): + if not is_multi_file(wrfseq): return wrfseq else: - if not _is_mapping(wrfseq): + if not is_mapping(wrfseq): if isinstance(wrfseq, (list, tuple, IterWrapper)): return wrfseq @@ -176,73 +170,18 @@ def _get_iterable(wrfseq): return wrfseq else: return dict(wrfseq) # generator/custom iterable class - -# Dictionary python 2-3 compatibility stuff -def viewitems(d): - func = getattr(d, "viewitems", None) - if func is None: - func = d.items - return func() - - -def viewkeys(d): - func = getattr(d, "viewkeys", None) - if func is None: - func = d.keys - return func() - - -def viewvalues(d): - func = getattr(d, "viewvalues", None) - if func is None: - func = d.values - return func() - -def isstr(s): - try: - return isinstance(s, basestring) - except NameError: - return isinstance(s, str) - - -# Python 2 rounding behavior -def _round2(x, d=0): - p = 10 ** d - return float(floor((x * p) + copysign(0.5, x)))/p - - -def py2round(x, d=0): - if version_info >= (3,): - return _round2(x, d) - - return round(x, d) - - -def py3range(*args): - if version_info >= (3,): - return range(*args) - - return xrange(*args) - - -def ucode(*args, **kwargs): - if version_info >= (3, ): - return str(*args, **kwargs) - - return unicode(*args, **kwargs) - # Helper to extract masked arrays from DataArrays that convert to NaN -def npvalues(da): - if not isinstance(da, DataArray): - result = da +def npvalues(array_type): + if not isinstance(array_type, DataArray): + result = array_type else: try: - fill_value = da.attrs["_FillValue"] + fill_value = array_type.attrs["_FillValue"] except KeyError: - result = da.values + result = array_type.values else: - result = ma.masked_invalid(da.values, copy=False) + result = ma.masked_invalid(array_type.values, copy=False) result.set_fill_value(fill_value) return result @@ -253,8 +192,8 @@ class either(object): self.varnames = varnames def __call__(self, wrfnc): - if _is_multi_file(wrfnc): - if not _is_mapping(wrfnc): + if is_multi_file(wrfnc): + if not is_mapping(wrfnc): wrfnc = next(iter(wrfnc)) else: entry = wrfnc[next(iter(viewkeys(wrfnc)))] @@ -319,7 +258,7 @@ class combine_dims(object): result.append(var.shape[dimidxs]) return tuple(result) - + class from_var(object): def __init__(self, varname, attribute): @@ -362,7 +301,7 @@ def _corners_moved(wrfnc, first_ll_corner, first_ur_corner, latvar, lonvar): return False -def _is_moving_domain(wrfseq, varname=None, latvar=either("XLAT", "XLAT_M"), +def is_moving_domain(wrfseq, varname=None, latvar=either("XLAT", "XLAT_M"), lonvar=either("XLONG", "XLONG_M")): if isinstance(latvar, either): @@ -372,17 +311,17 @@ def _is_moving_domain(wrfseq, varname=None, latvar=either("XLAT", "XLAT_M"), lonvar = lonvar(wrfseq) # In case it's just a single file - if not _is_multi_file(wrfseq): + if not is_multi_file(wrfseq): wrfseq = [wrfseq] # Slow, but safe. Compare the corner points to the first item and see # any move. User iterator protocol in case wrfseq is not a list/tuple. - if not _is_mapping(wrfseq): + if not is_mapping(wrfseq): wrf_iter = iter(wrfseq) first_wrfnc = next(wrf_iter) else: entry = wrfseq[next(iter(viewkeys(wrfseq)))] - return _is_moving_domain(entry, varname, latvar, lonvar) + return is_moving_domain(entry, varname, latvar, lonvar) # Quick check on pressure coordinates, bypassing the need to search the # domain corner points @@ -475,10 +414,10 @@ def extract_global_attrs(wrfnc, attrs): else: attrlist = attrs - multifile = _is_multi_file(wrfnc) + multifile = is_multi_file(wrfnc) if multifile: - if not _is_mapping(wrfnc): + if not is_mapping(wrfnc): wrfnc = next(iter(wrfnc)) else: entry = wrfnc[next(iter(viewkeys(wrfnc)))] @@ -487,8 +426,8 @@ def extract_global_attrs(wrfnc, attrs): return {attr:_get_global_attr(wrfnc, attr) for attr in attrlist} def extract_dim(wrfnc, dim): - if _is_multi_file(wrfnc): - if not _is_mapping(wrfnc): + if is_multi_file(wrfnc): + if not is_mapping(wrfnc): wrfnc = next(iter(wrfnc)) else: entry = wrfnc[next(iter(viewkeys(wrfnc)))] @@ -509,7 +448,7 @@ def _combine_dict(wrfdict, varname, timeidx, method, meta): first_key = next(key_iter) keynames.append(first_key) - is_moving = _is_moving_domain(wrfdict, varname) + is_moving = is_moving_domain(wrfdict, varname) first_array = _extract_var(wrfdict[first_key], varname, timeidx, is_moving=is_moving, method=method, @@ -591,7 +530,7 @@ def _find_max_time_size(wrfseq): def _build_data_array(wrfnc, varname, timeidx, is_moving_domain): - multitime = _is_multi_time_req(timeidx) + multitime = is_multi_time_req(timeidx) time_idx_or_slice = timeidx if not multitime else slice(None) var = wrfnc.variables[varname] data = var[time_idx_or_slice, :] @@ -611,10 +550,10 @@ def _build_data_array(wrfnc, varname, timeidx, is_moving_domain): except AttributeError: if is_coordvar(varname): # Coordinate variable (most likely XLAT or XLONG) - lat_coord, lon_coord = _get_coord_pairs(varname) + lat_coord, lon_coord = get_coord_pairs(varname) time_coord = None - if is_moving_domain and _has_time_coord(wrfnc): + if is_moving_domain and has_time_coord(wrfnc): time_coord = "XTIME" else: @@ -769,11 +708,11 @@ def _find_arr_for_time(wrfseq, varname, timeidx, is_moving, meta): # TODO: implement in C def _cat_files(wrfseq, varname, timeidx, is_moving, squeeze, meta): if is_moving is None: - is_moving = _is_moving_domain(wrfseq, varname) + is_moving = is_moving_domain(wrfseq, varname) file_times = extract_times(wrfseq, ALL_TIMES) - multitime = _is_multi_time_req(timeidx) + multitime = is_multi_time_req(timeidx) # For single times, just need to find the ncfile and appropriate # time index, and return that array @@ -920,8 +859,8 @@ def _get_numfiles(wrfseq): # TODO: implement in C def _join_files(wrfseq, varname, timeidx, is_moving, meta): if is_moving is None: - is_moving = _is_moving_domain(wrfseq, varname) - multitime = _is_multi_time_req(timeidx) + is_moving = is_moving_domain(wrfseq, varname) + multitime = is_multi_time_req(timeidx) numfiles = _get_numfiles(wrfseq) maxtimes = _find_max_time_size(wrfseq) @@ -1101,10 +1040,10 @@ def combine_files(wrfseq, varname, timeidx, is_moving=None, method="cat", squeeze=True, meta=True): # Handles generators, single files, lists, tuples, custom classes - wrfseq = _get_iterable(wrfseq) + wrfseq = get_iterable(wrfseq) # Dictionary is unique - if _is_mapping(wrfseq): + if is_mapping(wrfseq): outarr = _combine_dict(wrfseq, varname, timeidx, method, meta) elif method.lower() == "cat": outarr = _cat_files(wrfseq, varname, timeidx, is_moving, @@ -1133,13 +1072,13 @@ def _extract_var(wrfnc, varname, timeidx, is_moving, return cache_var - multitime = _is_multi_time_req(timeidx) - multifile = _is_multi_file(wrfnc) + multitime = is_multi_time_req(timeidx) + multifile = is_multi_file(wrfnc) if not multifile: if xarray_enabled() and meta: if is_moving is None: - is_moving = _is_moving_domain(wrfnc, varname) + is_moving = is_moving_domain(wrfnc, varname) result = _build_data_array(wrfnc, varname, timeidx, is_moving) else: if not multitime: @@ -1167,16 +1106,16 @@ def extract_vars(wrfnc, timeidx, varnames, method="cat", squeeze=True, for var in varlist} # Python 3 compatability -def _npbytes_to_str(var): +def npbytes_to_str(var): return (bytes(c).decode("utf-8") for c in var[:]) def _make_time(timearr): - return dt.datetime.strptime("".join(_npbytes_to_str(timearr)), + return dt.datetime.strptime("".join(npbytes_to_str(timearr)), "%Y-%m-%d_%H:%M:%S") def _file_times(wrfnc, timeidx): - multitime = _is_multi_time_req(timeidx) + multitime = is_multi_time_req(timeidx) if multitime: times = wrfnc.variables["Times"][:,:] for i in py3range(times.shape[0]): @@ -1187,7 +1126,7 @@ def _file_times(wrfnc, timeidx): def extract_times(wrfnc, timeidx): - multi_file = _is_multi_file(wrfnc) + multi_file = is_multi_file(wrfnc) if not multi_file: wrf_list = [wrfnc] else: @@ -1199,9 +1138,9 @@ def extract_times(wrfnc, timeidx): def is_standard_wrf_var(wrfnc, var): - multifile = _is_multi_file(wrfnc) + multifile = is_multi_file(wrfnc) if multifile: - if not _is_mapping(wrfnc): + if not is_mapping(wrfnc): wrfnc = next(iter(wrfnc)) else: entry = wrfnc[next(iter(viewkeys(wrfnc)))] @@ -1268,7 +1207,7 @@ def get_proj_params(wrfnc, timeidx=0, varname=None): "TRUELAT1", "TRUELAT2", "MOAD_CEN_LAT", "STAND_LON", "POLE_LAT", "POLE_LON")) - multitime = _is_multi_time_req(timeidx) + multitime = is_multi_time_req(timeidx) if not multitime: time_idx_or_slice = timeidx else: @@ -1281,7 +1220,7 @@ def get_proj_params(wrfnc, timeidx=0, varname=None): lon_coord = coord_names[0] lat_coord = coord_names[1] else: - lat_coord, lon_coord = _get_coord_pairs(varname) + lat_coord, lon_coord = get_coord_pairs(varname) else: lat_coord, lon_coord = latlon_coordvars(wrfnc.variables) @@ -1439,6 +1378,9 @@ def arg_location(func, argname, args, kwargs): _arg_location = _arg_location2 return _arg_location(func, argname, args, kwargs) + +def psafilepath(): + return os.path.join(os.path.dirname(__file__), "data", "psadilookup.dat") diff --git a/src/wrf/uvdecorator.py b/src/wrf/uvdecorator.py deleted file mode 100644 index 619a21e..0000000 --- a/src/wrf/uvdecorator.py +++ /dev/null @@ -1,229 +0,0 @@ -from __future__ import (absolute_import, division, print_function, - unicode_literals) - -import numpy as np - -import wrapt - -#from .destag import destagger -from .util import iter_left_indexes, py3range, npvalues -from .config import xarray_enabled -from .constants import Constants - -if xarray_enabled(): - from xarray import DataArray - - -# def uvmet_left_iter(): -# """Decorator to handle iterating over leftmost dimensions when using -# multiple files and/or multiple times with the uvmet product. -# -# """ -# @wrapt.decorator -# def func_wrapper(wrapped, instance, args, kwargs): -# u = args[0] -# v = args[1] -# lat = args[2] -# lon = args[3] -# cen_long = args[4] -# cone = args[5] -# -# if u.ndim == lat.ndim: -# num_right_dims = 2 -# is_3d = False -# else: -# num_right_dims = 3 -# is_3d = True -# -# is_stag = False -# if ((u.shape[-1] != lat.shape[-1]) or -# (u.shape[-2] != lat.shape[-2])): -# is_stag = True -# -# if is_3d: -# extra_dim_num = u.ndim - 3 -# else: -# extra_dim_num = u.ndim - 2 -# -# if is_stag: -# u = destagger(u,-1) -# v = destagger(v,-2) -# -# # No special left side iteration, return the function result -# if (extra_dim_num == 0): -# return wrapped(u, v, lat, lon, cen_long, cone) -# -# # Start by getting the left-most 'extra' dims -# outdims = u.shape[0:extra_dim_num] -# extra_dims = list(outdims) # Copy the left-most dims for iteration -# -# # Append the right-most dimensions -# outdims += [2] # For u/v components -# -# #outdims += [u.shape[x] for x in py3range(-num_right_dims,0,1)] -# outdims += list(u.shape[-num_right_dims:]) -# -# output = np.empty(outdims, u.dtype) -# -# for left_idxs in iter_left_indexes(extra_dims): -# # Make the left indexes plus a single slice object -# # The single slice will handle all the dimensions to -# # the right (e.g. [1,1,:]) -# left_and_slice_idxs = tuple([x for x in left_idxs] + [slice(None)]) -# -# new_u = u[left_and_slice_idxs] -# new_v = v[left_and_slice_idxs] -# new_lat = lat[left_and_slice_idxs] -# new_lon = lon[left_and_slice_idxs] -# -# # Call the numerical routine -# result = wrapped(new_u, new_v, new_lat, new_lon, cen_long, cone) -# -# # Note: The 2D version will return a 3D array with a 1 length -# # dimension. Numpy is unable to broadcast this without -# # sqeezing first. -# result = np.squeeze(result) -# -# output[left_and_slice_idxs] = result[:] -# -# return output -# -# return func_wrapper - -def uvmet_left_iter_nocopy(alg_dtype=np.float64): - """Decorator to handle iterating over leftmost dimensions when using - multiple files and/or multiple times with the uvmet product. - - """ - @wrapt.decorator - def func_wrapper(wrapped, instance, args, kwargs): - u = args[0] - v = args[1] - lat = args[2] - lon = args[3] - cen_long = args[4] - cone = args[5] - - orig_dtype = u.dtype - - lat_lon_fixed = False - if lat.ndim == 2: - lat_lon_fixed = True - - if lon.ndim == 2 and not lat_lon_fixed: - raise ValueError("'lat' and 'lon' shape mismatch") - - num_left_dims_u = u.ndim - 2 - num_left_dims_lat = lat.ndim - 2 - - if (num_left_dims_lat > num_left_dims_u): - raise ValueError("number of 'lat' dimensions is greater than 'u'") - - if lat_lon_fixed: - mode = 0 # fixed lat/lon - else: - if num_left_dims_u == num_left_dims_lat: - mode = 1 # lat/lon same as u - else: - mode = 2 # probably 3D with 2D lat/lon plus Time - - has_missing = False - u_arr = u - if isinstance(u, DataArray): - u_arr = npvalues(u) - - v_arr = v - if isinstance(v, DataArray): - v_arr = npvalues(v) - - umissing = Constants.DEFAULT_FILL - if isinstance(u_arr, np.ma.MaskedArray): - has_missing = True - umissing = u_arr.fill_value - - vmissing = Constants.DEFAULT_FILL - if isinstance(v_arr, np.ma.MaskedArray): - has_missing = True - vmissing = v_arr.fill_value - - uvmetmissing = umissing - - is_stag = 0 - if (u.shape[-1] != lat.shape[-1] or u.shape[-2] != lat.shape[-2]): - is_stag = 1 - # Sanity check - if (v.shape[-1] == lat.shape[-1] or v.shape[-2] == lat.shape[-2]): - raise ValueError("u is staggered but v is not") - - if (v.shape[-1] != lat.shape[-1] or v.shape[-2] != lat.shape[-2]): - is_stag = 1 - # Sanity check - if (u.shape[-1] == lat.shape[-1] or u.shape[-2] == lat.shape[-2]): - raise ValueError("v is staggered but u is not") - - - - # No special left side iteration, return the function result - if (num_left_dims_u == 0): - return wrapped(u, v, lat, lon, cen_long, cone, isstag=is_stag, - has_missing=has_missing, umissing=umissing, - vmissing=vmissing, uvmetmissing=uvmetmissing) - - # Initial output is time,nz,2,ny,nx to create contiguous views - outdims = u.shape[0:num_left_dims_u] - extra_dims = tuple(outdims) # Copy the left-most dims for iteration - - outdims += (2,) - - outdims += lat.shape[-2:] - - outview_array = np.empty(outdims, alg_dtype) - - for left_idxs in iter_left_indexes(extra_dims): - left_and_slice_idxs = left_idxs + (slice(None),) - - if mode == 0: - lat_left_and_slice = (slice(None),) - elif mode == 1: - lat_left_and_slice = left_and_slice_idxs - elif mode == 2: - # Only need the left-most - lat_left_and_slice = tuple(left_idx - for left_idx in left_idxs[0:num_left_dims_lat]) - - - new_u = u[left_and_slice_idxs] - new_v = v[left_and_slice_idxs] - new_lat = lat[lat_left_and_slice] - new_lon = lon[lat_left_and_slice] - outview = outview_array[left_and_slice_idxs] - - # Call the numerical routine - result = wrapped(new_u, new_v, new_lat, new_lon, cen_long, cone, - isstag=is_stag, has_missing=has_missing, - umissing=umissing, vmissing=vmissing, - uvmetmissing=uvmetmissing, outview=outview) - - # Make sure the result is the same data as what got passed in - # Can delete this once everything works - if (result.__array_interface__["data"][0] != - outview.__array_interface__["data"][0]): - raise RuntimeError("output array was copied") - - # Need to reshape this so that u_v is left dim, then time (or others), - # then nz, ny, nz - output_dims = (2,) - output_dims += extra_dims - output_dims += lat.shape[-2:] - output = np.empty(output_dims, orig_dtype) - - output[0,:] = outview_array[...,0,:,:].astype(orig_dtype) - output[1,:] = outview_array[...,1,:,:].astype(orig_dtype) - - if has_missing: - output = np.ma.masked_values(output, uvmetmissing) - - return output - - return func_wrapper - diff --git a/src/wrf/vorticity.py b/src/wrf/vorticity.py index 74fd62d..d611d8a 100755 --- a/src/wrf/vorticity.py +++ b/src/wrf/vorticity.py @@ -1,7 +1,7 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) -from .extension import computeavo, computepvo +from .extension import _avo, _pvo from .util import extract_vars, extract_global_attrs from .metadecorators import copy_and_set_metadata @@ -27,7 +27,7 @@ def get_avo(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, dx = attrs["DX"] dy = attrs["DY"] - return computeavo(u, v, msfu, msfv, msfm, cor, dx, dy) + return _avo(u, v, msfu, msfv, msfm, cor, dx, dy) @copy_and_set_metadata(copy_varname="T", name="pvo", @@ -58,5 +58,5 @@ def get_pvo(wrfnc, timeidx=0, method="cat", squeeze=True, cache=None, full_t = t + 300 full_p = p + pb - return computepvo(u, v, full_t, full_p, msfu, msfv, msfm, cor, dx, dy) + return _pvo(u, v, full_t, full_p, msfu, msfv, msfm, cor, dx, dy) \ No newline at end of file diff --git a/src/wrf/wind.py b/src/wrf/wind.py index 1cc36b9..98d5bf3 100755 --- a/src/wrf/wind.py +++ b/src/wrf/wind.py @@ -28,20 +28,20 @@ def _calc_wspd_wdir(u, v, two_d, units): outdims = list(wspd.shape[0:idx_end]) + [2] + list(wspd.shape[idx_end:]) - res = np.zeros(outdims, wspd.dtype) + result = np.zeros(outdims, wspd.dtype) idxs0 = ((0,Ellipsis, slice(None), slice(None), slice(None)) if not two_d else - (1,Ellipsis, slice(None), slice(None))) + (1, Ellipsis, slice(None), slice(None))) idxs1 = ((1, Ellipsis, slice(None), slice(None), slice(None)) if not two_d else (0, Ellipsis, slice(None), slice(None))) - res[idxs0] = wspd[:] - res[idxs1] = wdir[:] + result[idxs0] = wspd[:] + result[idxs1] = wdir[:] - return res + return result @set_wind_metadata(copy_varname=either("P", "PRES"), @@ -76,6 +76,7 @@ def get_v_destag(wrfnc, timeidx=0, method="cat", squeeze=True, v_vars = extract_vars(wrfnc, timeidx, varname, method, squeeze, cache, meta=False) v = destagger(v_vars[varname], -2) + return v @@ -137,5 +138,5 @@ def get_destag_wspd_wdir10(wrfnc, timeidx=0, method="cat", v = (v_vars[varname] if varname == "V10" else destagger(v_vars[varname][...,0,:,:], -2)) - return _calc_wspd_wdir(u,v,True,units) + return _calc_wspd_wdir(u, v, True, units) diff --git a/test/ipynb/WRF_Workshop_Demo.ipynb b/test/ipynb/WRF_Workshop_Demo.ipynb index 471e283..56b17d2 100644 --- a/test/ipynb/WRF_Workshop_Demo.ipynb +++ b/test/ipynb/WRF_Workshop_Demo.ipynb @@ -1,5 +1,72 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Demo for `wrf-python`\n", + "\n", + "# 1.0 Introduction\n", + "\n", + "1) **Created to provide Python with the same functionality found in WRF-NCL**\n", + " * WRF variable computation and extraction\n", + " * 2D and 3D interpolation routines\n", + " * WRF-ARW only\n", + " * Metadata\n", + "2) **Key differences with WRF-NCL**:\n", + " * Plotting is handled through matplotlib (with cartopy or basemap), or PyNGL.\n", + " * Metadata is optional and can be disabled\n", + " \n", + "**`wrf-python` is a work in progress and should be considered \"pre-alpha\". Changes to the API are likely to occur between now and the first official release.** \n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "# 2.0 Data Structures : `numpy.ndarray` and `xarray.DataArray`\n", + "\n", + "\n", + "`numpy.ndarray`:\n", + "----------------\n", + "* Standard array object in Python for array-based computations.\n", + "* Supports all standard compiled types and also Python types.\n", + "* Has methods to reshape, perform mathematical calculations, elementwise operations, etc.\n", + "* Supports missing/fill values using the `numpy.ma.MaskedArray` subclass\n", + "* Does not support metadata.\n", + "\n", + "`xarray.DataArray` (if enabled):\n", + "--------------------------------\n", + "* Adds metadata capabilities to the numpy array by wrapping around it.\n", + "* **HAS A** numpy array, is not a numpy array subclass.\n", + "* Supports many of the numpy methods, but generally requires the numpy array to be extracted out for computations.\n", + "* __Always uses NaN to represent missing/fill values__, rather than the MaskedArray type familiar to numpy users.\n", + "\n", + "\n", + "`npvalues` method:\n", + "------------------\n", + "1. If no missing/fill values, simply extracts the numpy array using the `DataArray.values` property.\n", + "2. If missing/fill values are found, converts the NaN values to the fill values and returns a MaskedArray." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 3.0 Examples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 1: Basic Variable Extraction with `getvar` and Print the DataArray and Numpy Array Result" + ] + }, { "cell_type": "code", "execution_count": null, @@ -22,16 +89,20 @@ "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", - "from matplotlib.cm import get_cmap\n", "from Nio import open_file\n", "from wrf import getvar, npvalues\n", "\n", - "#filename = \"/Users/ladwig/Documents/wrf_files/wrfout_d01_2016-02-25_18_00_00\"\n", - "#filename = \"/Users/ladwig/Documents/wrf_files/wrfout_d01_2010-06-13_21:00:00\"\n", - "filename = \"wrfout_d01_2010-06-13_21:00:00\"\n", + "# Open the output NetCDF file with PyNIO\n", + "filename = \"wrfout_d01_2010-06-13_21-00-00\"\n", "pynio_filename = filename + \".nc\"\n", "ncfile = open_file(pynio_filename)\n", "\n", + "# Alternative using netCDF4-python (for reference)\n", + "# Do 'conda install netcdf4' if the netcdf4 package is not installed\n", + "#from netCDF4 import Dataset as nc\n", + "#filename = \"wrfout_d01_2010-06-13_21-00-00\"\n", + "#ncfile = nc(filename)\n", + "\n", "# Extract the terrain height, which will be returned as an xarray.DataArray object (if available). DataArray\n", "# objects include meta data, similar to NCL's variables.\n", "# Note: can also use the 'ter' variable\n", @@ -45,6 +116,13 @@ "print (terrain_numpy)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 2: Use `getvar` to Extract the 'HGT' Variable and Make a Plot Using Matplotlib with Basemap" + ] + }, { "cell_type": "code", "execution_count": null, @@ -59,10 +137,8 @@ "from Nio import open_file\n", "from wrf import getvar, npvalues\n", "\n", - "\n", - "#filename = \"/Users/ladwig/Documents/wrf_files/wrfout_d01_2016-02-25_18_00_00\"\n", - "#filename = \"/Users/ladwig/Documents/wrf_files/wrfout_d01_2010-06-13_21:00:00\"\n", - "filename = \"wrfout_d01_2010-06-13_21:00:00\"\n", + "# Open the output NetCDF file with PyNIO\n", + "filename = \"wrfout_d01_2010-06-13_21-00-00\"\n", "pynio_filename = filename + \".nc\"\n", "ncfile = open_file(pynio_filename)\n", "\n", @@ -107,6 +183,13 @@ "plt.show()\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 3: Use `getvar` to Compute Dewpoint and Make a Plot Using Matplotlib with Basemap" + ] + }, { "cell_type": "code", "execution_count": null, @@ -122,10 +205,8 @@ "from Nio import open_file\n", "from wrf import getvar, npvalues\n", "\n", - "\n", - "#filename = \"/Users/ladwig/Documents/wrf_files/wrfout_d01_2016-02-25_18_00_00\"\n", - "#filename = \"/Users/ladwig/Documents/wrf_files/wrfout_d01_2010-06-13_21:00:00\"\n", - "filename = \"wrfout_d01_2010-06-13_21:00:00\"\n", + "# Open the output NetCDF file with PyNIO\n", + "filename = \"wrfout_d01_2010-06-13_21-00-00\"\n", "pynio_filename = filename + \".nc\"\n", "ncfile = open_file(pynio_filename)\n", "\n", @@ -174,6 +255,13 @@ "plt.show()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 4: Create a Vertical Cross-Section Using `vertcross` and Make a Plot Using Matplotlib with Basemap" + ] + }, { "cell_type": "code", "execution_count": null, @@ -189,16 +277,14 @@ "from Nio import open_file\n", "from wrf import getvar, vertcross, npvalues\n", "\n", - "# Open the output netcdf file\n", - "#filename = \"/Users/ladwig/Documents/wrf_files/wrfout_d01_2016-02-25_18_00_00\"\n", - "#filename = \"/Users/ladwig/Documents/wrf_files/wrfout_d01_2010-06-13_21:00:00\"\n", - "filename = \"wrfout_d01_2010-06-13_21:00:00\"\n", + "# Open the output NetCDF file with PyNIO\n", + "filename = \"wrfout_d01_2010-06-13_21-00-00\"\n", "pynio_filename = filename + \".nc\"\n", "ncfile = open_file(pynio_filename)\n", "\n", "# Extract pressure and model height\n", - "p = getvar(ncfile, \"pressure\")\n", - "z = getvar(ncfile, \"z\")\n", + "p = getvar(ncfile, \"pressure\", timeidx=0)\n", + "z = getvar(ncfile, \"z\", timeidx=0)\n", "\n", "# Define a horizontal cross section going left to right using a pivot point in the center of the grid\n", "# with an angle of 90.0 degrees (0 degrees is vertical).\n", @@ -246,6 +332,13 @@ "plt.show()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 5: Interpolate Wind and Height to the 500 hPa Level Using `interplevel` and Make a Plot of the 500 hPa Wind Barbs, Wind Speed, and Height Contours Using Matplotlib with Basemap" + ] + }, { "cell_type": "code", "execution_count": null, @@ -260,19 +353,17 @@ "from Nio import open_file\n", "from wrf import getvar, interplevel, npvalues\n", "\n", - "# Open the output netcdf file\n", - "#filename = \"/Users/ladwig/Documents/wrf_files/wrfout_d01_2016-02-25_18_00_00\"\n", - "#filename = \"/Users/ladwig/Documents/wrf_files/wrfout_d01_2010-06-13_21:00:00\"\n", - "filename = \"wrfout_d01_2010-06-13_21:00:00\"\n", + "# Open the output NetCDF file with PyNIO\n", + "filename = \"wrfout_d01_2010-06-13_21-00-00\"\n", "pynio_filename = filename + \".nc\"\n", "ncfile = open_file(pynio_filename)\n", "\n", "# Extract pressure, model height, u and v winds on mass points\n", - "p = getvar(ncfile, \"pressure\")\n", - "z = getvar(ncfile, \"z\", units=\"dm\")\n", - "ua = getvar(ncfile, \"ua\", units=\"kts\")\n", - "va = getvar(ncfile, \"va\", units=\"kts\")\n", - "wspd = getvar(ncfile, \"wspd_wdir\", units=\"kts\")[0,...]\n", + "p = getvar(ncfile, \"pressure\", timeidx=0)\n", + "z = getvar(ncfile, \"z\", timeidx=0, units=\"dm\")\n", + "ua = getvar(ncfile, \"ua\", timeidx=0, units=\"kts\")\n", + "va = getvar(ncfile, \"va\", timeidx=0, units=\"kts\")\n", + "wspd = getvar(ncfile, \"wspd_wdir\", timeidx=0, units=\"kts\")[0,...]\n", "\n", "# Interpolate height, u, and v to to 500 hPa\n", "ht_500 = interplevel(z, p, 500)\n", diff --git a/test/ipynb/nocopy_test.ipynb b/test/ipynb/nocopy_test.ipynb index 9fb799e..600f913 100644 --- a/test/ipynb/nocopy_test.ipynb +++ b/test/ipynb/nocopy_test.ipynb @@ -483,6 +483,67 @@ "print (\"\\n\")\n" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "\n", + "import numpy as np\n", + "\n", + "from wrf import (ALL_TIMES, getvar, cape_2d, cape_3d, extract_vars, tk, destagger, ConversionFactors, Constants)\n", + "from netCDF4 import Dataset as nc\n", + "\n", + "timeidx = ALL_TIMES\n", + "method = \"cat\"\n", + "squeeze=True\n", + "cache=None\n", + "timeidx = None\n", + "\n", + "wrfnc = nc(\"/Users/ladwig/Documents/wrf_files/wrfout_d01_2010-06-13_21:00:00\")\n", + "\n", + "wrfnc = [wrfnc, wrfnc]\n", + "\n", + "varnames = (\"T\", \"P\", \"PB\", \"QVAPOR\", \"PH\", \"PHB\", \"HGT\", \"PSFC\")\n", + "ncvars = extract_vars(wrfnc, timeidx, varnames, method, squeeze, cache,\n", + " meta=True)\n", + "t = ncvars[\"T\"]\n", + "p = ncvars[\"P\"]\n", + "pb = ncvars[\"PB\"]\n", + "qvapor = ncvars[\"QVAPOR\"]\n", + "ph = ncvars[\"PH\"]\n", + "phb = ncvars[\"PHB\"]\n", + "ter = ncvars[\"HGT\"]\n", + "psfc = ncvars[\"PSFC\"]\n", + " \n", + "full_t = t + Constants.T_BASE\n", + "full_p = p + pb\n", + "tkel = tk(full_p, full_t)\n", + " \n", + "geopt = ph + phb\n", + "geopt_unstag = destagger(geopt, -3)\n", + "height = geopt_unstag/Constants.G\n", + " \n", + "# Convert pressure to hPa\n", + "p_hpa = ConversionFactors.PA_TO_HPA * full_p\n", + "psfc_hpa = ConversionFactors.PA_TO_HPA * psfc \n", + "\n", + "ter_follow = 1\n", + "\n", + "cape2d = cape_2d(p_hpa, tkel, qvapor, height, ter, psfc_hpa, ter_follow, \n", + " missing=Constants.DEFAULT_FILL, meta=True)\n", + "\n", + "cape3d = cape_3d(p_hpa, tkel, qvapor, height, ter, psfc_hpa, ter_follow, \n", + " missing=Constants.DEFAULT_FILL, meta=True)\n", + "\n", + "print (cape2d)\n", + "print (cape3d)\n", + "\n" + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/test/utests.py b/test/utests.py index afe9698..fbf8d50 100644 --- a/test/utests.py +++ b/test/utests.py @@ -83,16 +83,29 @@ def make_test(varname, wrf_in, referent, multi=False, repeat=3, pynio=False): nc = Nio.open_file(wrf_file) in_wrfnc = [nc for i in xrange(repeat)] + # Note: remove this after cloudfrac is included in NCL + # For now just make sure it runs + if varname == "cloudfrac": + my_vals = getvar(in_wrfnc, "cloudfrac", timeidx=timeidx) + return + + refnc = NetCDF(referent) if not multi: ref_vals = refnc.variables[varname][:] else: data = refnc.variables[varname][:] - if varname != "uvmet" and varname != "uvmet10": + if (varname != "uvmet" and varname != "uvmet10" + and varname != "cape_2d" and varname != "cape_3d"): new_dims = [repeat] + [x for x in data.shape] - else: + elif (varname == "uvmet" or varname == "uvmet10" + or varname == "cape_3d"): new_dims = [2] + [repeat] + [x for x in data.shape[1:]] + elif (varname == "cape_2d"): + new_dims = [4] + [repeat] + [x for x in data.shape[1:]] + + masked=False if (isinstance(data, ma.core.MaskedArray)): masked=True @@ -103,24 +116,36 @@ def make_test(varname, wrf_in, referent, multi=False, repeat=3, pynio=False): ref_vals = ma.asarray(n.zeros(new_dims, data.dtype)) for i in xrange(repeat): - if varname != "uvmet" and varname != "uvmet10": + if (varname != "uvmet" and varname != "uvmet10" + and varname != "cape_2d" and varname != "cape_3d"): ref_vals[i,:] = data[:] if masked: ref_vals.mask[i,:] = data.mask[:] - else: + elif (varname == "uvmet" or varname == "uvmet10" + or varname=="cape_3d"): ref_vals[0, i, :] = data[0,:] ref_vals[1, i, :] = data[1,:] if masked: - ref_vals.mask[0,i,:] = data.mask[:] - ref_vals.mask[1,i,:] = data.mask[:] + ref_vals.mask[0,i,:] = data.mask[0,:] + ref_vals.mask[1,i,:] = data.mask[1,:] + elif varname == "cape_2d": + ref_vals[0, i, :] = data[0,:] + ref_vals[1, i, :] = data[1,:] + ref_vals[2, i, :] = data[2,:] + ref_vals[3, i, :] = data[3,:] + if masked: + ref_vals.mask[0,i,:] = data.mask[0,:] + ref_vals.mask[1,i,:] = data.mask[1,:] + ref_vals.mask[2,i,:] = data.mask[2,:] + ref_vals.mask[3,i,:] = data.mask[3,:] if (varname == "tc"): my_vals = getvar(in_wrfnc, "temp", timeidx=timeidx, units="c") - tol = 0 + tol = 1/100. atol = .1 # Note: NCL uses 273.16 as conversion for some reason nt.assert_allclose(npvalues(my_vals), ref_vals, tol, atol) elif (varname == "pw"): @@ -131,18 +156,30 @@ def make_test(varname, wrf_in, referent, multi=False, repeat=3, pynio=False): nt.assert_allclose(npvalues(my_vals), ref_vals, tol, atol) elif (varname == "cape_2d"): cape_2d = getvar(in_wrfnc, varname, timeidx=timeidx) - tol = 0/100. # Not sure why different, F77 vs F90? - atol = .2 - nt.assert_allclose(npvalues(cape_2d), ref_vals, tol, atol) + tol = 0/100. + atol = 200.0 + # Let's only compare CAPE values until the F90 changes are + # merged back in to NCL. The modifications to the R and CP + # changes TK enough that non-lifting parcels could lift, thus + # causing wildly different values in LCL + nt.assert_allclose(npvalues(cape_2d[0,:]), ref_vals[0,:], tol, atol) elif (varname == "cape_3d"): cape_3d = getvar(in_wrfnc, varname, timeidx=timeidx) - tol = 0/100. # Not sure why different, F77 vs F90? - atol = .01 + # Changing the R and CP constants, while keeping TK within + # 2%, can lead to some big changes in CAPE. Tolerances + # have been set wide when comparing the with the original + # NCL. Change back when the F90 code is merged back with + # NCL + tol = 0/100. + atol = 200.0 + + #print n.amax(n.abs(npvalues(cape_3d[0,:]) - ref_vals[0,:])) nt.assert_allclose(npvalues(cape_3d), ref_vals, tol, atol) else: my_vals = getvar(in_wrfnc, varname, timeidx=timeidx) - tol = 0/100. - atol = 0.0001 + tol = 2/100. + atol = 0.1 + #print (n.amax(n.abs(npvalues(my_vals) - ref_vals))) nt.assert_allclose(npvalues(my_vals), ref_vals, tol, atol) @@ -289,10 +326,11 @@ def make_interp_test(varname, wrf_in, referent, multi=False, timeidx=timeidx, log_p=True) - tol = 0/100. + tol = 5/100. atol = 0.0001 field = n.squeeze(field) + #print (n.amax(n.abs(npvalues(field) - fld_tk_theta))) nt.assert_allclose(npvalues(field), fld_tk_theta, tol, atol) # Tk to theta-e @@ -310,10 +348,11 @@ def make_interp_test(varname, wrf_in, referent, multi=False, timeidx=timeidx, log_p=True) - tol = 0/100. - atol = 0.0001 + tol = 3/100. + atol = 50.0001 field = n.squeeze(field) + #print (n.amax(n.abs(npvalues(field) - fld_tk_theta_e)/fld_tk_theta_e)*100) nt.assert_allclose(npvalues(field), fld_tk_theta_e, tol, atol) # Tk to pressure @@ -333,6 +372,7 @@ def make_interp_test(varname, wrf_in, referent, multi=False, field = n.squeeze(field) + #print (n.amax(n.abs(npvalues(field) - fld_tk_pres))) nt.assert_allclose(npvalues(field), fld_tk_pres, tol, atol) # Tk to geoht_msl @@ -350,6 +390,7 @@ def make_interp_test(varname, wrf_in, referent, multi=False, log_p=True) field = n.squeeze(field) + #print (n.amax(n.abs(npvalues(field) - fld_tk_ght_msl))) nt.assert_allclose(npvalues(field), fld_tk_ght_msl, tol, atol) # Tk to geoht_agl @@ -367,6 +408,7 @@ def make_interp_test(varname, wrf_in, referent, multi=False, log_p=True) field = n.squeeze(field) + #print (n.amax(n.abs(npvalues(field) - fld_tk_ght_agl))) nt.assert_allclose(npvalues(field), fld_tk_ght_agl, tol, atol) # Hgt to pressure @@ -385,6 +427,7 @@ def make_interp_test(varname, wrf_in, referent, multi=False, log_p=True) field = n.squeeze(field) + #print (n.amax(n.abs(npvalues(field) - fld_ht_pres))) nt.assert_allclose(npvalues(field), fld_ht_pres, tol, atol) # Pressure to theta @@ -403,6 +446,7 @@ def make_interp_test(varname, wrf_in, referent, multi=False, log_p=True) field = n.squeeze(field) + #print (n.amax(n.abs(npvalues(field) - fld_pres_theta))) nt.assert_allclose(npvalues(field), fld_pres_theta, tol, atol) # Theta-e to pres @@ -421,6 +465,7 @@ def make_interp_test(varname, wrf_in, referent, multi=False, log_p=True) field = n.squeeze(field) + #print (n.amax(n.abs(npvalues(field) - fld_thetae_pres))) nt.assert_allclose(npvalues(field), fld_thetae_pres, tol, atol) return test @@ -438,7 +483,7 @@ if __name__ == "__main__": "geopt", "helicity", "lat", "lon", "omg", "p", "pressure", "pvo", "pw", "rh2", "rh", "slp", "ter", "td2", "td", "tc", "theta", "tk", "tv", "twb", "updraft_helicity", "ua", "va", - "wa", "uvmet10", "uvmet", "z", "ctt"] + "wa", "uvmet10", "uvmet", "z", "ctt", "cloudfrac"] interp_methods = ["interplevel", "vertcross", "interpline", "vinterp"] try: @@ -490,6 +535,6 @@ if __name__ == "__main__": test_interp_func1) setattr(WRFInterpTest, 'test_pynio_multi_{0}'.format(method), test_interp_func2) - + ut.main() \ No newline at end of file diff --git a/test/viewtest.py b/test/viewtest.py index 3f672b9..5dab455 100644 --- a/test/viewtest.py +++ b/test/viewtest.py @@ -1,21 +1,26 @@ import numpy as np import wrf._wrffortran +errlen = int(wrf._wrffortran.constants.errlen) + a = np.ones((3,3,3)) b = np.zeros((3,3,3,3)) +c = np.zeros(errlen, "c") errstat = np.array(0) -errmsg = np.zeros(512, "c") +errmsg = np.zeros(errlen, "c") + +c[:] = "Test String" for i in xrange(2): outview = b[i,:] outview = outview.T - q = wrf._wrffortran.testfunc(a,outview,errstat=errstat,errstr=errmsg) - q[1,1,1] = 100 + q = wrf._wrffortran.testfunc(a,outview,c,errstat=errstat,errmsg=errmsg) + print errstat + -print errstat -print b -str_bytes = (bytes(c).decode("utf-8") for c in errmsg[:]) +str_bytes = (bytes(char).decode("utf-8") for char in errmsg[:]) +print repr(errmsg) print "".join(str_bytes).strip() \ No newline at end of file