pvlib 0.10.5__py3-none-any.whl → 0.11.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. pvlib/__init__.py +1 -0
  2. pvlib/albedo.py +168 -0
  3. pvlib/data/ASTMG173.csv +2004 -0
  4. pvlib/iam.py +28 -28
  5. pvlib/iotools/__init__.py +0 -1
  6. pvlib/iotools/midc.py +15 -10
  7. pvlib/iotools/psm3.py +10 -25
  8. pvlib/iotools/srml.py +0 -61
  9. pvlib/irradiance.py +133 -95
  10. pvlib/location.py +13 -5
  11. pvlib/modelchain.py +2 -165
  12. pvlib/pvsystem.py +23 -63
  13. pvlib/shading.py +350 -0
  14. pvlib/spectrum/__init__.py +5 -0
  15. pvlib/spectrum/mismatch.py +572 -43
  16. pvlib/spectrum/spectrl2.py +8 -8
  17. pvlib/tests/iotools/test_psm3.py +0 -18
  18. pvlib/tests/iotools/test_srml.py +1 -43
  19. pvlib/tests/test_albedo.py +84 -0
  20. pvlib/tests/test_inverter.py +2 -2
  21. pvlib/tests/test_irradiance.py +35 -2
  22. pvlib/tests/test_location.py +26 -18
  23. pvlib/tests/test_modelchain.py +0 -57
  24. pvlib/tests/test_pvsystem.py +11 -39
  25. pvlib/tests/test_shading.py +167 -1
  26. pvlib/tests/test_singlediode.py +0 -19
  27. pvlib/tests/test_spectrum.py +283 -22
  28. pvlib/tests/test_temperature.py +7 -7
  29. pvlib/tests/test_tools.py +24 -0
  30. pvlib/tests/test_transformer.py +60 -0
  31. pvlib/tools.py +27 -0
  32. pvlib/transformer.py +117 -0
  33. {pvlib-0.10.5.dist-info → pvlib-0.11.0a1.dist-info}/METADATA +1 -1
  34. {pvlib-0.10.5.dist-info → pvlib-0.11.0a1.dist-info}/RECORD +38 -34
  35. {pvlib-0.10.5.dist-info → pvlib-0.11.0a1.dist-info}/WHEEL +1 -1
  36. pvlib/data/astm_g173_am15g.csv +0 -2003
  37. {pvlib-0.10.5.dist-info → pvlib-0.11.0a1.dist-info}/AUTHORS.md +0 -0
  38. {pvlib-0.10.5.dist-info → pvlib-0.11.0a1.dist-info}/LICENSE +0 -0
  39. {pvlib-0.10.5.dist-info → pvlib-0.11.0a1.dist-info}/top_level.txt +0 -0
pvlib/location.py CHANGED
@@ -4,7 +4,7 @@ This module contains the Location class.
4
4
 
5
5
  # Will Holmgren, University of Arizona, 2014-2016.
6
6
 
7
- import os
7
+ import pathlib
8
8
  import datetime
9
9
 
10
10
  import pandas as pd
@@ -14,6 +14,7 @@ import h5py
14
14
  from pvlib import solarposition, clearsky, atmosphere, irradiance
15
15
  from pvlib.tools import _degrees_to_index
16
16
 
17
+
17
18
  class Location:
18
19
  """
19
20
  Location objects are convenient containers for latitude, longitude,
@@ -44,8 +45,11 @@ class Location:
44
45
  pytz.timezone objects will be converted to strings.
45
46
  ints and floats must be in hours from UTC.
46
47
 
47
- altitude : float, default 0.
48
+ altitude : float, optional
48
49
  Altitude from sea level in meters.
50
+ If not specified, the altitude will be fetched from
51
+ :py:func:`pvlib.location.lookup_altitude`.
52
+ If no data is available for the location, the altitude is set to 0.
49
53
 
50
54
  name : string, optional
51
55
  Sets the name attribute of the Location object.
@@ -55,7 +59,8 @@ class Location:
55
59
  pvlib.pvsystem.PVSystem
56
60
  """
57
61
 
58
- def __init__(self, latitude, longitude, tz='UTC', altitude=0, name=None):
62
+ def __init__(self, latitude, longitude, tz='UTC', altitude=None,
63
+ name=None):
59
64
 
60
65
  self.latitude = latitude
61
66
  self.longitude = longitude
@@ -75,6 +80,9 @@ class Location:
75
80
  else:
76
81
  raise TypeError('Invalid tz specification')
77
82
 
83
+ if altitude is None:
84
+ altitude = lookup_altitude(latitude, longitude)
85
+
78
86
  self.altitude = altitude
79
87
 
80
88
  self.name = name
@@ -427,8 +435,8 @@ def lookup_altitude(latitude, longitude):
427
435
 
428
436
  """
429
437
 
430
- pvlib_path = os.path.dirname(os.path.abspath(__file__))
431
- filepath = os.path.join(pvlib_path, 'data', 'Altitude.h5')
438
+ pvlib_path = pathlib.Path(__file__).parent
439
+ filepath = pvlib_path / 'data' / 'Altitude.h5'
432
440
 
433
441
  latitude_index = _degrees_to_index(latitude, coordinate='latitude')
434
442
  longitude_index = _degrees_to_index(longitude, coordinate='longitude')
pvlib/modelchain.py CHANGED
@@ -13,14 +13,11 @@ import pandas as pd
13
13
  from dataclasses import dataclass, field
14
14
  from typing import Union, Tuple, Optional, TypeVar
15
15
 
16
- from pvlib import (atmosphere, clearsky, inverter, pvsystem, solarposition,
17
- temperature, iam)
16
+ from pvlib import pvsystem, iam
18
17
  import pvlib.irradiance # avoid name conflict with full import
19
18
  from pvlib.pvsystem import _DC_MODEL_PARAMS
20
19
  from pvlib.tools import _build_kwargs
21
20
 
22
- from pvlib._deprecation import deprecated
23
-
24
21
  # keys that are used to detect input data and assign data to appropriate
25
22
  # ModelChain attribute
26
23
  # for ModelChain.weather
@@ -41,7 +38,7 @@ DATA_KEYS = WEATHER_KEYS + POA_KEYS + TEMPERATURE_KEYS
41
38
 
42
39
  # these dictionaries contain the default configuration for following
43
40
  # established modeling sequences. They can be used in combination with
44
- # basic_chain and ModelChain. They are used by the ModelChain methods
41
+ # ModelChain, particularly they are used by the methods
45
42
  # ModelChain.with_pvwatts, ModelChain.with_sapm, etc.
46
43
 
47
44
  # pvwatts documentation states that it uses the following reference for
@@ -62,165 +59,6 @@ SAPM_CONFIG = dict(
62
59
  )
63
60
 
64
61
 
65
- @deprecated(
66
- since='0.9.1',
67
- name='pvlib.modelchain.basic_chain',
68
- alternative=('pvlib.modelchain.ModelChain.with_pvwatts'
69
- ' or pvlib.modelchain.ModelChain.with_sapm'),
70
- addendum='Note that the with_xyz methods take different model parameters.'
71
- )
72
- def basic_chain(times, latitude, longitude,
73
- surface_tilt, surface_azimuth,
74
- module_parameters, temperature_model_parameters,
75
- inverter_parameters,
76
- irradiance=None, weather=None,
77
- transposition_model='haydavies',
78
- solar_position_method='nrel_numpy',
79
- airmass_model='kastenyoung1989',
80
- altitude=None, pressure=None,
81
- **kwargs):
82
- """
83
- An experimental function that computes all of the modeling steps
84
- necessary for calculating power or energy for a PV system at a given
85
- location.
86
-
87
- Parameters
88
- ----------
89
- times : DatetimeIndex
90
- Times at which to evaluate the model.
91
-
92
- latitude : float.
93
- Positive is north of the equator.
94
- Use decimal degrees notation.
95
-
96
- longitude : float.
97
- Positive is east of the prime meridian.
98
- Use decimal degrees notation.
99
-
100
- surface_tilt : numeric
101
- Surface tilt angles in decimal degrees.
102
- The tilt angle is defined as degrees from horizontal
103
- (e.g. surface facing up = 0, surface facing horizon = 90)
104
-
105
- surface_azimuth : numeric
106
- Surface azimuth angles in decimal degrees.
107
- The azimuth convention is defined
108
- as degrees east of north
109
- (North=0, South=180, East=90, West=270).
110
-
111
- module_parameters : dict or Series
112
- Module parameters as defined by the SAPM. See pvsystem.sapm for
113
- details.
114
-
115
- temperature_model_parameters : dict or Series
116
- Temperature model parameters as defined by the SAPM.
117
- See temperature.sapm_cell for details.
118
-
119
- inverter_parameters : dict or Series
120
- Inverter parameters as defined by the CEC. See
121
- :py:func:`inverter.sandia` for details.
122
-
123
- irradiance : DataFrame, optional
124
- If not specified, calculates clear sky data.
125
- Columns must be 'dni', 'ghi', 'dhi'.
126
-
127
- weather : DataFrame, optional
128
- If not specified, assumes air temperature is 20 C and
129
- wind speed is 0 m/s.
130
- Columns must be 'wind_speed', 'temp_air'.
131
-
132
- transposition_model : str, default 'haydavies'
133
- Passed to system.get_irradiance.
134
-
135
- solar_position_method : str, default 'nrel_numpy'
136
- Passed to solarposition.get_solarposition.
137
-
138
- airmass_model : str, default 'kastenyoung1989'
139
- Passed to atmosphere.relativeairmass.
140
-
141
- altitude : float, optional
142
- If not specified, computed from ``pressure``. Assumed to be 0 m
143
- if ``pressure`` is also unspecified.
144
-
145
- pressure : float, optional
146
- If not specified, computed from ``altitude``. Assumed to be 101325 Pa
147
- if ``altitude`` is also unspecified.
148
-
149
- **kwargs
150
- Arbitrary keyword arguments.
151
- See code for details.
152
-
153
- Returns
154
- -------
155
- output : (dc, ac)
156
- Tuple of DC power (with SAPM parameters) (DataFrame) and AC
157
- power (Series).
158
- """
159
-
160
- if altitude is None and pressure is None:
161
- altitude = 0.
162
- pressure = 101325.
163
- elif altitude is None:
164
- altitude = atmosphere.pres2alt(pressure)
165
- elif pressure is None:
166
- pressure = atmosphere.alt2pres(altitude)
167
-
168
- solar_position = solarposition.get_solarposition(
169
- times, latitude, longitude, altitude=altitude, pressure=pressure,
170
- method=solar_position_method, **kwargs)
171
-
172
- # possible error with using apparent zenith with some models
173
- airmass = atmosphere.get_relative_airmass(
174
- solar_position['apparent_zenith'], model=airmass_model)
175
- airmass = atmosphere.get_absolute_airmass(airmass, pressure)
176
- dni_extra = pvlib.irradiance.get_extra_radiation(solar_position.index)
177
-
178
- aoi = pvlib.irradiance.aoi(surface_tilt, surface_azimuth,
179
- solar_position['apparent_zenith'],
180
- solar_position['azimuth'])
181
-
182
- if irradiance is None:
183
- linke_turbidity = clearsky.lookup_linke_turbidity(
184
- solar_position.index, latitude, longitude)
185
- irradiance = clearsky.ineichen(
186
- solar_position['apparent_zenith'],
187
- airmass,
188
- linke_turbidity,
189
- altitude=altitude,
190
- dni_extra=dni_extra
191
- )
192
-
193
- total_irrad = pvlib.irradiance.get_total_irradiance(
194
- surface_tilt,
195
- surface_azimuth,
196
- solar_position['apparent_zenith'],
197
- solar_position['azimuth'],
198
- irradiance['dni'],
199
- irradiance['ghi'],
200
- irradiance['dhi'],
201
- model=transposition_model,
202
- dni_extra=dni_extra)
203
-
204
- if weather is None:
205
- weather = {'wind_speed': 0, 'temp_air': 20}
206
-
207
- cell_temperature = temperature.sapm_cell(
208
- total_irrad['poa_global'], weather['temp_air'], weather['wind_speed'],
209
- temperature_model_parameters['a'], temperature_model_parameters['b'],
210
- temperature_model_parameters['deltaT'])
211
-
212
- effective_irradiance = pvsystem.sapm_effective_irradiance(
213
- total_irrad['poa_direct'], total_irrad['poa_diffuse'], airmass, aoi,
214
- module_parameters)
215
-
216
- dc = pvsystem.sapm(effective_irradiance, cell_temperature,
217
- module_parameters)
218
-
219
- ac = inverter.sandia(dc['v_mp'], dc['p_mp'], inverter_parameters)
220
-
221
- return dc, ac
222
-
223
-
224
62
  def get_orientation(strategy, **kwargs):
225
63
  """
226
64
  Determine a PV system's surface tilt and surface azimuth
@@ -238,7 +76,6 @@ def get_orientation(strategy, **kwargs):
238
76
  -------
239
77
  surface_tilt, surface_azimuth
240
78
  """
241
-
242
79
  if strategy == 'south_at_latitude_tilt':
243
80
  surface_azimuth = 180
244
81
  surface_tilt = kwargs['latitude']
pvlib/pvsystem.py CHANGED
@@ -19,6 +19,7 @@ from typing import Optional, Union
19
19
 
20
20
  from pvlib._deprecation import deprecated, warn_deprecated
21
21
 
22
+ import pvlib # used to avoid albedo name collision in the Array class
22
23
  from pvlib import (atmosphere, iam, inverter, irradiance,
23
24
  singlediode as _singlediode, spectrum, temperature)
24
25
  from pvlib.tools import _build_kwargs, _build_args
@@ -131,13 +132,13 @@ class PVSystem:
131
132
 
132
133
  albedo : float, optional
133
134
  Ground surface albedo. If not supplied, then ``surface_type`` is used
134
- to look up a value in ``irradiance.SURFACE_ALBEDOS``.
135
+ to look up a value in :py:const:`pvlib.albedo.SURFACE_ALBEDOS`.
135
136
  If ``surface_type`` is also not supplied then a ground surface albedo
136
137
  of 0.25 is used.
137
138
 
138
139
  surface_type : string, optional
139
- The ground surface type. See ``irradiance.SURFACE_ALBEDOS`` for
140
- valid values.
140
+ The ground surface type. See :py:const:`pvlib.albedo.SURFACE_ALBEDOS`
141
+ for valid values.
141
142
 
142
143
  module : string, optional
143
144
  The model name of the modules.
@@ -721,15 +722,13 @@ class PVSystem:
721
722
  )
722
723
 
723
724
  def singlediode(self, photocurrent, saturation_current,
724
- resistance_series, resistance_shunt, nNsVth,
725
- ivcurve_pnts=None):
725
+ resistance_series, resistance_shunt, nNsVth):
726
726
  """Wrapper around the :py:func:`pvlib.pvsystem.singlediode` function.
727
727
 
728
728
  See :py:func:`pvsystem.singlediode` for details
729
729
  """
730
730
  return singlediode(photocurrent, saturation_current,
731
- resistance_series, resistance_shunt, nNsVth,
732
- ivcurve_pnts=ivcurve_pnts)
731
+ resistance_series, resistance_shunt, nNsVth)
733
732
 
734
733
  def i_from_v(self, voltage, photocurrent, saturation_current,
735
734
  resistance_series, resistance_shunt, nNsVth):
@@ -907,13 +906,13 @@ class Array:
907
906
 
908
907
  albedo : float, optional
909
908
  Ground surface albedo. If not supplied, then ``surface_type`` is used
910
- to look up a value in ``irradiance.SURFACE_ALBEDOS``.
909
+ to look up a value in :py:const:`pvlib.albedo.SURFACE_ALBEDOS`.
911
910
  If ``surface_type`` is also not supplied then a ground surface albedo
912
911
  of 0.25 is used.
913
912
 
914
913
  surface_type : string, optional
915
- The ground surface type. See ``irradiance.SURFACE_ALBEDOS`` for valid
916
- values.
914
+ The ground surface type. See :py:const:`pvlib.albedo.SURFACE_ALBEDOS`
915
+ for valid values.
917
916
 
918
917
  module : string, optional
919
918
  The model name of the modules.
@@ -956,7 +955,7 @@ class Array:
956
955
 
957
956
  self.surface_type = surface_type
958
957
  if albedo is None:
959
- self.albedo = irradiance.SURFACE_ALBEDOS.get(surface_type, 0.25)
958
+ self.albedo = pvlib.albedo.SURFACE_ALBEDOS.get(surface_type, 0.25)
960
959
  else:
961
960
  self.albedo = albedo
962
961
 
@@ -2318,9 +2317,10 @@ def sapm_effective_irradiance(poa_direct, poa_diffuse, airmass_absolute, aoi,
2318
2317
  a module's cells.
2319
2318
 
2320
2319
  The model is
2320
+
2321
2321
  .. math::
2322
2322
 
2323
- `Ee = f_1(AM_a) (E_b f_2(AOI) + f_d E_d)`
2323
+ Ee = f_1(AM_a) (E_b f_2(AOI) + f_d E_d)
2324
2324
 
2325
2325
  where :math:`Ee` is effective irradiance (W/m2), :math:`f_1` is a fourth
2326
2326
  degree polynomial in air mass :math:`AM_a`, :math:`E_b` is beam (direct)
@@ -2350,8 +2350,7 @@ def sapm_effective_irradiance(poa_direct, poa_diffuse, airmass_absolute, aoi,
2350
2350
 
2351
2351
 
2352
2352
  def singlediode(photocurrent, saturation_current, resistance_series,
2353
- resistance_shunt, nNsVth, ivcurve_pnts=None,
2354
- method='lambertw'):
2353
+ resistance_shunt, nNsVth, method='lambertw'):
2355
2354
  r"""
2356
2355
  Solve the single diode equation to obtain a photovoltaic IV curve.
2357
2356
 
@@ -2403,14 +2402,6 @@ def singlediode(photocurrent, saturation_current, resistance_series,
2403
2402
  junction in Kelvin, and :math:`q` is the charge of an electron
2404
2403
  (coulombs). ``0 < nNsVth``. [V]
2405
2404
 
2406
- ivcurve_pnts : int, optional
2407
- Number of points in the desired IV curve. If not specified or 0, no
2408
- points on the IV curves will be produced.
2409
-
2410
- .. deprecated:: 0.10.0
2411
- Use :py:func:`pvlib.pvsystem.v_from_i` and
2412
- :py:func:`pvlib.pvsystem.i_from_v` instead.
2413
-
2414
2405
  method : str, default 'lambertw'
2415
2406
  Determines the method used to calculate points on the IV curve. The
2416
2407
  options are ``'lambertw'``, ``'newton'``, or ``'brentq'``.
@@ -2420,20 +2411,15 @@ def singlediode(photocurrent, saturation_current, resistance_series,
2420
2411
  dict or pandas.DataFrame
2421
2412
  The returned dict-like object always contains the keys/columns:
2422
2413
 
2423
- * i_sc - short circuit current in amperes.
2424
- * v_oc - open circuit voltage in volts.
2425
- * i_mp - current at maximum power point in amperes.
2426
- * v_mp - voltage at maximum power point in volts.
2427
- * p_mp - power at maximum power point in watts.
2428
- * i_x - current, in amperes, at ``v = 0.5*v_oc``.
2429
- * i_xx - current, in amperes, at ``v = 0.5*(v_oc+v_mp)``.
2414
+ * i_sc - short circuit current in amperes.
2415
+ * v_oc - open circuit voltage in volts.
2416
+ * i_mp - current at maximum power point in amperes.
2417
+ * v_mp - voltage at maximum power point in volts.
2418
+ * p_mp - power at maximum power point in watts.
2419
+ * i_x - current, in amperes, at ``v = 0.5*v_oc``.
2420
+ * i_xx - current, in amperes, at ``v = 0.5*(v_oc+v_mp)``.
2430
2421
 
2431
- A dict is returned when the input parameters are scalars or
2432
- ``ivcurve_pnts > 0``. If ``ivcurve_pnts > 0``, the output dictionary
2433
- will also include the keys:
2434
-
2435
- * i - IV curve current in amperes.
2436
- * v - IV curve voltage in volts.
2422
+ A dict is returned when the input parameters are scalars.
2437
2423
 
2438
2424
  See also
2439
2425
  --------
@@ -2457,13 +2443,6 @@ def singlediode(photocurrent, saturation_current, resistance_series,
2457
2443
  that guarantees convergence by bounding the voltage between zero and
2458
2444
  open-circuit.
2459
2445
 
2460
- If the method is either ``'newton'`` or ``'brentq'`` and ``ivcurve_pnts``
2461
- are indicated, then :func:`pvlib.singlediode.bishop88` [4]_ is used to
2462
- calculate the points on the IV curve points at diode voltages from zero to
2463
- open-circuit voltage with a log spacing that gets closer as voltage
2464
- increases. If the method is ``'lambertw'`` then the calculated points on
2465
- the IV curve are linearly spaced.
2466
-
2467
2446
  References
2468
2447
  ----------
2469
2448
  .. [1] S.R. Wenham, M.A. Green, M.E. Watt, "Applied Photovoltaics" ISBN
@@ -2480,21 +2459,13 @@ def singlediode(photocurrent, saturation_current, resistance_series,
2480
2459
  photovoltaic cell interconnection circuits" JW Bishop, Solar Cell (1988)
2481
2460
  https://doi.org/10.1016/0379-6787(88)90059-2
2482
2461
  """
2483
- if ivcurve_pnts:
2484
- warn_deprecated('0.10.0', name='pvlib.pvsystem.singlediode',
2485
- alternative=('pvlib.pvsystem.v_from_i and '
2486
- 'pvlib.pvsystem.i_from_v'),
2487
- obj_type='parameter ivcurve_pnts',
2488
- removal='0.11.0')
2489
2462
  args = (photocurrent, saturation_current, resistance_series,
2490
2463
  resistance_shunt, nNsVth) # collect args
2491
2464
  # Calculate points on the IV curve using the LambertW solution to the
2492
2465
  # single diode equation
2493
2466
  if method.lower() == 'lambertw':
2494
- out = _singlediode._lambertw(*args, ivcurve_pnts)
2467
+ out = _singlediode._lambertw(*args)
2495
2468
  points = out[:7]
2496
- if ivcurve_pnts:
2497
- ivcurve_i, ivcurve_v = out[7:]
2498
2469
  else:
2499
2470
  # Calculate points on the IV curve using either 'newton' or 'brentq'
2500
2471
  # methods. Voltages are determined by first solving the single diode
@@ -2516,21 +2487,10 @@ def singlediode(photocurrent, saturation_current, resistance_series,
2516
2487
  )
2517
2488
  points = i_sc, v_oc, i_mp, v_mp, p_mp, i_x, i_xx
2518
2489
 
2519
- # calculate the IV curve if requested using bishop88
2520
- if ivcurve_pnts:
2521
- vd = v_oc * (
2522
- (11.0 - np.logspace(np.log10(11.0), 0.0, ivcurve_pnts)) / 10.0
2523
- )
2524
- ivcurve_i, ivcurve_v, _ = _singlediode.bishop88(vd, *args)
2525
-
2526
2490
  columns = ('i_sc', 'v_oc', 'i_mp', 'v_mp', 'p_mp', 'i_x', 'i_xx')
2527
2491
 
2528
- if all(map(np.isscalar, args)) or ivcurve_pnts:
2492
+ if all(map(np.isscalar, args)):
2529
2493
  out = {c: p for c, p in zip(columns, points)}
2530
-
2531
- if ivcurve_pnts:
2532
- out.update(i=ivcurve_i, v=ivcurve_v)
2533
-
2534
2494
  return out
2535
2495
 
2536
2496
  points = np.atleast_1d(*points) # convert scalars to 1d-arrays