Repository: pvlib/pvlib-python

Issue:
zenith vs solar_zenith in psm3 variable maps
Should `'zenith': 'solar_zenith_angle', ` in `REQUEST_VARIABLE_MAP` instead be `'solar_zenith': 'solar_zenith_angle', `? In `VARIABLE_MAP` it is `solar_zenith`.

https://github.com/pvlib/pvlib-python/blob/2ca40aa377d0871905f3c12f7ab0de0d437e2e21/pvlib/iotools/psm3.py#L45-L61

Hints from issue comments:
@cwhanse: I think @williamhobbs is correct, line 52 should be 'solar_zenith': 'solar_zenith_angle'@ayushjariyal: @williamhobbs Is this issue still unresolved?@williamhobbs: > Is this issue still unresolved?

@ayushjariyal Yes, it it still unresolved. I already have another PR open, and will probably not start on this until that one is resolved, so feel free to work on it yourself, if that's why you are asking.@ayushjariyal: @williamhobbs Can you please review the changes and let me know if any further improvements are needed?@williamhobbs: > [@williamhobbs](https://github.com/williamhobbs) Can you please review the changes and let me know if any further improvements are needed?

@ayushjariyal, looks good to me!

Solution patch:
diff --git a/ci/requirements-py3.12.yml b/ci/requirements-py3.12.yml
index f3d8fc2..8293bff 100644
--- a/ci/requirements-py3.12.yml
+++ b/ci/requirements-py3.12.yml
@@ -25,4 +25,4 @@ dependencies:
     - statsmodels
     - pip:
         - nrel-pysam>=2.0
-        # - solarfactors  # required shapely<2 isn't available for 3.12
+        - solarfactors
diff --git a/docs/sphinx/source/whatsnew/v0.11.3.rst b/docs/sphinx/source/whatsnew/v0.11.3.rst
index 5a847c0..6363275 100644
--- a/docs/sphinx/source/whatsnew/v0.11.3.rst
+++ b/docs/sphinx/source/whatsnew/v0.11.3.rst
@@ -10,13 +10,18 @@ Deprecations
 
 Enhancements
 ~~~~~~~~~~~~
+* :py:func:`~pvlib.irradiance.gti_dirint` now raises an informative message
+  when input data don't include values with AOI<90 (:issue:`1342`, :pull:`2347`)
 * Fix a bug in :py:func:`pvlib.bifacial.get_irradiance_poa` which may have yielded non-zero
   ground irradiance when the sun was below the horizon. (:issue:`2245`, :pull:`2359`)
+* Fix a bug where :py:func:`pvlib.transformer.simple_efficiency` could only be imported
+  using the `from pvlib.transformer` syntax (:pull:`2388`)
 
 Documentation
 ~~~~~~~~~~~~~
 * Fix Procedural and Object Oriented simulation examples having slightly different results, in :ref:`introtutorial`. (:issue:`2366`, :pull:`2367`)
 * Restructure the user guide with subsections (:issue:`2302`, :pull:`2310`)
+* Add references for :py:func:`pvlib.snow.loss_townsend`. (:issue:`2383`, :pull:`2384`)
 
 Testing
 ~~~~~~~
@@ -38,5 +43,8 @@ Contributors
 ~~~~~~~~~~~~
 * Rajiv Daxini (:ghuser:`RDaxini`)
 * Mark Campanelli (:ghuser:`markcampanelli`)
+* Cliff Hansen (:ghuser:`cwhanse`)
 * Jason Lun Leung (:ghuser:`jason-rpkt`)
 * Manoj K S (:ghuser:`manojks1999`)
+* Kurt Rhee (:ghuser:`kurt-rhee`)
+* Ayush jariyal (:ghuser:`ayushjariyal`)
diff --git a/pvlib/__init__.py b/pvlib/__init__.py
index b5b0786..3e6e56b 100644
--- a/pvlib/__init__.py
+++ b/pvlib/__init__.py
@@ -27,4 +27,5 @@ from pvlib import (  # noqa: F401
     temperature,
     tools,
     tracking,
+    transformer,
 )
diff --git a/pvlib/iotools/psm3.py b/pvlib/iotools/psm3.py
index 34199b4..92ebbeb 100644
--- a/pvlib/iotools/psm3.py
+++ b/pvlib/iotools/psm3.py
@@ -49,7 +49,7 @@ REQUEST_VARIABLE_MAP = {
     'ghi_clear': 'clearsky_ghi',
     'dhi_clear': 'clearsky_dhi',
     'dni_clear': 'clearsky_dni',
-    'zenith': 'solar_zenith_angle',
+    'solar_zenith': 'solar_zenith_angle',
     'temp_air': 'air_temperature',
     'temp_dew': 'dew_point',
     'relative_humidity': 'relative_humidity',
diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py
index 7fbb1ea..846560d 100644
--- a/pvlib/irradiance.py
+++ b/pvlib/irradiance.py
@@ -2368,6 +2368,9 @@ def gti_dirint(poa_global, aoi, solar_zenith, solar_azimuth, times,
            irradiance, Solar Energy 122, 1037-1046.
            :doi:`10.1016/j.solener.2015.10.024`
     """
+    # check input data and raise Exceptions where data will cause the
+    # algorithm to fail
+    _gti_dirint_check_input(aoi)
 
     aoi_lt_90 = aoi < 90
 
@@ -2399,6 +2402,17 @@ def gti_dirint(poa_global, aoi, solar_zenith, solar_azimuth, times,
     return output
 
 
+def _gti_dirint_check_input(aoi):
+    r"""
+    Helper for gti_dirint
+
+    Raises Exceptions from input data that cause the algorithm to fail.
+    """
+    if not (aoi < 90).any():
+        raise ValueError("There are no times with AOI < 90. "
+                         "gti_dirint requires some data with AOI < 90.")
+
+
 def _gti_dirint_lt_90(poa_global, aoi, aoi_lt_90, solar_zenith, solar_azimuth,
                       times, surface_tilt, surface_azimuth, pressure=101325.,
                       use_delta_kt_prime=True, temp_dew=None, albedo=.25,
diff --git a/pvlib/snow.py b/pvlib/snow.py
index 190fe7b..bc2cccb 100644
--- a/pvlib/snow.py
+++ b/pvlib/snow.py
@@ -278,9 +278,8 @@ def loss_townsend(snow_total, snow_events, surface_tilt, relative_humidity,
     axis to the module edge.
 
     The parameter `string_factor` is an enhancement added to the model after
-    publication of [1]_ per private communication with the model's author. The
-    definition for snow events documented above is also based on private
-    communication with the model's author.
+    publication of [1]_, as described in [2]_.
+    The definition for snow events documented above is based on [3]_.
 
     References
     ----------
@@ -288,6 +287,14 @@ def loss_townsend(snow_total, snow_events, surface_tilt, relative_humidity,
        update from two winters of measurements in the SIERRA. 37th IEEE
        Photovoltaic Specialists Conference, Seattle, WA, USA.
        :doi:`10.1109/PVSC.2011.6186627`
+    .. [2] Townsend, T. and Previtali, J. (2023). A Fresh Dusting: Current
+        Uses of the Townsend Snow Model. In "Photovoltaic Reliability
+        Workshop (PVRW) 2023 Proceedings: Posters.", ed. Silverman,
+        T. J. Dec. 2023. NREL/CP-5900-87918.
+        Available at: https://www.nrel.gov/docs/fy25osti/90585.pdf
+    .. [3] Townsend, T. (2013). Predicting PV Energy Loss Caused by Snow.
+        Solar Power International, Chicago IL.
+        :doi:`10.13140/RG.2.2.14299.68647`
     '''
 
     # unit conversions from cm and m to in, from C to K, and from % to fraction


Test patch:
diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py
index 9352e97..b56c366 100644
--- a/pvlib/tests/test_irradiance.py
+++ b/pvlib/tests/test_irradiance.py
@@ -928,6 +928,23 @@ def test_gti_dirint():
     assert_frame_equal(output, expected)
 
 
+def test_gti_dirint_data_error():
+    times = pd.DatetimeIndex(
+        ['2014-06-24T06-0700', '2014-06-24T09-0700', '2014-06-24T12-0700'])
+    poa_global = np.array([20, 300, 1000])
+    zenith = np.array([80, 45, 20])
+    azimuth = np.array([90, 135, 180])
+    surface_tilt = 30
+    surface_azimuth = 180
+
+    aoi = np.array([100, 170, 110])
+    with pytest.raises(
+            ValueError, match="There are no times with AOI < 90"):
+        irradiance.gti_dirint(
+            poa_global, aoi, zenith, azimuth, times, surface_tilt,
+            surface_azimuth)
+
+
 def test_erbs():
     index = pd.DatetimeIndex(['20190101']*3 + ['20190620'])
     ghi = pd.Series([0, 50, 1000, 1000], index=index)