Repository: pvlib/pvlib-python

Issue:
change eta_m to module_efficiency
`temperature.noct_sam` uses `eta_m_ref` to describe the module efficiency at reference conditions and `temperature.pvsyst_cell` uses `eta_m` to describe the module efficiency generically.

Just calling both of these `module_efficiency` would make the function signatures easily understandable by many more people. I'd be ok with `module_efficiency_ref` but I don't think that precision is very important.

I skimmed [pvterms](https://duramat.github.io/pv-terms/) and didn't see a suggestion for this quantity.

`temperature.noct_sam` has not yet been released and it's just a positional argument, so changing the name is trivial. `temperature.pvsyst_cell` would need a deprecation cycle.

Originally discussed in https://github.com/pvlib/pvlib-python/pull/1177#discussion_r589081257

Assignment of milestone indicates that we will act on this or close it forever before 0.9 is released.



Discussion:
I support this change.

Patch:
diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py
--- a/pvlib/modelchain.py
+++ b/pvlib/modelchain.py
@@ -977,7 +977,7 @@ def infer_temperature_model(self):
             return self.faiman_temp
         elif {'noct_installed'} <= params:
             return self.fuentes_temp
-        elif {'noct', 'eta_m_ref'} <= params:
+        elif {'noct', 'module_efficiency'} <= params:
             return self.noct_sam_temp
         else:
             raise ValueError(f'could not infer temperature model from '
diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py
--- a/pvlib/pvsystem.py
+++ b/pvlib/pvsystem.py
@@ -671,7 +671,9 @@ def pvsyst_celltemp(self, poa_global, temp_air, wind_speed=1.0):
         wind_speed = self._validate_per_array(wind_speed, system_wide=True)
 
         def build_celltemp_kwargs(array):
-            return {**_build_kwargs(['eta_m', 'alpha_absorption'],
+            # TODO remove 'eta_m' after deprecation of this parameter
+            return {**_build_kwargs(['eta_m', 'module_efficiency',
+                                     'alpha_absorption'],
                                     array.module_parameters),
                     **_build_kwargs(['u_c', 'u_v'],
                                     array.temperature_model_parameters)}
@@ -843,10 +845,10 @@ def _build_kwargs_noct_sam(array):
                 # bundled with kwargs for simplicity
                 temp_model_kwargs['noct'] = \
                     array.temperature_model_parameters['noct']
-                temp_model_kwargs['eta_m_ref'] = \
-                    array.temperature_model_parameters['eta_m_ref']
+                temp_model_kwargs['module_efficiency'] = \
+                    array.temperature_model_parameters['module_efficiency']
             except KeyError:
-                msg = ('Parameters noct and eta_m_ref are required.'
+                msg = ('Parameters noct and module_efficiency are required.'
                        ' Found {} in temperature_model_parameters.'
                        .format(array.temperature_model_parameters))
                 raise KeyError(msg)
diff --git a/pvlib/temperature.py b/pvlib/temperature.py
--- a/pvlib/temperature.py
+++ b/pvlib/temperature.py
@@ -6,6 +6,7 @@
 import numpy as np
 import pandas as pd
 from pvlib.tools import sind
+from pvlib._deprecation import warn_deprecated
 
 TEMPERATURE_MODEL_PARAMETERS = {
     'sapm': {
@@ -285,7 +286,7 @@ def sapm_cell_from_module(module_temperature, poa_global, deltaT,
 
 
 def pvsyst_cell(poa_global, temp_air, wind_speed=1.0, u_c=29.0, u_v=0.0,
-                eta_m=0.1, alpha_absorption=0.9):
+                eta_m=None, module_efficiency=0.1, alpha_absorption=0.9):
     r"""
     Calculate cell temperature using an empirical heat loss factor model
     as implemented in PVsyst.
@@ -313,12 +314,14 @@ def pvsyst_cell(poa_global, temp_air, wind_speed=1.0, u_c=29.0, u_v=0.0,
     u_v : float, default 0.0
         Combined heat loss factor influenced by wind. Parameter :math:`U_{v}`
         in :eq:`pvsyst`.
-        :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]`
+        :math:`\left[ \frac{\text{W}/\text{m}^2}{\text{C}\ \left( \text{m/s} \right)} \right]`  # noQA: E501
+
+    eta_m : numeric, default None (deprecated, use module_efficiency instead)
 
-    eta_m : numeric, default 0.1
-        Module external efficiency as a fraction, i.e.,
-        :math:`DC\ power / (POA\ irradiance \times module\ area)`.
-        Parameter :math:`\eta_{m}` in :eq:`pvsyst`.
+    module_efficiency : numeric, default 0.1
+        Module external efficiency as a fraction. Parameter :math:`\eta_{m}`
+        in :eq:`pvsyst`. Calculate as
+        :math:`\eta_{m} = DC\ power / (POA\ irradiance \times module\ area)`.
 
     alpha_absorption : numeric, default 0.9
         Absorption coefficient. Parameter :math:`\alpha` in :eq:`pvsyst`.
@@ -370,8 +373,13 @@ def pvsyst_cell(poa_global, temp_air, wind_speed=1.0, u_c=29.0, u_v=0.0,
     37.93103448275862
     """
 
+    if eta_m:
+        warn_deprecated(
+            since='v0.9', message='eta_m overwriting module_efficiency',
+            name='eta_m', alternative='module_efficiency', removal='v0.10')
+        module_efficiency = eta_m
     total_loss_factor = u_c + u_v * wind_speed
-    heat_input = poa_global * alpha_absorption * (1 - eta_m)
+    heat_input = poa_global * alpha_absorption * (1 - module_efficiency)
     temp_difference = heat_input / total_loss_factor
     return temp_air + temp_difference
 
@@ -719,7 +727,7 @@ def _adj_for_mounting_standoff(x):
                         [0., 18., 11., 6., 2., 0.])
 
 
-def noct_sam(poa_global, temp_air, wind_speed, noct, eta_m_ref,
+def noct_sam(poa_global, temp_air, wind_speed, noct, module_efficiency,
              effective_irradiance=None, transmittance_absorptance=0.9,
              array_height=1, mount_standoff=4):
     r'''
@@ -744,9 +752,9 @@ def noct_sam(poa_global, temp_air, wind_speed, noct, eta_m_ref,
         Nominal operating cell temperature [C], determined at conditions of
         800 W/m^2 irradiance, 20 C ambient air temperature and 1 m/s wind.
 
-    eta_m_ref : float
+    module_efficiency : float
         Module external efficiency [unitless] at reference conditions of
-        1000 W/m^2 and 20C. Calculate as
+        1000 W/m^2 and 20C. Denoted as :math:`eta_{m}` in [1]_. Calculate as
         :math:`\eta_{m} = \frac{V_{mp} I_{mp}}{A \times 1000 W/m^2}`
         where A is module area [m^2].
 
@@ -810,6 +818,6 @@ def noct_sam(poa_global, temp_air, wind_speed, noct, eta_m_ref,
     # [1] Eq. 10.37 isn't clear on exactly what "G" is. SAM SSC code uses
     # poa_global where G appears
     cell_temp_init = poa_global / 800. * (noct_adj - 20.)
-    heat_loss = 1 - eta_m_ref / tau_alpha
+    heat_loss = 1 - module_efficiency / tau_alpha
     wind_loss = 9.5 / (5.7 + 3.8 * wind_adj)
     return temp_air + cell_temp_init * heat_loss * wind_loss


Test patch:
diff --git a/pvlib/tests/test_modelchain.py b/pvlib/tests/test_modelchain.py
--- a/pvlib/tests/test_modelchain.py
+++ b/pvlib/tests/test_modelchain.py
@@ -201,7 +201,7 @@ def pvwatts_dc_pvwatts_ac_faiman_temp_system():
 @pytest.fixture(scope="function")
 def pvwatts_dc_pvwatts_ac_pvsyst_temp_system():
     module_parameters = {'pdc0': 220, 'gamma_pdc': -0.003}
-    temp_model_params = {'u_c': 29.0, 'u_v': 0.0, 'eta_m': 0.1,
+    temp_model_params = {'u_c': 29.0, 'u_v': 0.0, 'module_efficiency': 0.1,
                          'alpha_absorption': 0.9}
     inverter_parameters = {'pdc0': 220, 'eta_inv_nom': 0.95}
     system = PVSystem(surface_tilt=32.2, surface_azimuth=180,
@@ -226,7 +226,7 @@ def pvwatts_dc_pvwatts_ac_fuentes_temp_system():
 @pytest.fixture(scope="function")
 def pvwatts_dc_pvwatts_ac_noct_sam_temp_system():
     module_parameters = {'pdc0': 220, 'gamma_pdc': -0.003}
-    temp_model_params = {'noct': 45, 'eta_m_ref': 0.2}
+    temp_model_params = {'noct': 45, 'module_efficiency': 0.2}
     inverter_parameters = {'pdc0': 220, 'eta_inv_nom': 0.95}
     system = PVSystem(surface_tilt=32.2, surface_azimuth=180,
                       module_parameters=module_parameters,
@@ -710,7 +710,7 @@ def test_run_model_with_weather_noct_sam_temp(sapm_dc_snl_ac_system, location,
     weather['wind_speed'] = 5
     weather['temp_air'] = 10
     sapm_dc_snl_ac_system.temperature_model_parameters = {
-        'noct': 45, 'eta_m_ref': 0.2
+        'noct': 45, 'module_efficiency': 0.2
     }
     mc = ModelChain(sapm_dc_snl_ac_system, location)
     mc.temperature_model = 'noct_sam'
@@ -941,7 +941,7 @@ def test__prepare_temperature_arrays_weather(sapm_dc_snl_ac_system_same_arrays,
                            ModelChain.faiman_temp),
                           ({'noct_installed': 45},
                            ModelChain.fuentes_temp),
-                          ({'noct': 45, 'eta_m_ref': 0.2},
+                          ({'noct': 45, 'module_efficiency': 0.2},
                            ModelChain.noct_sam_temp)])
 def test_temperature_models_arrays_multi_weather(
         temp_params, temp_model,
diff --git a/pvlib/tests/test_pvsystem.py b/pvlib/tests/test_pvsystem.py
--- a/pvlib/tests/test_pvsystem.py
+++ b/pvlib/tests/test_pvsystem.py
@@ -392,7 +392,7 @@ def two_array_system(pvsyst_module_params, cec_module_params):
     temperature_model['noct_installed'] = 45
     # parameters for noct_sam temperature model
     temperature_model['noct'] = 45.
-    temperature_model['eta_m_ref'] = 0.2
+    temperature_model['module_efficiency'] = 0.2
     module_params = {**pvsyst_module_params, **cec_module_params}
     return pvsystem.PVSystem(
         arrays=[
@@ -471,8 +471,9 @@ def test_PVSystem_pvsyst_celltemp(mocker):
     temp_model_params = temperature.TEMPERATURE_MODEL_PARAMETERS['pvsyst'][
         parameter_set]
     alpha_absorption = 0.85
-    eta_m = 0.17
-    module_parameters = {'alpha_absorption': alpha_absorption, 'eta_m': eta_m}
+    module_efficiency = 0.17
+    module_parameters = {'alpha_absorption': alpha_absorption,
+                         'module_efficiency': module_efficiency}
     system = pvsystem.PVSystem(module_parameters=module_parameters,
                                temperature_model_parameters=temp_model_params)
     mocker.spy(temperature, 'pvsyst_cell')
@@ -481,8 +482,9 @@ def test_PVSystem_pvsyst_celltemp(mocker):
     wind = 0.5
     out = system.pvsyst_celltemp(irrad, temp, wind_speed=wind)
     temperature.pvsyst_cell.assert_called_once_with(
-        irrad, temp, wind, temp_model_params['u_c'], temp_model_params['u_v'],
-        eta_m, alpha_absorption)
+        irrad, temp, wind_speed=wind, u_c=temp_model_params['u_c'],
+        u_v=temp_model_params['u_v'], module_efficiency=module_efficiency,
+        alpha_absorption=alpha_absorption)
     assert (out < 90) and (out > 70)
 
 
@@ -500,16 +502,16 @@ def test_PVSystem_faiman_celltemp(mocker):
 
 
 def test_PVSystem_noct_celltemp(mocker):
-    poa_global, temp_air, wind_speed, noct, eta_m_ref = (1000., 25., 1., 45.,
-                                                         0.2)
+    poa_global, temp_air, wind_speed, noct, module_efficiency = (
+        1000., 25., 1., 45., 0.2)
     expected = 55.230790492
-    temp_model_params = {'noct': noct, 'eta_m_ref': eta_m_ref}
+    temp_model_params = {'noct': noct, 'module_efficiency': module_efficiency}
     system = pvsystem.PVSystem(temperature_model_parameters=temp_model_params)
     mocker.spy(temperature, 'noct_sam')
     out = system.noct_sam_celltemp(poa_global, temp_air, wind_speed)
     temperature.noct_sam.assert_called_once_with(
         poa_global, temp_air, wind_speed, effective_irradiance=None, noct=noct,
-        eta_m_ref=eta_m_ref)
+        module_efficiency=module_efficiency)
     assert_allclose(out, expected)
     # dufferent types
     out = system.noct_sam_celltemp(np.array(poa_global), np.array(temp_air),
@@ -533,8 +535,8 @@ def test_PVSystem_noct_celltemp(mocker):
 
 
 def test_PVSystem_noct_celltemp_error():
-    poa_global, temp_air, wind_speed, eta_m_ref = (1000., 25., 1., 0.2)
-    temp_model_params = {'eta_m_ref': eta_m_ref}
+    poa_global, temp_air, wind_speed, module_efficiency = (1000., 25., 1., 0.2)
+    temp_model_params = {'module_efficiency': module_efficiency}
     system = pvsystem.PVSystem(temperature_model_parameters=temp_model_params)
     with pytest.raises(KeyError):
         system.noct_sam_celltemp(poa_global, temp_air, wind_speed)
diff --git a/pvlib/tests/test_temperature.py b/pvlib/tests/test_temperature.py
--- a/pvlib/tests/test_temperature.py
+++ b/pvlib/tests/test_temperature.py
@@ -6,6 +6,7 @@
 from numpy.testing import assert_allclose
 
 from pvlib import temperature, tools
+from pvlib._deprecation import pvlibDeprecationWarning
 
 
 @pytest.fixture
@@ -72,7 +73,7 @@ def test_pvsyst_cell_default():
 
 def test_pvsyst_cell_kwargs():
     result = temperature.pvsyst_cell(900, 20, wind_speed=5.0, u_c=23.5,
-                                     u_v=6.25, eta_m=0.1)
+                                     u_v=6.25, module_efficiency=0.1)
     assert_allclose(result, 33.315, 0.001)
 
 
@@ -96,6 +97,13 @@ def test_pvsyst_cell_series():
     assert_series_equal(expected, result)
 
 
+def test_pvsyst_cell_eta_m_deprecated():
+    with pytest.warns(pvlibDeprecationWarning):
+        result = temperature.pvsyst_cell(900, 20, wind_speed=5.0, u_c=23.5,
+                                         u_v=6.25, eta_m=0.1)
+        assert_allclose(result, 33.315, 0.001)
+
+
 def test_faiman_default():
     result = temperature.faiman(900, 20, 5)
     assert_allclose(result, 35.203, 0.001)
@@ -215,16 +223,16 @@ def test_fuentes_timezone(tz):
 
 
 def test_noct_sam():
-    poa_global, temp_air, wind_speed, noct, eta_m_ref = (1000., 25., 1., 45.,
-                                                         0.2)
+    poa_global, temp_air, wind_speed, noct, module_efficiency = (
+        1000., 25., 1., 45., 0.2)
     expected = 55.230790492
     result = temperature.noct_sam(poa_global, temp_air, wind_speed, noct,
-                                  eta_m_ref)
+                                  module_efficiency)
     assert_allclose(result, expected)
     # test with different types
     result = temperature.noct_sam(np.array(poa_global), np.array(temp_air),
                                   np.array(wind_speed), np.array(noct),
-                                  np.array(eta_m_ref))
+                                  np.array(module_efficiency))
     assert_allclose(result, expected)
     dr = pd.date_range(start='2020-01-01 12:00:00', end='2020-01-01 13:00:00',
                        freq='1H')
@@ -232,7 +240,7 @@ def test_noct_sam():
                                   pd.Series(index=dr, data=temp_air),
                                   pd.Series(index=dr, data=wind_speed),
                                   pd.Series(index=dr, data=noct),
-                                  eta_m_ref)
+                                  module_efficiency)
     assert_series_equal(result, pd.Series(index=dr, data=expected))
 
 
@@ -242,7 +250,7 @@ def test_noct_sam_against_sam():
     # NOCT cell temperature model), with the only change being the soiling
     # loss is set to 0. Weather input is TMY3 for Phoenix AZ.
     # Values are taken from the Jan 1 12:00:00 timestamp.
-    poa_total, temp_air, wind_speed, noct, eta_m_ref = (
+    poa_total, temp_air, wind_speed, noct, module_efficiency = (
         860.673, 25, 3, 46.4, 0.20551)
     poa_total_after_refl = 851.458  # from SAM output
     # compute effective irradiance
@@ -259,7 +267,7 @@ def test_noct_sam_against_sam():
     array_height = 1
     mount_standoff = 4.0
     result = temperature.noct_sam(poa_total, temp_air, wind_speed, noct,
-                                  eta_m_ref, effective_irradiance,
+                                  module_efficiency, effective_irradiance,
                                   transmittance_absorptance, array_height,
                                   mount_standoff)
     expected = 43.0655
@@ -268,14 +276,14 @@ def test_noct_sam_against_sam():
 
 
 def test_noct_sam_options():
-    poa_global, temp_air, wind_speed, noct, eta_m_ref = (1000., 25., 1., 45.,
-                                                         0.2)
+    poa_global, temp_air, wind_speed, noct, module_efficiency = (
+        1000., 25., 1., 45., 0.2)
     effective_irradiance = 1100.
     transmittance_absorptance = 0.8
     array_height = 2
     mount_standoff = 2.0
     result = temperature.noct_sam(poa_global, temp_air, wind_speed, noct,
-                                  eta_m_ref, effective_irradiance,
+                                  module_efficiency, effective_irradiance,
                                   transmittance_absorptance, array_height,
                                   mount_standoff)
     expected = 60.477703576