Browse Source

Merge branch 'release/1.3.0'

main 1.3.0
Bill Ladwig 6 years ago
parent
commit
059b97468c
  1. 11
      .circleci/conda_env.yml
  2. 73
      .circleci/config.yml
  3. 38
      LICENSE
  4. 2
      build_scripts/chey_intel_mkl_omp.sh
  5. 2
      build_scripts/gnu_no_omp.sh
  6. 2
      build_scripts/gnu_omp.sh
  7. 2
      build_scripts/win_mingw_no_omp.bat
  8. 2
      build_scripts/win_mingw_omp.bat
  9. 2
      build_scripts/win_msvc_mingw_no_omp.bat
  10. 2
      build_scripts/win_msvc_mingw_omp.bat
  11. BIN
      doc/source/_static/images/basemap_500.png
  12. BIN
      doc/source/_static/images/basemap_front.png
  13. BIN
      doc/source/_static/images/basemap_slp.png
  14. BIN
      doc/source/_static/images/cartopy_500.png
  15. BIN
      doc/source/_static/images/cartopy_cross.png
  16. BIN
      doc/source/_static/images/cartopy_slp.png
  17. BIN
      doc/source/_static/images/cross_mtns.png
  18. BIN
      doc/source/_static/images/matthew.png
  19. BIN
      doc/source/_static/images/matthew_cross.png
  20. 4
      doc/source/_templates/product_table.txt
  21. 119
      doc/source/_templates/subproducts.txt
  22. 7
      doc/source/conf.py
  23. 14
      doc/source/diagnostics.rst
  24. 17
      doc/source/internal_api/index.rst
  25. 164
      doc/source/new.rst
  26. 308
      doc/source/plot.rst
  27. 8
      doc/source/tutorial.rst
  28. 2
      fortran/calc_uh.f90
  29. 4
      fortran/wrf_constants.f90
  30. 11
      fortran/wrf_relhl.f90
  31. 108
      fortran/wrf_user.f90
  32. 6
      fortran/wrf_vinterp.f90
  33. 795
      fortran/wrffortran.pyf
  34. 4
      requirements.txt
  35. 8
      setup.py
  36. 43
      src/wrf/computation.py
  37. 2
      src/wrf/destag.py
  38. 55
      src/wrf/extension.py
  39. 408
      src/wrf/g_cape.py
  40. 335
      src/wrf/g_cloudfrac.py
  41. 8
      src/wrf/g_helicity.py
  42. 192
      src/wrf/g_latlon.py
  43. 280
      src/wrf/g_uvmet.py
  44. 282
      src/wrf/g_wind.py
  45. 261
      src/wrf/interp.py
  46. 25
      src/wrf/interputils.py
  47. 7
      src/wrf/latlonutils.py
  48. 154
      src/wrf/metadecorators.py
  49. 56
      src/wrf/projection.py
  50. 72
      src/wrf/routines.py
  51. 122
      src/wrf/specialdec.py
  52. 23
      src/wrf/util.py
  53. 2
      src/wrf/version.py
  54. BIN
      test/ci_tests/ci_result_file.nc
  55. BIN
      test/ci_tests/ci_test_file.nc
  56. 13
      test/ci_tests/make_test_file.py
  57. 10
      test/ci_tests/utests.py
  58. 257
      test/ipynb/Doc_Examples.ipynb
  59. 195
      test/ipynb/WRF_python_demo.ipynb
  60. 519
      test/ncl_get_var.ncl
  61. BIN
      test/plot_tests/d01/avo.png
  62. BIN
      test/plot_tests/d01/cape2d_only.png
  63. BIN
      test/plot_tests/d01/cape3d_only.png
  64. BIN
      test/plot_tests/d01/cape_2d.png
  65. BIN
      test/plot_tests/d01/cape_3d.png
  66. BIN
      test/plot_tests/d01/cfrac.png
  67. BIN
      test/plot_tests/d01/cin2d_only.png
  68. BIN
      test/plot_tests/d01/cin3d_only.png
  69. BIN
      test/plot_tests/d01/ctt.png
  70. BIN
      test/plot_tests/d01/dbz.png
  71. BIN
      test/plot_tests/d01/eth.png
  72. BIN
      test/plot_tests/d01/geopt.png
  73. BIN
      test/plot_tests/d01/helicity.png
  74. BIN
      test/plot_tests/d01/high_cfrac.png
  75. BIN
      test/plot_tests/d01/lat.png
  76. BIN
      test/plot_tests/d01/lcl.png
  77. BIN
      test/plot_tests/d01/lfc.png
  78. BIN
      test/plot_tests/d01/lon.png
  79. BIN
      test/plot_tests/d01/low_cfrac.png
  80. BIN
      test/plot_tests/d01/mdbz.png
  81. BIN
      test/plot_tests/d01/mid_cfrac.png
  82. BIN
      test/plot_tests/d01/omg.png
  83. BIN
      test/plot_tests/d01/p.png
  84. BIN
      test/plot_tests/d01/pressure.png
  85. BIN
      test/plot_tests/d01/pvo.png
  86. BIN
      test/plot_tests/d01/pw.png
  87. BIN
      test/plot_tests/d01/rh.png
  88. BIN
      test/plot_tests/d01/rh2.png
  89. BIN
      test/plot_tests/d01/slp.png
  90. BIN
      test/plot_tests/d01/tc.png
  91. BIN
      test/plot_tests/d01/td.png
  92. BIN
      test/plot_tests/d01/td2.png
  93. BIN
      test/plot_tests/d01/ter.png
  94. BIN
      test/plot_tests/d01/theta.png
  95. BIN
      test/plot_tests/d01/tk.png
  96. BIN
      test/plot_tests/d01/tv.png
  97. BIN
      test/plot_tests/d01/twb.png
  98. BIN
      test/plot_tests/d01/ua.png
  99. BIN
      test/plot_tests/d01/updraft_helicity.png
  100. BIN
      test/plot_tests/d01/uvmet.png
  101. Some files were not shown because too many files have changed in this diff Show More

11
.circleci/conda_env.yml

@ -0,0 +1,11 @@
name: wrf-python
channels:
- conda-forge
dependencies:
- gcc
- setuptools
- python
- numpy
- wrapt
- xarray
- netcdf4

73
.circleci/config.yml

@ -0,0 +1,73 @@
# Python CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-python/ for more details
#
version: 2
jobs:
build:
docker:
# specify the version you desire here
# use `-browsers` prefix for selenium tests, e.g. `3.6.1-browsers`
- image: circleci/python:3.6.1
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/postgres:9.4
working_directory: ~/repo
steps:
- checkout
# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum ".circleci/conda_env.yml" }}
- run:
name: install conda and dependencies
command: |
test -d ~/miniconda3 && exit 0
echo "Installing a fresh version of Miniconda."
MINICONDA_URL="https://repo.continuum.io/miniconda"
MINICONDA_FILE="Miniconda3-latest-Linux-x86_64.sh"
curl -L -O "${MINICONDA_URL}/${MINICONDA_FILE}"
bash $MINICONDA_FILE -b
source ~/miniconda3/bin/activate root
conda env create -f .circleci/conda_env.yml
- save_cache:
paths:
- ~/miniconda3
key: v1-dependencies-{{ checksum ".circleci/conda_env.yml" }}
- run:
name: build wrf-python
command: |
source ~/miniconda3/bin/activate wrf-python
cd fortran/build_help
gfortran -o sizes -fopenmp omp_sizes.f90
LD_LIBRARY_PATH=~/miniconda3/envs/wrf-python/lib python sub_sizes.py
cd ..
gfortran -E ompgen.F90 -fopenmp -cpp -o omp.f90
cd ..
python setup.py config_fc --f90flags="-mtune=generic -fopenmp" build_ext --libraries="gomp" build
python setup.py install --single-version-externally-managed --record=record.txt
# run tests!
# this example uses Django's built-in test-runner
# other common Python testing frameworks include pytest and nose
# https://pytest.org
# https://nose.readthedocs.io
- run:
name: run tests
command: |
source ~/miniconda3/bin/activate wrf-python
cd test/ci_tests
python utests.py
- store_artifacts:
path: test-reports
destination: test-reports

38
LICENSE

@ -1,32 +1,14 @@
PLEASE READ THIS SOFTWARE LICENSE ("LICENSE") CAREFULLY BEFORE USING THE Copyright 2016 University Corporation for Atmospheric Research
SOFTWARE. BY USING THE SOFTWARE, YOU ARE AGREEING TO BE BOUND BY ALL OF THE
TERMS OF THIS LICENSE. IF YOU DO NOT AGREE TO THE TERMS OF THIS LICENSE,
DO NOT USE THE SOFTWARE.
Copyright © 2016 the University Corporation for Atmospheric Research ("UCAR"). Licensed under the Apache License, Version 2.0 (the "License");
All rights reserved. Developed by NCAR's Computational and Information Systems you may not use this file except in compliance with the License.
Laboratory, UCAR, www2.cisl.ucar.edu. You may obtain a copy of the License at
Redistribution and use of the Software in source and binary forms, with or http://www.apache.org/licenses/LICENSE-2.0
without modification, is permitted provided that the following conditions
are met:
- Neither the names of NCAR's Computational and Information Systems Laboratory, Unless required by applicable law or agreed to in writing, software
the University Corporation for Atmospheric Research, nor the names of its distributed under the License is distributed on an "AS IS" BASIS,
sponsors or contributors may be used to endorse or promote products derived WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
from this Software without specific prior written permission. See the License for the specific language governing permissions and
limitations under the License.
- Redistributions of source code must retain the above copyright notices, this
list of conditions, and the disclaimer below.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions, and the disclaimer below in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.

2
build_scripts/chey_intel_mkl_omp.sh

@ -7,7 +7,7 @@ python sub_sizes.py
cd .. cd ..
ifort ompgen.F90 -qopenmp -fpp -save-temps > /dev/null 2>&1 ifort ompgen.F90 -qopenmp -fpp -save-temps > /dev/null 2>&1
mv ompgen.i90 omp.f90 mv ompgen.i90 omp.f90
f2py *.f90 -m _wrffortran -h wrffortran.pyf --overwrite-signature #f2py *.f90 -m _wrffortran -h wrffortran.pyf --overwrite-signature
cd .. cd ..
python setup.py clean --all python setup.py clean --all

2
build_scripts/gnu_no_omp.sh

@ -2,7 +2,7 @@
cd ../fortran cd ../fortran
gfortran -E ompgen.F90 -cpp -o omp.f90 gfortran -E ompgen.F90 -cpp -o omp.f90
f2py *.f90 -m _wrffortran -h wrffortran.pyf --overwrite-signature #f2py *.f90 -m _wrffortran -h wrffortran.pyf --overwrite-signature
cd .. cd ..
python setup.py clean --all python setup.py clean --all

2
build_scripts/gnu_omp.sh

@ -6,7 +6,7 @@ python sub_sizes.py
cd .. cd ..
gfortran -E ompgen.F90 -fopenmp -cpp -o omp.f90 gfortran -E ompgen.F90 -fopenmp -cpp -o omp.f90
f2py *.f90 -m _wrffortran -h wrffortran.pyf --overwrite-signature #f2py *.f90 -m _wrffortran -h wrffortran.pyf --overwrite-signature
cd .. cd ..
python setup.py clean --all python setup.py clean --all

2
build_scripts/win_mingw_no_omp.bat

@ -1,7 +1,7 @@
cd ../fortran cd ../fortran
CALL gfortran -E ompgen.F90 -cpp -o omp.f90 CALL gfortran -E ompgen.F90 -cpp -o omp.f90
REM Wildcards not working on Windows for some reason REM Wildcards not working on Windows for some reason
CALL f2py -m _wrffortran -h wrffortran.pyf --overwrite-signature wrf_constants.f90 wrf_testfunc.f90 wrf_user.f90 rip_cape.f90 wrf_cloud_fracf.f90 wrf_fctt.f90 wrf_user_dbz.f90 wrf_relhl.f90 calc_uh.f90 wrf_user_latlon_routines.f90 wrf_pvo.f90 eqthecalc.f90 wrf_rip_phys_routines.f90 wrf_pw.f90 wrf_vinterp.f90 wrf_wind.f90 omp.f90 REM CALL f2py -m _wrffortran -h wrffortran.pyf --overwrite-signature wrf_constants.f90 wrf_testfunc.f90 wrf_user.f90 rip_cape.f90 wrf_cloud_fracf.f90 wrf_fctt.f90 wrf_user_dbz.f90 wrf_relhl.f90 calc_uh.f90 wrf_user_latlon_routines.f90 wrf_pvo.f90 eqthecalc.f90 wrf_rip_phys_routines.f90 wrf_pw.f90 wrf_vinterp.f90 wrf_wind.f90 omp.f90
cd .. cd ..
CALL python setup.py clean --all CALL python setup.py clean --all

2
build_scripts/win_mingw_omp.bat

@ -5,7 +5,7 @@ CALL python sub_sizes.py
cd .. cd ..
CALL gfortran -E ompgen.F90 -cpp -fopenmp -o omp.f90 CALL gfortran -E ompgen.F90 -cpp -fopenmp -o omp.f90
REM Wildcards not working on Windows for some reason REM Wildcards not working on Windows for some reason
CALLf2py -m _wrffortran -h wrffortran.pyf --overwrite-signature wrf_constants.f90 wrf_testfunc.f90 wrf_user.f90 rip_cape.f90 wrf_cloud_fracf.f90 wrf_fctt.f90 wrf_user_dbz.f90 wrf_relhl.f90 calc_uh.f90 wrf_user_latlon_routines.f90 wrf_pvo.f90 eqthecalc.f90 wrf_rip_phys_routines.f90 wrf_pw.f90 wrf_vinterp.f90 wrf_wind.f90 omp.f90 REM CALL f2py -m _wrffortran -h wrffortran.pyf --overwrite-signature wrf_constants.f90 wrf_testfunc.f90 wrf_user.f90 rip_cape.f90 wrf_cloud_fracf.f90 wrf_fctt.f90 wrf_user_dbz.f90 wrf_relhl.f90 calc_uh.f90 wrf_user_latlon_routines.f90 wrf_pvo.f90 eqthecalc.f90 wrf_rip_phys_routines.f90 wrf_pw.f90 wrf_vinterp.f90 wrf_wind.f90 omp.f90
cd .. cd ..
CALL python setup.py clean --all CALL python setup.py clean --all

2
build_scripts/win_msvc_mingw_no_omp.bat

@ -1,7 +1,7 @@
cd ../fortran cd ../fortran
CALL gfortran -E ompgen.F90 -cpp -o omp.f90 CALL gfortran -E ompgen.F90 -cpp -o omp.f90
REM Wildcards not working on Windows for some reason REM Wildcards not working on Windows for some reason
CALL f2py -m _wrffortran -h wrffortran.pyf --overwrite-signature wrf_constants.f90 wrf_testfunc.f90 wrf_user.f90 rip_cape.f90 wrf_cloud_fracf.f90 wrf_fctt.f90 wrf_user_dbz.f90 wrf_relhl.f90 calc_uh.f90 wrf_user_latlon_routines.f90 wrf_pvo.f90 eqthecalc.f90 wrf_rip_phys_routines.f90 wrf_pw.f90 wrf_vinterp.f90 wrf_wind.f90 omp.f90 REM CALL f2py -m _wrffortran -h wrffortran.pyf --overwrite-signature wrf_constants.f90 wrf_testfunc.f90 wrf_user.f90 rip_cape.f90 wrf_cloud_fracf.f90 wrf_fctt.f90 wrf_user_dbz.f90 wrf_relhl.f90 calc_uh.f90 wrf_user_latlon_routines.f90 wrf_pvo.f90 eqthecalc.f90 wrf_rip_phys_routines.f90 wrf_pw.f90 wrf_vinterp.f90 wrf_wind.f90 omp.f90
cd .. cd ..
CALL python setup.py clean --all CALL python setup.py clean --all

2
build_scripts/win_msvc_mingw_omp.bat

@ -5,7 +5,7 @@ CALL python sub_sizes.py
cd .. cd ..
CALL gfortran -E ompgen.F90 -cpp -fopenmp -o omp.f90 CALL gfortran -E ompgen.F90 -cpp -fopenmp -o omp.f90
REM Wildcards not working on Windows for some reason REM Wildcards not working on Windows for some reason
CALL f2py -m _wrffortran -h wrffortran.pyf --overwrite-signature wrf_constants.f90 wrf_testfunc.f90 wrf_user.f90 rip_cape.f90 wrf_cloud_fracf.f90 wrf_fctt.f90 wrf_user_dbz.f90 wrf_relhl.f90 calc_uh.f90 wrf_user_latlon_routines.f90 wrf_pvo.f90 eqthecalc.f90 wrf_rip_phys_routines.f90 wrf_pw.f90 wrf_vinterp.f90 wrf_wind.f90 omp.f90 REM CALL f2py -m _wrffortran -h wrffortran.pyf --overwrite-signature wrf_constants.f90 wrf_testfunc.f90 wrf_user.f90 rip_cape.f90 wrf_cloud_fracf.f90 wrf_fctt.f90 wrf_user_dbz.f90 wrf_relhl.f90 calc_uh.f90 wrf_user_latlon_routines.f90 wrf_pvo.f90 eqthecalc.f90 wrf_rip_phys_routines.f90 wrf_pw.f90 wrf_vinterp.f90 wrf_wind.f90 omp.f90
cd .. cd ..
CALL python setup.py clean --all CALL python setup.py clean --all

BIN
doc/source/_static/images/basemap_500.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 KiB

After

Width:  |  Height:  |  Size: 148 KiB

BIN
doc/source/_static/images/basemap_front.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 73 KiB

BIN
doc/source/_static/images/basemap_slp.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 96 KiB

BIN
doc/source/_static/images/cartopy_500.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 KiB

After

Width:  |  Height:  |  Size: 192 KiB

BIN
doc/source/_static/images/cartopy_cross.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 21 KiB

BIN
doc/source/_static/images/cartopy_slp.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

After

Width:  |  Height:  |  Size: 116 KiB

BIN
doc/source/_static/images/cross_mtns.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
doc/source/_static/images/matthew.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 80 KiB

BIN
doc/source/_static/images/matthew_cross.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 18 KiB

4
doc/source/_templates/product_table.txt

@ -9,9 +9,9 @@
| | | | | | | | | |
| | | degF | | | | | degF | |
+--------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ +--------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| cape_2d | 2D cape (mcape/mcin/lcl/lfc) | J kg-1 ; J kg-1 ; m ; m | **missing** (float): Fill value for output only | | cape_2d | 2D CAPE (MCAPE/MCIN/LCL/LFC) | J kg-1 ; J kg-1 ; m ; m | **missing** (float): Fill value for output only |
+--------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ +--------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| cape_3d | 3D cape and cin | J kg-1 | **missing** (float): Fill value for output only | | cape_3d | 3D CAPE and CIN | J kg-1 | **missing** (float): Fill value for output only |
+--------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ +--------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| ctt | Cloud Top Temperature | degC | **fill_nocloud** (boolean): Set to True to use fill values for cloud free regions rather than surface temperature. Default is *False*. | | ctt | Cloud Top Temperature | degC | **fill_nocloud** (boolean): Set to True to use fill values for cloud free regions rather than surface temperature. Default is *False*. |
| | | | | | | | | |

119
doc/source/_templates/subproducts.txt

@ -0,0 +1,119 @@
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| Variable Name | Calculated From | Description | Available Units | Additional Keyword Arguments |
+====================+======================+===============================================================+=============================+=========================================================================================================================================================+
| mcape | cape_2d | 2D Max CAPE | J kg-1 | **missing** (float): Fill value for output only |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| mcin | cape_2d | 2D Max CIN | J kg-1 | **missing** (float): Fill value for output only |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| lcl | cape_2d | 2D Lifted Condensation Level | J kg-1 | **missing** (float): Fill value for output only |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| lfc | cape_2d | 2D Level of Free Convection | J kg-1 | **missing** (float): Fill value for output only |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| cape3d_only | cape_3d | 3D CAPE | J kg-1 | **missing** (float): Fill value for output only |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| cin3d_only | cape_3d | 3D CIN | J kg-1 | **missing** (float): Fill value for output only |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| low_cloudfrac | cloudfrac | Cloud Fraction for Low Clouds | % | **vert_type** (str): The vertical coordinate type for the cloud thresholds. Must be 'height_agl', 'height_msl', or 'pres'. Default is 'height_agl'. |
| | | | | |
| | | | | **low_thresh** (float): The low cloud threshold (meters for 'height_agl' and 'height_msl', pascals for 'pres'). Default is 300 m (97000 Pa) |
| | | | | |
| | | | | **mid_thresh** (float): The mid cloud threshold (meters for 'height_agl' and 'height_msl', pascals for 'pres'). Default is 2000 m (80000 Pa) |
| | | | | |
| | | | | **high_thresh** (float): The high cloud threshold (meters for 'height_agl' and 'height_msl', pascals for 'pres'). Default is 6000 m (45000 Pa) |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| mid_cloudfrac | cloudfrac | Cloud Fraction for Mid Clouds | % | **vert_type** (str): The vertical coordinate type for the cloud thresholds. Must be 'height_agl', 'height_msl', or 'pres'. Default is 'height_agl'. |
| | | | | |
| | | | | **low_thresh** (float): The low cloud threshold (meters for 'height_agl' and 'height_msl', pascals for 'pres'). Default is 300 m (97000 Pa) |
| | | | | |
| | | | | **mid_thresh** (float): The mid cloud threshold (meters for 'height_agl' and 'height_msl', pascals for 'pres'). Default is 2000 m (80000 Pa) |
| | | | | |
| | | | | **high_thresh** (float): The high cloud threshold (meters for 'height_agl' and 'height_msl', pascals for 'pres'). Default is 6000 m (45000 Pa) |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| high_cloudfrac | cloudfrac | Cloud Fraction for High Clouds | % | **vert_type** (str): The vertical coordinate type for the cloud thresholds. Must be 'height_agl', 'height_msl', or 'pres'. Default is 'height_agl'. |
| | | | | |
| | | | | **low_thresh** (float): The low cloud threshold (meters for 'height_agl' and 'height_msl', pascals for 'pres'). Default is 300 m (97000 Pa) |
| | | | | |
| | | | | **mid_thresh** (float): The mid cloud threshold (meters for 'height_agl' and 'height_msl', pascals for 'pres'). Default is 2000 m (80000 Pa) |
| | | | | |
| | | | | **high_thresh** (float): The high cloud threshold (meters for 'height_agl' and 'height_msl', pascals for 'pres'). Default is 6000 m (45000 Pa) |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| uvmet_wspd | uvmet_wspd_wdir | Wind Speed | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | | |
| | | Rotated to Earth Coordinates | km h-1 | |
| | | | | |
| | | | mi h-1 | |
| | | | | |
| | | | kt | |
| | | | | |
| | | | ft s-1 | |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| uvmet_wdir | uvmet_wspd_wdir | Wind Direction (wind_from_direction) | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | | |
| | | Rotated to Earth Coordinates | km h-1 | |
| | | | | |
| | | | mi h-1 | |
| | | | | |
| | | | kt | |
| | | | | |
| | | | ft s-1 | |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| uvmet10_wspd | uvmet10_wspd_wdir | 10m Wind Speed | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | | |
| | | Rotated to Earth Coordinates | km h-1 | |
| | | | | |
| | | | mi h-1 | |
| | | | | |
| | | | kt | |
| | | | | |
| | | | ft s-1 | |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| uvmet10_wdir | uvmet10_wspd_wdir | 10m Wind Direction (wind_from_direction) | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | | |
| | | Rotated to Earth Coordinates | km h-1 | |
| | | | | |
| | | | mi h-1 | |
| | | | | |
| | | | kt | |
| | | | | |
| | | | ft s-1 | |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| wspd | wspd_wdir | Wind Speed | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | | |
| | | in Grid Coordinates | km h-1 | |
| | | | | |
| | | | mi h-1 | |
| | | | | |
| | | | kt | |
| | | | | |
| | | | ft s-1 | |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| wdir | wspd_wdir | Wind Direction (wind_from_direction) | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | | |
| | | in Grid Coordinates | km h-1 | |
| | | | | |
| | | | mi h-1 | |
| | | | | |
| | | | kt | |
| | | | | |
| | | | ft s-1 | |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| wspd10 | wspd_wdir10 | 10m Wind Speed | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | | |
| | | in Grid Coordinates | km h-1 | |
| | | | | |
| | | | mi h-1 | |
| | | | | |
| | | | kt | |
| | | | | |
| | | | ft s-1 | |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
| wdir10 | wspd_wdir10 | 10m Wind Direction (wind_from_direction) | m s-1 | **units** (str) : Set to desired units. Default is *'m s-1'*. |
| | | | | |
| | | in Grid Coordinates | km h-1 | |
| | | | | |
| | | | mi h-1 | |
| | | | | |
| | | | kt | |
| | | | | |
| | | | ft s-1 | |
+--------------------+----------------------+---------------------------------------------------------------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+

7
doc/source/conf.py

@ -75,15 +75,18 @@ extensions = [
'sphinx.ext.napoleon', 'sphinx.ext.napoleon',
'sphinx.ext.autosummary', 'sphinx.ext.autosummary',
'sphinx.ext.intersphinx', 'sphinx.ext.intersphinx',
'sphinx.ext.mathjax'
] ]
#mathjax_path = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML"
intersphinx_mapping = { intersphinx_mapping = {
'matplotlib': ('http://matplotlib.org/', None), 'matplotlib': ('http://matplotlib.org/', None),
'basemap' : ('http://matplotlib.org/basemap/', None), 'basemap' : ('http://matplotlib.org/basemap/', None),
'cartopy' : (
'http://scitools.org.uk/cartopy/docs/latest/index.html', None),
'python': ('http://docs.python.org/3/', None), 'python': ('http://docs.python.org/3/', None),
'numpy': ('http://docs.scipy.org/doc/numpy/', None), 'numpy': ('http://docs.scipy.org/doc/numpy/', None),
'scipy' :
('https://docs.scipy.org/doc/scipy/reference/', None),
'xarray': ('http://xarray.pydata.org/en/stable/', None), 'xarray': ('http://xarray.pydata.org/en/stable/', None),
'wrapt': ('http://wrapt.readthedocs.io/en/latest/', 'wrapt': ('http://wrapt.readthedocs.io/en/latest/',
None) None)

14
doc/source/diagnostics.rst

@ -5,3 +5,17 @@ Table of Available Diagnostics
.. include:: _templates/product_table.txt .. include:: _templates/product_table.txt
.. _subdiagnostic-table:
Table of Subproduct Diagnostics
----------------------------------
Some diagnostics (e.g. cape_2d) include multiple products in its
output. These products have been broken out in to individual diagnostics
to help those utilities that are unable to work with multiple outputs.
These individual diagnostics can be requested like any other diagnostic
using :meth:`wrf.getvar`. These are summarized in the table below.
.. include:: _templates/subproducts.txt

17
doc/source/internal_api/index.rst

@ -53,6 +53,23 @@ The routines below are called internally by :meth:`wrf.getvar`.
wrf.g_wind.get_w_destag wrf.g_wind.get_w_destag
wrf.g_wind.get_destag_wspd_wdir wrf.g_wind.get_destag_wspd_wdir
wrf.g_wind.get_destag_wspd_wdir10 wrf.g_wind.get_destag_wspd_wdir10
wrf.g_wind.get_destag_wspd
wrf.g_wind.get_destag_wdir
wrf.g_wind.get_destag_wspd10
wrf.g_wind.get_destag_wdir10
wrf.g_uvmet.get_uvmet_wspd
wrf.g_uvmet.get_uvmet_wdir
wrf.g_uvmet.get_uvmet10_wspd
wrf.g_uvmet.get_uvmet10_wdir
wrf.g_cloudfrac.get_low_cloudfrac
wrf.g_cloudfrac.get_mid_cloudfrac
wrf.g_cloudfrac.get_high_cloudfrac
wrf.g_cape.get_cape2d_only
wrf.g_cape.get_cin2d_only
wrf.g_cape.get_lcl
wrf.g_cape.get_lfc
wrf.g_cape.get_3dcape_only
wrf.g_cape.get_3dcin_only
------------------------- -------------------------

164
doc/source/new.rst

@ -4,8 +4,52 @@ What's New
Releases Releases
------------- -------------
v1.2.0 v1.3.0 (December 2018)
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
- Release 1.3.0
- Fixed FutureWarning issue with destag routine (thank you honnorat!)
- Fixed computational problems with updraft_helicity, and values are no longer
scaled by 1000.
- Removed version constraints for wrapt and setuptools.
- Fixed xarray being a hard dependency.
- Fixed unit issues with vinterp when pressure values are extracted below
ground. Also added support for height fields in km and pressure fields in
hPa. The documentation has been improved.
- Fixed the smooth2d routine so that it actually works. It never worked
correctly before (nor did it work in NCL). Users can now specify the
center weight of the kernel and the documentation has been updated to
describe how it works.
- Fixed the storm relative helicity algorithm so that it works in the southern
hemisphere. The raw algorithm now requires latitude input if used
in the southern hemisphere, otherwise the northern hemisphere is assumed.
- Fixed an issue with the latest version of cartopy 0.17 (thanks honnorat!)
- Fixed an issue where invalid keyword arguments weren't throwing errors when
extracting standard WRF variables.
- Fixed minor issues related to moving nests when using line interpolation and
vertical cross sections. It is still an error to request all times when
using lat/lon coordinates with a moving nest, but otherwise knows how to
run when all times are requested. This never really worked quite right.
- Removed the pyf file from setup.py since it is generated via the build
system.
- Added an autolevels parameter for the vertical cross section so that users
can specify the number of vertical levels to use if they don't want to
specify them manually.
- The interplevel routine has been improved. Users can now specify a single
level, multiple levels, or a 2D array (e.g. PBLH) to interpolate to.
Performance has been improved when interpolating a multiple product
field like wspd_wdir.
- Products that produce multiple outputs can now have the outputs requested
individually. See :ref:`subdiagnostic-table` for a list of what is available.
- Much of this version of wrf-python has been back ported to NCL in the
upcoming 6.6.0 release. The diagnostics should produce the same results
in both packages.
- Now released under the Apache 2.0 license.
v1.2.0 (May 2018)
^^^^^^^^^^^^^^^^^^^^^^^^^
- Release 1.2.0 - Release 1.2.0
- Previous versions of wrf-python promoted the strings used in xarray (e.g. - Previous versions of wrf-python promoted the strings used in xarray (e.g.
@ -17,8 +61,8 @@ v1.2.0
errors, so we've decided to bump the major version number. errors, so we've decided to bump the major version number.
v1.1.3 v1.1.3 (March 2018)
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
- Release 1.1.3 - Release 1.1.3
- Fixed/Enhanced the cloud top temperature diagnostic. - Fixed/Enhanced the cloud top temperature diagnostic.
@ -39,15 +83,15 @@ v1.1.3
cape_3d. cape_3d.
v1.1.2 v1.1.2 (February 2018)
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
- Release 1.1.2 - Release 1.1.2
- Fix OpenMP directive issue with cloud top temperature. - Fix OpenMP directive issue with cloud top temperature.
v1.1.1 v1.1.1 (February 2018)
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
- Release 1.1.1 - Release 1.1.1
- Added script for building on Cheyenne with maxed out Intel settings, which - Added script for building on Cheyenne with maxed out Intel settings, which
@ -59,8 +103,8 @@ v1.1.1
- Fix cape_2d private variable bug when running with multiple CPUs. - Fix cape_2d private variable bug when running with multiple CPUs.
v1.1.0 v1.1.0 (January 2018)
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
- Release 1.1.0 - Release 1.1.0
- Computational routines now support multiple cores using OpenMP. See - Computational routines now support multiple cores using OpenMP. See
@ -107,15 +151,15 @@ v1.1.0
services like AppVeyor. services like AppVeyor.
v1.0.5 v1.0.5 (September 2017)
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
- Release 1.0.5 - Release 1.0.5
- Reduced the CI test file sizes by half. - Reduced the CI test file sizes by half.
v1.0.4 v1.0.4 (September 2017)
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
- Release 1.0.4 - Release 1.0.4
- Fix warnings with CI tests which were caused by fill values being written - Fix warnings with CI tests which were caused by fill values being written
@ -123,23 +167,25 @@ v1.0.4
- Added the __eq__ operator to the WrfProj projection base class. - Added the __eq__ operator to the WrfProj projection base class.
- Fixed array order issue when using the raw CAPE routine with 1D arrays. - Fixed array order issue when using the raw CAPE routine with 1D arrays.
v1.0.3
^^^^^^^^^^^^^^ v1.0.3 (June 2017)
^^^^^^^^^^^^^^^^^^^^^
- Relase 1.0.3 - Relase 1.0.3
- Fixed an issue with the cartopy Mercator subclass where the xlimits were - Fixed an issue with the cartopy Mercator subclass where the xlimits were
being calculated to the same value (or very close), causing blank plots. being calculated to the same value (or very close), causing blank plots.
v1.0.2
^^^^^^^^^^^^^^ v1.0.2 (May 2017)
^^^^^^^^^^^^^^^^^^^^^
- Release 1.0.2 - Release 1.0.2
- Fixed issue with the wspd_wdir product types when sequences of files are - Fixed issue with the wspd_wdir product types when sequences of files are
used. used.
v1.0.1 v1.0.1 (March 2017)
^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
- Release 1.0.1 - Release 1.0.1
- Fixed issue with initialization of PolarStereographic and LatLon map - Fixed issue with initialization of PolarStereographic and LatLon map
@ -149,8 +195,8 @@ v1.0.1
so wrf-python should as well. so wrf-python should as well.
v1.0.0 v1.0.0 (March 2017)
^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
- Release 1.0.0. - Release 1.0.0.
- Fixed issue with not being able to set the thread-local coordinate cache to - Fixed issue with not being able to set the thread-local coordinate cache to
@ -163,80 +209,6 @@ v1.0.0
column of data. column of data.
Beta Releases
--------------
v1.0b3
^^^^^^^^^^^^^
- Beta release 3.
- Improvements made for conda-forge integration testing.
- Fixed an incorrectly initialized variable issue with vinterp. This issue
mainly impacts the unit tests for continuous integration testing with
conda-forge, since the data set used for these tests is heavily cropped.
- Back-ported the inspect.BoundArguments.apply_defaults so that Python 3.4
works. Windows users that want to try out wrf-python with Python 3.4
can use the bladwig conda channel to get it.
v1.0b2
^^^^^^^^^^^^^^
- Beta release 2.
- xarray 0.9 no longer includes default index dimensions in the coordinate
mappings. This was causing a crash in the routines that cause a reduction
in dimension shape, mainly the interpolation routines. This has been
fixed.
- Documentation updated to show the new output from xarray.
v1.0b1
^^^^^^^^^^^^^
- Beta release 1.
- Added more packaging boilerplate.
- Note: Currently unable to build with Python 3.5 on Windows, due to
issues with distutils, numpy distutils, and mingw compiler. Will attempt
to find a workaround before the next release. Windows users should use
Python 2.7 or Python 3.4 for now.
----------------
Alpha Releases
----------------
v1.0a3
^^^^^^^^^^^^
- Alpha release 3.
- Added docstrings.
- The mapping API has changed.
- The projection attributes are no longer arrays for moving domains.
- Utility functions have been added for extracting geobounds. It is now
easier to get map projection objects from sliced variables.
- Utility functions have been added for getting cartopy, basemap, and pyngl
objects.
- Users should no longer need to use xarray attributes directly
- Now uses CoordPair for cross sections so that lat/lon can be used instead of
raw x,y grid coordinates.
- Renamed npvalues to to_np which is more intuitive.
- Fixed issue with generator expressions.
- Renamed some functions and arguments.
-------------
Known Issues
--------------
v1.0.0
^^^^^^^^
- Currently unable to build on Windows with Python 3.5+ using open source
mingw compiler. The mingwpy project is working on resolving the
incompatibilities between mingw and Visual Studio 2015 that was used to
build Python 3.5+. Numpy 1.13 also has improved f2py support for
Python 3.5+ on Windows, so this will be revisited when it is released.

308
doc/source/plot.rst

@ -10,11 +10,11 @@ for a future release.
Matplotlib With Cartopy Matplotlib With Cartopy
------------------------- -------------------------
Cartopy is becoming the main tool for base mapping with matplotlib, but you should Cartopy is becoming the main tool for base mapping with matplotlib, but you
be aware of a few shortcomings when working with WRF data. should be aware of a few shortcomings when working with WRF data.
- The builtin transformations of coordinates when calling the contouring functions - The builtin transformations of coordinates when calling the contouring
do not work correctly with the rotated pole projection. The functions do not work correctly with the rotated pole projection. The
transform_points method needs to be called manually on the latitude and transform_points method needs to be called manually on the latitude and
longitude arrays. longitude arrays.
@ -40,7 +40,8 @@ Plotting a Two-dimensional Field
import cartopy.crs as crs import cartopy.crs as crs
from cartopy.feature import NaturalEarthFeature from cartopy.feature import NaturalEarthFeature
from wrf import to_np, getvar, smooth2d, get_cartopy, cartopy_xlim, cartopy_ylim, latlon_coords from wrf import (to_np, getvar, smooth2d, get_cartopy, cartopy_xlim,
cartopy_ylim, latlon_coords)
# Open the NetCDF file # Open the NetCDF file
ncfile = Dataset("wrfout_d01_2016-10-07_00_00_00") ncfile = Dataset("wrfout_d01_2016-10-07_00_00_00")
@ -48,8 +49,9 @@ Plotting a Two-dimensional Field
# Get the sea level pressure # Get the sea level pressure
slp = getvar(ncfile, "slp") slp = getvar(ncfile, "slp")
# Smooth the sea level pressure since it tends to be noisy near the mountains # Smooth the sea level pressure since it tends to be noisy near the
smooth_slp = smooth2d(slp, 3) # mountains
smooth_slp = smooth2d(slp, 3, cenweight=4)
# Get the latitude and longitude points # Get the latitude and longitude points
lats, lons = latlon_coords(slp) lats, lons = latlon_coords(slp)
@ -58,26 +60,29 @@ Plotting a Two-dimensional Field
cart_proj = get_cartopy(slp) cart_proj = get_cartopy(slp)
# Create a figure # Create a figure
fig = plt.figure(figsize=(12,9)) fig = plt.figure(figsize=(12,6))
# Set the GeoAxes to the projection used by WRF # Set the GeoAxes to the projection used by WRF
ax = plt.axes(projection=cart_proj) ax = plt.axes(projection=cart_proj)
# Download and add the states and coastlines # Download and add the states and coastlines
states = NaturalEarthFeature(category='cultural', scale='50m', facecolor='none', states = NaturalEarthFeature(category="cultural", scale="50m",
name='admin_1_states_provinces_shp') facecolor="none",
ax.add_feature(states, linewidth=.5) name="admin_1_states_provinces_shp")
ax.add_feature(states, linewidth=.5, edgecolor="black")
ax.coastlines('50m', linewidth=0.8) ax.coastlines('50m', linewidth=0.8)
# Make the contour outlines and filled contours for the smoothed sea level pressure. # Make the contour outlines and filled contours for the smoothed sea level
# pressure.
plt.contour(to_np(lons), to_np(lats), to_np(smooth_slp), 10, colors="black", plt.contour(to_np(lons), to_np(lats), to_np(smooth_slp), 10, colors="black",
transform=crs.PlateCarree()) transform=crs.PlateCarree())
plt.contourf(to_np(lons), to_np(lats), to_np(smooth_slp), 10, transform=crs.PlateCarree(), plt.contourf(to_np(lons), to_np(lats), to_np(smooth_slp), 10,
transform=crs.PlateCarree(),
cmap=get_cmap("jet")) cmap=get_cmap("jet"))
# Add a color bar # Add a color bar
plt.colorbar(ax=ax, shrink=.62) plt.colorbar(ax=ax, shrink=.98)
# Set the map limits. Not really necessary, but used for demonstration. # Set the map bounds
ax.set_xlim(cartopy_xlim(smooth_slp)) ax.set_xlim(cartopy_xlim(smooth_slp))
ax.set_ylim(cartopy_ylim(smooth_slp)) ax.set_ylim(cartopy_ylim(smooth_slp))
@ -105,7 +110,8 @@ Horizontal Interpolation to a Pressure Level
import cartopy.crs as crs import cartopy.crs as crs
from cartopy.feature import NaturalEarthFeature from cartopy.feature import NaturalEarthFeature
from wrf import getvar, interplevel, to_np, latlon_coords, get_cartopy, cartopy_xlim, cartopy_ylim from wrf import (getvar, interplevel, to_np, latlon_coords, get_cartopy,
cartopy_xlim, cartopy_ylim)
# Open the NetCDF file # Open the NetCDF file
ncfile = Dataset("wrfout_d01_2016-10-07_00_00_00") ncfile = Dataset("wrfout_d01_2016-10-07_00_00_00")
@ -134,27 +140,31 @@ Horizontal Interpolation to a Pressure Level
ax = plt.axes(projection=cart_proj) ax = plt.axes(projection=cart_proj)
# Download and add the states and coastlines # Download and add the states and coastlines
states = NaturalEarthFeature(category='cultural', scale='50m', facecolor='none', states = NaturalEarthFeature(category="cultural", scale="50m",
name='admin_1_states_provinces_shp') facecolor="none",
ax.add_feature(states, linewidth=0.5) name="admin_1_states_provinces_shp")
ax.add_feature(states, linewidth=0.5, edgecolor="black")
ax.coastlines('50m', linewidth=0.8) ax.coastlines('50m', linewidth=0.8)
# Add the 500 hPa geopotential height contours # Add the 500 hPa geopotential height contours
levels = np.arange(520., 580., 6.) levels = np.arange(520., 580., 6.)
contours = plt.contour(to_np(lons), to_np(lats), to_np(ht_500), levels=levels, colors="black", contours = plt.contour(to_np(lons), to_np(lats), to_np(ht_500),
levels=levels, colors="black",
transform=crs.PlateCarree()) transform=crs.PlateCarree())
plt.clabel(contours, inline=1, fontsize=10, fmt="%i") plt.clabel(contours, inline=1, fontsize=10, fmt="%i")
# Add the wind speed contours # Add the wind speed contours
levels = [25, 30, 35, 40, 50, 60, 70, 80, 90, 100, 110, 120] levels = [25, 30, 35, 40, 50, 60, 70, 80, 90, 100, 110, 120]
wspd_contours = plt.contourf(to_np(lons), to_np(lats), to_np(wspd_500), levels=levels, wspd_contours = plt.contourf(to_np(lons), to_np(lats), to_np(wspd_500),
levels=levels,
cmap=get_cmap("rainbow"), cmap=get_cmap("rainbow"),
transform=crs.PlateCarree()) transform=crs.PlateCarree())
plt.colorbar(wspd_contours, ax=ax, orientation="horizontal", pad=.05) plt.colorbar(wspd_contours, ax=ax, orientation="horizontal", pad=.05)
# Add the 500 hPa wind barbs, only plotting every 125th data point. # Add the 500 hPa wind barbs, only plotting every 125th data point.
plt.barbs(to_np(lons[::125,::125]), to_np(lats[::125,::125]), to_np(u_500[::125, ::125]), plt.barbs(to_np(lons[::125,::125]), to_np(lats[::125,::125]),
to_np(v_500[::125, ::125]), transform=crs.PlateCarree(), length=6) to_np(u_500[::125, ::125]), to_np(v_500[::125, ::125]),
transform=crs.PlateCarree(), length=6)
# Set the map bounds # Set the map bounds
ax.set_xlim(cartopy_xlim(ht_500)) ax.set_xlim(cartopy_xlim(ht_500))
@ -187,8 +197,8 @@ plot, see :ref:`cross_example`.
import cartopy.feature as cfeature import cartopy.feature as cfeature
from netCDF4 import Dataset from netCDF4 import Dataset
from wrf import (getvar, to_np, vertcross, smooth2d, CoordPair, GeoBounds, get_cartopy, from wrf import (getvar, to_np, vertcross, smooth2d, CoordPair, GeoBounds,
latlon_coords, cartopy_xlim, cartopy_ylim) get_cartopy, latlon_coords, cartopy_xlim, cartopy_ylim)
# Open the NetCDF file # Open the NetCDF file
ncfile = Dataset("wrfout_d01_2016-10-07_00_00_00") ncfile = Dataset("wrfout_d01_2016-10-07_00_00_00")
@ -206,12 +216,13 @@ plot, see :ref:`cross_example`.
start_point = CoordPair(lat=26.76, lon=-80.0) start_point = CoordPair(lat=26.76, lon=-80.0)
end_point = CoordPair(lat=26.76, lon=-77.8) end_point = CoordPair(lat=26.76, lon=-77.8)
# Compute the vertical cross-section interpolation. Also, include the lat/lon # Compute the vertical cross-section interpolation. Also, include the
# points along the cross-section in the metadata by setting latlon to True. # lat/lon points along the cross-section in the metadata by setting latlon
z_cross = vertcross(Z, z, wrfin=ncfile, start_point=start_point, end_point=end_point, # to True.
latlon=True, meta=True) z_cross = vertcross(Z, z, wrfin=ncfile, start_point=start_point,
wspd_cross = vertcross(wspd, z, wrfin=ncfile, start_point=start_point, end_point=end_point, end_point=end_point, latlon=True, meta=True)
latlon=True, meta=True) wspd_cross = vertcross(wspd, z, wrfin=ncfile, start_point=start_point,
end_point=end_point, latlon=True, meta=True)
dbz_cross = 10.0 * np.log10(z_cross) dbz_cross = 10.0 * np.log10(z_cross)
# Get the lat/lon points # Get the lat/lon points
@ -221,31 +232,37 @@ plot, see :ref:`cross_example`.
cart_proj = get_cartopy(slp) cart_proj = get_cartopy(slp)
# Create a figure that will have 3 subplots # Create a figure that will have 3 subplots
fig = plt.figure(figsize=(10,7)) fig = plt.figure(figsize=(12,9))
ax_ctt = fig.add_subplot(1,2,1,projection=cart_proj) ax_ctt = fig.add_subplot(1,2,1,projection=cart_proj)
ax_wspd = fig.add_subplot(2,2,2) ax_wspd = fig.add_subplot(2,2,2)
ax_dbz = fig.add_subplot(2,2,4) ax_dbz = fig.add_subplot(2,2,4)
# Download and create the states, land, and oceans using cartopy features # Download and create the states, land, and oceans using cartopy features
states = cfeature.NaturalEarthFeature(category='cultural', scale='50m', facecolor='none', states = cfeature.NaturalEarthFeature(category='cultural', scale='50m',
facecolor='none',
name='admin_1_states_provinces_shp') name='admin_1_states_provinces_shp')
land = cfeature.NaturalEarthFeature(category='physical', name='land', scale='50m', land = cfeature.NaturalEarthFeature(category='physical', name='land',
scale='50m',
facecolor=cfeature.COLORS['land']) facecolor=cfeature.COLORS['land'])
ocean = cfeature.NaturalEarthFeature(category='physical', name='ocean', scale='50m', ocean = cfeature.NaturalEarthFeature(category='physical', name='ocean',
scale='50m',
facecolor=cfeature.COLORS['water']) facecolor=cfeature.COLORS['water'])
# Make the pressure contours # Make the pressure contours
contour_levels = [960, 965, 970, 975, 980, 990] contour_levels = [960, 965, 970, 975, 980, 990]
c1 = ax_ctt.contour(lons, lats, to_np(smooth_slp), levels=contour_levels, colors="white", c1 = ax_ctt.contour(lons, lats, to_np(smooth_slp), levels=contour_levels,
transform=crs.PlateCarree(), zorder=3, linewidths=1.0) colors="white", transform=crs.PlateCarree(), zorder=3,
linewidths=1.0)
# Create the filled cloud top temperature contours # Create the filled cloud top temperature contours
contour_levels = [-80.0, -70.0, -60, -50, -40, -30, -20, -10, 0, 10] contour_levels = [-80.0, -70.0, -60, -50, -40, -30, -20, -10, 0, 10]
ctt_contours = ax_ctt.contourf(to_np(lons), to_np(lats), to_np(ctt), contour_levels, ctt_contours = ax_ctt.contourf(to_np(lons), to_np(lats), to_np(ctt),
cmap=get_cmap("Greys"), transform=crs.PlateCarree(), zorder=2) contour_levels, cmap=get_cmap("Greys"),
transform=crs.PlateCarree(), zorder=2)
ax_ctt.plot([start_point.lon, end_point.lon], [start_point.lat, end_point.lat], ax_ctt.plot([start_point.lon, end_point.lon],
color="yellow", marker="o", transform=crs.PlateCarree(), zorder=3) [start_point.lat, end_point.lat], color="yellow", marker="o",
transform=crs.PlateCarree(), zorder=3)
# Create the color bar for cloud top temperature # Create the color bar for cloud top temperature
cb_ctt = fig.colorbar(ctt_contours, ax=ax_ctt, shrink=.60) cb_ctt = fig.colorbar(ctt_contours, ax=ax_ctt, shrink=.60)
@ -271,7 +288,8 @@ plot, see :ref:`cross_example`.
# Make the contour plot for dbz # Make the contour plot for dbz
levels = [5 + 5*n for n in range(15)] levels = [5 + 5*n for n in range(15)]
dbz_contours = ax_dbz.contourf(to_np(dbz_cross), levels=levels, cmap=get_cmap("jet")) dbz_contours = ax_dbz.contourf(to_np(dbz_cross), levels=levels,
cmap=get_cmap("jet"))
cb_dbz = fig.colorbar(dbz_contours, ax=ax_dbz) cb_dbz = fig.colorbar(dbz_contours, ax=ax_dbz)
cb_dbz.ax.tick_params(labelsize=5) cb_dbz.ax.tick_params(labelsize=5)
@ -308,9 +326,9 @@ plot, see :ref:`cross_example`.
Matplotlib with Basemap Matplotlib with Basemap
----------------------- -----------------------
Although basemap is in maintenance mode only and becoming deprecated, it is still Although basemap is in maintenance mode only and becoming deprecated, it is
widely used by many programmers. Cartopy is becoming the preferred package for still widely used by many programmers. Cartopy is becoming the preferred
mapping, however it suffers from growing pains in some areas package for mapping, however it suffers from growing pains in some areas
(can't use latitude/longitude labels for many map projections). If you (can't use latitude/longitude labels for many map projections). If you
run in to these issues, basemap is likely to accomplish what you need. run in to these issues, basemap is likely to accomplish what you need.
@ -337,8 +355,9 @@ Plotting a Two-Dimensional Field
# Get the sea level pressure # Get the sea level pressure
slp = getvar(ncfile, "slp") slp = getvar(ncfile, "slp")
# Smooth the sea level pressure since it tends to be noisy near the mountains # Smooth the sea level pressure since it tends to be noisy near the
smooth_slp = smooth2d(slp, 3) # mountains
smooth_slp = smooth2d(slp, 3, cenweight=4)
# Get the latitude and longitude points # Get the latitude and longitude points
lats, lons = latlon_coords(slp) lats, lons = latlon_coords(slp)
@ -354,8 +373,9 @@ Plotting a Two-Dimensional Field
bm.drawstates(linewidth=0.25) bm.drawstates(linewidth=0.25)
bm.drawcountries(linewidth=0.25) bm.drawcountries(linewidth=0.25)
# Convert the lats and lons to x and y. Make sure you convert the lats and lons to # Convert the lats and lons to x and y. Make sure you convert the lats and
# numpy arrays via to_np, or basemap crashes with an undefined RuntimeError. # lons to numpy arrays via to_np, or basemap crashes with an undefined
# RuntimeError.
x, y = bm(to_np(lons), to_np(lats)) x, y = bm(to_np(lons), to_np(lats))
# Draw the contours and filled contours # Draw the contours and filled contours
@ -458,7 +478,8 @@ plot, see :ref:`cross_example`.
from matplotlib.cm import get_cmap from matplotlib.cm import get_cmap
from netCDF4 import Dataset from netCDF4 import Dataset
from wrf import getvar, to_np, vertcross, smooth2d, CoordPair, get_basemap, latlon_coords from wrf import (getvar, to_np, vertcross, smooth2d, CoordPair,
get_basemap, latlon_coords)
# Open the NetCDF file # Open the NetCDF file
ncfile = Dataset("wrfout_d01_2016-10-07_00_00_00") ncfile = Dataset("wrfout_d01_2016-10-07_00_00_00")
@ -476,19 +497,20 @@ plot, see :ref:`cross_example`.
start_point = CoordPair(lat=26.76, lon=-80.0) start_point = CoordPair(lat=26.76, lon=-80.0)
end_point = CoordPair(lat=26.76, lon=-77.8) end_point = CoordPair(lat=26.76, lon=-77.8)
# Compute the vertical cross-section interpolation. Also, include the lat/lon points # Compute the vertical cross-section interpolation. Also, include the
# along the cross-section in the metadata by setting latlon to True. # lat/lon points along the cross-section in the metadata by setting latlon
z_cross = vertcross(Z, z, wrfin=ncfile, start_point=start_point, end_point=end_point, # to True.
latlon=True, meta=True) z_cross = vertcross(Z, z, wrfin=ncfile, start_point=start_point,
wspd_cross = vertcross(wspd, z, wrfin=ncfile, start_point=start_point, end_point=end_point, end_point=end_point, latlon=True, meta=True)
latlon=True, meta=True) wspd_cross = vertcross(wspd, z, wrfin=ncfile, start_point=start_point,
end_point=end_point, latlon=True, meta=True)
dbz_cross = 10.0 * np.log10(z_cross) dbz_cross = 10.0 * np.log10(z_cross)
# Get the latitude and longitude points # Get the latitude and longitude points
lats, lons = latlon_coords(slp) lats, lons = latlon_coords(slp)
# Create the figure that will have 3 subplots # Create the figure that will have 3 subplots
fig = plt.figure(figsize=(10,7)) fig = plt.figure(figsize=(12,9))
ax_ctt = fig.add_subplot(1,2,1) ax_ctt = fig.add_subplot(1,2,1)
ax_wspd = fig.add_subplot(2,2,2) ax_wspd = fig.add_subplot(2,2,2)
ax_dbz = fig.add_subplot(2,2,4) ax_dbz = fig.add_subplot(2,2,4)
@ -501,15 +523,16 @@ plot, see :ref:`cross_example`.
# Make the pressure contours # Make the pressure contours
contour_levels = [960, 965, 970, 975, 980, 990] contour_levels = [960, 965, 970, 975, 980, 990]
c1 = bm.contour(x, y, to_np(smooth_slp), levels=contour_levels, colors="white", c1 = bm.contour(x, y, to_np(smooth_slp), levels=contour_levels,
zorder=3, linewidths=1.0, ax=ax_ctt) colors="white", zorder=3, linewidths=1.0, ax=ax_ctt)
# Create the filled cloud top temperature contours # Create the filled cloud top temperature contours
contour_levels = [-80.0, -70.0, -60, -50, -40, -30, -20, -10, 0, 10] contour_levels = [-80.0, -70.0, -60, -50, -40, -30, -20, -10, 0, 10]
ctt_contours = bm.contourf(x, y, to_np(ctt), contour_levels, cmap=get_cmap("Greys"), ctt_contours = bm.contourf(x, y, to_np(ctt), contour_levels,
zorder=2, ax=ax_ctt) cmap=get_cmap("Greys"), zorder=2, ax=ax_ctt)
point_x, point_y = bm([start_point.lon, end_point.lon], [start_point.lat, end_point.lat]) point_x, point_y = bm([start_point.lon, end_point.lon],
[start_point.lat, end_point.lat])
bm.plot([point_x[0], point_x[1]], [point_y[0], point_y[1]], color="yellow", bm.plot([point_x[0], point_x[1]], [point_y[0], point_y[1]], color="yellow",
marker="o", zorder=3, ax=ax_ctt) marker="o", zorder=3, ax=ax_ctt)
@ -522,8 +545,12 @@ plot, see :ref:`cross_example`.
bm.drawstates(linewidth=0.25, ax=ax_ctt) bm.drawstates(linewidth=0.25, ax=ax_ctt)
bm.drawcountries(linewidth=0.25, ax=ax_ctt) bm.drawcountries(linewidth=0.25, ax=ax_ctt)
bm.fillcontinents(color=np.array([ 0.9375 , 0.9375 , 0.859375]), bm.fillcontinents(color=np.array([ 0.9375 , 0.9375 , 0.859375]),
ax=ax_ctt, lake_color=np.array([ 0.59375 , 0.71484375, 0.8828125 ])) ax=ax_ctt,
bm.drawmapboundary(fill_color=np.array([ 0.59375 , 0.71484375, 0.8828125 ]), ax=ax_ctt) lake_color=np.array([0.59375 ,
0.71484375,
0.8828125 ]))
bm.drawmapboundary(fill_color=np.array([ 0.59375 , 0.71484375, 0.8828125 ]),
ax=ax_ctt)
# Draw Parallels # Draw Parallels
parallels = np.arange(np.amin(lats), 30., 2.5) parallels = np.arange(np.amin(lats), 30., 2.5)
@ -547,7 +574,8 @@ plot, see :ref:`cross_example`.
# Make the contour plot for dbz # Make the contour plot for dbz
levels = [5 + 5*n for n in range(15)] levels = [5 + 5*n for n in range(15)]
dbz_contours = ax_dbz.contourf(to_np(dbz_cross), levels=levels, cmap=get_cmap("jet")) dbz_contours = ax_dbz.contourf(to_np(dbz_cross), levels=levels,
cmap=get_cmap("jet"))
cb_dbz = fig.colorbar(dbz_contours, ax=ax_dbz) cb_dbz = fig.colorbar(dbz_contours, ax=ax_dbz)
cb_dbz.ax.tick_params(labelsize=5) cb_dbz.ax.tick_params(labelsize=5)
@ -583,6 +611,7 @@ plot, see :ref:`cross_example`.
.. _cross_example: .. _cross_example:
Vertical Cross Section Vertical Cross Section
------------------------------- -------------------------------
@ -616,10 +645,10 @@ plotted using the standard matplotlib API.
start_point = CoordPair(lat=26.76, lon=-80.0) start_point = CoordPair(lat=26.76, lon=-80.0)
end_point = CoordPair(lat=26.76, lon=-77.8) end_point = CoordPair(lat=26.76, lon=-77.8)
# Compute the vertical cross-section interpolation. Also, include the lat/lon # Compute the vertical cross-section interpolation. Also, include the
# points along the cross-section. # lat/lon points along the cross-section.
wspd_cross = vertcross(wspd, z, wrfin=ncfile, start_point=start_point, end_point=end_point, wspd_cross = vertcross(wspd, z, wrfin=ncfile, start_point=start_point,
latlon=True, meta=True) end_point=end_point, latlon=True, meta=True)
# Create the figure # Create the figure
fig = plt.figure(figsize=(12,6)) fig = plt.figure(figsize=(12,6))
@ -634,7 +663,8 @@ plotted using the standard matplotlib API.
# Set the x-ticks to use latitude and longitude labels. # Set the x-ticks to use latitude and longitude labels.
coord_pairs = to_np(wspd_cross.coords["xy_loc"]) coord_pairs = to_np(wspd_cross.coords["xy_loc"])
x_ticks = np.arange(coord_pairs.shape[0]) x_ticks = np.arange(coord_pairs.shape[0])
x_labels = [pair.latlon_str(fmt="{:.2f}, {:.2f}") for pair in to_np(coord_pairs)] x_labels = [pair.latlon_str(fmt="{:.2f}, {:.2f}")
for pair in to_np(coord_pairs)]
ax.set_xticks(x_ticks[::20]) ax.set_xticks(x_ticks[::20])
ax.set_xticklabels(x_labels[::20], rotation=45, fontsize=8) ax.set_xticklabels(x_labels[::20], rotation=45, fontsize=8)
@ -651,4 +681,142 @@ plotted using the standard matplotlib API.
plt.title("Vertical Cross Section of Wind Speed (kt)") plt.title("Vertical Cross Section of Wind Speed (kt)")
plt.show() plt.show()
Cross Section with Mountains
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The example below shows how to make a cross section with the mountainous
terrain filled.
.. image:: _static/images/cross_mtns.png
:scale: 100%
:align: center
.. code-block:: python
import numpy as np
from matplotlib import pyplot
from matplotlib.cm import get_cmap
from matplotlib.colors import from_levels_and_colors
from cartopy import crs
from cartopy.feature import NaturalEarthFeature, COLORS
from netCDF4 import Dataset
from wrf import (getvar, to_np, get_cartopy, latlon_coords, vertcross,
cartopy_xlim, cartopy_ylim, interpline, CoordPair)
wrf_file = Dataset("wrfout_d01_2010-06-04_00:00:00")
# Define the cross section start and end points
cross_start = CoordPair(lat=43.5, lon=-116.5)
cross_end = CoordPair(lat=43.5, lon=-114)
# Get the WRF variables
ht = getvar(wrf_file, "z", timeidx=-1)
ter = getvar(wrf_file, "ter", timeidx=-1)
dbz = getvar(wrf_file, "dbz", timeidx=-1)
max_dbz = getvar(wrf_file, "mdbz", timeidx=-1)
Z = 10**(dbz/10.) # Use linear Z for interpolation
# Compute the vertical cross-section interpolation. Also, include the
# lat/lon points along the cross-section in the metadata by setting latlon
# to True.
z_cross = vertcross(Z, ht, wrfin=wrf_file,
start_point=cross_start,
end_point=cross_end,
latlon=True, meta=True)
# Convert back to dBz after interpolation
dbz_cross = 10.0 * np.log10(z_cross)
# Add back the attributes that xarray dropped from the operations above
dbz_cross.attrs.update(z_cross.attrs)
dbz_cross.attrs["description"] = "radar reflectivity cross section"
dbz_cross.attrs["units"] = "dBZ"
# To remove the slight gap between the dbz contours and terrain due to the
# contouring of gridded data, a new vertical grid spacing, and model grid
# staggering, fill in the lower grid cells with the first non-missing value
# for each column.
# Make a copy of the z cross data. Let's use regular numpy arrays for this.
dbz_cross_filled = np.ma.copy(to_np(dbz_cross))
# For each cross section column, find the first index with non-missing
# values and copy these to the missing elements below.
for i in range(dbz_cross_filled.shape[-1]):
column_vals = dbz_cross_filled[:,i]
# Let's find the lowest index that isn't filled. The nonzero function
# finds all unmasked values greater than 0. Since 0 is a valid value
# for dBZ, let's change that threshold to be -200 dBZ instead.
first_idx = int(np.transpose((column_vals > -200).nonzero())[0])
dbz_cross_filled[0:first_idx, i] = dbz_cross_filled[first_idx, i]
# Get the terrain heights along the cross section line
ter_line = interpline(ter, wrfin=wrf_file, start_point=cross_start,
end_point=cross_end)
# Get the lat/lon points
lats, lons = latlon_coords(dbz)
# Get the cartopy projection object
cart_proj = get_cartopy(dbz)
# Create the figure
fig = pyplot.figure(figsize=(8,6))
ax_cross = pyplot.axes()
dbz_levels = np.arange(5., 75., 5.)
# Create the color table found on NWS pages.
dbz_rgb = np.array([[4,233,231],
[1,159,244], [3,0,244],
[2,253,2], [1,197,1],
[0,142,0], [253,248,2],
[229,188,0], [253,149,0],
[253,0,0], [212,0,0],
[188,0,0],[248,0,253],
[152,84,198]], np.float32) / 255.0
dbz_map, dbz_norm = from_levels_and_colors(dbz_levels, dbz_rgb,
extend="max")
# Make the cross section plot for dbz
dbz_levels = np.arange(5.,75.,5.)
xs = np.arange(0, dbz_cross.shape[-1], 1)
ys = to_np(dbz_cross.coords["vertical"])
dbz_contours = ax_cross.contourf(xs,
ys,
to_np(dbz_cross_filled),
levels=dbz_levels,
cmap=dbz_map,
norm=dbz_norm,
extend="max")
# Add the color bar
cb_dbz = fig.colorbar(dbz_contours, ax=ax_cross)
cb_dbz.ax.tick_params(labelsize=8)
# Fill in the mountain area
ht_fill = ax_cross.fill_between(xs, 0, to_np(ter_line),
facecolor="saddlebrown")
# Set the x-ticks to use latitude and longitude labels
coord_pairs = to_np(dbz_cross.coords["xy_loc"])
x_ticks = np.arange(coord_pairs.shape[0])
x_labels = [pair.latlon_str() for pair in to_np(coord_pairs)]
# Set the desired number of x ticks below
num_ticks = 5
thin = int((len(x_ticks) / num_ticks) + .5)
ax_cross.set_xticks(x_ticks[::thin])
ax_cross.set_xticklabels(x_labels[::thin], rotation=45, fontsize=8)
# Set the x-axis and y-axis labels
ax_cross.set_xlabel("Latitude, Longitude", fontsize=12)
ax_cross.set_ylabel("Height (m)", fontsize=12)
# Add a title
ax_cross.set_title("Cross-Section of Reflectivity (dBZ)", {"fontsize" : 14})
pyplot.show()

8
doc/source/tutorial.rst

@ -12,7 +12,6 @@ Upcoming Tutorials
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
tutorials/boise_2018.rst
Past Tutorials Past Tutorials
@ -21,8 +20,11 @@ Past Tutorials
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
tutorials/wrf_workshop_2017.rst tutorials/boise_2018.rst
tutorials/tutorial_03_2018.rst
tutorials/wrf_workshop_2018.rst tutorials/wrf_workshop_2018.rst
tutorials/tutorial_03_2018.rst
tutorials/wrf_workshop_2017.rst

2
fortran/calc_uh.f90

@ -154,8 +154,6 @@ SUBROUTINE DCALCUH(nx, ny, nz, nzp1, zp, mapfct, dx, dy, uhmnhgt, uhmxhgt, us, &
!$OMP END PARALLEL !$OMP END PARALLEL
uh = uh*1000. ! Scale according to Kain et al. (2008)
RETURN RETURN
END SUBROUTINE DCALCUH END SUBROUTINE DCALCUH

4
fortran/wrf_constants.f90

@ -1,8 +1,8 @@
! These are chosen to match the wrf module_model_constants.F where ! These are chosen to match the wrf module_model_constants.F where
! applicable ! applicable
MODULE wrf_constants MODULE wrf_constants
INTEGER :: ERRLEN=512 INTEGER, PARAMETER :: ERRLEN=512
INTEGER :: ALGERR=64 INTEGER, PARAMETER :: ALGERR=64
REAL(KIND=8), PARAMETER :: WRF_EARTH_RADIUS = 6370000.D0 REAL(KIND=8), PARAMETER :: WRF_EARTH_RADIUS = 6370000.D0
REAL(KIND=8), PARAMETER :: T_BASE = 300.0D0 REAL(KIND=8), PARAMETER :: T_BASE = 300.0D0

11
fortran/wrf_relhl.f90

@ -31,7 +31,7 @@
! *************************************************************** ! ***************************************************************
! NCLFORTSTART ! NCLFORTSTART
SUBROUTINE DCALRELHL(u, v, ght, ter, top, sreh, miy, mjx, mkzh) SUBROUTINE DCALRELHL(u, v, ght, ter, lat, top, sreh, miy, mjx, mkzh)
USE wrf_constants, ONLY : PI, RAD_PER_DEG, DEG_PER_RAD USE wrf_constants, ONLY : PI, RAD_PER_DEG, DEG_PER_RAD
IMPLICIT NONE IMPLICIT NONE
@ -43,6 +43,7 @@ SUBROUTINE DCALRELHL(u, v, ght, ter, top, sreh, miy, mjx, mkzh)
REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(IN) :: u, v, ght REAL(KIND=8), DIMENSION(miy,mjx,mkzh), INTENT(IN) :: u, v, ght
REAL(KIND=8), INTENT(IN) :: top REAL(KIND=8), INTENT(IN) :: top
REAL(KIND=8), DIMENSION(miy,mjx), INTENT(IN) :: ter REAL(KIND=8), DIMENSION(miy,mjx), INTENT(IN) :: ter
REAL(KIND=8), DIMENSION(miy,mjx), INTENT(IN) :: lat
REAL(KIND=8), DIMENSION(miy,mjx), INTENT(OUT) :: sreh REAL(KIND=8), DIMENSION(miy,mjx), INTENT(OUT) :: sreh
! NCLEND ! NCLEND
@ -100,7 +101,13 @@ SUBROUTINE DCALRELHL(u, v, ght, ter, top, sreh, miy, mjx, mkzh)
ENDIF ENDIF
bsp = 0.75D0*asp bsp = 0.75D0*asp
bdr = adr + 30.D0
IF (lat(i,j) .GE. 0) THEN ! Northern hemisphern
bdr = adr + 30.D0
ELSE ! Southern hemisphere
bdr = adr - 30.D0
END IF
IF (bdr .GT. 360.D0) THEN IF (bdr .GT. 360.D0) THEN
bdr = bdr - 360.D0 bdr = bdr - 360.D0
ENDIF ENDIF

108
fortran/wrf_user.f90

@ -64,7 +64,67 @@ END SUBROUTINE DCOMPUTETK
! NCLFORTSTART ! NCLFORTSTART
SUBROUTINE DINTERP3DZ(data3d, out2d, zdata, desiredloc, nx, ny, nz, missingval) SUBROUTINE DINTERP3DZ(data3d, out2d, zdata, levels, nx, ny, nz, nlev, missingval)
IMPLICIT NONE
!f2py threadsafe
!f2py intent(in,out) :: out2d
INTEGER, INTENT(IN) :: nx, ny, nz, nlev
REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: data3d
REAL(KIND=8), DIMENSION(nx,ny,nlev), INTENT(OUT) :: out2d
REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: zdata
REAL(KIND=8), DIMENSION(nlev), INTENT(IN) :: levels
REAL(KIND=8), INTENT(IN) :: missingval
! NCLEND
INTEGER :: i,j,kp,ip,im,lev
LOGICAL :: dointerp
REAL(KIND=8) :: w1,w2,desiredloc
! does vertical coordinate increase or decrease with increasing k?
! set offset appropriately
ip = 0
im = 1
IF (zdata(1,1,1) .GT. zdata(1,1,nz)) THEN
ip = 1
im = 0
END IF
!$OMP PARALLEL DO COLLAPSE(3) PRIVATE(i,j,lev,kp,dointerp,w1,w2,desiredloc) &
!$OMP FIRSTPRIVATE(ip,im) SCHEDULE(runtime)
DO lev = 1,nlev
DO i = 1,nx
DO j = 1,ny
! Initialize to missing. Was initially hard-coded to -999999.
out2d(i,j,lev) = missingval
dointerp = .FALSE.
kp = nz
desiredloc = levels(lev)
DO WHILE ((.NOT. dointerp) .AND. (kp >= 2))
IF (((zdata(i,j,kp-im) < desiredloc) .AND. (zdata(i,j,kp-ip) > desiredloc))) THEN
w2 = (desiredloc - zdata(i,j,kp-im))/(zdata(i,j,kp-ip) - zdata(i,j,kp-im))
w1 = 1.D0 - w2
out2d(i,j,lev) = w1*data3d(i,j,kp-im) + w2*data3d(i,j,kp-ip)
dointerp = .TRUE.
END IF
kp = kp - 1
END DO
END DO
END DO
END DO
!$OMP END PARALLEL DO
RETURN
END SUBROUTINE DINTERP3DZ
! NCLFORTSTART
SUBROUTINE DINTERP3DZ_2DLEV(data3d, out2d, zdata, levs2d, nx, ny, nz, missingval)
IMPLICIT NONE IMPLICIT NONE
!f2py threadsafe !f2py threadsafe
@ -74,14 +134,14 @@ SUBROUTINE DINTERP3DZ(data3d, out2d, zdata, desiredloc, nx, ny, nz, missingval)
REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: data3d REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: data3d
REAL(KIND=8), DIMENSION(nx,ny), INTENT(OUT) :: out2d REAL(KIND=8), DIMENSION(nx,ny), INTENT(OUT) :: out2d
REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: zdata REAL(KIND=8), DIMENSION(nx,ny,nz), INTENT(IN) :: zdata
REAL(KIND=8), INTENT(IN) :: desiredloc REAL(KIND=8), DIMENSION(nx,ny), INTENT(IN) :: levs2d
REAL(KIND=8), INTENT(IN) :: missingval REAL(KIND=8), INTENT(IN) :: missingval
! NCLEND ! NCLEND
INTEGER :: i,j,kp,ip,im INTEGER :: i,j,kp,ip,im
LOGICAL :: dointerp LOGICAL :: dointerp
REAL(KIND=8) :: w1,w2 REAL(KIND=8) :: w1,w2,desiredloc
! does vertical coordinate increase or decrease with increasing k? ! does vertical coordinate increase or decrease with increasing k?
! set offset appropriately ! set offset appropriately
@ -93,7 +153,7 @@ SUBROUTINE DINTERP3DZ(data3d, out2d, zdata, desiredloc, nx, ny, nz, missingval)
im = 0 im = 0
END IF END IF
!$OMP PARALLEL DO COLLAPSE(2) PRIVATE(i,j,kp,dointerp,w1,w2) & !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(i,j,kp,dointerp,w1,w2,desiredloc) &
!$OMP FIRSTPRIVATE(ip,im) SCHEDULE(runtime) !$OMP FIRSTPRIVATE(ip,im) SCHEDULE(runtime)
DO i = 1,nx DO i = 1,nx
DO j = 1,ny DO j = 1,ny
@ -101,6 +161,7 @@ SUBROUTINE DINTERP3DZ(data3d, out2d, zdata, desiredloc, nx, ny, nz, missingval)
out2d(i,j) = missingval out2d(i,j) = missingval
dointerp = .FALSE. dointerp = .FALSE.
kp = nz kp = nz
desiredloc = levs2d(i,j)
DO WHILE ((.NOT. dointerp) .AND. (kp >= 2)) DO WHILE ((.NOT. dointerp) .AND. (kp >= 2))
IF (((zdata(i,j,kp-im) < desiredloc) .AND. (zdata(i,j,kp-ip) > desiredloc))) THEN IF (((zdata(i,j,kp-im) < desiredloc) .AND. (zdata(i,j,kp-ip) > desiredloc))) THEN
@ -117,7 +178,7 @@ SUBROUTINE DINTERP3DZ(data3d, out2d, zdata, desiredloc, nx, ny, nz, missingval)
RETURN RETURN
END SUBROUTINE DINTERP3DZ END SUBROUTINE DINTERP3DZ_2DLEV
! PORT DZSTAG HERE ! PORT DZSTAG HERE
@ -479,7 +540,7 @@ END SUBROUTINE DCOMPUTESEAPRS
! must make the same change below to filter2d. ! must make the same change below to filter2d.
! NCLFORTSTART ! NCLFORTSTART
SUBROUTINE DFILTER2D(a, b, nx, ny, it, missing) SUBROUTINE DFILTER2D(a, b, nx, ny, it, missing, cenweight)
IMPLICIT NONE IMPLICIT NONE
@ -488,14 +549,16 @@ SUBROUTINE DFILTER2D(a, b, nx, ny, it, missing)
INTEGER, INTENT(IN) :: nx, ny, it INTEGER, INTENT(IN) :: nx, ny, it
REAL(KIND=8), DIMENSION(nx, ny), INTENT(INOUT) :: a REAL(KIND=8), DIMENSION(nx, ny), INTENT(INOUT) :: a
REAL(KIND=8), INTENT(IN) :: missing REAL(KIND=8), INTENT(IN) :: missing, cenweight
REAL(KIND=8), DIMENSION(nx, ny), INTENT(INOUT) :: b REAL(KIND=8), DIMENSION(nx, ny), INTENT(INOUT) :: b
! NCLEND ! NCLEND
REAL(KIND=8), PARAMETER :: COEF=0.25D0
INTEGER :: i, j, iter INTEGER :: i, j, iter
REAL(KIND=8) :: cenmult, coef
cenmult = (cenweight) / 2.
coef = 1.0 / (4. + cenweight)
DO iter=1,it DO iter=1,it
!$OMP PARALLEL DO COLLAPSE(2) SCHEDULE(runtime) !$OMP PARALLEL DO COLLAPSE(2) SCHEDULE(runtime)
@ -508,25 +571,25 @@ SUBROUTINE DFILTER2D(a, b, nx, ny, it, missing)
!$OMP PARALLEL DO COLLAPSE(2) SCHEDULE(runtime) !$OMP PARALLEL DO COLLAPSE(2) SCHEDULE(runtime)
DO j=2,ny-1 DO j=2,ny-1
DO i=1,nx DO i=2,nx-1
IF (b(i,j-1) .EQ. missing .OR. b(i,j) .EQ. missing .OR. & IF (b(i,j-1) .EQ. missing .OR. b(i,j) .EQ. missing .OR. &
b(i,j+1) .EQ. missing) THEN b(i,j+1) .EQ. missing) THEN
a(i,j) = a(i,j) a(i,j) = a(i,j)
ELSE ELSE
a(i,j) = a(i,j) + COEF*(b(i,j-1) - 2*b(i,j) + b(i,j+1)) a(i,j) = coef*(b(i,j-1) + cenmult*b(i,j) + b(i,j+1))
END IF END IF
END DO END DO
END DO END DO
!$OMP END PARALLEL DO !$OMP END PARALLEL DO
!$OMP PARALLEL DO COLLAPSE(2) SCHEDULE(runtime) !$OMP PARALLEL DO COLLAPSE(2) SCHEDULE(runtime)
DO j=1,ny DO j=2,ny-1
DO i=2,nx-1 DO i=2,nx-1
IF (b(i-1,j) .EQ. missing .OR. b(i,j) .EQ. missing .OR. & IF (b(i-1,j) .EQ. missing .OR. b(i,j) .EQ. missing .OR. &
b(i+1,j) .EQ. missing) THEN b(i+1,j) .EQ. missing) THEN
a(i,j) = a(i,j) a(i,j) = a(i,j)
ELSE ELSE
a(i,j) = a(i,j) + COEF*(b(i-1,j) - 2*b(i,j) + b(i+1,j)) a(i,j) = a(i,j) + coef*(b(i-1,j) + cenmult*b(i,j) + b(i+1,j))
END IF END IF
END DO END DO
END DO END DO
@ -556,7 +619,7 @@ END SUBROUTINE DFILTER2D
! must make the same change below to dfilter2d. ! must make the same change below to dfilter2d.
! NCLFORTSTART ! NCLFORTSTART
SUBROUTINE FILTER2D(a, b, nx, ny, it, missing) SUBROUTINE FILTER2D(a, b, nx, ny, it, missing, cenweight)
IMPLICIT NONE IMPLICIT NONE
!f2py threadsafe !f2py threadsafe
@ -564,14 +627,17 @@ SUBROUTINE FILTER2D(a, b, nx, ny, it, missing)
INTEGER, INTENT(IN) :: nx, ny, it INTEGER, INTENT(IN) :: nx, ny, it
REAL(KIND=4), DIMENSION(nx, ny), INTENT(INOUT) :: a REAL(KIND=4), DIMENSION(nx, ny), INTENT(INOUT) :: a
REAL(KIND=4), INTENT(IN) :: missing REAL(KIND=4), INTENT(IN) :: missing, cenweight
REAL(KIND=4), DIMENSION(nx, ny), INTENT(INOUT) :: b REAL(KIND=4), DIMENSION(nx, ny), INTENT(INOUT) :: b
! NCLEND ! NCLEND
REAL(KIND=4), PARAMETER :: COEF=0.25 !REAL(KIND=8), PARAMETER :: COEF = .125
INTEGER :: i, j, iter INTEGER :: i, j, iter
REAL(KIND=8) :: cenmult, coef
cenmult = (cenweight) / 2.
coef = 1.0 / (4. + cenweight)
!$OMP PARALLEL !$OMP PARALLEL
@ -586,25 +652,25 @@ SUBROUTINE FILTER2D(a, b, nx, ny, it, missing)
!$OMP DO COLLAPSE(2) SCHEDULE(runtime) !$OMP DO COLLAPSE(2) SCHEDULE(runtime)
DO j=2,ny-1 DO j=2,ny-1
DO i=1,nx DO i=2,nx-1
IF (b(i,j-1) .EQ. missing .OR. b(i,j) .EQ. missing .OR. & IF (b(i,j-1) .EQ. missing .OR. b(i,j) .EQ. missing .OR. &
b(i,j+1) .EQ. missing) THEN b(i,j+1) .EQ. missing) THEN
a(i,j) = a(i,j) a(i,j) = a(i,j)
ELSE ELSE
a(i,j) = a(i,j) + COEF*(b(i,j-1) - 2*b(i,j) + b(i,j+1)) a(i,j) = coef*(b(i,j-1) + cenmult*b(i,j) + b(i,j+1))
END IF END IF
END DO END DO
END DO END DO
!$OMP END DO !$OMP END DO
!$OMP DO COLLAPSE(2) SCHEDULE(runtime) !$OMP DO COLLAPSE(2) SCHEDULE(runtime)
DO j=1,ny DO j=2,ny-1
DO i=2,nx-1 DO i=2,nx-1
IF (b(i-1,j) .EQ. missing .OR. b(i,j) .EQ. missing .OR. & IF (b(i-1,j) .EQ. missing .OR. b(i,j) .EQ. missing .OR. &
b(i+1,j) .EQ. missing) THEN b(i+1,j) .EQ. missing) THEN
a(i,j) = a(i,j) a(i,j) = a(i,j)
ELSE ELSE
a(i,j) = a(i,j) + COEF*(b(i-1,j) - 2*b(i,j)+b(i+1,j)) a(i,j) = a(i,j) + coef*(b(i-1,j) + cenmult*b(i,j) + b(i+1,j))
END IF END IF
END DO END DO
END DO END DO

6
fortran/wrf_vinterp.f90

@ -340,7 +340,7 @@ SUBROUTINE wrf_vintrp(datain, dataout, pres, tk, qvp, ght, terrain,&
plev = ((ezlev - ezlhsl)*& plev = ((ezlev - ezlhsl)*&
psurf + (ezsurf - ezlev)*plhsl)/(ezsurf - ezlhsl) psurf + (ezsurf - ezlev)*plhsl)/(ezsurf - ezlhsl)
IF (icase .EQ. 1) THEN IF (icase .EQ. 1) THEN
tempout(i,j) = plev tempout(i,j) = plev * 100.
CYCLE CYCLE
END IF END IF
END IF END IF
@ -377,7 +377,7 @@ SUBROUTINE wrf_vintrp(datain, dataout, pres, tk, qvp, ght, terrain,&
zlev = -sclht*LOG(vlev) zlev = -sclht*LOG(vlev)
plev = pbot*(1. + USSALR/vt*(zbot - zlev))**EXPONI plev = pbot*(1. + USSALR/vt*(zbot - zlev))**EXPONI
IF (icase .EQ. 1) THEN IF (icase .EQ. 1) THEN
tempout(i,j) = plev tempout(i,j) = plev * 100.
CYCLE CYCLE
END IF END IF
END IF END IF
@ -395,7 +395,7 @@ SUBROUTINE wrf_vintrp(datain, dataout, pres, tk, qvp, ght, terrain,&
! Potential temperature - theta ! Potential temperature - theta
ELSE IF (icase .EQ. 5) THEN ELSE IF (icase .EQ. 5) THEN
tempout(i,j) = tlev*(1000.D0/plev)**gammam tempout(i,j) = tlev*(1000.D0/plev)**gammam
! extraolation for equivalent potential temperature ! extrapolation for equivalent potential temperature
ELSE IF (icase .EQ. 6) THEN ELSE IF (icase .EQ. 6) THEN
e = qvapor*plev/(EPS + qvapor) e = qvapor*plev/(EPS + qvapor)
tlcl = TLCLC1/(LOG(tlev**TLCLC2/e) - TLCLC3) + TLCLC4 tlcl = TLCLC1/(LOG(tlev**TLCLC2/e) - TLCLC3) + TLCLC4

795
fortran/wrffortran.pyf

@ -1,795 +0,0 @@
! -*- f90 -*-
! Note: the context of this file is case sensitive.
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 deqthecalc(qvp,tmk,prs,eth,miy,mjx,mkzh) ! in :_wrffortran:eqthecalc.f90
threadsafe
use wrf_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
module omp_constants ! in :_wrffortran:omp.f90
integer, parameter,optional :: fomp_nest_lock_kind=8
integer(kind=4), parameter,optional :: fomp_sched_dynamic=2
integer(kind=4), parameter,optional :: fomp_sched_guided=3
integer, parameter,optional :: fomp_sched_kind=4
integer(kind=4), parameter,optional :: fomp_sched_static=1
integer, parameter,optional :: fomp_lock_kind=4
integer(kind=4), parameter,optional :: fomp_sched_auto=4
end module omp_constants
function fomp_enabled() ! in :_wrffortran:omp.f90
threadsafe
logical :: fomp_enabled
end function fomp_enabled
subroutine fomp_set_num_threads(num_threads) ! in :_wrffortran:omp.f90
threadsafe
integer intent(in) :: num_threads
end subroutine fomp_set_num_threads
function fomp_get_num_threads() ! in :_wrffortran:omp.f90
threadsafe
integer :: fomp_get_num_threads
end function fomp_get_num_threads
function fomp_get_max_threads() ! in :_wrffortran:omp.f90
threadsafe
integer :: fomp_get_max_threads
end function fomp_get_max_threads
function fomp_get_thread_num() ! in :_wrffortran:omp.f90
threadsafe
integer :: fomp_get_thread_num
end function fomp_get_thread_num
function fomp_get_num_procs() ! in :_wrffortran:omp.f90
threadsafe
integer :: fomp_get_num_procs
end function fomp_get_num_procs
function fomp_in_parallel() ! in :_wrffortran:omp.f90
threadsafe
logical :: fomp_in_parallel
end function fomp_in_parallel
subroutine fomp_set_dynamic(dynamic_threads) ! in :_wrffortran:omp.f90
threadsafe
logical intent(in) :: dynamic_threads
end subroutine fomp_set_dynamic
function fomp_get_dynamic() ! in :_wrffortran:omp.f90
threadsafe
logical :: fomp_get_dynamic
end function fomp_get_dynamic
subroutine fomp_set_nested(nested) ! in :_wrffortran:omp.f90
threadsafe
logical intent(in) :: nested
end subroutine fomp_set_nested
function fomp_get_nested() ! in :_wrffortran:omp.f90
threadsafe
logical :: fomp_get_nested
end function fomp_get_nested
subroutine fomp_set_schedule(kind,modifier) ! in :_wrffortran:omp.f90
threadsafe
use omp_constants, only: fomp_sched_kind
integer(kind=4) intent(in) :: kind
integer intent(in) :: modifier
end subroutine fomp_set_schedule
subroutine fomp_get_schedule(kind,modifier) ! in :_wrffortran:omp.f90
threadsafe
use omp_constants, only: fomp_sched_kind
integer(kind=4) intent(out) :: kind
integer intent(out) :: modifier
end subroutine fomp_get_schedule
function fomp_get_thread_limit() ! in :_wrffortran:omp.f90
threadsafe
integer :: fomp_get_thread_limit
end function fomp_get_thread_limit
subroutine fomp_set_max_active_levels(max_levels) ! in :_wrffortran:omp.f90
threadsafe
integer intent(in) :: max_levels
end subroutine fomp_set_max_active_levels
function fomp_get_max_active_levels() ! in :_wrffortran:omp.f90
threadsafe
integer :: fomp_get_max_active_levels
end function fomp_get_max_active_levels
function fomp_get_level() ! in :_wrffortran:omp.f90
threadsafe
integer :: fomp_get_level
end function fomp_get_level
function fomp_get_ancestor_thread_num(level) ! in :_wrffortran:omp.f90
threadsafe
integer intent(in) :: level
integer :: fomp_get_ancestor_thread_num
end function fomp_get_ancestor_thread_num
function fomp_get_team_size(level) ! in :_wrffortran:omp.f90
threadsafe
integer intent(in) :: level
integer :: fomp_get_team_size
end function fomp_get_team_size
function fomp_get_active_level() ! in :_wrffortran:omp.f90
threadsafe
integer :: fomp_get_active_level
end function fomp_get_active_level
function fomp_in_final() ! in :_wrffortran:omp.f90
threadsafe
logical :: fomp_in_final
end function fomp_in_final
subroutine fomp_init_lock(svar) ! in :_wrffortran:omp.f90
threadsafe
use omp_constants, only: fomp_lock_kind
integer(kind=4) intent(out) :: svar
end subroutine fomp_init_lock
subroutine fomp_init_nest_lock(nvar) ! in :_wrffortran:omp.f90
threadsafe
use omp_constants, only: fomp_nest_lock_kind
integer(kind=8) intent(out) :: nvar
end subroutine fomp_init_nest_lock
subroutine fomp_destroy_lock(svar) ! in :_wrffortran:omp.f90
threadsafe
use omp_constants, only: fomp_lock_kind
integer(kind=4) intent(inout) :: svar
end subroutine fomp_destroy_lock
subroutine fomp_destroy_nest_lock(nvar) ! in :_wrffortran:omp.f90
threadsafe
use omp_constants, only: fomp_nest_lock_kind
integer(kind=8) intent(inout) :: nvar
end subroutine fomp_destroy_nest_lock
subroutine fomp_set_lock(svar) ! in :_wrffortran:omp.f90
threadsafe
use omp_constants, only: fomp_lock_kind
integer(kind=4) intent(inout) :: svar
end subroutine fomp_set_lock
subroutine fomp_set_nest_lock(nvar) ! in :_wrffortran:omp.f90
threadsafe
use omp_constants, only: fomp_nest_lock_kind
integer(kind=8) intent(inout) :: nvar
end subroutine fomp_set_nest_lock
subroutine fomp_unset_lock(svar) ! in :_wrffortran:omp.f90
threadsafe
use omp_constants, only: fomp_lock_kind
integer(kind=4) intent(inout) :: svar
end subroutine fomp_unset_lock
subroutine fomp_unset_nest_lock(nvar) ! in :_wrffortran:omp.f90
threadsafe
use omp_constants, only: fomp_nest_lock_kind
integer(kind=8) intent(inout) :: nvar
end subroutine fomp_unset_nest_lock
function fomp_test_lock(svar) ! in :_wrffortran:omp.f90
threadsafe
use omp_constants, only: fomp_lock_kind
integer(kind=4) intent(inout) :: svar
logical :: fomp_test_lock
end function fomp_test_lock
function fomp_test_nest_lock(nvar) ! in :_wrffortran:omp.f90
threadsafe
use omp_constants, only: fomp_nest_lock_kind
integer(kind=8) intent(inout) :: nvar
integer :: fomp_test_nest_lock
end function fomp_test_nest_lock
function fomp_get_wtime() ! in :_wrffortran:omp.f90
threadsafe
real(kind=8) :: fomp_get_wtime
end function fomp_get_wtime
function fomp_get_wtick() ! in :_wrffortran:omp.f90
threadsafe
real(kind=8) :: fomp_get_wtick
end function fomp_get_wtick
function tvirtual(temp,ratmix) ! in :_wrffortran:rip_cape.f90
threadsafe
use wrf_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 wrf_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 wrf_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,mix,mjy,mkzh,ter_follow) ! in :_wrffortran:rip_cape.f90
real(kind=8) dimension(mkzh,mix,mjy),intent(in) :: prs
real(kind=8) dimension(mix,mjy),intent(in),depend(mix,mjy) :: sfp
real(kind=8) dimension(mkzh,mix,mjy),intent(out),depend(mkzh,mix,mjy) :: pf
integer, optional,intent(in),check(shape(prs,1)==mix),depend(prs) :: mix=shape(prs,1)
integer, optional,intent(in),check(shape(prs,2)==mjy),depend(prs) :: mjy=shape(prs,2)
integer, optional,intent(in),check(shape(prs,0)==mkzh),depend(prs) :: mkzh=shape(prs,0)
integer intent(in) :: ter_follow
end subroutine dpfcalc
subroutine dcapecalc3d(prs,tmk,qvp,ght,ter,sfp,cape,cin,prsf,prs_new,tmk_new,qvp_new,ght_new,cmsg,mix,mjy,mkzh,ter_follow,psafile,errstat,errmsg) ! in :_wrffortran:rip_cape.f90
threadsafe
use wrf_constants, only: tlclc2,gamma,tlclc1,rgasmd,tlclc4,g,tlclc3,thtecon3,eps,rd,cpmd,celkel,gammamd,eslcon2,eslcon1,cp,thtecon1,ezero,thtecon2
real(kind=8) dimension(mix,mjy,mkzh),intent(in) :: prs
real(kind=8) dimension(mix,mjy,mkzh),intent(in),depend(mix,mjy,mkzh) :: tmk
real(kind=8) dimension(mix,mjy,mkzh),intent(in),depend(mix,mjy,mkzh) :: qvp
real(kind=8) dimension(mix,mjy,mkzh),intent(in),depend(mix,mjy,mkzh) :: ght
real(kind=8) dimension(mix,mjy),intent(in),depend(mix,mjy) :: ter
real(kind=8) dimension(mix,mjy),intent(in),depend(mix,mjy) :: sfp
real(kind=8) dimension(mix,mjy,mkzh),intent(out,in),depend(mix,mjy,mkzh) :: cape
real(kind=8) dimension(mix,mjy,mkzh),intent(out,in),depend(mix,mjy,mkzh) :: cin
real(kind=8) dimension(mkzh,mix,mjy),intent(inout),depend(mkzh,mix,mjy) :: prsf
real(kind=8) dimension(mkzh,mix,mjy),intent(inout),depend(mkzh,mix,mjy) :: prs_new
real(kind=8) dimension(mkzh,mix,mjy),intent(inout),depend(mkzh,mix,mjy) :: tmk_new
real(kind=8) dimension(mkzh,mix,mjy),intent(inout),depend(mkzh,mix,mjy) :: qvp_new
real(kind=8) dimension(mkzh,mix,mjy),intent(inout),depend(mkzh,mix,mjy) :: ght_new
real(kind=8) intent(in) :: cmsg
integer, optional,intent(in),check(shape(prs,0)==mix),depend(prs) :: mix=shape(prs,0)
integer, optional,intent(in),check(shape(prs,1)==mjy),depend(prs) :: mjy=shape(prs,1)
integer, optional,intent(in),check(shape(prs,2)==mkzh),depend(prs) :: mkzh=shape(prs,2)
integer intent(in) :: ter_follow
character*(*) intent(in) :: psafile
integer intent(inout) :: errstat
character*(*) intent(inout) :: errmsg
end subroutine dcapecalc3d
subroutine dcapecalc2d(prs,tmk,qvp,ght,ter,sfp,cape,cin,prsf,prs_new,tmk_new,qvp_new,ght_new,cmsg,mix,mjy,mkzh,ter_follow,psafile,errstat,errmsg) ! in :_wrffortran:rip_cape.f90
threadsafe
use wrf_constants, only: tlclc2,gamma,tlclc1,rgasmd,tlclc4,g,tlclc3,thtecon3,eps,rd,cpmd,celkel,gammamd,eslcon2,eslcon1,cp,thtecon1,ezero,thtecon2
real(kind=8) dimension(mix,mjy,mkzh),intent(in) :: prs
real(kind=8) dimension(mix,mjy,mkzh),intent(in),depend(mix,mjy,mkzh) :: tmk
real(kind=8) dimension(mix,mjy,mkzh),intent(in),depend(mix,mjy,mkzh) :: qvp
real(kind=8) dimension(mix,mjy,mkzh),intent(in),depend(mix,mjy,mkzh) :: ght
real(kind=8) dimension(mix,mjy),intent(in),depend(mix,mjy) :: ter
real(kind=8) dimension(mix,mjy),intent(in),depend(mix,mjy) :: sfp
real(kind=8) dimension(mix,mjy,mkzh),intent(out,in),depend(mix,mjy,mkzh) :: cape
real(kind=8) dimension(mix,mjy,mkzh),intent(out,in),depend(mix,mjy,mkzh) :: cin
real(kind=8) dimension(mkzh,mix,mjy),intent(inout),depend(mkzh,mix,mjy) :: prsf
real(kind=8) dimension(mkzh,mix,mjy),intent(inout),depend(mkzh,mix,mjy) :: prs_new
real(kind=8) dimension(mkzh,mix,mjy),intent(inout),depend(mkzh,mix,mjy) :: tmk_new
real(kind=8) dimension(mkzh,mix,mjy),intent(inout),depend(mkzh,mix,mjy) :: qvp_new
real(kind=8) dimension(mkzh,mix,mjy),intent(inout),depend(mkzh,mix,mjy) :: ght_new
real(kind=8) intent(in) :: cmsg
integer, optional,intent(in),check(shape(prs,0)==mix),depend(prs) :: mix=shape(prs,0)
integer, optional,intent(in),check(shape(prs,1)==mjy),depend(prs) :: mjy=shape(prs,1)
integer, optional,intent(in),check(shape(prs,2)==mkzh),depend(prs) :: mkzh=shape(prs,2)
integer intent(in) :: ter_follow
character*(*) intent(in) :: psafile
integer intent(inout) :: errstat
character*(*) intent(inout) :: errmsg
end subroutine dcapecalc2d
subroutine dcloudfrac(pres,rh,lowc,midc,highc,nz,ns,ew) ! in :_wrffortran:wrf_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
subroutine dcloudfrac2(vert,rh,vert_inc_w_height,low_thresh,mid_thresh,high_thresh,msg,lowc,midc,highc,nz,ns,ew) ! in :_wrffortran:wrf_cloud_fracf.f90
threadsafe
real(kind=8) dimension(ew,ns,nz),intent(in) :: vert
real(kind=8) dimension(ew,ns,nz),intent(in),depend(ew,ns,nz) :: rh
integer intent(in) :: vert_inc_w_height
real(kind=8) intent(in) :: low_thresh
real(kind=8) intent(in) :: mid_thresh
real(kind=8) intent(in) :: high_thresh
real(kind=8) intent(in) :: msg
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(vert,2)==nz),depend(vert) :: nz=shape(vert,2)
integer, optional,check(shape(vert,1)==ns),depend(vert) :: ns=shape(vert,1)
integer, optional,check(shape(vert,0)==ew),depend(vert) :: ew=shape(vert,0)
end subroutine dcloudfrac2
module wrf_constants ! in :_wrffortran:wrf_constants.f90
real(kind=4), parameter,optional :: default_fill_float=9.96920996839e+36
integer(kind=8), parameter,optional :: default_fill_int64=int(-9223372036854775806d0, kind=8)
real(kind=8), parameter,optional :: wrf_earth_radius=6370000.d0
character(len=1), parameter,optional :: default_fill_char=achar(0)
real(kind=8), parameter,optional :: rhowat=1000.d0
real(kind=8), parameter,optional :: t_base=300.0d0
real(kind=8), parameter,optional :: cp=1004.5d0
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 :: rv=461.6d0
real(kind=8), parameter,optional,depend(pi) :: rad_per_deg=pi/180.d0
real(kind=8), parameter,optional :: default_fill_double=9.9692099683868690d36
real(kind=8), parameter,optional :: rd=287.d0
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.1415926535897932384626433d0
integer(kind=1), parameter,optional :: default_fill_int8=-127
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
integer(kind=2), parameter,optional :: default_fill_int16=-32767
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.190163098879
real(kind=8), parameter,optional :: rgasmd=.608d0
real(kind=8), parameter,optional :: g=9.81d0
integer, optional :: errlen=512
integer(kind=4), parameter,optional :: default_fill_int32=-2147483647
real(kind=8), parameter,optional :: gamma_seven=720.d0
real(kind=8), parameter,optional,depend(cpmd,rgasmd) :: gammamd=-0.279
real(kind=8), parameter,optional :: eps=0.622d0
integer, optional :: algerr=64
real(kind=8), parameter,optional,depend(cp,rd) :: gamma=0.285714285714
real(kind=8), parameter,optional,depend(expon,rd,ussalr,g) :: exponi=5.25864379523
end module wrf_constants
subroutine wrfcttcalc(prs,tk,qci,qcw,qvp,ght,ter,ctt,pf,haveqci,fill_nocloud,missing,opt_thresh,nz,ns,ew) ! in :_wrffortran:wrf_fctt.f90
threadsafe
use wrf_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
real(kind=8) dimension(ew,ns,nz),intent(inout),depend(ew,ns,nz) :: pf
integer intent(in) :: haveqci
integer intent(in) :: fill_nocloud
real(kind=8) intent(in) :: missing
real(kind=8) intent(in) :: opt_thresh
integer, optional,intent(in),check(shape(prs,2)==nz),depend(prs) :: nz=shape(prs,2)
integer, optional,intent(in),check(shape(prs,1)==ns),depend(prs) :: ns=shape(prs,1)
integer, optional,intent(in),check(shape(prs,0)==ew),depend(prs) :: ew=shape(prs,0)
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 wrf_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 wrf_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 wrf_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 wrf_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 wrf_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 wrf_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 testfunc(a,b,c,nx,ny,nz,errstat,errmsg) ! in :_wrffortran:wrf_testfunc.f90
use wrf_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 intent(inout) :: errstat
character*(*) intent(inout) :: errmsg
end subroutine testfunc
subroutine dcomputepi(pi,pressure,nx,ny,nz) ! in :_wrffortran:wrf_user.f90
threadsafe
use wrf_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)
integer, optional,intent(in),check(shape(pi,1)==ny),depend(pi) :: ny=shape(pi,1)
integer, optional,intent(in),check(shape(pi,2)==nz),depend(pi) :: nz=shape(pi,2)
end subroutine dcomputepi
subroutine dcomputetk(tk,pressure,theta,nx) ! in :_wrffortran:wrf_user.f90
threadsafe
use wrf_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
integer, optional,intent(in),check(len(tk)>=nx),depend(tk) :: nx=len(tk)
end subroutine dcomputetk
subroutine dinterp3dz(data3d,out2d,zdata,desiredloc,nx,ny,nz,missingval) ! in :_wrffortran:wrf_user.f90
threadsafe
real(kind=8) dimension(nx,ny,nz),intent(in) :: data3d
real(kind=8) dimension(nx,ny),intent(out,in),depend(nx,ny) :: out2d
real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: zdata
real(kind=8) intent(in) :: desiredloc
integer, optional,intent(in),check(shape(data3d,0)==nx),depend(data3d) :: nx=shape(data3d,0)
integer, optional,intent(in),check(shape(data3d,1)==ny),depend(data3d) :: ny=shape(data3d,1)
integer, optional,intent(in),check(shape(data3d,2)==nz),depend(data3d) :: nz=shape(data3d,2)
real(kind=8) intent(in) :: missingval
end subroutine dinterp3dz
subroutine dzstag(znew,nx,ny,nz,z,nxz,nyz,nzz,terrain) ! in :_wrffortran:wrf_user.f90
threadsafe
real(kind=8) dimension(nx,ny,nz),intent(out,in) :: znew
integer, optional,intent(in),check(shape(znew,0)==nx),depend(znew) :: nx=shape(znew,0)
integer, optional,intent(in),check(shape(znew,1)==ny),depend(znew) :: ny=shape(znew,1)
integer, optional,intent(in),check(shape(znew,2)==nz),depend(znew) :: nz=shape(znew,2)
real(kind=8) dimension(nxz,nyz,nzz),intent(in) :: z
integer, optional,intent(in),check(shape(z,0)==nxz),depend(z) :: nxz=shape(z,0)
integer, optional,intent(in),check(shape(z,1)==nyz),depend(z) :: nyz=shape(z,1)
integer, optional,intent(in),check(shape(z,2)==nzz),depend(z) :: nzz=shape(z,2)
real(kind=8) dimension(nxz,nyz),intent(in),depend(nxz,nyz) :: terrain
end subroutine dzstag
subroutine dinterp2dxy(v3d,v2d,xy,nx,ny,nz,nxy) ! in :_wrffortran:wrf_user.f90
threadsafe
real(kind=8) dimension(nx,ny,nz),intent(in) :: v3d
real(kind=8) dimension(nxy,nz),intent(out,in),depend(nz) :: v2d
real(kind=8) dimension(2,nxy),intent(in),depend(nxy) :: xy
integer, optional,intent(in),check(shape(v3d,0)==nx),depend(v3d) :: nx=shape(v3d,0)
integer, optional,intent(in),check(shape(v3d,1)==ny),depend(v3d) :: ny=shape(v3d,1)
integer, optional,intent(in),check(shape(v3d,2)==nz),depend(v3d) :: nz=shape(v3d,2)
integer, optional,intent(in),check(shape(v2d,0)==nxy),depend(v2d) :: nxy=shape(v2d,0)
end subroutine dinterp2dxy
subroutine dinterp1d(v_in,v_out,z_in,z_out,vmsg,nz_in,nz_out) ! in :_wrffortran:wrf_user.f90
threadsafe
real(kind=8) dimension(nz_in),intent(in) :: v_in
real(kind=8) dimension(nz_out),intent(out,in) :: v_out
real(kind=8) dimension(nz_in),intent(in),depend(nz_in) :: z_in
real(kind=8) dimension(nz_out),intent(in),depend(nz_out) :: z_out
real(kind=8) intent(in) :: vmsg
integer, optional,intent(in),check(len(v_in)>=nz_in),depend(v_in) :: nz_in=len(v_in)
integer, optional,intent(in),check(len(v_out)>=nz_out),depend(v_out) :: nz_out=len(v_out)
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 wrf_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)
real(kind=8) dimension(nx,ny,nz),intent(in) :: z
real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: t
real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: p
real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: q
real(kind=8) dimension(nx,ny),intent(out,in),depend(nx,ny) :: sea_level_pressure
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 intent(inout) :: errstat
character*(*) intent(inout) :: errmsg
end subroutine dcomputeseaprs
subroutine dfilter2d(a,b,nx,ny,it,missing) ! in :_wrffortran:wrf_user.f90
threadsafe
real(kind=8) dimension(nx,ny),intent(in,out) :: a
real(kind=8) dimension(nx,ny),intent(inout),depend(nx,ny) :: b
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 intent(in) :: it
real(kind=8) intent(in) :: missing
end subroutine dfilter2d
subroutine filter2d(a,b,nx,ny,it,missing) ! in :_wrffortran:wrf_user.f90
threadsafe
real(kind=4) dimension(nx,ny),intent(in,out) :: a
real(kind=4) dimension(nx,ny),intent(inout),depend(nx,ny) :: b
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 intent(in) :: it
real(kind=4) intent(in) :: missing
end subroutine filter2d
subroutine dcomputerh(qv,p,t,rh,nx) ! in :_wrffortran:wrf_user.f90
threadsafe
use wrf_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
real(kind=8) dimension(nx),intent(out,in),depend(nx) :: rh
integer, optional,intent(in),check(len(qv)>=nx),depend(qv) :: nx=len(qv)
end subroutine dcomputerh
subroutine dgetijlatlong(lat_array,long_array,lat,longitude,ii,jj,nx,ny,imsg) ! in :_wrffortran:wrf_user.f90
threadsafe
real(kind=8) dimension(nx,ny),intent(in) :: lat_array
real(kind=8) dimension(nx,ny),intent(in),depend(nx,ny) :: long_array
real(kind=8) :: lat
real(kind=8) :: longitude
integer intent(out,in) :: ii
integer intent(out,in) :: jj
integer, optional,intent(in),check(shape(lat_array,0)==nx),depend(lat_array) :: nx=shape(lat_array,0)
integer, optional,intent(in),check(shape(lat_array,1)==ny),depend(lat_array) :: ny=shape(lat_array,1)
integer intent(in) :: imsg
end subroutine dgetijlatlong
subroutine dcomputeuvmet(u,v,uvmet,longca,longcb,flong,flat,cen_long,cone,rpd,nx,ny,nxp1,nyp1,istag,is_msg_val,umsg,vmsg,uvmetmsg) ! in :_wrffortran:wrf_user.f90
threadsafe
real(kind=8) dimension(nxp1,ny),intent(in) :: u
real(kind=8) dimension(nx,nyp1),intent(in) :: v
real(kind=8) dimension(nx,ny,2),intent(out,in),depend(nx,ny) :: uvmet
real(kind=8) dimension(nx,ny),intent(inout),depend(nx,ny) :: longca
real(kind=8) dimension(nx,ny),intent(inout),depend(nx,ny) :: longcb
real(kind=8) dimension(nx,ny),intent(in),depend(nx,ny) :: flong
real(kind=8) dimension(nx,ny),intent(in),depend(nx,ny) :: flat
real(kind=8) intent(in) :: cen_long
real(kind=8) intent(in) :: cone
real(kind=8) intent(in) :: rpd
integer, optional,intent(in),check(shape(v,0)==nx),depend(v) :: nx=shape(v,0)
integer, optional,intent(in),check(shape(u,1)==ny),depend(u) :: ny=shape(u,1)
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)
integer intent(in) :: istag
logical intent(in) :: is_msg_val
real(kind=8) intent(in) :: umsg
real(kind=8) intent(in) :: vmsg
real(kind=8) intent(in) :: uvmetmsg
end subroutine dcomputeuvmet
subroutine dcomputetd(td,pressure,qv_in,nx) ! in :_wrffortran:wrf_user.f90
threadsafe
real(kind=8) dimension(nx),intent(out,in) :: td
real(kind=8) dimension(nx),intent(in),depend(nx) :: pressure
real(kind=8) dimension(nx),intent(in),depend(nx) :: qv_in
integer, optional,intent(in),check(len(td)>=nx),depend(td) :: nx=len(td)
end subroutine dcomputetd
subroutine dcomputeiclw(iclw,pressure,qc_in,nx,ny,nz) ! in :_wrffortran:wrf_user.f90
threadsafe
use wrf_constants, only: g
real(kind=8) dimension(nx,ny),intent(out,in) :: iclw
real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny) :: pressure
real(kind=8) dimension(nx,ny,nz),intent(in),depend(nx,ny,nz) :: qc_in
integer, optional,intent(in),check(shape(iclw,0)==nx),depend(iclw) :: nx=shape(iclw,0)
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 calcdbz(prs,tmk,qvp,qra,qsn,qgr,sn0,ivarint,iliqskin,dbz,nx,ny,nz) ! in :_wrffortran:wrf_user_dbz.f90
threadsafe
use wrf_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 wrf_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 wrf_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 wrf_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),intent(in),depend(ew,ns,nz) :: lvprs
real(kind=8) dimension(ew,ns),intent(in),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) ! in :_wrffortran:wrf_vinterp.f90
threadsafe
use wrf_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
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,tempout,rmsg,errstat,errmsg) ! in :_wrffortran:wrf_vinterp.f90
threadsafe
use wrf_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) dimension(ew,ns),intent(inout),depend(ew,ns) :: tempout
real(kind=8) intent(in) :: rmsg
integer intent(inout) :: errstat
character*(*) intent(inout) :: errmsg
end subroutine wrf_vintrp
subroutine dcomputewspd(wspd,u,v,nx,ny) ! in :_wrffortran:wrf_wind.f90
threadsafe
real(kind=8) dimension(nx,ny),intent(out,in) :: wspd
real(kind=8) dimension(nx,ny),intent(in),depend(nx,ny) :: u
real(kind=8) dimension(nx,ny),intent(in),depend(nx,ny) :: v
integer, optional,intent(in),check(shape(wspd,0)==nx),depend(wspd) :: nx=shape(wspd,0)
integer, optional,intent(in),check(shape(wspd,1)==ny),depend(wspd) :: ny=shape(wspd,1)
end subroutine dcomputewspd
subroutine dcomputewdir(wdir,u,v,nx,ny) ! in :_wrffortran:wrf_wind.f90
threadsafe
use wrf_constants, only: deg_per_rad
real(kind=8) dimension(nx,ny),intent(out,in) :: wdir
real(kind=8) dimension(nx,ny),intent(in),depend(nx,ny) :: u
real(kind=8) dimension(nx,ny),intent(in),depend(nx,ny) :: v
integer, optional,intent(in),check(shape(wdir,0)==nx),depend(wdir) :: nx=shape(wdir,0)
integer, optional,intent(in),check(shape(wdir,1)==ny),depend(wdir) :: ny=shape(wdir,1)
end subroutine dcomputewdir
end interface
end python module _wrffortran
! This file was auto-generated with f2py (version:2).
! See http://cens.ioc.ee/projects/f2py2e/

4
requirements.txt

@ -1,3 +1,3 @@
numpy>=1.11 numpy>=1.11
wrapt>=1.10 wrapt
setuptools>=38.0 setuptools

8
setup.py

@ -40,8 +40,7 @@ ext1 = numpy.distutils.core.Extension(
"fortran/wrf_pw.f90", "fortran/wrf_pw.f90",
"fortran/wrf_vinterp.f90", "fortran/wrf_vinterp.f90",
"fortran/wrf_wind.f90", "fortran/wrf_wind.f90",
"fortran/omp.f90", "fortran/omp.f90"]
"fortran/wrffortran.pyf"]
) )
with open("src/wrf/version.py") as f: with open("src/wrf/version.py") as f:
@ -86,12 +85,13 @@ numpy.distutils.core.setup(
classifiers = ["Development Status :: 5 - Production/Stable", classifiers = ["Development Status :: 5 - Production/Stable",
"Intended Audience :: Science/Research", "Intended Audience :: Science/Research",
"Intended Audience :: Developers", "Intended Audience :: Developers",
"License :: OSI Approved", "License :: OSI Approved :: Apache Software License",
"Programming Language :: Fortran", "Programming Language :: Fortran",
"Programming Language :: Python :: 2.7", "Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Topic :: Scientific/Engineering :: Atmospheric Science", "Topic :: Scientific/Engineering :: Atmospheric Science",
"Topic :: Software Development", "Topic :: Software Development",
"Operating System :: POSIX", "Operating System :: POSIX",
@ -100,7 +100,7 @@ numpy.distutils.core.setup(
"Operating System :: Microsoft :: Windows"], "Operating System :: Microsoft :: Windows"],
name = "wrf-python", name = "wrf-python",
platforms = ["any"], platforms = ["any"],
license = "OSI Approved", license = "Apache License 2.0",
version = __version__, version = __version__,
packages = setuptools.find_packages("src"), packages = setuptools.find_packages("src"),
ext_modules = ext_modules, ext_modules = ext_modules,

43
src/wrf/computation.py

@ -677,21 +677,38 @@ def uvmet(u, v, lat, lon, cen_long, cone, meta=True, units="m s-1"):
@set_smooth_metdata() @set_smooth_metdata()
def smooth2d(field, passes, meta=True): def smooth2d(field, passes, cenweight=2.0, meta=True):
"""Return the field smoothed. """Return the field smoothed.
This routine does not modify the original data. The smoothing kernel applied is:
.. math::
\\frac{1}{4 + cenweight} * \\begin{bmatrix}
0 & 1 & 0 \\\\
1 & cenweight & 1 \\\\
0 & 1 & 0
\\end{bmatrix}
Data values along the borders are left unchanged. This routine does not
modify the original data supplied by the *field* parameter..
If you need more general purpose multidimensional filtering tools,
try the :meth:`scipy.ndimage.convolve` method.
Args: Args:
field (:class:`xarray.DataArray` or :class:`numpy.ndarray`): The field field (:class:`xarray.DataArray` or :class:`numpy.ndarray`): The field
to smooth, which must be at least two dimensions. Missing/fill to smooth, which must be at least two dimensions. Missing/fill
values will be ignored as long as the type is either a values will be ignored as long as the type is either a
:class:`numpy.ma.MaskedArray or a :class:`xarray.DataArray` with :class:`numpy.ma.MaskedArray` or a :class:`xarray.DataArray` with
a *_FillValue* attribute. a *_FillValue* attribute.
passes (:obj:`int`): The number of smoothing passes. passes (:obj:`int`): The number of smoothing passes.
cenweight (:obj:`float`, optional): The weight to apply to the
center of the smoothing kernel. Default is 2.0.
meta (:obj:`bool`): Set to False to disable metadata and return meta (:obj:`bool`): Set to False to disable metadata and return
:class:`numpy.ndarray` instead of :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True. :class:`xarray.DataArray`. Default is True.
@ -705,9 +722,13 @@ def smooth2d(field, passes, meta=True):
be either a :class:`numpy.ndarray` or a :class:`numpy.ma.MaskedArray` be either a :class:`numpy.ndarray` or a :class:`numpy.ma.MaskedArray`
depending on the type for *field*. depending on the type for *field*.
See Also:
:meth:`scipy.ndimage.convolve`
""" """
return _smooth2d(field, passes) return _smooth2d(field, passes, cenweight)
@set_cape_alg_metadata(is2d=True, copyarg="pres_hpa") @set_cape_alg_metadata(is2d=True, copyarg="pres_hpa")
@ -1277,7 +1298,7 @@ def dbz(pres, tkel, qv, qr, qs=None, qg=None, use_varint=False,
@set_alg_metadata(2, "terrain", units="m2 s-2", @set_alg_metadata(2, "terrain", units="m2 s-2",
description="storm relative helicity") description="storm relative helicity")
def srhel(u, v, height, terrain, top=3000.0, meta=True): def srhel(u, v, height, terrain, top=3000.0, lats=None, meta=True):
"""Return the storm relative helicity. """Return the storm relative helicity.
This function calculates storm relative helicity from WRF ARW output. This function calculates storm relative helicity from WRF ARW output.
@ -1323,6 +1344,11 @@ def srhel(u, v, height, terrain, top=3000.0, meta=True):
top (:obj:`float`): The height of the layer below which helicity is top (:obj:`float`): The height of the layer below which helicity is
calculated (meters above ground level). calculated (meters above ground level).
lats (:class:`xarray.DataArray` or :class:`numpy.ndarray`, optional):
Array of latitudes. This is required if any (or all) of your
domain is in the southern hemisphere. If not provided, the
northern hemisphere is assumed. Default is None.
meta (:obj:`bool`): Set to False to disable metadata and return meta (:obj:`bool`): Set to False to disable metadata and return
:class:`numpy.ndarray` instead of :class:`numpy.ndarray` instead of
@ -1352,7 +1378,12 @@ def srhel(u, v, height, terrain, top=3000.0, meta=True):
_v = np.ascontiguousarray(v[...,::-1,:,:]) _v = np.ascontiguousarray(v[...,::-1,:,:])
_height = np.ascontiguousarray(height[...,::-1,:,:]) _height = np.ascontiguousarray(height[...,::-1,:,:])
return _srhel(_u, _v, _height, terrain, top) if lats is None:
_lats = np.ones_like(terrain)
else:
_lats = lats
return _srhel(_u, _v, _height, terrain, _lats, top)
@set_alg_metadata(2, "u", refvarndims=3, units="m2 s-2", @set_alg_metadata(2, "u", refvarndims=3, units="m2 s-2",

2
src/wrf/destag.py

@ -57,7 +57,7 @@ def destagger(var, stagger_dim, meta=False):
dim_ranges_1[stagger_dim] = slice1 dim_ranges_1[stagger_dim] = slice1
dim_ranges_2[stagger_dim] = slice2 dim_ranges_2[stagger_dim] = slice2
result = .5*(var[dim_ranges_1] + var[dim_ranges_2]) result = .5*(var[tuple(dim_ranges_1)] + var[tuple(dim_ranges_2)])
return result return result

55
src/wrf/extension.py

@ -11,7 +11,7 @@ from wrf._wrffortran import (dcomputetk, dinterp3dz, dinterp2dxy, dinterp1d,
dcomputeabsvort, dlltoij, dijtoll, deqthecalc, dcomputeabsvort, dlltoij, dijtoll, deqthecalc,
omgcalc, virtual_temp, wetbulbcalc, dcomputepw, omgcalc, virtual_temp, wetbulbcalc, dcomputepw,
wrf_monotonic, wrf_vintrp, dcomputewspd, wrf_monotonic, wrf_vintrp, dcomputewspd,
dcomputewdir, dcomputewdir, dinterp3dz_2dlev,
fomp_set_num_threads, fomp_get_num_threads, fomp_set_num_threads, fomp_get_num_threads,
fomp_get_max_threads, fomp_get_thread_num, fomp_get_max_threads, fomp_get_thread_num,
fomp_get_num_procs, fomp_in_parallel, fomp_get_num_procs, fomp_in_parallel,
@ -34,7 +34,8 @@ from .decorators import (left_iteration, cast_type,
from .util import combine_dims, npbytes_to_str, psafilepath from .util import combine_dims, npbytes_to_str, psafilepath
from .py3compat import py3range from .py3compat import py3range
from .specialdec import (uvmet_left_iter, cape_left_iter, from .specialdec import (uvmet_left_iter, cape_left_iter,
cloudfrac_left_iter, check_cape_args) cloudfrac_left_iter, check_cape_args,
interplevel_left_iter, check_interplevel_args)
class DiagnosticError(Exception): class DiagnosticError(Exception):
"""Raised when an error occurs in a diagnostic routine.""" """Raised when an error occurs in a diagnostic routine."""
@ -73,9 +74,9 @@ class DiagnosticError(Exception):
# below assume that Fortran-ordered views are being used. This allows # below assume that Fortran-ordered views are being used. This allows
# f2py to pass the array pointers directly to the Fortran routine. # f2py to pass the array pointers directly to the Fortran routine.
@check_args(0, 3, (3, 3, None, None)) @check_interplevel_args(is2dlev=False)
@left_iteration(3, 2, ref_var_idx=0, ignore_args=(2,3)) @interplevel_left_iter(is2dlev=False)
@cast_type(arg_idxs=(0,1)) @cast_type(arg_idxs=(0,1,2))
@extract_and_transpose() @extract_and_transpose()
def _interpz3d(field3d, z, desiredloc, missingval, outview=None): def _interpz3d(field3d, z, desiredloc, missingval, outview=None):
"""Wrapper for dinterp3dz. """Wrapper for dinterp3dz.
@ -83,9 +84,10 @@ def _interpz3d(field3d, z, desiredloc, missingval, outview=None):
Located in wrf_user.f90. Located in wrf_user.f90.
""" """
if outview is None: if outview is None:
outview = np.empty(field3d.shape[0:2], np.float64, order="F") outshape = field3d.shape[0:2] + desiredloc.shape
outview = np.empty(outshape, np.float64, order="F")
result = dinterp3dz(field3d, result = dinterp3dz(field3d,
outview, outview,
z, z,
@ -94,6 +96,27 @@ def _interpz3d(field3d, z, desiredloc, missingval, outview=None):
return result return result
@check_interplevel_args(is2dlev=True)
@interplevel_left_iter(is2dlev=True)
@cast_type(arg_idxs=(0,1,2))
@extract_and_transpose()
def _interpz3d_lev2d(field3d, z, lev2d, missingval, outview=None):
"""Wrapper for dinterp3dz.
Located in wrf_user.f90.
"""
if outview is None:
outview = np.empty(field3d.shape[0:2], np.float64, order="F")
result = dinterp3dz_2dlev(field3d,
outview,
z,
lev2d,
missingval)
return result
@check_args(0, 3, (3,)) @check_args(0, 3, (3,))
@left_iteration(3, combine_dims([(0,-3),(1,-2)]), ref_var_idx=0, @left_iteration(3, combine_dims([(0,-3),(1,-2)]), ref_var_idx=0,
ignore_args=(1,)) ignore_args=(1,))
@ -486,11 +509,11 @@ def _wetbulb(p, tk, qv, psafile=psafilepath(), outview=None):
return result return result
@check_args(0, 3, (3,3,3,2)) @check_args(0, 3, (3,3,3,2,2))
@left_iteration(3, 2, ref_var_idx=0, ignore_args=(4,)) @left_iteration(3, 2, ref_var_idx=0, ignore_args=(5,))
@cast_type(arg_idxs=(0,1,2,3)) @cast_type(arg_idxs=(0,1,2,3,4))
@extract_and_transpose() @extract_and_transpose()
def _srhel(u, v, z, ter, top, outview=None): def _srhel(u, v, z, ter, lats, top, outview=None):
"""Wrapper for dcalrelhl. """Wrapper for dcalrelhl.
Located in wrf_relhl.f90. Located in wrf_relhl.f90.
@ -503,6 +526,7 @@ def _srhel(u, v, z, ter, top, outview=None):
v, v,
z, z,
ter, ter,
lats,
top, top,
outview) outview)
@ -799,10 +823,10 @@ def _ctt(p_hpa, tk, qice, qcld, qv, ght, ter, haveqci, fill_nocloud,
@check_args(0, 2, (2,)) @check_args(0, 2, (2,))
@left_iteration(2, 2, ref_var_idx=0, ignore_args=(1,)) @left_iteration(2, 2, ref_var_idx=0, ignore_args=(1,2))
@cast_type(arg_idxs=(0,)) @cast_type(arg_idxs=(0,))
@extract_and_transpose() @extract_and_transpose()
def _smooth2d(field, passes, outview=None): def _smooth2d(field, passes, cenweight, outview=None):
"""Wrapper for dfilter2d. """Wrapper for dfilter2d.
Located in wrf_user.f90. Located in wrf_user.f90.
@ -826,7 +850,8 @@ def _smooth2d(field, passes, outview=None):
dfilter2d(outview, dfilter2d(outview,
field_tmp, field_tmp,
passes, passes,
missing) missing,
cenweight)
return outview return outview

408
src/wrf/g_cape.py

@ -12,7 +12,7 @@ from .metadecorators import set_cape_metadata
@set_cape_metadata(is2d=True) @set_cape_metadata(is2d=True)
def get_2dcape(wrfin, timeidx=0, method="cat", squeeze=True, cache=None, def get_2dcape(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None, missing=default_fill(np.float64)): meta=True, _key=None, missing=default_fill(np.float64)):
"""Return the 2d fields of MCAPE, MCIN, LCL, and LFC. """Return the two-dimensional fields of MCAPE, MCIN, LCL, and LFC.
The leftmost dimension of the returned array represents four different The leftmost dimension of the returned array represents four different
quantities: quantities:
@ -223,6 +223,412 @@ def get_3dcape(wrfin, timeidx=0, method="cat",
return ma.masked_values(cape_cin, missing) return ma.masked_values(cape_cin, missing)
def get_cape2d_only(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None, missing=default_fill(np.float64)):
"""Return the two-dimensional field of MCAPE (Max Convective Available
Potential Energy).
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
missing (:obj:`float`): The fill value to use for the output.
Default is :data:`wrf.default_fill(np.float64)`.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
2D MCAPE field.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_2dcape(wrfin, timeidx, method, squeeze, cache,
meta, _key, missing)[0,:]
if meta:
result.attrs["description"] = "mcape"
result.attrs["units"] = "J kg-1"
return result
def get_cin2d_only(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None, missing=default_fill(np.float64)):
"""Return the two-dimensional field of MCIN (Max Convective Inhibition).
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
missing (:obj:`float`): The fill value to use for the output.
Default is :data:`wrf.default_fill(np.float64)`.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
2D MCIN field.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_2dcape(wrfin, timeidx, method, squeeze, cache,
meta, _key, missing)[1,:]
if meta:
result.attrs["description"] = "mcin"
result.attrs["units"] = "J kg-1"
return result
def get_lcl(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None, missing=default_fill(np.float64)):
"""Return the two-dimensional field of LCL (Lifted Condensation Level).
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
missing (:obj:`float`): The fill value to use for the output.
Default is :data:`wrf.default_fill(np.float64)`.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
2D LCL field.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_2dcape(wrfin, timeidx, method, squeeze, cache,
meta, _key, missing)[2,:]
if meta:
result.attrs["description"] = "lcl"
result.attrs["units"] = "m"
return result
def get_lfc(wrfin, timeidx=0, method="cat", squeeze=True, cache=None,
meta=True, _key=None, missing=default_fill(np.float64)):
"""Return the two-dimensional field of LFC (Level of Free Convection).
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
missing (:obj:`float`): The fill value to use for the output.
Default is :data:`wrf.default_fill(np.float64)`.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
2D LFC field.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_2dcape(wrfin, timeidx, method, squeeze, cache,
meta, _key, missing)[3,:]
if meta:
result.attrs["description"] = "lfc"
result.attrs["units"] = "m"
return result
def get_3dcape_only(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True,
_key=None, missing=default_fill(np.float64)):
"""Return the three-dimensional field of CAPE (Convective Available
Potential Energy).
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
missing (:obj:`float`): The fill value to use for the output.
Default is :data:`wrf.default_fill(np.float64)`.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
3D CAPE field.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_3dcape(wrfin, timeidx, method, squeeze, cache, meta,
_key, missing)[0,:]
if meta:
result.attrs["description"] = "cape"
result.attrs["units"] = "J kg-1"
return result
def get_3dcin_only(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True,
_key=None, missing=default_fill(np.float64)):
"""Return the three-dimensional field of CIN (Convective Inhibition).
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
missing (:obj:`float`): The fill value to use for the output.
Default is :data:`wrf.default_fill(np.float64)`.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
3D CIN field.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_3dcape(wrfin, timeidx, method, squeeze, cache, meta,
_key, missing)[1,:]
if meta:
result.attrs["description"] = "cin"
result.attrs["units"] = "J kg-1"
return result

335
src/wrf/g_cloudfrac.py

@ -161,3 +161,338 @@ def get_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
return ma.masked_values(cfrac, missing) return ma.masked_values(cfrac, missing)
def get_low_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
vert_type="height_agl", low_thresh=None, mid_thresh=None,
high_thresh=None, missing=default_fill(np.float64)):
"""Return the cloud fraction for the low level clouds.
If the vertical coordinate type is 'height_agl' or 'height_msl', the
default cloud levels are defined as:
300 m <= low_cloud < 2000 m
2000 m <= mid_cloud < 6000 m
6000 m <= high_cloud
For 'pressure', the default cloud levels are defined as:
97000 Pa <= low_cloud < 80000 Pa
80000 Pa <= mid_cloud < 45000 Pa
45000 Pa <= high_cloud
Note that the default low cloud levels are chosen to
exclude clouds near the surface (fog). If you want fog included, set
*low_thresh* to ~99500 Pa if *vert_type* is set to 'pressure', or 15 m if
using 'height_msl' or 'height_agl'. Keep in mind that the lowest mass grid
points are slightly above the ground, and in order to find clouds, the
*low_thresh* needs to be set to values that are slightly greater than
(less than) the lowest height (pressure) values.
When using 'pressure' or 'height_agl' for *vert_type*, there is a
possibility that the lowest WRF level will be higher than the low_cloud or
mid_cloud threshold, particularly for mountainous regions. When this
happens, a fill value will be used in the output.
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
vert_type (:obj:`str`, optional): The type of vertical coordinate used
to determine cloud type thresholds. Must be 'height_agl',
'height_msl', or 'pres'. The default is 'height_agl'.
low_thresh (:obj:`float`, optional): The lower bound for what is
considered a low cloud. If *vert_type* is 'pres', the default is
97000 Pa. If *vert_type* is 'height_agl' or 'height_msl', then the
default is 300 m.
mid_thresh (:obj:`float`, optional): The lower bound for what is
considered a mid level cloud. If *vert_type* is 'pres', the
default is 80000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 2000 m.
high_thresh (:obj:`float`, optional): The lower bound for what is
considered a high level cloud. If *vert_type* is 'pres', the
default is 45000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 6000 m.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
cloud fraction array for low level clouds.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_cloudfrac(wrfin, timeidx, method, squeeze,
cache, meta, _key,
vert_type, low_thresh, mid_thresh,
high_thresh, missing)[0,:]
if meta:
result.attrs["description"] = "low clouds"
return result
def get_mid_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
vert_type="height_agl", low_thresh=None, mid_thresh=None,
high_thresh=None, missing=default_fill(np.float64)):
"""Return the cloud fraction for the mid level clouds.
If the vertical coordinate type is 'height_agl' or 'height_msl', the
default cloud levels are defined as:
300 m <= low_cloud < 2000 m
2000 m <= mid_cloud < 6000 m
6000 m <= high_cloud
For 'pressure', the default cloud levels are defined as:
97000 Pa <= low_cloud < 80000 Pa
80000 Pa <= mid_cloud < 45000 Pa
45000 Pa <= high_cloud
Note that the default low cloud levels are chosen to
exclude clouds near the surface (fog). If you want fog included, set
*low_thresh* to ~99500 Pa if *vert_type* is set to 'pressure', or 15 m if
using 'height_msl' or 'height_agl'. Keep in mind that the lowest mass grid
points are slightly above the ground, and in order to find clouds, the
*low_thresh* needs to be set to values that are slightly greater than
(less than) the lowest height (pressure) values.
When using 'pressure' or 'height_agl' for *vert_type*, there is a
possibility that the lowest WRF level will be higher than the low_cloud or
mid_cloud threshold, particularly for mountainous regions. When this
happens, a fill value will be used in the output.
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
vert_type (:obj:`str`, optional): The type of vertical coordinate used
to determine cloud type thresholds. Must be 'height_agl',
'height_msl', or 'pres'. The default is 'height_agl'.
low_thresh (:obj:`float`, optional): The lower bound for what is
considered a low cloud. If *vert_type* is 'pres', the default is
97000 Pa. If *vert_type* is 'height_agl' or 'height_msl', then the
default is 300 m.
mid_thresh (:obj:`float`, optional): The lower bound for what is
considered a mid level cloud. If *vert_type* is 'pres', the
default is 80000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 2000 m.
high_thresh (:obj:`float`, optional): The lower bound for what is
considered a high level cloud. If *vert_type* is 'pres', the
default is 45000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 6000 m.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
cloud fraction array for mid level clouds.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_cloudfrac(wrfin, timeidx, method, squeeze,
cache, meta, _key,
vert_type, low_thresh, mid_thresh,
high_thresh, missing)[1,:]
if meta:
result.attrs["description"] = "mid clouds"
return result
def get_high_cloudfrac(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
vert_type="height_agl", low_thresh=None, mid_thresh=None,
high_thresh=None, missing=default_fill(np.float64)):
"""Return the cloud fraction for the high level clouds.
If the vertical coordinate type is 'height_agl' or 'height_msl', the
default cloud levels are defined as:
300 m <= low_cloud < 2000 m
2000 m <= mid_cloud < 6000 m
6000 m <= high_cloud
For 'pressure', the default cloud levels are defined as:
97000 Pa <= low_cloud < 80000 Pa
80000 Pa <= mid_cloud < 45000 Pa
45000 Pa <= high_cloud
Note that the default low cloud levels are chosen to
exclude clouds near the surface (fog). If you want fog included, set
*low_thresh* to ~99500 Pa if *vert_type* is set to 'pressure', or 15 m if
using 'height_msl' or 'height_agl'. Keep in mind that the lowest mass grid
points are slightly above the ground, and in order to find clouds, the
*low_thresh* needs to be set to values that are slightly greater than
(less than) the lowest height (pressure) values.
When using 'pressure' or 'height_agl' for *vert_type*, there is a
possibility that the lowest WRF level will be higher than the low_cloud or
mid_cloud threshold, particularly for mountainous regions. When this
happens, a fill value will be used in the output.
This functions extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
vert_type (:obj:`str`, optional): The type of vertical coordinate used
to determine cloud type thresholds. Must be 'height_agl',
'height_msl', or 'pres'. The default is 'height_agl'.
low_thresh (:obj:`float`, optional): The lower bound for what is
considered a low cloud. If *vert_type* is 'pres', the default is
97000 Pa. If *vert_type* is 'height_agl' or 'height_msl', then the
default is 300 m.
mid_thresh (:obj:`float`, optional): The lower bound for what is
considered a mid level cloud. If *vert_type* is 'pres', the
default is 80000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 2000 m.
high_thresh (:obj:`float`, optional): The lower bound for what is
considered a high level cloud. If *vert_type* is 'pres', the
default is 45000 Pa. If *vert_type* is 'height_agl' or
'height_msl', then the default is 6000 m.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The
cloud fraction array for high level clouds.
If xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_cloudfrac(wrfin, timeidx, method, squeeze,
cache, meta, _key,
vert_type, low_thresh, mid_thresh,
high_thresh, missing)[2,:]
if meta:
result.attrs["description"] = "high clouds"
return result

8
src/wrf/g_helicity.py

@ -7,6 +7,7 @@ from .extension import _srhel, _udhel
from .destag import destagger from .destag import destagger
from .util import extract_vars, extract_global_attrs, either from .util import extract_vars, extract_global_attrs, either
from .metadecorators import copy_and_set_metadata from .metadecorators import copy_and_set_metadata
from .g_latlon import get_lat
@copy_and_set_metadata(copy_varname="HGT", name="srh", @copy_and_set_metadata(copy_varname="HGT", name="srh",
description="storm relative helicity", description="storm relative helicity",
@ -72,6 +73,9 @@ def get_srh(wrfin, timeidx=0, method="cat", squeeze=True,
""" """
# Top can either be 3000 or 1000 (for 0-1 srh or 0-3 srh) # Top can either be 3000 or 1000 (for 0-1 srh or 0-3 srh)
lats = get_lat(wrfin, timeidx, method, squeeze,
cache, meta=False, _key=_key, stagger=None)
ncvars = extract_vars(wrfin, timeidx, ("HGT", "PH", "PHB"), ncvars = extract_vars(wrfin, timeidx, ("HGT", "PH", "PHB"),
method, squeeze, cache, meta=False, method, squeeze, cache, meta=False,
_key=_key) _key=_key)
@ -101,7 +105,7 @@ def get_srh(wrfin, timeidx=0, method="cat", squeeze=True,
v1 = np.ascontiguousarray(v[...,::-1,:,:]) v1 = np.ascontiguousarray(v[...,::-1,:,:])
z1 = np.ascontiguousarray(z[...,::-1,:,:]) z1 = np.ascontiguousarray(z[...,::-1,:,:])
srh = _srhel(u1, v1, z1, ter, top) srh = _srhel(u1, v1, z1, ter, lats, top)
return srh return srh
@ -197,7 +201,7 @@ def get_uh(wrfin, timeidx=0, method="cat", squeeze=True,
meta=False, _key=_key) meta=False, _key=_key)
v = destagger(v_vars[varname], -2) v = destagger(v_vars[varname], -2)
zp = ph + phb zp = (ph + phb) / Constants.G
uh = _udhel(zp, mapfct, u, v, wstag, dx, dy, bottom, top) uh = _udhel(zp, mapfct, u, v, wstag, dx, dy, bottom, top)

192
src/wrf/g_latlon.py

@ -3,14 +3,17 @@ from __future__ import (absolute_import, division, print_function)
from collections import OrderedDict from collections import OrderedDict
import numpy as np import numpy as np
from xarray import DataArray
from .util import extract_vars, get_id, get_iterable, is_mapping, to_np from .util import extract_vars, get_id, get_iterable, is_mapping, to_np
from .py3compat import viewkeys from .py3compat import viewkeys
from .latlonutils import _lat_varname, _lon_varname, _ll_to_xy, _xy_to_ll from .latlonutils import _lat_varname, _lon_varname, _ll_to_xy, _xy_to_ll
from .metadecorators import set_latlon_metadata from .metadecorators import set_latlon_metadata
from .constants import Constants, ProjectionTypes
from .config import xarray_enabled from .config import xarray_enabled
if xarray_enabled():
from xarray import DataArray
def get_lat(wrfin, timeidx=0, method="cat", squeeze=True, def get_lat(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None, cache=None, meta=True, _key=None,
@ -365,8 +368,8 @@ def ll_to_xy(wrfin, latitude, longitude, timeidx=0,
- 'v': Use the same staggered grid as the v wind component, - 'v': Use the same staggered grid as the v wind component,
which has a staggered south_north (y) dimension. which has a staggered south_north (y) dimension.
as_int (:obj:`bool`): Set to True to return the x,y values as as_int (:obj:`bool`): Set to False to return the x,y values as
:obj:`int`, otherwise they will be returned as :obj:`float`. :obj:`float`, otherwise they will be returned as :obj:`int`.
Returns: Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The :class:`xarray.DataArray` or :class:`numpy.ndarray`: The
@ -384,7 +387,128 @@ def ll_to_xy(wrfin, latitude, longitude, timeidx=0,
return _ll_to_xy(latitude, longitude, _wrfin, timeidx, stagger, "cat", return _ll_to_xy(latitude, longitude, _wrfin, timeidx, stagger, "cat",
squeeze, None, _key, as_int, **{}) squeeze, None, _key, as_int, **{})
def _set_defaults(projparams):
"""Check projection parameters and set defaults.
Throws an exception if projection parameters required by WPS are not
provided, along with any other parameters required by the map projection
transformation routines.
For parameters not used by the projection type, defaults are used so that
the None values don't pass through to fortran downstream.
Args:
projparams (:obj:`dict`): Projection parameters dictionary.
Returns:
:obj:`dict`: The projection parameters with default values inserted
where applicable.
"""
_params = dict(projparams)
map_proj = _params.get("map_proj")
# All projections require these arguments
if map_proj is None:
raise ValueError("'map_proj' cannot be None")
if _params.get("ref_lat") is None:
raise ValueError("'ref_lat' cannot be None")
if _params.get("ref_lon") is None:
raise ValueError("'ref_lon' cannot be None")
if _params.get("known_x") is None:
raise ValueError("'known_x' cannot be None")
if _params.get("known_y") is None:
raise ValueError("'known_y' cannot be None")
if _params.get("dx") is None:
raise ValueError("'dx' cannot be None")
# Requires truelat1,stand_lon, truelat2, dx, dy
if map_proj == ProjectionTypes.LAMBERT_CONFORMAL:
if _params.get("truelat1") is None:
raise ValueError("'truelat1' cannot be None")
if _params.get("stand_lon") is None:
raise ValueError("'stand_lon' cannot be None")
if _params.get("truelat2") is None:
_params["truelat2"] = _params["truelat1"]
# Requires truelat1, stand_lon
elif map_proj == ProjectionTypes.POLAR_STEREOGRAPHIC:
if _params.get("truelat1") is None:
raise ValueError("'truelat1' cannot be None")
if _params.get("stand_lon") is None:
raise ValueError("'stand_lon' cannot be None")
# Requires truelat1
elif map_proj == ProjectionTypes.MERCATOR:
if _params.get("truelat1") is None:
raise ValueError("'truelat1' cannot be None")
if _params.get("stand_lon") is None:
_params["stand_lon"] = 0.0
# Requires pole_lat, pole_lon, stand_lon
elif map_proj == ProjectionTypes.LAT_LON:
if _params.get("stand_lon") is None:
raise ValueError("'stand_lon' cannot be None")
if _params.get("dy") is None:
raise ValueError("'dy' cannot be None")
if _params.get("pole_lat") is None:
raise ValueError("'pole_lat' cannot be None")
if _params.get("pole_lon") is None:
raise ValueError("'pole_lon' cannot be None")
if _params.get("latinc") is None:
_params["latinc"] = ((_params["dy"]*360.0)/2.0 /
Constants.PI/Constants.WRF_EARTH_RADIUS)
if _params.get("loninc") is None:
_params["loninc"] = ((_params["dx"]*360.0)/2.0 /
Constants.PI/Constants.WRF_EARTH_RADIUS)
else:
raise ValueError("invalid 'map_proj' value of {}".format(map_proj))
# Set these to defaults if not used so that the Fortran routines
# don't crash
if _params.get("truelat1") is None:
_params["truelat1"] = 0.
if _params.get("truelat2") is None:
_params["truelat2"] = 0.
if _params.get("pole_lat") is None:
_params["pole_lat"] = 90.0
if _params.get("pole_lon") is None:
_params["pole_lon"] = 0.0
if _params.get("dx") is None:
_params["dx"] = 0.0
if _params.get("dy") is None:
_params["dy"] = 0.0
if _params.get("latinc") is None:
_params["latinc"] = 0.
if _params.get("loninc") is None:
_params["loninc"] = 0.
return _params
@set_latlon_metadata(xy=True) @set_latlon_metadata(xy=True)
@ -421,19 +545,21 @@ def ll_to_xy_proj(latitude, longitude, meta=True, squeeze=True, as_int=True,
return :class:`numpy.ndarray` instead of return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True. :class:`xarray.DataArray`. Default is True.
as_int (:obj:`bool`): Set to True to return the x,y values as as_int (:obj:`bool`): Set to False to return the x,y values as
:obj:`int`, otherwise they will be returned as :obj:`float`. :obj:`float`, otherwise they will be returned as :obj:`int`.
Default is True.
map_proj (:obj:`int`): Model projection [1=Lambert Conformal, map_proj (:obj:`int`): Model projection [1=Lambert Conformal,
2=Polar Stereographic, 3=Mercator, 6=Lat-Lon]. Required. 2=Polar Stereographic, 3=Mercator, 6=Lat-Lon]. Required.
truelat1 (:obj:`float`): True latitude 1. Required for truelat1 (:obj:`float`): Latitude of true scale 1. Required for
map_proj = 1, 2, 3 (defaults to 0 otherwise). map_proj = 1, 2, 3 (defaults to 0 otherwise).
truelat2 (:obj:`float`): True latitude 2. Optional for truelat2 (:obj:`float`): Latitude of true scale 2. Optional for
map_proj = 1 (defaults to 0 otherwise). map_proj = 1 (defaults to 0 otherwise).
stand_lon (:obj:`float`): Standard longitude. Required. stand_lon (:obj:`float`): Standard longitude. Required for *map_proj* =
1, 2, 6 (defaults to 0 otherwise).
ref_lat (:obj:`float`): A reference latitude. Required. ref_lat (:obj:`float`): A reference latitude. Required.
@ -445,25 +571,25 @@ def ll_to_xy_proj(latitude, longitude, meta=True, squeeze=True, as_int=True,
known_y (:obj:`float`): The known y-coordinate associated with known_y (:obj:`float`): The known y-coordinate associated with
*ref_lat*. Required. *ref_lat*. Required.
pole_lat (:obj:`float`): Pole latitude. Optional for pole_lat (:obj:`float`): Pole latitude. Required for
*map_proj* = 6 (defaults to 90 otherwise). *map_proj* = 6 (use 90 for no rotation).
pole_lon (:obj:`float`): Pole longitude. Optional for pole_lon (:obj:`float`): Pole longitude. Required for
*map_proj* = 6 (defaults to 0 otherwise). *map_proj* = 6 (use 0 for no rotation).
dx (:obj:`float`): The x spacing in meters at the true latitude. dx (:obj:`float`): The x spacing in meters at the true latitude.
Required for *map_proj* = 1, 2, 3 (defaults to 0 otherwise). Required for all map projections.
dy (:obj:`float`) - The y spacing in meters at the true latitude. dy (:obj:`float`) - The y spacing in meters at the true latitude.
Required for *map_proj* = 1, 2, 3 (defaults to 0 otherwise). Required for *map_proj* = 6 (defaults to 0 otherwise).
latinc (:obj:`float`): Required for *map_proj* = 6. Defined as: latinc (:obj:`float`): Optional for *map_proj* = 6. Default is:
.. code-block:: python .. code-block:: python
latinc = (dy*360.0)/2.0/Constants.PI/Constants.WRF_EARTH_RADIUS latinc = (dy*360.0)/2.0/Constants.PI/Constants.WRF_EARTH_RADIUS
loninc (:obj:`float`): Required for *map_proj* = 6. Defined as: loninc (:obj:`float`): Optional for *map_proj* = 6. Default is:
.. code-block:: python .. code-block:: python
@ -478,11 +604,13 @@ def ll_to_xy_proj(latitude, longitude, meta=True, squeeze=True, as_int=True,
""" """
loc = locals() loc = locals()
projparams = {name : loc[name] for name in ("map_proj", "truelat1", _projparams = {name : loc[name] for name in ("map_proj", "truelat1",
"truelat2", "stand_lon", "ref_lat", "truelat2", "stand_lon", "ref_lat",
"ref_lon", "pole_lat", "pole_lon", "ref_lon", "pole_lat", "pole_lon",
"known_x", "known_y", "dx", "dy", "known_x", "known_y", "dx", "dy",
"latinc", "loninc")} "latinc", "loninc")}
projparams = _set_defaults(_projparams)
return _ll_to_xy(latitude, longitude, None, 0, True, "cat", squeeze, None, return _ll_to_xy(latitude, longitude, None, 0, True, "cat", squeeze, None,
None, as_int, **projparams) None, as_int, **projparams)
@ -589,19 +717,17 @@ def xy_to_ll_proj(x, y, meta=True, squeeze=True, map_proj=None, truelat1=None,
return :class:`numpy.ndarray` instead of return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True. :class:`xarray.DataArray`. Default is True.
as_int (:obj:`bool`): Set to True to return the x,y values as
:obj:`int`, otherwise they will be returned as :obj:`float`.
map_proj (:obj:`int`): Model projection [1=Lambert Conformal, map_proj (:obj:`int`): Model projection [1=Lambert Conformal,
2=Polar Stereographic, 3=Mercator, 6=Lat-Lon]. Required. 2=Polar Stereographic, 3=Mercator, 6=Lat-Lon]. Required.
truelat1 (:obj:`float`): True latitude 1. Required for truelat1 (:obj:`float`): Latitude of true scale 1. Required for
map_proj = 1, 2, 3 (defaults to 0 otherwise). map_proj = 1, 2, 3 (defaults to 0 otherwise).
truelat2 (:obj:`float`): True latitude 2. Optional for truelat2 (:obj:`float`): Latitude of true scale 2. Optional for
map_proj = 1 (defaults to 0 otherwise). map_proj = 1 (defaults to 0 otherwise).
stand_lon (:obj:`float`): Standard longitude. Required. stand_lon (:obj:`float`): Standard longitude. Required for *map_proj* =
1, 2, 6 (defaults to 0 otherwise).
ref_lat (:obj:`float`): A reference latitude. Required. ref_lat (:obj:`float`): A reference latitude. Required.
@ -613,25 +739,25 @@ def xy_to_ll_proj(x, y, meta=True, squeeze=True, map_proj=None, truelat1=None,
known_y (:obj:`float`): The known y-coordinate associated with known_y (:obj:`float`): The known y-coordinate associated with
*ref_lat*. Required. *ref_lat*. Required.
pole_lat (:obj:`float`): Pole latitude. Optional for pole_lat (:obj:`float`): Pole latitude. Required for
*map_proj* = 6 (defaults to 90 otherwise). *map_proj* = 6 (use 90 for no rotation).
pole_lon (:obj:`float`): Pole longitude. Optional for pole_lon (:obj:`float`): Pole longitude. Required for
*map_proj* = 6 (defaults to 0 otherwise). *map_proj* = 6 (use 0 for no rotation).
dx (:obj:`float`): The x spacing in meters at the true latitude. dx (:obj:`float`): The x spacing in meters at the true latitude.
Required for *map_proj* = 1, 2, 3 (defaults to 0 otherwise). Required for all map projections.
dy (:obj:`float`) - The y spacing in meters at the true latitude. dy (:obj:`float`) - The y spacing in meters at the true latitude.
Required for *map_proj* = 1, 2, 3 (defaults to 0 otherwise). Required for *map_proj* = 6 (defaults to 0 otherwise).
latinc (:obj:`float`): Required for *map_proj* = 6. Defined as: latinc (:obj:`float`): Optional for *map_proj* = 6. Default is:
.. code-block:: python .. code-block:: python
latinc = (dy*360.0)/2.0/Constants.PI/Constants.WRF_EARTH_RADIUS latinc = (dy*360.0)/2.0/Constants.PI/Constants.WRF_EARTH_RADIUS
loninc (:obj:`float`): Required for *map_proj* = 6. Defined as: loninc (:obj:`float`): Optional for *map_proj* = 6. Default is:
.. code-block:: python .. code-block:: python
@ -646,11 +772,13 @@ def xy_to_ll_proj(x, y, meta=True, squeeze=True, map_proj=None, truelat1=None,
be a :class:`numpy.ndarray` object with no metadata. be a :class:`numpy.ndarray` object with no metadata.
""" """
loc = locals() loc = locals()
projparams = {name : loc[name] for name in ("map_proj", "truelat1", _projparams = {name : loc[name] for name in ("map_proj", "truelat1",
"truelat2", "stand_lon", "ref_lat", "truelat2", "stand_lon", "ref_lat",
"ref_lon", "pole_lat", "pole_lon", "ref_lon", "pole_lat", "pole_lon",
"known_x", "known_y", "dx", "dy", "known_x", "known_y", "dx", "dy",
"latinc", "loninc")} "latinc", "loninc")}
projparams = _set_defaults(_projparams)
return _xy_to_ll(x, y, None, 0, None, "cat", squeeze, None, None, return _xy_to_ll(x, y, None, 0, None, "cat", squeeze, None, None,
**projparams) **projparams)

280
src/wrf/g_uvmet.py

@ -520,7 +520,287 @@ def get_uvmet10_wspd_wdir(wrfin, timeidx=0, method="cat", squeeze=True,
return _calc_wspd_wdir(uvmet10[0,...,:,:], uvmet10[1,...,:,:], True, units) return _calc_wspd_wdir(uvmet10[0,...,:,:], uvmet10[1,...,:,:], True, units)
def get_uvmet_wspd(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
units="m s-1"):
"""Return the wind speed for the wind rotated to earth coordinates.
This function should be used when comparing with observations.
This function extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'uvmet_wspd_wdir'.
Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wind speed
for the wind rotated to earth coordinates. If
xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_uvmet_wspd_wdir(wrfin, timeidx, method, squeeze,
cache, meta, _key, units)[0,:]
if meta:
result.attrs["description"] = "earth rotated wspd"
return result
def get_uvmet_wdir(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
units="m s-1"):
"""Return the wind direction for the wind rotated to earth coordinates.
This function should be used when comparing with observations.
This function extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'uvmet_wspd_wdir'.
Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wind direction
for the wind rotated to earth coordinates. If
xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_uvmet_wspd_wdir(wrfin, timeidx, method, squeeze,
cache, meta, _key, units)[1,:]
if meta:
result.attrs["description"] = "earth rotated wdir"
return result
def get_uvmet10_wspd(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
units="m s-1"):
"""Return the wind speed for the 10m wind rotated to earth coordinates.
This function should be used when comparing with observations.
This function extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'uvmet_wspd_wdir'.
Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wind speed
for the 10m wind rotated to earth coordinates. If
xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_uvmet10_wspd_wdir(wrfin, timeidx, method, squeeze,
cache, meta, _key, units)[0,:]
if meta:
result.attrs["description"] = "10m earth rotated wspd"
return result
def get_uvmet10_wdir(wrfin, timeidx=0, method="cat", squeeze=True,
cache=None, meta=True, _key=None,
units="m s-1"):
"""Return the wind direction for the 10m wind rotated to earth coordinates.
This function should be used when comparing with observations.
This function extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'uvmet_wspd_wdir'.
Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wind direction
for the 10m wind rotated to earth coordinates. If
xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_uvmet10_wspd_wdir(wrfin, timeidx, method, squeeze,
cache, meta, _key, units)[1,:]
if meta:
result.attrs["description"] = "10m earth rotated wdir"
return result

282
src/wrf/g_wind.py

@ -332,7 +332,7 @@ def get_destag_wspd_wdir(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None, squeeze=True, cache=None, meta=True, _key=None,
units="m s-1"): units="m s-1"):
"""Return the wind speed and wind direction for the wind in the projected """Return the wind speed and wind direction for the wind in the projected
coordinate space. coordinate (i.e. grid) space.
The wind speed and direction from this function will be relative to the The wind speed and direction from this function will be relative to the
grid. This function should not be used to compare with observations, grid. This function should not be used to compare with observations,
@ -423,7 +423,7 @@ def get_destag_wspd_wdir10(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None, squeeze=True, cache=None, meta=True, _key=None,
units="m s-1"): units="m s-1"):
"""Return the wind speed and wind direction for the 10m wind in """Return the wind speed and wind direction for the 10m wind in
projected coordinate space. projected coordinate (i.e. grid) space.
The wind speed and direction from this function will be relative to the The wind speed and direction from this function will be relative to the
grid. This function should not be used to compare with observations, grid. This function should not be used to compare with observations,
@ -507,3 +507,281 @@ def get_destag_wspd_wdir10(wrfin, timeidx=0, method="cat",
return _calc_wspd_wdir(u, v, True, units) return _calc_wspd_wdir(u, v, True, units)
def get_destag_wspd(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None,
units="m s-1"):
"""Return the wind speed in the projected coordinate (i.e. grid) space.
This function extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'wspd_wdir'.
Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wind
speed in projected space. If
xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_destag_wspd_wdir(wrfin, timeidx, method, squeeze, cache,
meta, _key, units)[0,:]
if meta:
result.attrs["description"] = "wspd in projection space"
return result
def get_destag_wdir(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None,
units="m s-1"):
"""Return the wind direction in the projected coordinate (i.e. grid) space.
This function extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for 'wspd_wdir'.
Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wind
direction in projected space. If
xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_destag_wspd_wdir(wrfin, timeidx, method, squeeze, cache,
meta, _key, units)[1,:]
if meta:
result.attrs["description"] = "wdir in projection space"
return result
def get_destag_wspd10(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None,
units="m s-1"):
"""Return the wind speed for the 10m wind in projected coordinate
(i.e. grid) space.
This function extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for
'wspd_wdir10'. Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wind speed
for the 10m wind in projected space. If
xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_destag_wspd_wdir10(wrfin, timeidx, method,
squeeze, cache, meta, _key, units)[0,:]
if meta:
result.attrs["description"] = "10m wspd in projection space"
return result
def get_destag_wdir10(wrfin, timeidx=0, method="cat",
squeeze=True, cache=None, meta=True, _key=None,
units="m s-1"):
"""Return the wind direction for the 10m wind in projected coordinate
(i.e. grid) space.
This function extracts the necessary variables from the NetCDF file
object in order to perform the calculation.
Args:
wrfin (:class:`netCDF4.Dataset`, :class:`Nio.NioFile`, or an \
iterable): WRF-ARW NetCDF
data as a :class:`netCDF4.Dataset`, :class:`Nio.NioFile`
or an iterable sequence of the aforementioned types.
timeidx (:obj:`int` or :data:`wrf.ALL_TIMES`, optional): The
desired time index. This value can be a positive integer,
negative integer, or
:data:`wrf.ALL_TIMES` (an alias for None) to return
all times in the file or sequence. The default is 0.
method (:obj:`str`, optional): The aggregation method to use for
sequences. Must be either 'cat' or 'join'.
'cat' combines the data along the Time dimension.
'join' creates a new dimension for the file index.
The default is 'cat'.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the
computational routines. It is primarily used for internal
purposes, but can also be used to improve performance by
eliminating the need to repeatedly extract the same variables
used in multiple diagnostics calculations, particularly when using
large sequences of files.
Default is None.
meta (:obj:`bool`, optional): Set to False to disable metadata and
return :class:`numpy.ndarray` instead of
:class:`xarray.DataArray`. Default is True.
_key (:obj:`int`, optional): A caching key. This is used for internal
purposes only. Default is None.
units (:obj:`str`): The desired units. Refer to the :meth:`getvar`
product table for a list of available units for
'wspd_wdir10'. Default is 'm s-1'.
Returns:
:class:`xarray.DataArray` or :class:`numpy.ndarray`: The wind direction
for the 10m wind in projected space. If
xarray is enabled and the *meta* parameter is True, then the result
will be a :class:`xarray.DataArray` object. Otherwise, the result will
be a :class:`numpy.ndarray` object with no metadata.
"""
result = get_destag_wspd_wdir10(wrfin, timeidx, method,
squeeze, cache, meta, _key, units)[1,:]
if meta:
result.attrs["description"] = "10m wdir in projection space"
return result

261
src/wrf/interp.py

@ -4,10 +4,11 @@ import numpy as np
import numpy.ma as ma import numpy.ma as ma
from .extension import (_interpz3d, _vertcross, _interpline, _smooth2d, from .extension import (_interpz3d, _vertcross, _interpline, _smooth2d,
_monotonic, _vintrp) _monotonic, _vintrp, _interpz3d_lev2d)
from .metadecorators import set_interp_metadata from .metadecorators import set_interp_metadata
from .util import extract_vars, is_staggered, get_id, to_np, get_iterable from .util import (extract_vars, is_staggered, get_id, to_np, get_iterable,
is_moving_domain, is_latlon_pair)
from .py3compat import py3range from .py3compat import py3range
from .interputils import get_xy, get_xy_z_params, to_xy_coords from .interputils import get_xy, get_xy_z_params, to_xy_coords
from .constants import Constants, default_fill, ConversionFactors from .constants import Constants, default_fill, ConversionFactors
@ -20,7 +21,7 @@ from wrf.g_pressure import get_pressure
# Note: Extension decorator is good enough to handle left dims # Note: Extension decorator is good enough to handle left dims
@set_interp_metadata("horiz") @set_interp_metadata("horiz")
def interplevel(field3d, vert, desiredlev, missing=default_fill(np.float64), def interplevel(field3d, vert, desiredlev, missing=default_fill(np.float64),
meta=True): squeeze=True, meta=True):
"""Return the three-dimensional field interpolated to a horizontal plane """Return the three-dimensional field interpolated to a horizontal plane
at the specified vertical level. at the specified vertical level.
@ -35,11 +36,20 @@ def interplevel(field3d, vert, desiredlev, missing=default_fill(np.float64),
pressure or height. This array must have the same dimensionality pressure or height. This array must have the same dimensionality
as *field3d*. as *field3d*.
desiredlev (:obj:`float`): The desired vertical level. desiredlev (:obj:`float`, 1D sequence, or :class:`numpy.ndarray`): The
desired vertical level(s). This can be a single value (e.g. 500),
a sequence of values (e.g. [1000, 850, 700, 500, 250]), or a
multidimensional array where the right two dimensions (ny x nx)
must match *field3d*, and any leftmost dimensions match
field3d.shape[:-3] (e.g. planetary boundary layer).
Must be in the same units as the *vert* parameter. Must be in the same units as the *vert* parameter.
missing (:obj:`float`): The fill value to use for the output. missing (:obj:`float`): The fill value to use for the output.
Default is :data:`wrf.default_fill(numpy.float64)`. Default is :data:`wrf.default_fill(numpy.float64)`.
squeeze (:obj:`bool`, optional): Set to False to prevent dimensions
with a size of 1 from being automatically removed from the shape
of the output. Default is True.
meta (:obj:`bool`): Set to False to disable metadata and return meta (:obj:`bool`): Set to False to disable metadata and return
:class:`numpy.ndarray` instead of :class:`numpy.ndarray` instead of
@ -66,26 +76,34 @@ def interplevel(field3d, vert, desiredlev, missing=default_fill(np.float64),
p = getvar(wrfin, "pressure") p = getvar(wrfin, "pressure")
ht = getvar(wrfin, "z", units="dm") ht = getvar(wrfin, "z", units="dm")
pblh = getvar(wrfin, "PBLH")
ht_500 = interplevel(ht, p, 500.0) ht_500 = interplevel(ht, p, 500.0)
""" """
# Some fields like uvmet have an extra left dimension for the product
# type, we'll handle that iteration here.
multi = True if field3d.ndim - vert.ndim == 1 else False
if not multi: _desiredlev = np.asarray(desiredlev)
result = _interpz3d(field3d, vert, desiredlev, missing) if _desiredlev.ndim == 0:
_desiredlev = np.array([desiredlev], np.float64)
levsare2d = False
else: else:
outshape = field3d.shape[0:-3] + field3d.shape[-2:] levsare2d = _desiredlev.ndim >= 2
result = np.empty(outshape, dtype=field3d.dtype)
if not levsare2d:
for i in py3range(field3d.shape[0]): result = _interpz3d(field3d, vert, _desiredlev, missing)
result[i,:] = ( else:
_interpz3d(field3d[i,:], vert, desiredlev, missing)[:]) result = _interpz3d_lev2d(field3d, vert, _desiredlev, missing)
return ma.masked_values (result, missing) masked = ma.masked_values (result, missing)
if not meta:
if squeeze:
return masked.squeeze()
return masked
@set_interp_metadata("cross") @set_interp_metadata("cross")
@ -94,7 +112,7 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64),
ll_point=None, ll_point=None,
pivot_point=None, angle=None, pivot_point=None, angle=None,
start_point=None, end_point=None, start_point=None, end_point=None,
latlon=False, cache=None, meta=True): latlon=False, autolevels=100, cache=None, meta=True):
"""Return the vertical cross section for a three-dimensional field. """Return the vertical cross section for a three-dimensional field.
The cross section is defined by a horizontal line through the domain. The cross section is defined by a horizontal line through the domain.
@ -213,6 +231,10 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64),
*latlon* is set to True. Otherwise, a warning will be issued, *latlon* is set to True. Otherwise, a warning will be issued,
and the latitude and longitude information will not be and the latitude and longitude information will not be
present. present.
autolevels(:obj:`int`, optional): The number of evenly spaced
automatically chosen vertical levels to use when *levels*
is None. Default is 100.
cache (:obj:`dict`, optional): A dictionary of (varname, ndarray) cache (:obj:`dict`, optional): A dictionary of (varname, ndarray)
that can be used to supply pre-extracted NetCDF variables to the that can be used to supply pre-extracted NetCDF variables to the
@ -236,10 +258,6 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64),
:class:`numpy.ndarray` object with no metadata. :class:`numpy.ndarray` object with no metadata.
""" """
if timeidx is None:
raise ValueError("'timeidx' must be a positive or negative integer")
# Some fields like uvmet have an extra left dimension for the product # Some fields like uvmet have an extra left dimension for the product
# type, we'll handle that iteration here. # type, we'll handle that iteration here.
multi = True if field3d.ndim - vert.ndim == 1 else False multi = True if field3d.ndim - vert.ndim == 1 else False
@ -254,9 +272,45 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64),
end_point_xy = None end_point_xy = None
pivot_point_xy = None pivot_point_xy = None
if (latlon is True or is_latlon_pair(start_point) or
is_latlon_pair(pivot_point)):
if wrfin is not None:
is_moving = is_moving_domain(wrfin)
else:
is_moving = False
if timeidx is None:
if wrfin is not None:
# Moving nests aren't supported with ALL_TIMES because the
# domain could move outside of the line, which causes
# crashes or different line lengths.
if is_moving:
raise ValueError("Requesting all times with a moving nest "
"is not supported when using lat/lon "
"cross sections because the domain could "
"move outside of the cross section. "
"You must request each time "
"individually.")
else:
# Domain not moving, just use 0
_timeidx = 0
# If using grid coordinates, then don't care about lat/lon
# coordinates. Just use 0.
else:
_timeidx = 0
else:
if is_moving:
_timeidx = timeidx
else:
# When using non-moving nests, set the time to 0
# to avoid problems downstream
_timeidx = 0
if pivot_point is not None: if pivot_point is not None:
if pivot_point.lat is not None and pivot_point.lon is not None: if pivot_point.lat is not None and pivot_point.lon is not None:
xy_coords = to_xy_coords(pivot_point, wrfin, timeidx, xy_coords = to_xy_coords(pivot_point, wrfin, _timeidx,
stagger, projection, ll_point) stagger, projection, ll_point)
pivot_point_xy = (xy_coords.x, xy_coords.y) pivot_point_xy = (xy_coords.x, xy_coords.y)
else: else:
@ -264,14 +318,14 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64),
if start_point is not None and end_point is not None: if start_point is not None and end_point is not None:
if start_point.lat is not None and start_point.lon is not None: if start_point.lat is not None and start_point.lon is not None:
xy_coords = to_xy_coords(start_point, wrfin, timeidx, xy_coords = to_xy_coords(start_point, wrfin, _timeidx,
stagger, projection, ll_point) stagger, projection, ll_point)
start_point_xy = (xy_coords.x, xy_coords.y) start_point_xy = (xy_coords.x, xy_coords.y)
else: else:
start_point_xy = (start_point.x, start_point.y) start_point_xy = (start_point.x, start_point.y)
if end_point.lat is not None and end_point.lon is not None: if end_point.lat is not None and end_point.lon is not None:
xy_coords = to_xy_coords(end_point, wrfin, timeidx, xy_coords = to_xy_coords(end_point, wrfin, _timeidx,
stagger, projection, ll_point) stagger, projection, ll_point)
end_point_xy = (xy_coords.x, xy_coords.y) end_point_xy = (xy_coords.x, xy_coords.y)
else: else:
@ -279,7 +333,8 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64),
xy, var2dz, z_var2d = get_xy_z_params(to_np(vert), pivot_point_xy, xy, var2dz, z_var2d = get_xy_z_params(to_np(vert), pivot_point_xy,
angle, start_point_xy, angle, start_point_xy,
end_point_xy, levels) end_point_xy, levels,
autolevels)
if not multi: if not multi:
result = _vertcross(field3d, xy, var2dz, z_var2d, missing) result = _vertcross(field3d, xy, var2dz, z_var2d, missing)
@ -295,10 +350,9 @@ def vertcross(field3d, vert, levels=None, missing=default_fill(np.float64),
@set_interp_metadata("line") @set_interp_metadata("line")
def interpline(field2d, pivot_point=None, def interpline(field2d, wrfin=None, timeidx=0, stagger=None, projection=None,
wrfin=None, timeidx=0, stagger=None, projection=None,
ll_point=None, ll_point=None,
angle=None, start_point=None, pivot_point=None, angle=None, start_point=None,
end_point=None, latlon=False, end_point=None, latlon=False,
cache=None, meta=True): cache=None, meta=True):
"""Return the two-dimensional field interpolated along a line. """Return the two-dimensional field interpolated along a line.
@ -420,8 +474,6 @@ def interpline(field2d, pivot_point=None,
""" """
if timeidx is None:
raise ValueError("'timeidx' must be a positive or negative integer")
try: try:
xy = cache["xy"] xy = cache["xy"]
@ -430,9 +482,45 @@ def interpline(field2d, pivot_point=None,
end_point_xy = None end_point_xy = None
pivot_point_xy = None pivot_point_xy = None
if (latlon is True or is_latlon_pair(start_point) or
is_latlon_pair(pivot_point)):
if wrfin is not None:
is_moving = is_moving_domain(wrfin)
else:
is_moving = False
if timeidx is None:
if wrfin is not None:
# Moving nests aren't supported with ALL_TIMES because the
# domain could move outside of the line, which causes
# crashes or different line lengths.
if is_moving:
raise ValueError("Requesting all times with a moving nest "
"is not supported when using a lat/lon "
"line because the domain could "
"move outside of line. "
"You must request each time "
"individually.")
else:
# Domain not moving, just use 0
_timeidx = 0
# If using grid coordinates, then don't care about lat/lon
# coordinates. Just use 0.
else:
_timeidx = 0
else:
if is_moving:
_timeidx = timeidx
else:
# When using non-moving nests, set the time to 0
# to avoid problems downstream
_timeidx = 0
if pivot_point is not None: if pivot_point is not None:
if pivot_point.lat is not None and pivot_point.lon is not None: if pivot_point.lat is not None and pivot_point.lon is not None:
xy_coords = to_xy_coords(pivot_point, wrfin, timeidx, xy_coords = to_xy_coords(pivot_point, wrfin, _timeidx,
stagger, projection, ll_point) stagger, projection, ll_point)
pivot_point_xy = (xy_coords.x, xy_coords.y) pivot_point_xy = (xy_coords.x, xy_coords.y)
else: else:
@ -440,22 +528,22 @@ def interpline(field2d, pivot_point=None,
if start_point is not None and end_point is not None: if start_point is not None and end_point is not None:
if start_point.lat is not None and start_point.lon is not None: if start_point.lat is not None and start_point.lon is not None:
xy_coords = to_xy_coords(start_point, wrfin, timeidx, xy_coords = to_xy_coords(start_point, wrfin, _timeidx,
stagger, projection, ll_point) stagger, projection, ll_point)
start_point_xy = (xy_coords.x, xy_coords.y) start_point_xy = (xy_coords.x, xy_coords.y)
else: else:
start_point_xy = (start_point.x, start_point.y) start_point_xy = (start_point.x, start_point.y)
if end_point.lat is not None and end_point.lon is not None: if end_point.lat is not None and end_point.lon is not None:
xy_coords = to_xy_coords(end_point, wrfin, timeidx, xy_coords = to_xy_coords(end_point, wrfin, _timeidx,
stagger, projection, ll_point) stagger, projection, ll_point)
end_point_xy = (xy_coords.x, xy_coords.y) end_point_xy = (xy_coords.x, xy_coords.y)
else: else:
end_point_xy = (end_point.x, end_point.y) end_point_xy = (end_point.x, end_point.y)
xy = get_xy(field2d, pivot_point_xy, angle, start_point_xy, xy = get_xy(field2d, pivot_point_xy, angle, start_point_xy,
end_point_xy) end_point_xy)
return _interpline(field2d, xy) return _interpline(field2d, xy)
@ -488,25 +576,38 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False,
[K] [K]
interp_levels (sequence): A 1D sequence of vertical levels to interp_levels (sequence): A 1D sequence of vertical levels to
interpolate to. interpolate to. Values must be in the same units as specified
above for the *vert_coord* parameter.
extrapolate (:obj:`bool`, optional): Set to True to extrapolate extrapolate (:obj:`bool`, optional): Set to True to extrapolate
values below ground. Default is False. values below ground. This is only performed when *vert_coord* is
a pressure or height type, and the *field_type* is a pressure type
(with height vertical coordinate), a height type (with pressure as
the vertical coordinate), or a temperature type (with either height
or pressure as the vertical coordinate). If those conditions are
not met, or *field_type* is None, then the lowest model level
will be used. Extrapolation is performed using standard atmosphere.
Default is False.
field_type (:obj:`str`, optional): field_type (:obj:`str`, optional):
The type of field. Default is None. The type of field. Default is None.
Valid strings are: Valid strings are:
* 'none': None * 'none': None
* 'pressure', 'pres', 'p': pressure * 'pressure', 'pres', 'p': pressure [Pa]
* 'z', 'ght': geopotential height * 'pressure_hpa', 'pres_hpa', 'p_hpa': pressure [hPa]
* 'z', 'ght': geopotential height [m]
* 'z_km', 'ght_km': geopotential height [km]
* 'tc': temperature [degC] * 'tc': temperature [degC]
* 'tk': temperature [K] * 'tk': temperature [K]
* 'theta', 'th': potential temperature [K] * 'theta', 'th': potential temperature [K]
* 'theta-e', 'thetae', 'eth': equivalent potential temperature * 'theta-e', 'thetae', 'eth': equivalent potential temperature
log_p (:obj:`bool`, optional): Use the log of the pressure for log_p (:obj:`bool`, optional): Set to True to use the log of the
interpolation instead of pressure. Default is False. vertical coordinate for interpolation. This is mainly intended
for pressure vertical coordinate types, but note that the log
will still be taken for any vertical coordinate type when
this is set to True. Default is False.
timeidx (:obj:`int`, optional): timeidx (:obj:`int`, optional):
The time index to use when extracting auxiallary variables used in The time index to use when extracting auxiallary variables used in
@ -556,16 +657,22 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False,
valid_coords = ("pressure", "pres", "p", "ght_msl", valid_coords = ("pressure", "pres", "p", "ght_msl",
"ght_agl", "theta", "th", "theta-e", "thetae", "eth") "ght_agl", "theta", "th", "theta-e", "thetae", "eth")
valid_field_types = ("none", "pressure", "pres", "p", "z", valid_field_types = ("none", "pressure", "pres", "p",
'pressure_hpa', 'pres_hpa', 'p_hpa', "z",
"tc", "tk", "theta", "th", "theta-e", "thetae", "tc", "tk", "theta", "th", "theta-e", "thetae",
"eth", "ght") "eth", "ght", 'z_km', 'ght_km')
icase_lookup = {"none" : 0, icase_lookup = {"none" : 0,
"p" : 1, "p" : 1,
"pres" : 1, "pres" : 1,
"pressure" : 1, "pressure" : 1,
"p_hpa" : 1,
"pres_hpa" : 1,
"pressure_hpa" : 1,
"z" : 2, "z" : 2,
"ght" : 2, "ght" : 2,
"z_km" : 2,
"ght_km" : 2,
"tc" : 3, "tc" : 3,
"tk" : 4, "tk" : 4,
"theta" : 5, "theta" : 5,
@ -574,6 +681,22 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False,
"thetae" : 6, "thetae" : 6,
"eth" : 6} "eth" : 6}
in_unitmap = {"p_hpa" : 1.0/ConversionFactors.PA_TO_HPA,
"pres_hpa" : 1.0/ConversionFactors.PA_TO_HPA,
"pressure_hpa" : 1.0/ConversionFactors.PA_TO_HPA,
"z_km" : 1.0/ConversionFactors.M_TO_KM,
"ght_km" : 1.0/ConversionFactors.M_TO_KM,
}
out_unitmap = {"p_hpa" : ConversionFactors.PA_TO_HPA,
"pres_hpa" : ConversionFactors.PA_TO_HPA,
"pressure_hpa" : ConversionFactors.PA_TO_HPA,
"z_km" : ConversionFactors.M_TO_KM,
"ght_km" : ConversionFactors.M_TO_KM,
}
# These constants match what's in the fortran code. # These constants match what's in the fortran code.
rgas = Constants.RD rgas = Constants.RD
ussalr = Constants.USSALR ussalr = Constants.USSALR
@ -583,18 +706,21 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False,
if not isinstance(interp_levels, np.ndarray): if not isinstance(interp_levels, np.ndarray):
interp_levels = np.asarray(interp_levels, np.float64) interp_levels = np.asarray(interp_levels, np.float64)
# TODO: Check if field is staggered if len(interp_levels) == 0:
raise ValueError("'interp_levels' contains no values")
# Check if field is staggered
if is_staggered(_wrfin, field): if is_staggered(_wrfin, field):
raise RuntimeError("Please unstagger field in the vertical") raise ValueError("Please unstagger field in the vertical")
# Check for valid coord # Check for valid coord
if vert_coord not in valid_coords: if vert_coord not in valid_coords:
raise RuntimeError("'%s' is not a valid vertical " raise ValueError("'%s' is not a valid vertical "
"coordinate type" % vert_coord) "coordinate type" % vert_coord)
# Check for valid field type # Check for valid field type
if field_type not in valid_field_types: if field_type not in valid_field_types:
raise RuntimeError("'%s' is not a valid field type" % field_type) raise ValueError("'%s' is not a valid field type" % field_type)
log_p_int = 1 if log_p else 0 log_p_int = 1 if log_p else 0
@ -605,14 +731,12 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False,
extrap = 1 extrap = 1
icase = icase_lookup[field_type] icase = icase_lookup[field_type]
# Extract vriables # Extract variables
#timeidx = -1 # Should this be an argument? ncvars = extract_vars(_wrfin, timeidx, ("PSFC", "QVAPOR"),
ncvars = extract_vars(_wrfin, timeidx, ("PSFC", "QVAPOR", "F"),
method, squeeze, cache, meta=False, _key=_key) method, squeeze, cache, meta=False, _key=_key)
sfp = ncvars["PSFC"] * ConversionFactors.PA_TO_HPA sfp = ncvars["PSFC"] * ConversionFactors.PA_TO_HPA
qv = ncvars["QVAPOR"] qv = ncvars["QVAPOR"]
coriolis = ncvars["F"]
terht = get_terrain(_wrfin, timeidx, units="m", terht = get_terrain(_wrfin, timeidx, units="m",
method=method, squeeze=squeeze, cache=cache, method=method, squeeze=squeeze, cache=cache,
@ -627,7 +751,7 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False,
method=method, squeeze=squeeze, cache=cache, method=method, squeeze=squeeze, cache=cache,
meta=False, _key=_key) meta=False, _key=_key)
smsfp = _smooth2d(sfp, 3) smsfp = _smooth2d(sfp, 3, 2.0)
vcor = 0 vcor = 0
@ -652,6 +776,10 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False,
method=method, squeeze=squeeze, cache=cache, method=method, squeeze=squeeze, cache=cache,
meta=False, _key=_key) meta=False, _key=_key)
coriolis = extract_vars(_wrfin, timeidx, "F",
method, squeeze, cache, meta=False,
_key=_key)["F"]
vcor = 4 vcor = 4
idir = 1 idir = 1
icorsw = 0 icorsw = 0
@ -675,6 +803,10 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False,
eth = get_eth(_wrfin, timeidx, method=method, squeeze=squeeze, eth = get_eth(_wrfin, timeidx, method=method, squeeze=squeeze,
cache=cache, meta=False, _key=_key) cache=cache, meta=False, _key=_key)
coriolis = extract_vars(_wrfin, timeidx, "F",
method, squeeze, cache, meta=False,
_key=_key)["F"]
p_hpa = p * ConversionFactors.PA_TO_HPA 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)
@ -693,12 +825,29 @@ def vinterp(wrfin, field, vert_coord, interp_levels, extrapolate=False,
"Verify that the 'timeidx' parameter matches the " "Verify that the 'timeidx' parameter matches the "
"same value used when extracting the 'field' " "same value used when extracting the 'field' "
"variable.") "variable.")
res = _vintrp(field, p, tk, qv, ght, terht, sfp, smsfp, # Some field types are in different units than the Fortran routine
# expects
conv_factor = in_unitmap.get(field_type)
if conv_factor is not None:
field_ = field * conv_factor
else:
field_ = field
res = _vintrp(field_, p, tk, qv, ght, terht, sfp, smsfp,
vcord_array, interp_levels, vcord_array, interp_levels,
icase, extrap, vcor, log_p_int, missing) icase, extrap, vcor, log_p_int, missing)
return ma.masked_values(res, missing) conv_factor = out_unitmap.get(field_type)
if conv_factor is not None:
res_ = res * conv_factor
else:
res_ = res
return ma.masked_values(res_, missing)

25
src/wrf/interputils.py

@ -156,13 +156,6 @@ def _calc_xy(xdim, ydim, pivot_point=None, angle=None,
if x1 >= xdim or y1 >= ydim: if x1 >= xdim or y1 >= ydim:
raise ValueError("end_point {} is outside of domain " raise ValueError("end_point {} is outside of domain "
"with shape {}".format(end_point, (xdim, ydim))) "with shape {}".format(end_point, (xdim, ydim)))
# From the original NCL code, but the error above will be thrown
# instead.
if ( x1 > xdim-1 ):
x1 = xdim - 1
if ( y1 > ydim-1):
y1 = ydim - 1
else: else:
raise ValueError("invalid start/end or pivot/angle arguments") raise ValueError("invalid start/end or pivot/angle arguments")
@ -185,7 +178,7 @@ def _calc_xy(xdim, ydim, pivot_point=None, angle=None,
def get_xy_z_params(z, pivot_point=None, angle=None, def get_xy_z_params(z, pivot_point=None, angle=None,
start_point=None, end_point=None, start_point=None, end_point=None,
levels=None): levels=None, autolevels=100):
"""Return the cross section parameters. """Return the cross section parameters.
This function returns the xy horizontal cross section line coordinates, This function returns the xy horizontal cross section line coordinates,
@ -224,6 +217,10 @@ def get_xy_z_params(z, pivot_point=None, angle=None,
vertical levels in the output array. If None, a fixed set of vertical levels in the output array. If None, a fixed set of
vertical levels is provided. Default is None. vertical levels is provided. Default is None.
autolevels(:obj:`int`, optional): The number of evenly spaced
automatically chosen vertical levels to use when *levels*
is None. Default is 100.
Returns: Returns:
:obj:`tuple`: A tuple containing the xy horizontal cross section :obj:`tuple`: A tuple containing the xy horizontal cross section
@ -248,20 +245,18 @@ def get_xy_z_params(z, pivot_point=None, angle=None,
if(var2dz[idx1] > var2dz[idx2]): # monotonically decreasing coordinate if(var2dz[idx1] > var2dz[idx2]): # monotonically decreasing coordinate
z_max = floor(np.amax(z)/10) * 10 # bottom value z_max = floor(np.amax(z)/10) * 10 # bottom value
z_min = ceil(np.amin(z)/10) * 10 # top value z_min = ceil(np.amin(z)/10) * 10 # top value
dz = 10 dz = (1.0/autolevels) * (z_max - z_min)
nlevels = int((z_max - z_min)/dz) z_var2d = np.zeros((autolevels), dtype=z.dtype)
z_var2d = np.zeros((nlevels), dtype=z.dtype)
z_var2d[0] = z_max z_var2d[0] = z_max
dz = -dz dz = -dz
else: else:
z_max = np.amax(z) z_max = np.amax(z)
z_min = 0. z_min = 0.
dz = 0.01*z_max dz = (1.0/autolevels)*z_max
nlevels = int(z_max/dz) z_var2d = np.zeros((autolevels), dtype=z.dtype)
z_var2d = np.zeros((nlevels), dtype=z.dtype)
z_var2d[0] = z_min z_var2d[0] = z_min
for i in py3range(1,nlevels): for i in py3range(1,autolevels):
z_var2d[i] = z_var2d[0] + i*dz z_var2d[i] = z_var2d[0] + i*dz
else: else:
z_var2d = np.asarray(levels, z.dtype) z_var2d = np.asarray(levels, z.dtype)

7
src/wrf/latlonutils.py

@ -167,8 +167,8 @@ def _get_proj_params(wrfin, timeidx, stagger, method, squeeze, cache, _key):
# Only need one file and one time if the domain is not moving # Only need one file and one time if the domain is not moving
if not is_moving: if not is_moving:
if is_multi_time_req(timeidx): # Always use the 0th time for non-moving domains to avoid problems
lat_timeidx = 0 lat_timeidx = 0
if is_multi_file(wrfin): if is_multi_file(wrfin):
if not is_mapping(wrfin): if not is_mapping(wrfin):
@ -179,7 +179,7 @@ def _get_proj_params(wrfin, timeidx, stagger, method, squeeze, cache, _key):
key = _key[first_entry] key = _key[first_entry]
return _get_proj_params(wrfin, timeidx, stagger, return _get_proj_params(wrfin, timeidx, stagger,
method, squeeze, cache, key) method, squeeze, cache, key)
xlat = extract_vars(wrfin, lat_timeidx, (latvar,), method, squeeze, cache, xlat = extract_vars(wrfin, lat_timeidx, (latvar,), method, squeeze, cache,
meta=False, _key=_key)[latvar] meta=False, _key=_key)[latvar]
xlon = extract_vars(wrfin, lat_timeidx, (lonvar,), method, squeeze, cache, xlon = extract_vars(wrfin, lat_timeidx, (lonvar,), method, squeeze, cache,
@ -233,7 +233,6 @@ def _kwarg_proj_params(**projparams):
# Sanity checks # Sanity checks
# Required args for all projections # Required args for all projections
for name, var in viewitems({"MAP_PROJ" : map_proj, for name, var in viewitems({"MAP_PROJ" : map_proj,
"STAND_LON" : stdlon,
"REF_LAT" : ref_lat, "REF_LAT" : ref_lat,
"REF_LON" : ref_lon, "REF_LON" : ref_lon,
"KNOWN_X" : known_x, "KNOWN_X" : known_x,

154
src/wrf/metadecorators.py

@ -9,7 +9,8 @@ import numpy.ma as ma
from .extension import _interpline from .extension import _interpline
from .util import (extract_vars, either, from_args, arg_location, from .util import (extract_vars, either, from_args, arg_location,
is_coordvar, latlon_coordvars, to_np, is_coordvar, latlon_coordvars, to_np,
from_var, iter_left_indexes, is_mapping) from_var, iter_left_indexes, is_mapping,
is_moving_domain, is_latlon_pair)
from .coordpair import CoordPair from .coordpair import CoordPair
from .py3compat import viewkeys, viewitems, py3range from .py3compat import viewkeys, viewitems, py3range
from .interputils import get_xy_z_params, get_xy, to_xy_coords from .interputils import get_xy_z_params, get_xy, to_xy_coords
@ -792,16 +793,21 @@ def _set_horiz_meta(wrapped, instance, args, kwargs):
""" """
argvars = from_args(wrapped, ("field3d", "vert", "desiredlev", argvars = from_args(wrapped, ("field3d", "vert", "desiredlev",
"missing"), "missing", "squeeze"),
*args, **kwargs) *args, **kwargs)
field3d = argvars["field3d"] field3d = argvars["field3d"]
z = argvars["vert"] z = argvars["vert"]
desiredloc = argvars["desiredlev"] desiredlev = argvars["desiredlev"]
_desiredlev = np.asarray(desiredlev)
missingval = argvars["missing"] missingval = argvars["missing"]
squeeze = argvars["squeeze"]
result = wrapped(*args, **kwargs) result = wrapped(*args, **kwargs)
levsare2d = _desiredlev.ndim >= 2
multiproduct = field3d.ndim - z.ndim == 1
# Defaults, in case the data isn't a DataArray # Defaults, in case the data isn't a DataArray
outname = None outname = None
outdimnames = None outdimnames = None
@ -812,34 +818,45 @@ def _set_horiz_meta(wrapped, instance, args, kwargs):
vert_units = None vert_units = None
if isinstance(z, DataArray): if isinstance(z, DataArray):
vert_units = z.attrs.get("units", None) vert_units = z.attrs.get("units", None)
# If we have no metadata to start with, only set the level
levelstr = ("{0} {1}".format(desiredloc, vert_units)
if vert_units is not None
else "{0}".format(desiredloc))
name_levelstr = ("{0}_{1}".format(desiredloc, vert_units)
if vert_units is not None
else "{0}".format(desiredloc))
if isinstance(field3d, DataArray): if isinstance(field3d, DataArray):
outcoords = OrderedDict() outcoords = OrderedDict()
outdimnames = list(field3d.dims) outdimnames = list(field3d.dims)
outcoords.update(field3d.coords) outcoords.update(field3d.coords)
outdimnames.remove(field3d.dims[-3])
del outdimnames[-3]
try: try:
del outcoords[field3d.dims[-3]] del outcoords[field3d.dims[-3]]
except KeyError: except KeyError:
pass # xarray 0.9 pass # xarray 0.9
if not levsare2d:
outdimnames.insert(-2, "level")
if _desiredlev.ndim == 0:
outcoords["level"] = [desiredlev]
else:
outcoords["level"] = _desiredlev
else:
if (_desiredlev.ndim == 2):
outcoords["level"] = field3d.dims[-2:], _desiredlev[:]
else:
if multiproduct:
d = field3d.dims[1:-3] + field3d.dims[-2:]
else:
d = field3d.dims[0:-3] + field3d.dims[-2:]
outcoords["level"] = d, _desiredlev[:]
outattrs.update(field3d.attrs) outattrs.update(field3d.attrs)
outname = "{0}_{1}".format(field3d.name, name_levelstr) outname = "{0}_interp".format(field3d.name)
else: else:
outname = "field3d_{0}".format(name_levelstr) outname = "field3d_interp"
outattrs["level"] = levelstr
outattrs["missing_value"] = missingval outattrs["missing_value"] = missingval
outattrs["_FillValue"] = missingval outattrs["_FillValue"] = missingval
outattrs["vert_units"] = vert_units
for key in ("MemoryOrder", "description"): for key in ("MemoryOrder", "description"):
try: try:
@ -847,8 +864,10 @@ def _set_horiz_meta(wrapped, instance, args, kwargs):
except KeyError: except KeyError:
pass pass
return DataArray(result, name=outname, dims=outdimnames, da = DataArray(result, name=outname, dims=outdimnames,
coords=outcoords, attrs=outattrs) coords=outcoords, attrs=outattrs)
return da.squeeze() if squeeze else da
def _set_cross_meta(wrapped, instance, args, kwargs): def _set_cross_meta(wrapped, instance, args, kwargs):
@ -889,7 +908,7 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
"latlon", "missing", "latlon", "missing",
"wrfin", "timeidx", "stagger", "projection", "wrfin", "timeidx", "stagger", "projection",
"ll_point", "pivot_point", "angle", "ll_point", "pivot_point", "angle",
"start_point", "end_point", "start_point", "end_point", "autolevels",
"cache"), "cache"),
*args, **kwargs) *args, **kwargs)
@ -907,15 +926,52 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
angle = argvars["angle"] angle = argvars["angle"]
start_point = argvars["start_point"] start_point = argvars["start_point"]
end_point = argvars["end_point"] end_point = argvars["end_point"]
autolevels = argvars["autolevels"]
cache = argvars["cache"] cache = argvars["cache"]
start_point_xy = None start_point_xy = None
end_point_xy = None end_point_xy = None
pivot_point_xy = None pivot_point_xy = None
if (inc_latlon is True or is_latlon_pair(start_point) or
is_latlon_pair(pivot_point)):
if wrfin is not None:
is_moving = is_moving_domain(wrfin)
else:
is_moving = False
if timeidx is None:
if wrfin is not None:
# Moving nests aren't supported with ALL_TIMES because the
# domain could move outside of the line, which causes
# crashes or different line lengths.
if is_moving:
raise ValueError("Requesting all times with a moving nest "
"is not supported when using lat/lon "
"cross sections because the domain could "
"move outside of the cross section. "
"You must request each time "
"individually.")
else:
# Domain not moving, just use 0
_timeidx = 0
# If using grid coordinates, then don't care about lat/lon
# coordinates. Just use 0.
else:
_timeidx = 0
else:
if is_moving:
_timeidx = timeidx
else:
# When using non-moving nests, set the time to 0
# to avoid problems downstream
_timeidx = 0
if pivot_point is not None: if pivot_point is not None:
if pivot_point.lat is not None and pivot_point.lon is not None: if pivot_point.lat is not None and pivot_point.lon is not None:
xy_coords = to_xy_coords(pivot_point, wrfin, timeidx, xy_coords = to_xy_coords(pivot_point, wrfin, _timeidx,
stagger, projection, ll_point) stagger, projection, ll_point)
pivot_point_xy = (xy_coords.x, xy_coords.y) pivot_point_xy = (xy_coords.x, xy_coords.y)
else: else:
@ -923,21 +979,21 @@ def _set_cross_meta(wrapped, instance, args, kwargs):
if start_point is not None and end_point is not None: if start_point is not None and end_point is not None:
if start_point.lat is not None and start_point.lon is not None: if start_point.lat is not None and start_point.lon is not None:
xy_coords = to_xy_coords(start_point, wrfin, timeidx, xy_coords = to_xy_coords(start_point, wrfin, _timeidx,
stagger, projection, ll_point) stagger, projection, ll_point)
start_point_xy = (xy_coords.x, xy_coords.y) start_point_xy = (xy_coords.x, xy_coords.y)
else: else:
start_point_xy = (start_point.x, start_point.y) start_point_xy = (start_point.x, start_point.y)
if end_point.lat is not None and end_point.lon is not None: if end_point.lat is not None and end_point.lon is not None:
xy_coords = to_xy_coords(end_point, wrfin, timeidx, xy_coords = to_xy_coords(end_point, wrfin, _timeidx,
stagger, projection, ll_point) stagger, projection, ll_point)
end_point_xy = (xy_coords.x, xy_coords.y) end_point_xy = (xy_coords.x, xy_coords.y)
else: else:
end_point_xy = (end_point.x, end_point.y) end_point_xy = (end_point.x, end_point.y)
xy, var2dz, z_var2d = get_xy_z_params(to_np(z), pivot_point_xy, angle, xy, var2dz, z_var2d = get_xy_z_params(to_np(z), pivot_point_xy, angle,
start_point_xy, end_point_xy, levels) start_point_xy, end_point_xy, levels, autolevels)
# Make a copy so we don't modify a user supplied cache # Make a copy so we don't modify a user supplied cache
if cache is not None: if cache is not None:
@ -1130,10 +1186,47 @@ def _set_line_meta(wrapped, instance, args, kwargs):
start_point_xy = None start_point_xy = None
end_point_xy = None end_point_xy = None
pivot_point_xy = None pivot_point_xy = None
if (inc_latlon is True or is_latlon_pair(start_point) or
is_latlon_pair(pivot_point)):
if wrfin is not None:
is_moving = is_moving_domain(wrfin)
else:
is_moving = False
if timeidx is None:
if wrfin is not None:
# Moving nests aren't supported with ALL_TIMES because the
# domain could move outside of the line, which causes
# crashes or different line lengths.
if is_moving:
raise ValueError("Requesting all times with a moving nest "
"is not supported when using a lat/lon "
"line because the domain could "
"move outside of line. "
"You must request each time "
"individually.")
else:
# Domain not moving, just use 0
_timeidx = 0
# If using grid coordinates, then don't care about lat/lon
# coordinates. Just use 0.
else:
_timeidx = 0
else:
if is_moving:
_timeidx = timeidx
else:
# When using non-moving nests, set the time to 0
# to avoid problems downstream
_timeidx = 0
if pivot_point is not None: if pivot_point is not None:
if pivot_point.lat is not None and pivot_point.lon is not None: if pivot_point.lat is not None and pivot_point.lon is not None:
xy_coords = to_xy_coords(pivot_point, wrfin, timeidx, xy_coords = to_xy_coords(pivot_point, wrfin, _timeidx,
stagger, projection, ll_point) stagger, projection, ll_point)
pivot_point_xy = (xy_coords.x, xy_coords.y) pivot_point_xy = (xy_coords.x, xy_coords.y)
else: else:
@ -1142,19 +1235,20 @@ def _set_line_meta(wrapped, instance, args, kwargs):
if start_point is not None and end_point is not None: if start_point is not None and end_point is not None:
if start_point.lat is not None and start_point.lon is not None: if start_point.lat is not None and start_point.lon is not None:
xy_coords = to_xy_coords(start_point, wrfin, timeidx, xy_coords = to_xy_coords(start_point, wrfin, _timeidx,
stagger, projection, ll_point) stagger, projection, ll_point)
start_point_xy = (xy_coords.x, xy_coords.y) start_point_xy = (xy_coords.x, xy_coords.y)
else: else:
start_point_xy = (start_point.x, start_point.y) start_point_xy = (start_point.x, start_point.y)
if end_point.lat is not None and end_point.lon is not None: if end_point.lat is not None and end_point.lon is not None:
xy_coords = to_xy_coords(end_point, wrfin, timeidx, xy_coords = to_xy_coords(end_point, wrfin, _timeidx,
stagger, projection, ll_point) stagger, projection, ll_point)
end_point_xy = (xy_coords.x, xy_coords.y) end_point_xy = (xy_coords.x, xy_coords.y)
else: else:
end_point_xy = (end_point.x, end_point.y) end_point_xy = (end_point.x, end_point.y)
xy = get_xy(field2d, pivot_point_xy, angle, start_point_xy, end_point_xy) xy = get_xy(field2d, pivot_point_xy, angle, start_point_xy, end_point_xy)
# Make a copy so we don't modify a user supplied cache # Make a copy so we don't modify a user supplied cache
@ -1645,7 +1739,7 @@ def set_interp_metadata(interp_type):
""" """
@wrapt.decorator @wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs): def func_wrapper(wrapped, instance, args, kwargs):
do_meta = from_args(wrapped, ("meta",), *args, **kwargs)["meta"] do_meta = from_args(wrapped, ("meta"), *args, **kwargs)["meta"]
if do_meta is None: if do_meta is None:
do_meta = True do_meta = True
@ -1839,11 +1933,12 @@ def set_smooth_metdata():
if not xarray_enabled() or not do_meta: if not xarray_enabled() or not do_meta:
return wrapped(*args, **kwargs) return wrapped(*args, **kwargs)
argvars = from_args(wrapped, ("field", "passes"), argvars = from_args(wrapped, ("field", "passes", "cenweight"),
*args, **kwargs) *args, **kwargs)
field = argvars["field"] field = argvars["field"]
passes = argvars["passes"] passes = argvars["passes"]
cenweight = argvars["cenweight"]
result = wrapped(*args, **kwargs) result = wrapped(*args, **kwargs)
@ -1858,6 +1953,7 @@ def set_smooth_metdata():
outcoords.update(field.coords) outcoords.update(field.coords)
outattrs.update(field.attrs) outattrs.update(field.attrs)
outattrs["passes"] = passes outattrs["passes"] = passes
outattrs["cenweight"] = cenweight
if isinstance(result, ma.MaskedArray): if isinstance(result, ma.MaskedArray):
outattrs["_FillValue"] = result.fill_value outattrs["_FillValue"] = result.fill_value

56
src/wrf/projection.py

@ -78,25 +78,43 @@ if cartopy_enabled():
self._xlimits = tuple(xlimits) self._xlimits = tuple(xlimits)
self._ylimits = tuple(limits[..., 1]) self._ylimits = tuple(limits[..., 1])
# Compatibility with cartopy >= 0.17
self._x_limits = self._xlimits
self._y_limits = self._ylimits
self._threshold = np.diff(self.x_limits)[0] / 720 self._threshold = np.diff(self.x_limits)[0] / 720
def _ismissing(val): def _ismissing(val, islat=True):
"""Return True if a value is None, greater than 90.0, or less than -90. """Return True if a value is None or out of bounds.
This function is used to check for invalid latitude values. This function is used to check for invalid latitude/longitude values.
Args: Args:
val (numeric): A numeric value. val (numeric): A numeric value.
islat (:obj:`bool`): Set to False if checking for longitude values.
Returns: Returns:
:obj:`bool`: True if the value is None, greater than 90.0, or less :obj:`bool`: True if the value is None, or an out of bounds value.
than -90.0. Otherwise, False is returned.
""" """
return val is None or val > 90. or val < -90. if islat:
if val is None:
return True
if math.fabs(val) > 90.:
return True
else:
if val is None:
return True
if math.fabs(val) > 360.:
return True
return False
class WrfProj(object): class WrfProj(object):
@ -291,7 +309,8 @@ class WrfProj(object):
return (None if not cartopy_enabled() return (None if not cartopy_enabled()
else crs.Globe(ellipse=None, else crs.Globe(ellipse=None,
semimajor_axis=Constants.WRF_EARTH_RADIUS, semimajor_axis=Constants.WRF_EARTH_RADIUS,
semiminor_axis=Constants.WRF_EARTH_RADIUS)) semiminor_axis=Constants.WRF_EARTH_RADIUS,
nadgrids="@null"))
def cartopy_xlim(self, geobounds): def cartopy_xlim(self, geobounds):
"""Return the x extents in projected coordinates for cartopy. """Return the x extents in projected coordinates for cartopy.
@ -592,7 +611,7 @@ class LambertConformal(WrfProj):
else self.truelat2) else self.truelat2)
_proj4 = ("+proj=lcc +units=meters +a={} +b={} +lat_1={} " _proj4 = ("+proj=lcc +units=meters +a={} +b={} +lat_1={} "
"+lat_2={} +lat_0={} +lon_0={}".format( "+lat_2={} +lat_0={} +lon_0={} +nadgrids=@null".format(
Constants.WRF_EARTH_RADIUS, Constants.WRF_EARTH_RADIUS,
Constants.WRF_EARTH_RADIUS, Constants.WRF_EARTH_RADIUS,
self.truelat1, self.truelat1,
@ -635,6 +654,9 @@ class Mercator(WrfProj):
if self.truelat1 == 0. or _ismissing(self.truelat1) if self.truelat1 == 0. or _ismissing(self.truelat1)
else self.truelat1) else self.truelat1)
self._stand_lon = (0. if _ismissing(self.stand_lon, islat=False)
else self.stand_lon)
def _cf_params(self): def _cf_params(self):
@ -654,7 +676,7 @@ class Mercator(WrfProj):
_pyngl.mpProjection = "Mercator" _pyngl.mpProjection = "Mercator"
_pyngl.mpDataBaseVersion = "MediumRes" _pyngl.mpDataBaseVersion = "MediumRes"
_pyngl.mpCenterLatF = 0.0 _pyngl.mpCenterLatF = 0.0
_pyngl.mpCenterLonF = self.stand_lon _pyngl.mpCenterLonF = self._stand_lon
_pyngl.mpLimitMode = "Corners" _pyngl.mpLimitMode = "Corners"
_pyngl.mpLeftCornerLonF = geobounds.bottom_left.lon _pyngl.mpLeftCornerLonF = geobounds.bottom_left.lon
@ -673,7 +695,7 @@ class Mercator(WrfProj):
return None return None
local_kwargs = dict(projection = "merc", local_kwargs = dict(projection = "merc",
lon_0 = self.stand_lon, lon_0 = self._stand_lon,
lat_0 = self.moad_cen_lat, lat_0 = self.moad_cen_lat,
lat_ts = self._lat_ts, lat_ts = self._lat_ts,
llcrnrlat = geobounds.bottom_left.lat, llcrnrlat = geobounds.bottom_left.lat,
@ -695,12 +717,12 @@ class Mercator(WrfProj):
if self._lat_ts == 0.0: if self._lat_ts == 0.0:
_cartopy = crs.Mercator( _cartopy = crs.Mercator(
central_longitude = self.stand_lon, central_longitude = self._stand_lon,
globe = self._globe()) globe = self._globe())
else: else:
_cartopy = MercatorWithLatTS( _cartopy = MercatorWithLatTS(
central_longitude = self.stand_lon, central_longitude = self._stand_lon,
latitude_true_scale = self._lat_ts, latitude_true_scale = self._lat_ts,
globe = self._globe()) globe = self._globe())
@ -710,10 +732,10 @@ class Mercator(WrfProj):
def _proj4(self): def _proj4(self):
_proj4 = ("+proj=merc +units=meters +a={} +b={} " _proj4 = ("+proj=merc +units=meters +a={} +b={} "
"+lon_0={} +lat_ts={}".format( "+lon_0={} +lat_ts={} +nadgrids=@null".format(
Constants.WRF_EARTH_RADIUS, Constants.WRF_EARTH_RADIUS,
Constants.WRF_EARTH_RADIUS, Constants.WRF_EARTH_RADIUS,
self.stand_lon, self._stand_lon,
self._lat_ts)) self._lat_ts))
return _proj4 return _proj4
@ -824,7 +846,7 @@ class PolarStereographic(WrfProj):
def _proj4(self): def _proj4(self):
_proj4 = ("+proj=stere +units=meters +a={} +b={} " _proj4 = ("+proj=stere +units=meters +a={} +b={} "
"+lat0={} +lon_0={} +lat_ts={}".format( "+lat0={} +lon_0={} +lat_ts={} +nadgrids=@null".format(
Constants.WRF_EARTH_RADIUS, Constants.WRF_EARTH_RADIUS,
Constants.WRF_EARTH_RADIUS, Constants.WRF_EARTH_RADIUS,
self._hemi, self._hemi,
@ -918,7 +940,7 @@ class LatLon(WrfProj):
return None return None
_cartopy = crs.PlateCarree(central_longitude=self.stand_lon, _cartopy = crs.PlateCarree(central_longitude=self.stand_lon,
globe=self._globe()) globe=self._globe())
return _cartopy return _cartopy
@ -930,7 +952,7 @@ class LatLon(WrfProj):
def _proj4(self): def _proj4(self):
_proj4 = ("+proj=eqc +units=meters +a={} +b={} " _proj4 = ("+proj=eqc +units=meters +a={} +b={} "
"+lon_0={}".format(Constants.WRF_EARTH_RADIUS, "+lon_0={} +nadgrids=@null".format(Constants.WRF_EARTH_RADIUS,
Constants.WRF_EARTH_RADIUS, Constants.WRF_EARTH_RADIUS,
self.stand_lon)) self.stand_lon))
return _proj4 return _proj4

72
src/wrf/routines.py

@ -2,7 +2,9 @@ from __future__ import (absolute_import, division, print_function)
from .util import (get_iterable, is_standard_wrf_var, extract_vars, viewkeys, from .util import (get_iterable, is_standard_wrf_var, extract_vars, viewkeys,
get_id) get_id)
from .g_cape import get_2dcape, get_3dcape from .g_cape import (get_2dcape, get_3dcape, get_cape2d_only,
get_cin2d_only, get_lcl, get_lfc, get_3dcape_only,
get_3dcin_only)
from .g_ctt import get_ctt from .g_ctt import get_ctt
from .g_dbz import get_dbz, get_max_dbz from .g_dbz import get_dbz, get_max_dbz
from .g_dewpoint import get_dp, get_dp_2m from .g_dewpoint import get_dp, get_dp_2m
@ -17,12 +19,16 @@ from .g_slp import get_slp
from .g_temp import get_tc, get_eth, get_temp, get_theta, get_tk, get_tv, get_tw from .g_temp import get_tc, get_eth, get_temp, get_theta, get_tk, get_tv, get_tw
from .g_terrain import get_terrain from .g_terrain import get_terrain
from .g_uvmet import (get_uvmet, get_uvmet10, get_uvmet10_wspd_wdir, from .g_uvmet import (get_uvmet, get_uvmet10, get_uvmet10_wspd_wdir,
get_uvmet_wspd_wdir) get_uvmet_wspd_wdir, get_uvmet_wspd, get_uvmet_wdir,
get_uvmet10_wspd, get_uvmet10_wdir)
from .g_vorticity import get_avo, get_pvo from .g_vorticity import get_avo, get_pvo
from .g_wind import (get_destag_wspd_wdir, get_destag_wspd_wdir10, from .g_wind import (get_destag_wspd_wdir, get_destag_wspd_wdir10,
get_u_destag, get_v_destag, get_w_destag) get_u_destag, get_v_destag, get_w_destag,
get_destag_wspd, get_destag_wdir, get_destag_wspd10,
get_destag_wdir10)
from .g_times import get_times, get_xtimes from .g_times import get_times, get_xtimes
from .g_cloudfrac import get_cloudfrac from .g_cloudfrac import (get_cloudfrac, get_low_cloudfrac, get_mid_cloudfrac,
get_high_cloudfrac)
# func is the function to call. kargs are required arguments that should # func is the function to call. kargs are required arguments that should
@ -70,7 +76,25 @@ _FUNC_MAP = {"cape2d" : get_2dcape,
"ctt" : get_ctt, "ctt" : get_ctt,
"cloudfrac" : get_cloudfrac, "cloudfrac" : get_cloudfrac,
"geopt_stag" : get_stag_geopt, "geopt_stag" : get_stag_geopt,
"zstag" : get_stag_height "zstag" : get_stag_height,
# Diagnostics below are extracted from multi-product diagnostics
"cape2d_only" : get_cape2d_only,
"cin2d_only" : get_cin2d_only,
"lcl" : get_lcl,
"lfc" : get_lfc,
"cape3d_only" : get_3dcape_only,
"cin3d_only": get_3dcin_only,
"uvmet_wspd" : get_uvmet_wspd,
"uvmet_wdir" : get_uvmet_wdir,
"uvmet10_wspd" : get_uvmet10_wspd,
"uvmet10_wdir" : get_uvmet10_wdir,
"wspd" : get_destag_wspd,
"wdir" : get_destag_wdir,
"wspd10" : get_destag_wspd10,
"wdir10" : get_destag_wdir10,
"low_cloudfrac" : get_low_cloudfrac,
"mid_cloudfrac" : get_mid_cloudfrac,
"high_cloudfrac" : get_high_cloudfrac
} }
_VALID_KARGS = {"cape2d" : ["missing"], _VALID_KARGS = {"cape2d" : ["missing"],
@ -118,6 +142,26 @@ _VALID_KARGS = {"cape2d" : ["missing"],
"mid_thresh", "high_thresh"], "mid_thresh", "high_thresh"],
"geopt_stag" : [], "geopt_stag" : [],
"zstag" : ["msl", "units"], "zstag" : ["msl", "units"],
"cape2d_only" : ["missing"],
"cin2d_only" : ["missing"],
"lcl" : ["missing"],
"lfc" : ["missing"],
"cape3d_only" : ["missing"],
"cin3d_only": ["missing"],
"uvmet_wspd" : ["units"],
"uvmet_wdir" : ["units"],
"uvmet10_wspd" : ["units"],
"uvmet10_wdir" : ["units"],
"wspd" : ["units"],
"wdir" : ["units"],
"wspd10" : ["units"],
"wdir10" : ["units"],
"low_cloudfrac" : ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"mid_cloudfrac" : ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"high_cloudfrac" : ["vert_type", "low_thresh",
"mid_thresh", "high_thresh"],
"default" : [] "default" : []
} }
@ -140,7 +184,14 @@ _ALIASES = {"cape_2d" : "cape2d",
"cfrac" : "cloudfrac", "cfrac" : "cloudfrac",
"wspd_wdir_uvmet" : "uvmet_wspd_wdir", "wspd_wdir_uvmet" : "uvmet_wspd_wdir",
"wspd_wdir_uvmet10" : "uvmet10_wspd_wdir", "wspd_wdir_uvmet10" : "uvmet10_wspd_wdir",
"th" : "theta" "th" : "theta",
"low_cfrac" : "low_cloudfrac",
"mid_cfrac" : "mid_cloudfrac",
"high_cfrac" : "high_cloudfrac",
"wspd_uvmet" : "uvmet_wspd" ,
"wdir_uvmet" : "uvmet_wdir" ,
"wspd_uvmet10" : "uvmet10_wspd" ,
"wdir_uvmet10" : "uvmet10_wdir" ,
} }
class ArgumentError(Exception): class ArgumentError(Exception):
@ -160,8 +211,12 @@ def _undo_alias(alias):
def _check_kargs(var, kargs): def _check_kargs(var, kargs):
for arg in viewkeys(kargs): for arg in viewkeys(kargs):
if arg not in _VALID_KARGS[var]: if arg not in _VALID_KARGS[var]:
raise ValueError("'%s' is an invalid keyword " if var != "default":
"argument for '%s'" % (arg, var)) raise ValueError("'{}' is an invalid keyword "
"argument for '{}'".format(arg, var))
else:
raise ValueError("'{}' is an invalid keyword "
"argument".format(arg))
def getvar(wrfin, varname, timeidx=0, def getvar(wrfin, varname, timeidx=0,
@ -277,6 +332,7 @@ def getvar(wrfin, varname, timeidx=0,
wrfin = get_iterable(wrfin) wrfin = get_iterable(wrfin)
if is_standard_wrf_var(wrfin, varname) and varname != "Times": if is_standard_wrf_var(wrfin, varname) and varname != "Times":
_check_kargs("default", kwargs)
return extract_vars(wrfin, timeidx, varname, return extract_vars(wrfin, timeidx, varname,
method, squeeze, cache, meta, _key)[varname] method, squeeze, cache, meta, _key)[varname]
elif varname == "Times": elif varname == "Times":

122
src/wrf/specialdec.py

@ -5,6 +5,7 @@ import numpy as np
import wrapt import wrapt
from .util import iter_left_indexes, to_np from .util import iter_left_indexes, to_np
from .py3compat import py3range
from .config import xarray_enabled from .config import xarray_enabled
from .constants import default_fill from .constants import default_fill
@ -520,6 +521,83 @@ def cloudfrac_left_iter(alg_dtype=np.float64):
return func_wrapper return func_wrapper
def interplevel_left_iter(is2dlev, alg_dtype=np.float64):
@wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs):
new_args = list(args)
new_kwargs = dict(kwargs)
field3d = args[0]
z = args[1]
levels = args[2]
num_left_dims = z.ndim - 3
orig_dtype = field3d.dtype
left_dims = z.shape[0:num_left_dims]
multiproduct = True if field3d.ndim - z.ndim == 1 else False
# No special left side iteration, build the output from the
# low, mid, high results.
if (num_left_dims == 0):
if multiproduct:
if not is2dlev:
outshape = (field3d.shape[0:-3] + levels.shape +
field3d.shape[-2:])
else:
outshape = (field3d.shape[0:-3] + field3d.shape[-2:])
output = np.empty(outshape, dtype=alg_dtype)
for i in py3range(field3d.shape[0]):
new_args[0] = field3d[i,:]
new_kwargs["outview"] = output[i,:]
_ = wrapped(*new_args, **new_kwargs)
else:
output = wrapped(*args, **kwargs)
return output
if multiproduct:
outdims = field3d.shape[0:1] + left_dims
else:
outdims = left_dims
extra_dims = tuple(outdims)
if not is2dlev:
outdims += levels.shape
outdims += z.shape[-2:]
outview_array = np.empty(outdims, alg_dtype)
for left_idxs in iter_left_indexes(extra_dims):
field_out_slice_idxs = left_idxs + (slice(None),)
if multiproduct:
z_slice_idxs = left_idxs[1:] + (slice(None),)
else:
z_slice_idxs = left_idxs + (slice(None),)
new_args[0] = field3d[field_out_slice_idxs]
new_args[1] = z[z_slice_idxs]
if is2dlev:
if levels.ndim > 2:
new_args[2] = levels[z_slice_idxs]
new_kwargs["outview"] = outview_array[field_out_slice_idxs]
_ = wrapped(*new_args, **new_kwargs)
output = outview_array.astype(orig_dtype)
return output
return func_wrapper
def check_cape_args(): def check_cape_args():
"""A decorator to check that the cape_3d arguments are valid. """A decorator to check that the cape_3d arguments are valid.
@ -574,3 +652,47 @@ def check_cape_args():
return func_wrapper return func_wrapper
def check_interplevel_args(is2dlev):
"""A decorator to check that the interplevel arguments are valid.
An exception is raised when an invalid argument is found.
Returns:
None
Raises:
:class:`ValueError`: Raised when an invalid argument is detected.
"""
@wrapt.decorator
def func_wrapper(wrapped, instance, args, kwargs):
field3d = args[0]
z = args[1]
levels = args[2]
multiproduct = True if (field3d.ndim - z.ndim) == 1 else False
if not multiproduct:
if field3d.shape != z.shape:
raise ValueError("arguments 0 and 1 must have the same shape")
else:
if field3d.shape[1:] != z.shape:
raise ValueError("argument 0 and 1 must have same rightmost "
"dimensions")
if is2dlev:
if levels.ndim != 2:
if (levels.shape[0:-2] != z.shape[0:-3] or
levels.shape[-2:] != z.shape[-2:]):
raise ValueError("argument 1 and 2 must have "
"the same leftmost and rightmost "
"dimensions")
return wrapped(*args, **kwargs)
return func_wrapper

23
src/wrf/util.py

@ -3392,7 +3392,7 @@ def latlon_coords(var, as_np=False):
var (:class:`xarray.DataArray`): A variable. var (:class:`xarray.DataArray`): A variable.
to_np (:obj:`bool`): Set to True to return the coordinates as as_np (:obj:`bool`): Set to True to return the coordinates as
:class:`numpy.ndarray` objects instead of :class:`numpy.ndarray` objects instead of
:class:`xarray.DataArray` objects. :class:`xarray.DataArray` objects.
@ -3880,13 +3880,24 @@ def pairs_to_latlon(pairs):
return lats, lons return lats, lons
def is_latlon_pair(pair):
"""Return True if the :class:`wrf.CoordPair` is a lat/lon pair
Args:
pair (:class:`wrf.CoordPair`): A single :class:`wrf.CoordPair` object.
Returns:
:obj:`bool`: True if the pair is a lat/lon pair.
"""
if pair is not None:
return (pair.lat is not None and pair.lon is not None)
else:
return False

2
src/wrf/version.py

@ -1,2 +1,2 @@
__version__ = "1.2.0" __version__ = "1.3.0"

BIN
test/ci_tests/ci_result_file.nc

Binary file not shown.

BIN
test/ci_tests/ci_test_file.nc

Binary file not shown.

13
test/ci_tests/make_test_file.py

@ -146,17 +146,17 @@ def make_result_file(opts):
for latlonmeth in LATLON_METHS: for latlonmeth in LATLON_METHS:
if latlonmeth == "xy": if latlonmeth == "xy":
# Hardcoded values from other unit tests # Hardcoded values from other unit tests
lats = [-55, -60, -65] lats = [22.0, 25.0, 27.0]
lons = [25, 30, 35] lons = [-90.0, -87.5, -83.75]
xy = ll_to_xy(infile, lats[0], lons[0]) xy = ll_to_xy(infile, lats[0], lons[0])
add_to_ncfile(outfile, xy, "xy") add_to_ncfile(outfile, xy, "xy")
else: else:
# Hardcoded from other unit tests # Hardcoded from other unit tests
i_s = np.asarray([10, 100, 150], int) - 1 x_s = np.asarray([10, 50, 90], int)
j_s = np.asarray([10, 100, 150], int) - 1 y_s = np.asarray([10, 50, 90], int)
ll = xy_to_ll(infile, i_s[0], j_s[0]) ll = xy_to_ll(infile, x_s[0], y_s[0])
add_to_ncfile(outfile, ll, "ll") add_to_ncfile(outfile, ll, "ll")
def main(opts): def main(opts):
@ -166,7 +166,8 @@ def main(opts):
if __name__ == "__main__": if __name__ == "__main__":
DEFAULT_FILE = ("/Users/ladwig/Documents/wrf_files/" DEFAULT_FILE = ("/Users/ladwig/Documents/wrf_files/"
"wrf_vortex_multi/wrfout_d02_2005-08-28_12:00:00") "wrf_vortex_multi/moving_nest/"
"wrfout_d02_2005-08-28_12:00:00")
parser = argparse.ArgumentParser(description="Generate conda test files " parser = argparse.ArgumentParser(description="Generate conda test files "
"for unit testing.") "for unit testing.")
parser.add_argument("-f", "--filename", required=False, parser.add_argument("-f", "--filename", required=False,

10
test/ci_tests/utests.py

@ -193,8 +193,8 @@ def make_latlon_test(testid, wrf_in, referent, single, multi=False, repeat=3,
# same whether there are multiple or single files # same whether there are multiple or single files
ref_vals = refnc.variables["xy"][:] ref_vals = refnc.variables["xy"][:]
# Lats/Lons taken from NCL script, just hard-coding for now # Lats/Lons taken from NCL script, just hard-coding for now
lats = [-55, -60, -65] lats = [22.0, 25.0, 27.0]
lons = [25, 30, 35] lons = [-90.0, -87.5, -83.75]
xy = ll_to_xy(in_wrfnc, lats[0], lons[0]) xy = ll_to_xy(in_wrfnc, lats[0], lons[0])
@ -208,10 +208,10 @@ def make_latlon_test(testid, wrf_in, referent, single, multi=False, repeat=3,
# i_s, j_s taken from NCL script, just hard-coding for now # i_s, j_s taken from NCL script, just hard-coding for now
# NCL uses 1-based indexing for this, so need to subtract 1 # NCL uses 1-based indexing for this, so need to subtract 1
i_s = np.asarray([10, 100, 150], int) - 1 x_s = np.asarray([10, 50, 90], int)
j_s = np.asarray([10, 100, 150], int) - 1 y_s = np.asarray([10, 50, 90], int)
ll = xy_to_ll(in_wrfnc, i_s[0], j_s[0]) ll = xy_to_ll(in_wrfnc, x_s[0], y_s[0])
nt.assert_allclose(to_np(ll), ref_vals) nt.assert_allclose(to_np(ll), ref_vals)

257
test/ipynb/Doc_Examples.ipynb

@ -108,8 +108,6 @@
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"%matplotlib inline\n",
"\n",
"from __future__ import (absolute_import, division, print_function, unicode_literals)\n", "from __future__ import (absolute_import, division, print_function, unicode_literals)\n",
"\n", "\n",
"import numpy as np\n", "import numpy as np\n",
@ -146,11 +144,11 @@
"levels = [5 + 5*n for n in range(15)]\n", "levels = [5 + 5*n for n in range(15)]\n",
"\n", "\n",
"# Make the contour plot\n", "# Make the contour plot\n",
"a = axes[0].contourf(to_np(wspd_cross))\n", "a = axes[0].contourf(to_np(wspd_cross), cmap=get_cmap(\"jet\"))\n",
"# Add the color bar\n", "# Add the color bar\n",
"fig.colorbar(a, ax=axes[0])\n", "fig.colorbar(a, ax=axes[0])\n",
"\n", "\n",
"b = axes[1].contourf(to_np(dbz_cross), levels=levels)\n", "b = axes[1].contourf(to_np(dbz_cross), levels=levels, cmap=get_cmap(\"jet\"))\n",
"fig.colorbar(b, ax=axes[1])\n", "fig.colorbar(b, ax=axes[1])\n",
"\n", "\n",
"# Set the x-ticks to use latitude and longitude labels.\n", "# Set the x-ticks to use latitude and longitude labels.\n",
@ -185,6 +183,13 @@
"plt.show()" "plt.show()"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Cartopy Panel Plot"
]
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
@ -193,8 +198,6 @@
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"%matplotlib inline\n",
"\n",
"from __future__ import (absolute_import, division, print_function, unicode_literals)\n", "from __future__ import (absolute_import, division, print_function, unicode_literals)\n",
"\n", "\n",
"import numpy as np\n", "import numpy as np\n",
@ -236,7 +239,7 @@
"cart_proj = get_cartopy(slp)\n", "cart_proj = get_cartopy(slp)\n",
"\n", "\n",
"# Create a figure that will have 3 subplots\n", "# Create a figure that will have 3 subplots\n",
"fig = plt.figure(figsize=(10,7))\n", "fig = plt.figure(figsize=(12,9))\n",
"ax_ctt = fig.add_subplot(1,2,1,projection=cart_proj)\n", "ax_ctt = fig.add_subplot(1,2,1,projection=cart_proj)\n",
"ax_wspd = fig.add_subplot(2,2,2)\n", "ax_wspd = fig.add_subplot(2,2,2)\n",
"ax_dbz = fig.add_subplot(2,2,4)\n", "ax_dbz = fig.add_subplot(2,2,4)\n",
@ -282,13 +285,13 @@
"wspd_contours = ax_wspd.contourf(to_np(wspd_cross), cmap=get_cmap(\"jet\"))\n", "wspd_contours = ax_wspd.contourf(to_np(wspd_cross), cmap=get_cmap(\"jet\"))\n",
"# Add the color bar\n", "# Add the color bar\n",
"cb_wspd = fig.colorbar(wspd_contours, ax=ax_wspd)\n", "cb_wspd = fig.colorbar(wspd_contours, ax=ax_wspd)\n",
"cb_wspd.ax.tick_params(labelsize=5)\n", "cb_wspd.ax.tick_params(labelsize=6)\n",
"\n", "\n",
"# Make the contour plot for dbz\n", "# Make the contour plot for dbz\n",
"levels = [5 + 5*n for n in range(15)]\n", "levels = [5 + 5*n for n in range(15)]\n",
"dbz_contours = ax_dbz.contourf(to_np(dbz_cross), levels=levels, cmap=get_cmap(\"jet\"))\n", "dbz_contours = ax_dbz.contourf(to_np(dbz_cross), levels=levels, cmap=get_cmap(\"jet\"))\n",
"cb_dbz = fig.colorbar(dbz_contours, ax=ax_dbz)\n", "cb_dbz = fig.colorbar(dbz_contours, ax=ax_dbz)\n",
"cb_dbz.ax.tick_params(labelsize=5)\n", "cb_dbz.ax.tick_params(labelsize=6)\n",
"\n", "\n",
"# Set the x-ticks to use latitude and longitude labels\n", "# Set the x-ticks to use latitude and longitude labels\n",
"coord_pairs = to_np(dbz_cross.coords[\"xy_loc\"])\n", "coord_pairs = to_np(dbz_cross.coords[\"xy_loc\"])\n",
@ -297,25 +300,25 @@
"ax_wspd.set_xticks(x_ticks[::20])\n", "ax_wspd.set_xticks(x_ticks[::20])\n",
"ax_wspd.set_xticklabels([], rotation=45)\n", "ax_wspd.set_xticklabels([], rotation=45)\n",
"ax_dbz.set_xticks(x_ticks[::20])\n", "ax_dbz.set_xticks(x_ticks[::20])\n",
"ax_dbz.set_xticklabels(x_labels[::20], rotation=45, fontsize=4) \n", "ax_dbz.set_xticklabels(x_labels[::20], rotation=45, fontsize=6) \n",
"\n", "\n",
"# Set the y-ticks to be height\n", "# Set the y-ticks to be height\n",
"vert_vals = to_np(dbz_cross.coords[\"vertical\"])\n", "vert_vals = to_np(dbz_cross.coords[\"vertical\"])\n",
"v_ticks = np.arange(vert_vals.shape[0])\n", "v_ticks = np.arange(vert_vals.shape[0])\n",
"ax_wspd.set_yticks(v_ticks[::20])\n", "ax_wspd.set_yticks(v_ticks[::20])\n",
"ax_wspd.set_yticklabels(vert_vals[::20], fontsize=4) \n", "ax_wspd.set_yticklabels(vert_vals[::20], fontsize=6) \n",
"ax_dbz.set_yticks(v_ticks[::20])\n", "ax_dbz.set_yticks(v_ticks[::20])\n",
"ax_dbz.set_yticklabels(vert_vals[::20], fontsize=4) \n", "ax_dbz.set_yticklabels(vert_vals[::20], fontsize=6) \n",
"\n", "\n",
"# Set the x-axis and y-axis labels\n", "# Set the x-axis and y-axis labels\n",
"ax_dbz.set_xlabel(\"Latitude, Longitude\", fontsize=5)\n", "ax_dbz.set_xlabel(\"Latitude, Longitude\", fontsize=8)\n",
"ax_wspd.set_ylabel(\"Height (m)\", fontsize=5)\n", "ax_wspd.set_ylabel(\"Height (m)\", fontsize=8)\n",
"ax_dbz.set_ylabel(\"Height (m)\", fontsize=5)\n", "ax_dbz.set_ylabel(\"Height (m)\", fontsize=8)\n",
"\n", "\n",
"# Add a title\n", "# Add a title\n",
"ax_ctt.set_title(\"Cloud Top Temperature (degC)\", {\"fontsize\" : 7})\n", "ax_ctt.set_title(\"Cloud Top Temperature (degC)\", {\"fontsize\" : 10})\n",
"ax_wspd.set_title(\"Cross-Section of Wind Speed (kt)\", {\"fontsize\" : 7})\n", "ax_wspd.set_title(\"Cross-Section of Wind Speed (kt)\", {\"fontsize\" : 10})\n",
"ax_dbz.set_title(\"Cross-Section of Reflectivity (dBZ)\", {\"fontsize\" : 7})\n", "ax_dbz.set_title(\"Cross-Section of Reflectivity (dBZ)\", {\"fontsize\" : 10})\n",
"\n", "\n",
"plt.savefig(\"/Users/ladwig/Documents/workspace/wrf_python/doc/source/_static/images/matthew.png\",\n", "plt.savefig(\"/Users/ladwig/Documents/workspace/wrf_python/doc/source/_static/images/matthew.png\",\n",
" transparent=True, bbox_inches=\"tight\")\n", " transparent=True, bbox_inches=\"tight\")\n",
@ -330,8 +333,6 @@
}, },
"outputs": [], "outputs": [],
"source": [ "source": [
"%matplotlib inline\n",
"# SLP\n",
"from __future__ import (absolute_import, division, print_function, unicode_literals)\n", "from __future__ import (absolute_import, division, print_function, unicode_literals)\n",
" \n", " \n",
"from netCDF4 import Dataset \n", "from netCDF4 import Dataset \n",
@ -349,7 +350,7 @@
"slp = getvar(ncfile, \"slp\")\n", "slp = getvar(ncfile, \"slp\")\n",
"\n", "\n",
"# Smooth the sea level pressure since it tends to be noisy near the mountains\n", "# Smooth the sea level pressure since it tends to be noisy near the mountains\n",
"smooth_slp = smooth2d(slp, 3)\n", "smooth_slp = smooth2d(slp, 3, cenweight=4)\n",
"\n", "\n",
"# Get the latitude and longitude points\n", "# Get the latitude and longitude points\n",
"lats, lons = latlon_coords(slp)\n", "lats, lons = latlon_coords(slp)\n",
@ -358,22 +359,22 @@
"cart_proj = get_cartopy(slp)\n", "cart_proj = get_cartopy(slp)\n",
"\n", "\n",
"# Create a figure\n", "# Create a figure\n",
"fig = plt.figure(figsize=(12,9))\n", "fig = plt.figure(figsize=(12,6.0))\n",
"# Set the GeoAxes to the projection used by WRF\n", "# Set the GeoAxes to the projection used by WRF\n",
"ax = plt.axes(projection=cart_proj)\n", "ax = plt.axes(projection=cart_proj)\n",
"\n", "\n",
"# Download and add the states and coastlines\n", "# Download and add the states and coastlines\n",
"states = NaturalEarthFeature(category='cultural', scale='50m', facecolor='none',\n", "states = NaturalEarthFeature(category='cultural', scale='50m', facecolor='none',\n",
" name='admin_1_states_provinces_shp')\n", " name='admin_1_states_provinces_shp')\n",
"ax.add_feature(states, linewidth=.5)\n", "ax.add_feature(states, linewidth=.5, edgecolor=\"black\")\n",
"ax.coastlines('50m', linewidth=0.8)\n", "ax.coastlines('50m', linewidth=0.8, zorder=3)\n",
"\n", "\n",
"# Make the contour outlines and filled contours for the smoothed sea level pressure.\n", "# Make the contour outlines and filled contours for the smoothed sea level pressure.\n",
"plt.contour(to_np(lons), to_np(lats), to_np(smooth_slp), 10, colors=\"black\", transform=crs.PlateCarree())\n", "plt.contour(to_np(lons), to_np(lats), to_np(smooth_slp), 10, colors=\"black\", transform=crs.PlateCarree())\n",
"plt.contourf(to_np(lons), to_np(lats), to_np(smooth_slp), 10, transform=crs.PlateCarree(), cmap=get_cmap(\"jet\"))\n", "plt.contourf(to_np(lons), to_np(lats), to_np(smooth_slp), 10, transform=crs.PlateCarree(), cmap=get_cmap(\"jet\"))\n",
"\n", "\n",
"# Add a color bar\n", "# Add a color bar\n",
"plt.colorbar(ax=ax, shrink=.62)\n", "plt.colorbar(ax=ax, shrink=.98)\n",
"\n", "\n",
"# Set the map limits. Not really necessary, but used for demonstration.\n", "# Set the map limits. Not really necessary, but used for demonstration.\n",
"ax.set_xlim(cartopy_xlim(smooth_slp))\n", "ax.set_xlim(cartopy_xlim(smooth_slp))\n",
@ -388,14 +389,19 @@
" transparent=True, bbox_inches=\"tight\")" " transparent=True, bbox_inches=\"tight\")"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Vertical Cross Section"
]
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"%matplotlib inline\n",
"\n",
"from __future__ import (absolute_import, division, print_function, unicode_literals)\n", "from __future__ import (absolute_import, division, print_function, unicode_literals)\n",
"\n", "\n",
"import numpy as np\n", "import numpy as np\n",
@ -457,6 +463,151 @@
"plt.show()" "plt.show()"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Vertical Cross Section with Mountains"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"import numpy as np\n",
"from matplotlib import pyplot\n",
"from matplotlib.cm import get_cmap\n",
"from matplotlib.colors import from_levels_and_colors\n",
"from cartopy import crs\n",
"from cartopy.feature import NaturalEarthFeature, COLORS\n",
"from netCDF4 import Dataset\n",
"from wrf import (getvar, to_np, get_cartopy, latlon_coords, vertcross,\n",
" cartopy_xlim, cartopy_ylim, interpline, CoordPair)\n",
"\n",
"wrf_file = Dataset(\"/Users/ladwig/Documents/wrf_files/boise_tutorial/orig/wrfout_d01_2010-06-04_00:00:00\")\n",
"\n",
"# Define the cross section start and end points\n",
"cross_start = CoordPair(lat=43.5, lon=-116.5)\n",
"cross_end = CoordPair(lat=43.5, lon=-114)\n",
"\n",
"# Get the WRF variables\n",
"ht = getvar(wrf_file, \"z\", timeidx=-1)\n",
"ter = getvar(wrf_file, \"ter\", timeidx=-1)\n",
"dbz = getvar(wrf_file, \"dbz\", timeidx=-1)\n",
"max_dbz = getvar(wrf_file, \"mdbz\", timeidx=-1)\n",
"Z = 10**(dbz/10.) # Use linear Z for interpolation\n",
"\n",
"# Compute the vertical cross-section interpolation. Also, include the lat/lon\n",
"# points along the cross-section in the metadata by setting latlon to True.\n",
"z_cross = vertcross(Z, ht, wrfin=wrf_file, \n",
" start_point=cross_start, \n",
" end_point=cross_end,\n",
" latlon=True, meta=True)\n",
"\n",
"# Convert back to dBz after interpolation\n",
"dbz_cross = 10.0 * np.log10(z_cross)\n",
"\n",
"# Add back the attributes that xarray dropped from the operations above\n",
"dbz_cross.attrs.update(z_cross.attrs)\n",
"dbz_cross.attrs[\"description\"] = \"radar reflectivity cross section\"\n",
"dbz_cross.attrs[\"units\"] = \"dBZ\"\n",
"\n",
"# To remove the slight gap between the dbz and terrain due to contouring, the new vertical \n",
"# grid spacing, and grid staggering, let's fill in the lower grid cells with the first non-missing \n",
"# value for each column.\n",
"\n",
"# Make a copy of the z cross data. Let's use regular numpy arrays for this.\n",
"dbz_cross_filled = np.ma.copy(to_np(dbz_cross))\n",
"\n",
"# For each cross section column, find the first index with non-missing values and copy\n",
"# these to the missing elements below.\n",
"for i in range(dbz_cross_filled.shape[-1]):\n",
" column_vals = dbz_cross_filled[:,i]\n",
" # Let's find the lowest index that isn't filled. The nonzero function \n",
" # finds all unmasked values greater than 0. Since 0 is a valid value\n",
" # for dBZ, let's change that threshold to be -200 dBZ instead. \n",
" first_idx = int(np.transpose((column_vals > -200).nonzero())[0])\n",
" dbz_cross_filled[0:first_idx, i] = dbz_cross_filled[first_idx, i]\n",
" \n",
"# Get the terrain heights along the cross section line\n",
"ter_line = interpline(ter, wrfin=wrf_file, start_point=cross_start, end_point=cross_end)\n",
"\n",
"# Get the lat/lon points\n",
"lats, lons = latlon_coords(dbz)\n",
"\n",
"# Get the cartopy projection object\n",
"cart_proj = get_cartopy(dbz)\n",
"\n",
"# Create a figure that will have 2 subplots (1 row, 2 columns)\n",
"fig = pyplot.figure(figsize=(12,9))\n",
"ax_cross = pyplot.axes()\n",
"\n",
"dbz_levels = np.arange(5., 75., 5.)\n",
"\n",
"# This is the NWS color table.\n",
"dbz_rgb = np.array([[4,233,231],\n",
" [1,159,244], [3,0,244],\n",
" [2,253,2], [1,197,1],\n",
" [0,142,0], [253,248,2],\n",
" [229,188,0], [253,149,0],\n",
" [253,0,0], [212,0,0],\n",
" [188,0,0],[248,0,253],\n",
" [152,84,198]], np.float32) / 255.0\n",
" \n",
"dbz_map, dbz_norm = from_levels_and_colors(dbz_levels, dbz_rgb, extend=\"max\")\n",
"\n",
"# Make the cross section plot for dbz\n",
"dbz_levels = np.arange(5.,75.,5.)\n",
"xs = np.arange(0, dbz_cross.shape[-1], 1)\n",
"ys = to_np(dbz_cross.coords[\"vertical\"])\n",
"dbz_contours = ax_cross.contourf(xs, \n",
" ys, \n",
" to_np(dbz_cross_filled), \n",
" levels=dbz_levels,\n",
" cmap=dbz_map, \n",
" norm=dbz_norm, \n",
" extend=\"max\")\n",
"cb_dbz = fig.colorbar(dbz_contours, ax=ax_cross)\n",
"cb_dbz.ax.tick_params(labelsize=8)\n",
"\n",
"# Fill in the mountain area\n",
"ht_fill = ax_cross.fill_between(xs, 0, to_np(ter_line), facecolor=\"saddlebrown\")\n",
"\n",
"# Set the x-ticks to use latitude and longitude labels\n",
"coord_pairs = to_np(dbz_cross.coords[\"xy_loc\"])\n",
"x_ticks = np.arange(coord_pairs.shape[0])\n",
"x_labels = [pair.latlon_str() for pair in to_np(coord_pairs)]\n",
"\n",
"# Set the desired number of x ticks below\n",
"num_ticks = 5\n",
"thin = int((len(x_ticks) / num_ticks) + .5)\n",
"ax_cross.set_xticks(x_ticks[::thin])\n",
"ax_cross.set_xticklabels(x_labels[::thin], rotation=45, fontsize=8)\n",
"\n",
"# Set the x-axis and y-axis labels\n",
"ax_cross.set_xlabel(\"Latitude, Longitude\", fontsize=12)\n",
"ax_cross.set_ylabel(\"Height (m)\", fontsize=12)\n",
"\n",
"# Add a title\n",
"ax_cross.set_title(\"Cross-Section of Reflectivity (dBZ)\", {\"fontsize\" : 14})\n",
"\n",
"plt.savefig(\"/Users/ladwig/Documents/workspace/wrf_python/doc/source/_static/images/cross_mtns.png\",\n",
" transparent=True, bbox_inches=\"tight\")\n",
"\n",
"pyplot.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Wind Barbs"
]
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
@ -503,7 +654,7 @@
"# Download and add the states and coastlines\n", "# Download and add the states and coastlines\n",
"states = NaturalEarthFeature(category='cultural', scale='50m', facecolor='none',\n", "states = NaturalEarthFeature(category='cultural', scale='50m', facecolor='none',\n",
" name='admin_1_states_provinces_shp')\n", " name='admin_1_states_provinces_shp')\n",
"ax.add_feature(states, linewidth=0.5)\n", "ax.add_feature(states, linewidth=0.5, edgecolor=\"black\")\n",
"ax.coastlines('50m', linewidth=0.8)\n", "ax.coastlines('50m', linewidth=0.8)\n",
"\n", "\n",
"# Add the 500 hPa geopotential height contours\n", "# Add the 500 hPa geopotential height contours\n",
@ -623,7 +774,7 @@
"slp = getvar(ncfile, \"slp\")\n", "slp = getvar(ncfile, \"slp\")\n",
"\n", "\n",
"# Smooth the sea level pressure since it tends to be noisy near the mountains\n", "# Smooth the sea level pressure since it tends to be noisy near the mountains\n",
"smooth_slp = smooth2d(slp, 3)\n", "smooth_slp = smooth2d(slp, 3, cenweight=4)\n",
"\n", "\n",
"# Get the latitude and longitude points\n", "# Get the latitude and longitude points\n",
"lats, lons = latlon_coords(slp)\n", "lats, lons = latlon_coords(slp)\n",
@ -632,7 +783,7 @@
"bm = get_basemap(slp)\n", "bm = get_basemap(slp)\n",
"\n", "\n",
"# Create a figure\n", "# Create a figure\n",
"fig = plt.figure(figsize=(12,9))\n", "fig = plt.figure(figsize=(12,6))\n",
"\n", "\n",
"# Add geographic outlines\n", "# Add geographic outlines\n",
"bm.drawcoastlines(linewidth=0.25)\n", "bm.drawcoastlines(linewidth=0.25)\n",
@ -648,7 +799,7 @@
"bm.contourf(x, y, to_np(smooth_slp), 10, cmap=get_cmap(\"jet\"))\n", "bm.contourf(x, y, to_np(smooth_slp), 10, cmap=get_cmap(\"jet\"))\n",
"\n", "\n",
"# Add a color bar\n", "# Add a color bar\n",
"plt.colorbar(shrink=.62)\n", "plt.colorbar(shrink=.98)\n",
"\n", "\n",
"plt.title(\"Sea Level Pressure (hPa)\")\n", "plt.title(\"Sea Level Pressure (hPa)\")\n",
"\n", "\n",
@ -664,7 +815,6 @@
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"%matplotlib inline\n",
"from __future__ import (absolute_import, division, print_function, unicode_literals)\n", "from __future__ import (absolute_import, division, print_function, unicode_literals)\n",
"\n", "\n",
"from netCDF4 import Dataset \n", "from netCDF4 import Dataset \n",
@ -731,14 +881,19 @@
"plt.show()" "plt.show()"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Basemap Panel Plot"
]
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"%matplotlib inline\n",
"\n",
"import numpy as np\n", "import numpy as np\n",
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"from matplotlib.cm import get_cmap\n", "from matplotlib.cm import get_cmap\n",
@ -772,7 +927,7 @@
"lats, lons = latlon_coords(slp)\n", "lats, lons = latlon_coords(slp)\n",
"\n", "\n",
"# Create the figure that will have 3 subplots\n", "# Create the figure that will have 3 subplots\n",
"fig = plt.figure(figsize=(10,7))\n", "fig = plt.figure(figsize=(12,9))\n",
"ax_ctt = fig.add_subplot(1,2,1)\n", "ax_ctt = fig.add_subplot(1,2,1)\n",
"ax_wspd = fig.add_subplot(2,2,2)\n", "ax_wspd = fig.add_subplot(2,2,2)\n",
"ax_dbz = fig.add_subplot(2,2,4)\n", "ax_dbz = fig.add_subplot(2,2,4)\n",
@ -827,13 +982,13 @@
"wspd_contours = ax_wspd.contourf(to_np(wspd_cross), cmap=get_cmap(\"jet\"))\n", "wspd_contours = ax_wspd.contourf(to_np(wspd_cross), cmap=get_cmap(\"jet\"))\n",
"# Add the color bar\n", "# Add the color bar\n",
"cb_wspd = fig.colorbar(wspd_contours, ax=ax_wspd)\n", "cb_wspd = fig.colorbar(wspd_contours, ax=ax_wspd)\n",
"cb_wspd.ax.tick_params(labelsize=5)\n", "cb_wspd.ax.tick_params(labelsize=6)\n",
"\n", "\n",
"# Make the contour plot for dbz\n", "# Make the contour plot for dbz\n",
"levels = [5 + 5*n for n in range(15)]\n", "levels = [5 + 5*n for n in range(15)]\n",
"dbz_contours = ax_dbz.contourf(to_np(dbz_cross), levels=levels, cmap=get_cmap(\"jet\"))\n", "dbz_contours = ax_dbz.contourf(to_np(dbz_cross), levels=levels, cmap=get_cmap(\"jet\"))\n",
"cb_dbz = fig.colorbar(dbz_contours, ax=ax_dbz)\n", "cb_dbz = fig.colorbar(dbz_contours, ax=ax_dbz)\n",
"cb_dbz.ax.tick_params(labelsize=5)\n", "cb_dbz.ax.tick_params(labelsize=6)\n",
"\n", "\n",
"# Set the x-ticks to use latitude and longitude labels.\n", "# Set the x-ticks to use latitude and longitude labels.\n",
"coord_pairs = to_np(dbz_cross.coords[\"xy_loc\"])\n", "coord_pairs = to_np(dbz_cross.coords[\"xy_loc\"])\n",
@ -842,25 +997,25 @@
"ax_wspd.set_xticks(x_ticks[::20])\n", "ax_wspd.set_xticks(x_ticks[::20])\n",
"ax_wspd.set_xticklabels([], rotation=45)\n", "ax_wspd.set_xticklabels([], rotation=45)\n",
"ax_dbz.set_xticks(x_ticks[::20])\n", "ax_dbz.set_xticks(x_ticks[::20])\n",
"ax_dbz.set_xticklabels(x_labels[::20], rotation=45, fontsize=4) \n", "ax_dbz.set_xticklabels(x_labels[::20], rotation=45, fontsize=6) \n",
"\n", "\n",
"# Set the y-ticks to be height.\n", "# Set the y-ticks to be height.\n",
"vert_vals = to_np(dbz_cross.coords[\"vertical\"])\n", "vert_vals = to_np(dbz_cross.coords[\"vertical\"])\n",
"v_ticks = np.arange(vert_vals.shape[0])\n", "v_ticks = np.arange(vert_vals.shape[0])\n",
"ax_wspd.set_yticks(v_ticks[::20])\n", "ax_wspd.set_yticks(v_ticks[::20])\n",
"ax_wspd.set_yticklabels(vert_vals[::20], fontsize=4) \n", "ax_wspd.set_yticklabels(vert_vals[::20], fontsize=6) \n",
"ax_dbz.set_yticks(v_ticks[::20])\n", "ax_dbz.set_yticks(v_ticks[::20])\n",
"ax_dbz.set_yticklabels(vert_vals[::20], fontsize=4) \n", "ax_dbz.set_yticklabels(vert_vals[::20], fontsize=6) \n",
"\n", "\n",
"# Set the x-axis and y-axis labels\n", "# Set the x-axis and y-axis labels\n",
"ax_dbz.set_xlabel(\"Latitude, Longitude\", fontsize=5)\n", "ax_dbz.set_xlabel(\"Latitude, Longitude\", fontsize=8)\n",
"ax_wspd.set_ylabel(\"Height (m)\", fontsize=5)\n", "ax_wspd.set_ylabel(\"Height (m)\", fontsize=8)\n",
"ax_dbz.set_ylabel(\"Height (m)\", fontsize=5)\n", "ax_dbz.set_ylabel(\"Height (m)\", fontsize=8)\n",
"\n", "\n",
"# Add titles\n", "# Add titles\n",
"ax_ctt.set_title(\"Cloud Top Temperature (degC)\", {\"fontsize\" : 7})\n", "ax_ctt.set_title(\"Cloud Top Temperature (degC)\", {\"fontsize\" : 10})\n",
"ax_wspd.set_title(\"Cross-Section of Wind Speed (kt)\", {\"fontsize\" : 7})\n", "ax_wspd.set_title(\"Cross-Section of Wind Speed (kt)\", {\"fontsize\" : 10})\n",
"ax_dbz.set_title(\"Cross-Section of Reflectivity (dBZ)\", {\"fontsize\" : 7})\n", "ax_dbz.set_title(\"Cross-Section of Reflectivity (dBZ)\", {\"fontsize\" : 10})\n",
"\n", "\n",
"plt.savefig(\"/Users/ladwig/Documents/workspace/wrf_python/doc/source/_static/images/basemap_front.png\",\n", "plt.savefig(\"/Users/ladwig/Documents/workspace/wrf_python/doc/source/_static/images/basemap_front.png\",\n",
" transparent=False, bbox_inches=\"tight\")\n", " transparent=False, bbox_inches=\"tight\")\n",
@ -1261,21 +1416,21 @@
], ],
"metadata": { "metadata": {
"kernelspec": { "kernelspec": {
"display_name": "Python 2", "display_name": "Python 3",
"language": "python", "language": "python",
"name": "python2" "name": "python3"
}, },
"language_info": { "language_info": {
"codemirror_mode": { "codemirror_mode": {
"name": "ipython", "name": "ipython",
"version": 2 "version": 3
}, },
"file_extension": ".py", "file_extension": ".py",
"mimetype": "text/x-python", "mimetype": "text/x-python",
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython2", "pygments_lexer": "ipython3",
"version": "2.7.14" "version": "3.6.7"
} }
}, },
"nbformat": 4, "nbformat": 4,

195
test/ipynb/WRF_python_demo.ipynb

@ -271,6 +271,182 @@
" " " "
] ]
}, },
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import tempfile\n",
"import glob\n",
"import shutil\n",
"import os\n",
"from netCDF4 import Dataset\n",
"from wrf import getvar, ll_to_xy, CoordPair, GeoBounds\n",
"\n",
"\n",
"class FileReduce(object):\n",
" def __init__(self, filenames, geobounds, tempdir=None, delete=True, reuse=True):\n",
" \"\"\"An iterable object for cutting out geographic domains.\n",
" \n",
" Args:\n",
" \n",
" filenames (sequence): A sequence of full paths to the WRF files\n",
" \n",
" geobounds (GeoBounds): A GeoBounds object defining the region of interest\n",
" \n",
" tempdir (str): The location to store the temporary cropped data files. If None, tempfile.mkdtemp is used.\n",
" \n",
" delete (bool): Set to True to delete the cropped files when FileReduce is garbage collected.\n",
" \n",
" reuse (bool): Set to True when you want to resuse the files that were previously converted. *tempdir* \n",
" must be set to a specific directory that contains the converted files.\n",
" \n",
" \"\"\"\n",
" self._filenames = filenames\n",
" self._i = 0\n",
" self._geobounds = geobounds\n",
" self._delete = delete\n",
" self._cache = set()\n",
" self._own_data = True\n",
" self._reuse = reuse\n",
" \n",
" if tempdir is not None:\n",
" if not os.path.exists(tempdir):\n",
" os.makedirs(tempdir)\n",
" self._tempdir = tempdir\n",
" if self._reuse:\n",
" self._cache = set((os.path.join(self._tempdir, name) \n",
" for name in os.listdir(self._tempdir)))\n",
" else:\n",
" self._tempdir = tempfile.mkdtemp()\n",
"\n",
" print (\"temporary directory is: {}\".format(self._tempdir))\n",
" self._prev = None\n",
" self._set_extents()\n",
" \n",
" def _set_extents(self):\n",
" fname = list(self._filenames)[0]\n",
" with Dataset(fname) as ncfile:\n",
" lons = [self._geobounds.bottom_left.lon, self._geobounds.top_right.lon]\n",
" lats = [self._geobounds.bottom_left.lat, self._geobounds.top_right.lat]\n",
" orig_west_east = len(ncfile.dimensions[\"west_east\"])\n",
" orig_south_north = len(ncfile.dimensions[\"south_north\"])\n",
" \n",
" \n",
" # Note: Not handling the moving nest here\n",
" # Extra points included around the boundaries to ensure domain is fully included\n",
" x_y = ll_to_xy(ncfile, lats, lons, meta=False)\n",
" self._start_x = 0 if x_y[0,0] == 0 else x_y[0,0] - 1\n",
" self._end_x = orig_west_east - 1 if x_y[0,1] >= orig_west_east - 1 else x_y[0,1] + 1\n",
" self._start_y = 0 if x_y[1,0] == 0 else x_y[1,0] - 1\n",
" self._end_y = orig_south_north if x_y[1,1] >= orig_south_north - 1 else x_y[1,1] + 1\n",
" \n",
" self._west_east = self._end_x - self._start_x + 1\n",
" self._west_east_stag = self._west_east + 1\n",
" self._south_north = self._end_y - self._start_y + 1\n",
" self._south_north_stag = self._south_north + 1\n",
" \n",
" \n",
" def __iter__(self):\n",
" return self\n",
" \n",
" def __copy__(self):\n",
" cp = type(self).__new__(self.__class__)\n",
" cp.__dict__.update(self.__dict__)\n",
" cp._own_data = False\n",
" cp._delete = False\n",
" \n",
" return cp\n",
" \n",
" def __del__(self):\n",
" if self._delete:\n",
" shutil.rmtree(self._tempdir)\n",
" \n",
" def reduce(self, fname):\n",
" outfilename = os.path.join(self._tempdir, \"reduced_\" + os.path.basename(fname))\n",
" \n",
" # WRF-Python can iterate over sequences several times during a 'getvar', so a cache is used to \n",
" if outfilename in self._cache:\n",
" return Dataset(outfilename)\n",
" \n",
" # New dimension sizes\n",
" dim_d = {\"west_east\" : self._west_east,\n",
" \"west_east_stag\" : self._west_east_stag,\n",
" \"south_north\" : self._south_north,\n",
" \"south_north_stag\" : self._south_north_stag\n",
" }\n",
" \n",
" # Data slice sizes for the 2D dimensions\n",
" slice_d = {\"west_east\" : slice(self._start_x, self._end_x + 1),\n",
" \"west_east_stag\" : slice(self._start_x, self._end_x + 2),\n",
" \"south_north\" : slice(self._start_y, self._end_y + 1),\n",
" \"south_north_stag\" : slice(self._start_y, self._end_y + 2)\n",
" }\n",
" \n",
" with Dataset(fname) as infile, Dataset(outfilename, mode=\"w\") as outfile:\n",
" print (\"reduce getting called!\")\n",
" \n",
" # Copy the global attributes\n",
" outfile.setncatts(infile.__dict__)\n",
"\n",
" # Copy Dimensions, limiting south_north and west_east to desired domain\n",
" for name, dimension in infile.dimensions.items():\n",
" dimsize = dim_d.get(name, len(dimension))\n",
" outfile.createDimension(name, dimsize)\n",
"\n",
" # Copy Variables \n",
" for name, variable in infile.variables.iteritems():\n",
" \n",
" new_slices = tuple((slice_d.get(dimname, slice(None)) for dimname in variable.dimensions))\n",
"\n",
" outvar = outfile.createVariable(name, variable.datatype, variable.dimensions)\n",
"\n",
" outvar[:] = variable[new_slices]\n",
"\n",
" outvar.setncatts(variable.__dict__)\n",
" \n",
" \n",
" result = Dataset(outfilename)\n",
" \n",
" self._cache.add(outfilename)\n",
" \n",
" return result\n",
" \n",
" \n",
" def next(self):\n",
" if self._i >= len(self._filenames):\n",
" if self._prev is not None:\n",
" self._prev.close()\n",
" raise StopIteration\n",
" else:\n",
" fname = self._filenames[self._i]\n",
" reduced_file = self.reduce(fname)\n",
" if self._prev is not None:\n",
" self._prev.close()\n",
" self._prev = reduced_file\n",
" \n",
" self._i += 1\n",
" \n",
" return reduced_file\n",
" \n",
" # Python 3\n",
" def __next__(self):\n",
" return self.next()\n",
"\n",
"ll = CoordPair(lat=24.0, lon=-87.)\n",
"ur = CoordPair(lat=27.0, lon=-84)\n",
"bounds = GeoBounds(ll, ur)\n",
"reduced_files = FileReduce(glob.glob(\"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest/wrfout_d02*\"),\n",
" bounds, tempdir=\"/Users/ladwig/mytemp\", delete=False, reuse=True)\n",
"\n",
"slp = getvar(reduced_files, \"slp\")\n",
"print(slp)\n",
"\n",
"\n",
"del (reduced_files)\n"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
@ -922,7 +1098,7 @@
"from wrf import getvar, ALL_TIMES\n", "from wrf import getvar, ALL_TIMES\n",
"from netCDF4 import Dataset as nc\n", "from netCDF4 import Dataset as nc\n",
"\n", "\n",
"dir = \"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi\"\n", "dir = \"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest\"\n",
"ncfilenames = [os.path.join(dir, x) for x in os.listdir(dir) if x.find(\"_d02_\") > 0]\n", "ncfilenames = [os.path.join(dir, x) for x in os.listdir(dir) if x.find(\"_d02_\") > 0]\n",
"ncfiles = [nc(x) for x in ncfilenames]\n", "ncfiles = [nc(x) for x in ncfilenames]\n",
"\n", "\n",
@ -1031,6 +1207,8 @@
"#vard = {varname: getvar(ncfiles, varname, method=\"join\", squeeze=False) for varname in wrf_vars}\n", "#vard = {varname: getvar(ncfiles, varname, method=\"join\", squeeze=False) for varname in wrf_vars}\n",
"for varname in wrf_vars:\n", "for varname in wrf_vars:\n",
" print(vard[varname])\n", " print(vard[varname])\n",
" \n",
"# NOTE: Warnings below are due to \"join\" and the fill values used since the last file only contains 1 time step.\n",
" " " "
] ]
}, },
@ -1044,7 +1222,7 @@
"from wrf import getvar\n", "from wrf import getvar\n",
"from netCDF4 import Dataset as nc\n", "from netCDF4 import Dataset as nc\n",
"\n", "\n",
"dir = \"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi\"\n", "dir = \"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest\"\n",
"ncfilenames = [os.path.join(dir, x) for x in os.listdir(dir) if x.find(\"_d02_\") > 0]\n", "ncfilenames = [os.path.join(dir, x) for x in os.listdir(dir) if x.find(\"_d02_\") > 0]\n",
"ncfiles = [nc(x) for x in ncfilenames]\n", "ncfiles = [nc(x) for x in ncfilenames]\n",
"\n", "\n",
@ -1081,7 +1259,7 @@
"from wrf import getvar\n", "from wrf import getvar\n",
"from netCDF4 import Dataset as nc\n", "from netCDF4 import Dataset as nc\n",
"\n", "\n",
"dir = \"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi\"\n", "dir = \"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest\"\n",
"ncfilenames = [os.path.join(dir, x) for x in os.listdir(dir) if x.find(\"_d02_\") > 0]\n", "ncfilenames = [os.path.join(dir, x) for x in os.listdir(dir) if x.find(\"_d02_\") > 0]\n",
"ncfiles = [nc(x) for x in ncfilenames]\n", "ncfiles = [nc(x) for x in ncfilenames]\n",
"\n", "\n",
@ -1112,6 +1290,13 @@
"del t2_line, t2" "del t2_line, t2"
] ]
}, },
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
@ -1165,7 +1350,7 @@
"from wrf import getvar, ALL_TIMES, geo_bounds, get_cartopy, get_basemap, get_pyngl, cartopy_xlim, cartopy_ylim\n", "from wrf import getvar, ALL_TIMES, geo_bounds, get_cartopy, get_basemap, get_pyngl, cartopy_xlim, cartopy_ylim\n",
"from netCDF4 import Dataset as nc\n", "from netCDF4 import Dataset as nc\n",
"\n", "\n",
"wrf_filenames = glob(\"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/wrfout_d02_*\")\n", "wrf_filenames = glob(\"/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest/wrfout_d02_*\")\n",
"ncfiles = [nc(x) for x in wrf_filenames]\n", "ncfiles = [nc(x) for x in wrf_filenames]\n",
"\n", "\n",
"slp = getvar(ncfiles, \"slp\", timeidx=ALL_TIMES)\n", "slp = getvar(ncfiles, \"slp\", timeidx=ALL_TIMES)\n",
@ -1241,7 +1426,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.6.4" "version": "3.6.7"
} }
}, },
"nbformat": 4, "nbformat": 4,

519
test/ncl_get_var.ncl

@ -4,25 +4,35 @@
;system("printenv") ;system("printenv")
if (.not. isvar("in_file")) then if (.not. isvar("dir")) then
in_file = "/Users/ladwig/Documents/wrf_files/wrfout_d02_2010-06-13_21:00:00.nc" dir = "/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest"
;in_file = "/Users/ladwig/Documents/wrf_files/wrfout_d01_2010-06-13_21:00:00.nc"
;in_file = "/Users/ladwig/Documents/wrf_files/wrf_vortex_multi/moving_nest/wrfout_d02_2005-08-28_00:00:00.nc"
end if end if
if (.not. isvar("pattern")) then
pattern = "wrfout_d02_*"
end if
if (.not. isvar("out_file")) then if (.not. isvar("out_file")) then
out_file = "/tmp/wrftest.nc" out_file = "/tmp/wrftest.nc"
end if end if
input_file = addfile(in_file,"r")
pat = dir + "/" + pattern
cmd = "ls " + pat
fils = systemfunc (cmd) ; file paths
input_file = addfiles(fils,"r")
system("/bin/rm -f " + out_file) ; remove if exists system("/bin/rm -f " + out_file) ; remove if exists
fout = addfile(out_file, "c") fout = addfile(out_file, "c")
time = 0 time = -1
wrf_vars = [/"avo", "eth", "cape_2d", "cape_3d", "ctt", "dbz", "mdbz", \ wrf_vars = [/"avo", "eth", "cape_2d", "cape_3d", "ctt", "dbz", "mdbz", \
"geopt", "helicity", "lat", "lon", "omg", "p", "pressure", \ "geopt", "helicity", "lat", "lon", "omg", "p", "pressure", \
"pvo", "pw", "rh2", "rh", "slp", "ter", "td2", "td", "tc", \ "pvo", "pw", "rh2", "rh", "slp", "ter", "td2", "td", "tc", \
"theta", "tk", "tv", "twb", "updraft_helicity", "ua", "va", \ "theta", "tk", "tv", "twb", "updraft_helicity", "ua", "va", \
"wa", "uvmet10", "uvmet", "z", "cfrac"/] "wa", "uvmet10", "uvmet", "z", "cfrac", "height_agl" /]
unique_dimname_list = NewList("fifo") unique_dimname_list = NewList("fifo")
unique_dimsize_list = NewList("fifo") unique_dimsize_list = NewList("fifo")
@ -40,148 +50,253 @@
; variables with unique names. This is the reason for all of the ; variables with unique names. This is the reason for all of the
; name attribute stuff below. ; name attribute stuff below.
do i = 0, ListCount(wrf_vars) - 1 do i = 0, ListCount(wrf_vars) - 1
print("working on: " + wrf_vars[i]) print("working on: " + wrf_vars[i])
v := wrf_user_getvar(input_file, wrf_vars[i], time) v := wrf_user_getvar(input_file, wrf_vars[i], time)
fout->$wrf_vars[i]$ = v
;if (wrf_vars[i] .eq. "avo") then
; print(v)
;end if
; pw is written in pure NCL and does not contain dimension names
; so manually creating the dimension names here
if (wrf_vars[i] .eq. "pw") then
dim_names := (/"south_north", "west_east"/)
dim_sizes := dimsizes(v)
else
dim_names := getvardims(v)
dim_sizes := dimsizes(v)
end if
vardata@$wrf_vars[i]$ := v
vardimnamedata@$wrf_vars[i]$ := dim_names
ListAppend(vardata_list,vardata@$wrf_vars[i]$)
ListAppend(full_vardimname_list, vardimnamedata@$wrf_vars[i]$)
;print(vardata_list)
dimname=True
dimsize=True
; Determine the unique dimensions names, which will be used when
; creating the output NetCDF file
do j=0, dimsizes(dim_sizes)-1
;print(dim_names)
;print(dim_names(j))
name_id = sprintf("dimname_%i",i*j)
size_id = sprintf("dimsize_%i",i*j)
dimname@$name_id$ = dim_names(j)
dimsize@$size_id$ = dim_sizes(j)
has_name = False
do k=0, ListCount(unique_dimname_list)-1
if ((/unique_dimname_list[k]/) .eq. (/dimname@$name_id$/)) then
has_name = True
end if
end do
if (.not. has_name) then
;print("inserting: " + dimname@$name_id$)
ListAppend(unique_dimname_list, dimname@$name_id$)
ListAppend(unique_dimsize_list, dimsize@$size_id$)
end if
end do
end do end do
setfileoption(fout,"DefineMode",True)
; Set global attributes
f_att = True ; assign file attributes
f_att@title = "NCL generated netCDF file"
f_att@Conventions = "None"
fileattdef(fout, f_att) ; copy file attributes
; Set up the NetCDF dimensions
d_names = new(ListCount(unique_dimname_list), string)
d_sizes = new(ListCount(unique_dimname_list), integer)
d_unlim = new(ListCount(unique_dimname_list), logical)
; Note: Need to do this copy since NCL can't coerce the list data to
; array data
do i=0, ListCount(unique_dimname_list) - 1
d_names(i) = unique_dimname_list[i]
d_sizes(i) = unique_dimsize_list[i]
d_unlim(i) = False
end do
filedimdef(fout, d_names, d_sizes, d_unlim)
; Save the variables to the NetCDF file
do i=0, ListCount(vardata_list)-1
d := vardata_list[i]
filevardef(fout, wrf_vars[i], typeof(d), full_vardimname_list[i])
filevarattdef(fout,wrf_vars[i], d)
fout->$wrf_vars[i]$ = (/d/)
end do
; Do the interpolation routines manually ; Do the interpolation routines manually
; 3D vertical cross section ;;;;;;;;;;;;;;;;;;; 3D vertical cross section
z = wrf_user_getvar(input_file, "z", 0) ; grid point height time = -1
p = wrf_user_getvar(input_file, "pressure", 0) ; total pressure
z := wrf_user_getvar(input_file, "z", time) ; grid point height
p := wrf_user_getvar(input_file, "pressure", time) ; total pressure
dimsz = dimsizes(z) dimsz = dimsizes(z)
pivot = (/ dimsz(2)/2, dimsz(1)/2 /) ; pivot point is center of domain pivot = (/ dimsz(3)/2, dimsz(2)/2 /) ; pivot point is center of domain
ht_cross = wrf_user_intrp3d(z,p,"v",pivot,90.0,False) ht_cross = wrf_user_intrp3d(z,p,"v",pivot,90.0,False)
p_cross = wrf_user_intrp3d(p,z,"v",pivot,90.0,False) p_cross = wrf_user_intrp3d(p,z,"v",pivot,90.0,False)
p_cross!0 = "Vertical_p"
p_cross!1 = "Horizontal_p"
fout->ht_cross = ht_cross
fout->p_cross = p_cross
time = 0
; For the new cross section routine
xopt = True
xopt@use_pivot = True
xopt@angle = 90.0
xopt@file_handle = input_file
xopt@timeidx = time
xopt@linecoords = True
ht_vertcross1 = wrf_user_vertcross(z, p, pivot, xopt)
fout->ht_vertcross1 = ht_vertcross1
; For the new cross section routine
xopt := True
xopt@use_pivot = True
xopt@angle = 90.0
xopt@levels = (/1000., 850., 700., 500., 250./)
xopt@file_handle = input_file
xopt@timeidx = time
xopt@linecoords = True
ht_vertcross2 = wrf_user_vertcross(z, p, pivot, xopt)
ht_vertcross2!1 = "vertical2"
ht_vertcross2!2 = "cross_line_idx2"
fout->ht_vertcross2 = ht_vertcross2
ht_cross_dims = dimsizes(ht_cross) ; Can only use a single time for lat/lon version at this time
p_cross_dims = dimsizes(p_cross)
; 3D horizontal interpolation vertdims = dimsizes(ht_vertcross2)
htdims = dimsizes(z)
lats = wrf_user_getvar(input_file, "lat", 0)
lons = wrf_user_getvar(input_file, "lon", 0)
start_lat = min(lats) + .25d*(max(lats) - min(lats))
end_lat = min(lats) + .65d*(max(lats) - min(lats))
start_lon = min(lons) + .25d*(max(lons) - min(lons))
end_lon = min(lons) + .65d*(max(lons) - min(lons))
start_end = (/ start_lon, start_lat, end_lon, end_lat /)
; For the new cross section routine
xopt := True
xopt@use_pivot = False
xopt@latlon = True
xopt@file_handle = input_file
xopt@timeidx = 0
xopt@linecoords = True
xopt@autolevels = 1000
ht_vertcross3 = wrf_user_vertcross(z, p, start_end, xopt)
ht_vertcross3!0 = "Time"
ht_vertcross3!1 = "vertical3"
ht_vertcross3!2 = "cross_line_idx3"
fout->ht_vertcross3 = ht_vertcross3
; Test the moving nest with lat/lon over time
times = wrf_user_getvar(input_file, "times", -1)
ntimes = dimsizes(times)
do i=0,ntimes-1
xopt@timeidx = i
name = sprinti("ht_vertcross_t%i", i)
p_var := p(i,:,:,:)
z_var := z(i,:,:,:)
ht_vertcross := wrf_user_vertcross(z_var, p_var, start_end, xopt)
dim0name = sprinti("vertical_t%i",i)
dim1name = sprinti("cross_line_idx_t%i",i)
ht_vertcross!0 = dim0name
ht_vertcross!1 = dim1name
fout->$name$ = ht_vertcross
end do
;;;;;;;;;;;;;;;;;;;;;;;; 3D horizontal interpolation
time = -1
z := wrf_user_getvar(input_file, "z", time) ; grid point height
p := wrf_user_getvar(input_file, "pressure", time) ; total pressure
; First, check backwards compat
plev = 500. ; 500 MB plev = 500. ; 500 MB
hlev = 5000; ; 5000 m
z_500 = wrf_user_intrp3d(z,p,"h",plev,0.,False) z_500 = wrf_user_intrp3d(z,p,"h",plev,0.,False)
z_500_dims = dimsizes(z_500) p_5000 = wrf_user_intrp3d(p,z,"h",hlev,0.,False)
fout->z_500 = z_500
fout->p_5000 = p_5000
plev := (/1000., 850., 500., 250./)
hlev := (/500., 2500., 5000., 10000. /)
z_multi = wrf_user_intrp3d(z,p,"h",plev,0.,False)
p_multi = wrf_user_intrp3d(p,z,"h",hlev,0.,False)
fout->z_multi = z_multi
fout->p_multi = p_multi
; Now check the new routine
plev := 500. ; 500 MB
hlev := 5000 ; 5000 m
z2_500 = wrf_user_interplevel(z,p,plev,False)
p2_5000 = wrf_user_interplevel(p,z,hlev,False)
fout->z2_500 = z2_500
fout->p2_5000 = p2_5000
; 2D interpolation along line
t2 = wrf_user_getvar(input_file, "T2", 0) plev := (/1000., 850., 500., 250./)
hlev := (/500., 2500., 5000., 10000. /)
z2_multi = wrf_user_interplevel(z,p,plev,False)
p2_multi = wrf_user_interplevel(p,z,hlev,False)
fout->z2_multi = z2_multi
fout->p2_multi = p2_multi
pblh = wrf_user_getvar(input_file, "PBLH", time)
opts := False
opts@inc2dlevs = True
p_lev2d = wrf_user_interplevel(p, z, pblh, opts)
fout->p_lev2d = p_lev2d
;;;;;;;;;;;;;;;;;;;;;;;; 2D interpolation along line
time = -1
t2 = wrf_user_getvar(input_file, "T2", time)
dimst2 = dimsizes(t2) dimst2 = dimsizes(t2)
pivot = (/ dimst2(1)/2, dimst2(0)/2 /) pivot = (/ dimst2(2)/2, dimst2(1)/2 /)
t2_line = wrf_user_intrp2d(t2, pivot, 90.0, False) t2_line = wrf_user_intrp2d(t2, pivot, 90.0, False)
t2_line_dims = dimsizes(t2_line)
fout->t2_line = t2_line
filedimdef(fout, (/"ht_cross_vert", "ht_cross_horiz", "p_cross_vert", "p_cross_horiz"/), \
(/ht_cross_dims(0), ht_cross_dims(1), p_cross_dims(0), p_cross_dims(1)/), \ ; For the new interplevel routine
(/False,False,False,False/)) xopt := True
filedimdef(fout, (/"z500_vert", "z500_horiz"/), \ xopt@use_pivot = True
(/z_500_dims(0), z_500_dims(1) /), \ xopt@angle = 90.0
(/False, False/)) xopt@latlon = False
filedimdef(fout, (/"t2_line_horiz"/), \ xopt@file_handle = input_file
(/t2_line_dims(0) /), \ xopt@timeidx = 0
(/False/)) xopt@linecoords = True
filevardef(fout, "ht_cross", typeof(ht_cross), (/"ht_cross_vert", "ht_cross_horiz"/)) t2_line2 = wrf_user_interpline(t2, pivot, xopt)
filevardef(fout, "p_cross", typeof(p_cross), (/"p_cross_vert", "p_cross_horiz"/))
filevardef(fout, "z_500", typeof(z_500), (/"z500_vert", "z500_horiz"/)) fout->t2_line2 = t2_line2
filevardef(fout, "t2_line", typeof(t2_line), (/"t2_line_horiz"/))
lats = wrf_user_getvar(input_file, "lat", 0)
filevarattdef(fout,"ht_cross", ht_cross) lons = wrf_user_getvar(input_file, "lon", 0)
filevarattdef(fout,"p_cross", p_cross)
filevarattdef(fout, "z_500", z_500) start_lat = min(lats) + .25d*(max(lats) - min(lats))
filevarattdef(fout, "t2_line", t2_line) end_lat = min(lats) + .65d*(max(lats) - min(lats))
fout->ht_cross = (/ht_cross/)
fout->p_cross = (/p_cross/) start_lon = min(lons) + .25d*(max(lons) - min(lons))
fout->z_500 = (/z_500/) end_lon = min(lons) + .65d*(max(lons) - min(lons))
fout->t2_line = (/t2_line/)
start_end = (/ start_lon, start_lat, end_lon, end_lat /)
; 3D interpolation to new vertical coordinates ; For the new line routine
xopt := True
xopt@use_pivot = False
xopt@latlon = True
xopt@file_handle = input_file
xopt@timeidx = 0
xopt@linecoords = True
t2_line3 = wrf_user_interpline(t2, start_end, xopt)
t2_line3!1 = "line_idx_t2_line3"
fout->t2_line3 = t2_line3
times = wrf_user_getvar(input_file, "times", -1)
ntimes = dimsizes(times)
do i=0,ntimes-1
xopt@timeidx = i
name = sprinti("t2_line_t%i", i)
dim0name = sprinti("lineidx_t%i",i)
var := t2(i,:,:)
t2_line := wrf_user_interpline(var, start_end, xopt)
t2_line!0 = dim0name
fout->$name$ = t2_line
end do
; Make sure the 1 time case still works
t2 := wrf_user_getvar(input_file, "T2", 0)
; For the new line routine
xopt := True
xopt@use_pivot = False
xopt@latlon = True
xopt@file_handle = input_file
xopt@timeidx = 0
xopt@linecoords = True
t2_line4 = wrf_user_interpline(t2, start_end, xopt)
t2_line4!0 = "t2_line4_idx"
fout->t2_line4 = t2_line4
;;;;;;;;;;;;;;;;;;;;;;; 3D interpolation to new vertical coordinates
time = -1
; interp t to theta ; interp t to theta
fld1 = wrf_user_getvar(input_file, "tk", -1) fld1 = wrf_user_getvar(input_file, "tk", time)
vert_coord = "theta" vert_coord = "theta"
interp_levels = (/200,300,500,1000/) interp_levels = (/200,300,500,1000/)
@ -191,32 +306,17 @@
opts@logP = True opts@logP = True
fld1_intrp = wrf_user_vert_interp(input_file,fld1,vert_coord,interp_levels,opts) fld1_intrp = wrf_user_vert_interp(input_file,fld1,vert_coord,interp_levels,opts)
fld1_intrp!1 = "interp_levels1"
fld1_dims = dimsizes(fld1_intrp) fout->fld_tk_theta = fld1_intrp
filedimdef(fout, (/"fld1_time", "fld1_levs", "fld1_sn", "fld1_we"/), \
(/fld1_dims(0), fld1_dims(1), fld1_dims(2), fld1_dims(3)/), \
(/False,False,False,False/))
filevardef(fout, "fld_tk_theta", typeof(fld1_intrp), (/"fld1_time", "fld1_levs", "fld1_sn", "fld1_we"/))
filevarattdef(fout,"fld_tk_theta", fld1_intrp)
fout->fld_tk_theta = (/fld1_intrp/)
; interp t to theta-e ; interp t to theta-e
fld2 = fld1 fld2 = fld1
vert_coord := "theta-e" vert_coord := "theta-e"
fld2_intrp = wrf_user_vert_interp(input_file,fld2,vert_coord,interp_levels,opts) fld2_intrp = wrf_user_vert_interp(input_file,fld2,vert_coord,interp_levels,opts)
fld2_intrp!1 = "interp_levels2"
fout->fld_tk_theta_e = fld2_intrp
fld2_dims = dimsizes(fld2_intrp)
filedimdef(fout, (/"fld2_time", "fld2_levs", "fld2_sn", "fld2_we"/), \
(/fld2_dims(0), fld2_dims(1), fld2_dims(2), fld2_dims(3)/), \
(/False,False,False,False/))
filevardef(fout, "fld_tk_theta_e", typeof(fld2_intrp), (/"fld2_time", "fld2_levs", "fld2_sn", "fld2_we"/))
filevarattdef(fout,"fld_tk_theta_e", fld2_intrp)
fout->fld_tk_theta_e = (/fld2_intrp/)
; interp t to pressure ; interp t to pressure
@ -224,34 +324,19 @@
vert_coord := "pressure" vert_coord := "pressure"
interp_levels := (/850,500/) interp_levels := (/850,500/)
fld3_intrp = wrf_user_vert_interp(input_file,fld3,vert_coord,interp_levels,opts) fld3_intrp = wrf_user_vert_interp(input_file,fld3,vert_coord,interp_levels,opts)
fld3_intrp!1 = "interp_levels3"
fout->fld_tk_pres = fld3_intrp
fld3_dims = dimsizes(fld3_intrp)
filedimdef(fout, (/"fld3_time", "fld3_levs", "fld3_sn", "fld3_we"/), \
(/fld3_dims(0), fld3_dims(1), fld3_dims(2), fld3_dims(3)/), \
(/False,False,False,False/))
filevardef(fout, "fld_tk_pres", typeof(fld3_intrp), (/"fld3_time", "fld3_levs", "fld3_sn", "fld3_we"/))
filevarattdef(fout,"fld_tk_pres", fld3_intrp)
fout->fld_tk_pres = (/fld3_intrp/)
; interp t to ght_msl ; interp t to ght_msl
fld4 = fld1 fld4 = fld1
vert_coord := "ght_msl" vert_coord := "ght_msl"
interp_levels := (/1,2/) interp_levels := (/1,2/)
fld4_intrp = wrf_user_vert_interp(input_file,fld4,vert_coord,interp_levels,opts) fld4_intrp = wrf_user_vert_interp(input_file,fld4,vert_coord,interp_levels,opts)
fld4_intrp!1 = "interp_levels4"
fout->fld_tk_ght_msl = fld4_intrp
fld4_dims = dimsizes(fld4_intrp)
filedimdef(fout, (/"fld4_time", "fld4_levs", "fld4_sn", "fld4_we"/), \
(/fld4_dims(0), fld4_dims(1), fld4_dims(2), fld4_dims(3)/), \
(/False,False,False,False/))
filevardef(fout, "fld_tk_ght_msl", typeof(fld4_intrp), (/"fld4_time", "fld4_levs", "fld4_sn", "fld4_we"/))
filevarattdef(fout,"fld_tk_ght_msl", fld4_intrp)
fout->fld_tk_ght_msl = (/fld4_intrp/)
; interp t to ght_agl ; interp t to ght_agl
@ -259,99 +344,69 @@
vert_coord := "ght_agl" vert_coord := "ght_agl"
interp_levels := (/1,2/) interp_levels := (/1,2/)
fld5_intrp = wrf_user_vert_interp(input_file,fld1,vert_coord,interp_levels,opts) fld5_intrp = wrf_user_vert_interp(input_file,fld1,vert_coord,interp_levels,opts)
fld5_intrp!1 = "interp_levels5"
fout->fld_tk_ght_agl = fld5_intrp
fld5_dims = dimsizes(fld5_intrp)
filedimdef(fout, (/"fld5_time", "fld5_levs", "fld5_sn", "fld5_we"/), \
(/fld5_dims(0), fld5_dims(1), fld5_dims(2), fld5_dims(3)/), \
(/False,False,False,False/))
filevardef(fout, "fld_tk_ght_agl", typeof(fld5_intrp), (/"fld5_time", "fld5_levs", "fld5_sn", "fld5_we"/))
filevarattdef(fout,"fld_tk_ght_agl", fld5_intrp)
fout->fld_tk_ght_agl = (/fld5_intrp/)
; interp ht to pres ; interp ht to pres
fld6 = wrf_user_getvar(input_file, "height", -1) fld6 = wrf_user_getvar(input_file, "height", time)
vert_coord := "pressure" vert_coord := "pressure"
opts@field_type = "ght" opts@field_type = "ght"
interp_levels := (/500,50/) interp_levels := (/500,50/)
fld6_intrp = wrf_user_vert_interp(input_file,fld6,vert_coord,interp_levels,opts) fld6_intrp = wrf_user_vert_interp(input_file,fld6,vert_coord,interp_levels,opts)
fld6_intrp!1 = "interp_levels6"
fout->fld_ht_pres = fld6_intrp
fld6_dims = dimsizes(fld6_intrp)
filedimdef(fout, (/"fld6_time", "fld6_levs", "fld6_sn", "fld6_we"/), \
(/fld6_dims(0), fld6_dims(1), fld6_dims(2), fld6_dims(3)/), \
(/False,False,False,False/))
filevardef(fout, "fld_ht_pres", typeof(fld6_intrp), (/"fld6_time", "fld6_levs", "fld6_sn", "fld6_we"/))
filevarattdef(fout,"fld_ht_pres", fld6_intrp)
fout->fld_ht_pres = (/fld6_intrp/)
; interp pres to theta ; interp pres to theta
fld7 = wrf_user_getvar(input_file, "pressure", -1) fld7 = wrf_user_getvar(input_file, "pressure", time)
vert_coord := "theta" vert_coord := "theta"
opts@field_type = "pressure" opts@field_type = "pressure"
interp_levels := (/200,300,500,1000/) interp_levels := (/200,300,500,1000/)
fld7_intrp = wrf_user_vert_interp(input_file,fld7,vert_coord,interp_levels,opts) fld7_intrp = wrf_user_vert_interp(input_file,fld7,vert_coord,interp_levels,opts)
fld7_intrp!1 = "interp_levels7"
fld7_dims = dimsizes(fld7_intrp)
filedimdef(fout, (/"fld7_time", "fld7_levs", "fld7_sn", "fld7_we"/), \
(/fld7_dims(0), fld7_dims(1), fld7_dims(2), fld7_dims(3)/), \
(/False,False,False,False/))
filevardef(fout, "fld_pres_theta", typeof(fld7_intrp), (/"fld7_time", "fld7_levs", "fld7_sn", "fld7_we"/))
filevarattdef(fout,"fld_pres_theta", fld7_intrp)
fout->fld_pres_theta = (/fld7_intrp/) fout->fld_pres_theta = (/fld7_intrp/)
; interp theta-e to pressure ; interp theta-e to pressure
fld8 = wrf_user_getvar(input_file, "eth", -1) fld8 = wrf_user_getvar(input_file, "eth", time)
vert_coord := "pressure" vert_coord := "pressure"
opts@field_type = "T" opts@field_type = "T"
interp_levels := (/850,500,5/) interp_levels := (/850,500,5/)
fld8_intrp = wrf_user_vert_interp(input_file,fld8,vert_coord,interp_levels,opts) fld8_intrp = wrf_user_vert_interp(input_file,fld8,vert_coord,interp_levels,opts)
fld8_intrp!1 = "interp_levels8"
fout->fld_thetae_pres = fld8_intrp
;;;;;;;;;;;;;;;;;;; lat/lon to x/y and x/y to lat/lon routines
lats := (/22.0, 25.0, 27.0 /)
lons := (/-90.0, -87.5, -83.75 /)
x_s = (/10, 50, 90 /)
y_s = (/10, 50, 90 /)
opt = True
opt@useTime = -1
opt@returnInt = False
xy1 = wrf_user_ll_to_xy(input_file, lons, lats, opt)
ll1 = wrf_user_xy_to_ll(input_file, x_s, y_s, opt)
fout->xy1 = xy1
fout->ll1 = ll1
opt = True
opt@useTime = 8
opt@returnInt = True
xy2 = wrf_user_ll_to_xy(input_file, lons, lats, opt)
ll2 = wrf_user_xy_to_ll(input_file, x_s, y_s, opt)
fld8_dims = dimsizes(fld8_intrp) fout->xy2 = xy2
fout->ll2 = ll2
filedimdef(fout, (/"fld8_time", "fld8_levs", "fld8_sn", "fld8_we"/), \
(/fld8_dims(0), fld8_dims(1), fld8_dims(2), fld8_dims(3)/), \
(/False,False,False,False/))
filevardef(fout, "fld_thetae_pres", typeof(fld8_intrp), (/"fld8_time", "fld8_levs", "fld8_sn", "fld8_we"/))
filevarattdef(fout,"fld_thetae_pres", fld8_intrp)
fout->fld_thetae_pres = (/fld8_intrp/)
; lat/lon to x/y and x/y to lat/lon routines
lats = (/-55, -60, -65 /)
lons = (/25, 30, 35 /)
i_s = (/10, 100, 150 /)
j_s = (/10, 100, 150 /)
ij = wrf_user_ll_to_ij(input_file, lons, lats, True)
ll = wrf_user_ij_to_ll(input_file, i_s, j_s, True)
ij_dims = dimsizes(ij)
ll_dims = dimsizes(ll)
filedimdef(fout, (/"i_j", "ij_idx"/), \
(/ij_dims(0), ij_dims(1)/), \
(/False,False/))
filedimdef(fout, (/"lat_lon", "ll_idx"/), \
(/ll_dims(0), ll_dims(1)/), \
(/False,False/))
filevardef(fout, "ij", typeof(ij), (/"i_j", "ij_idx"/))
filevardef(fout, "ll", typeof(ll), (/"lat_lon", "ll_idx"/))
filevarattdef(fout,"ij", ij)
filevarattdef(fout,"ll", ll)
fout->ij = (/ij/)
fout->ll = (/ll/)
delete(fout) delete(fout)

BIN
test/plot_tests/d01/avo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
test/plot_tests/d01/cape2d_only.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

BIN
test/plot_tests/d01/cape3d_only.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

BIN
test/plot_tests/d01/cape_2d.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

BIN
test/plot_tests/d01/cape_3d.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

BIN
test/plot_tests/d01/cfrac.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

BIN
test/plot_tests/d01/cin2d_only.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

BIN
test/plot_tests/d01/cin3d_only.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

BIN
test/plot_tests/d01/ctt.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

BIN
test/plot_tests/d01/dbz.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
test/plot_tests/d01/eth.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

BIN
test/plot_tests/d01/geopt.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
test/plot_tests/d01/helicity.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
test/plot_tests/d01/high_cfrac.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

BIN
test/plot_tests/d01/lat.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
test/plot_tests/d01/lcl.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

BIN
test/plot_tests/d01/lfc.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

BIN
test/plot_tests/d01/lon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
test/plot_tests/d01/low_cfrac.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

BIN
test/plot_tests/d01/mdbz.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
test/plot_tests/d01/mid_cfrac.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

BIN
test/plot_tests/d01/omg.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

BIN
test/plot_tests/d01/p.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

BIN
test/plot_tests/d01/pressure.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

BIN
test/plot_tests/d01/pvo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

BIN
test/plot_tests/d01/pw.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

BIN
test/plot_tests/d01/rh.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

BIN
test/plot_tests/d01/rh2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

BIN
test/plot_tests/d01/slp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
test/plot_tests/d01/tc.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
test/plot_tests/d01/td.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
test/plot_tests/d01/td2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
test/plot_tests/d01/ter.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
test/plot_tests/d01/theta.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
test/plot_tests/d01/tk.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
test/plot_tests/d01/tv.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
test/plot_tests/d01/twb.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
test/plot_tests/d01/ua.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

BIN
test/plot_tests/d01/updraft_helicity.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
test/plot_tests/d01/uvmet.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save