pvlib 0.9.4a1__py3-none-any.whl → 0.10.0__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.
- pvlib/__init__.py +3 -2
- pvlib/atmosphere.py +23 -173
- pvlib/bifacial/infinite_sheds.py +88 -277
- pvlib/bifacial/utils.py +270 -28
- pvlib/data/adr-library-cec-inverters-2019-03-05.csv +5009 -0
- pvlib/data/precise_iv_curves1.json +10251 -0
- pvlib/data/precise_iv_curves2.json +10251 -0
- pvlib/data/precise_iv_curves_parameter_sets1.csv +33 -0
- pvlib/data/precise_iv_curves_parameter_sets2.csv +33 -0
- pvlib/data/test_psm3_2017.csv +17521 -17521
- pvlib/data/test_psm3_2019_5min.csv +288 -288
- pvlib/data/test_read_psm3.csv +17522 -17522
- pvlib/data/test_read_pvgis_horizon.csv +49 -0
- pvlib/data/variables_style_rules.csv +3 -0
- pvlib/iam.py +207 -51
- pvlib/inverter.py +6 -1
- pvlib/iotools/__init__.py +7 -2
- pvlib/iotools/acis.py +516 -0
- pvlib/iotools/midc.py +4 -4
- pvlib/iotools/psm3.py +59 -42
- pvlib/iotools/pvgis.py +84 -28
- pvlib/iotools/sodapro.py +8 -6
- pvlib/iotools/srml.py +121 -18
- pvlib/iotools/surfrad.py +2 -2
- pvlib/iotools/tmy.py +146 -102
- pvlib/irradiance.py +270 -15
- pvlib/ivtools/sde.py +14 -20
- pvlib/ivtools/sdm.py +31 -20
- pvlib/ivtools/utils.py +127 -6
- pvlib/location.py +3 -2
- pvlib/modelchain.py +67 -70
- pvlib/pvarray.py +225 -0
- pvlib/pvsystem.py +169 -539
- pvlib/shading.py +43 -2
- pvlib/singlediode.py +216 -66
- pvlib/snow.py +36 -15
- pvlib/soiling.py +3 -3
- pvlib/spa.py +327 -368
- pvlib/spectrum/__init__.py +8 -2
- pvlib/spectrum/mismatch.py +335 -0
- pvlib/temperature.py +124 -13
- pvlib/tests/bifacial/test_infinite_sheds.py +44 -106
- pvlib/tests/bifacial/test_utils.py +102 -5
- pvlib/tests/conftest.py +0 -31
- pvlib/tests/iotools/test_acis.py +213 -0
- pvlib/tests/iotools/test_midc.py +6 -6
- pvlib/tests/iotools/test_psm3.py +7 -5
- pvlib/tests/iotools/test_pvgis.py +21 -14
- pvlib/tests/iotools/test_sodapro.py +1 -1
- pvlib/tests/iotools/test_srml.py +71 -6
- pvlib/tests/iotools/test_tmy.py +43 -8
- pvlib/tests/ivtools/test_sde.py +19 -17
- pvlib/tests/ivtools/test_sdm.py +9 -4
- pvlib/tests/ivtools/test_utils.py +96 -1
- pvlib/tests/test_atmosphere.py +8 -64
- pvlib/tests/test_clearsky.py +0 -1
- pvlib/tests/test_iam.py +74 -1
- pvlib/tests/test_irradiance.py +56 -2
- pvlib/tests/test_location.py +1 -1
- pvlib/tests/test_modelchain.py +33 -76
- pvlib/tests/test_pvarray.py +46 -0
- pvlib/tests/test_pvsystem.py +366 -201
- pvlib/tests/test_shading.py +35 -0
- pvlib/tests/test_singlediode.py +306 -29
- pvlib/tests/test_snow.py +84 -1
- pvlib/tests/test_soiling.py +8 -7
- pvlib/tests/test_solarposition.py +7 -7
- pvlib/tests/test_spa.py +6 -7
- pvlib/tests/test_spectrum.py +145 -1
- pvlib/tests/test_temperature.py +29 -11
- pvlib/tests/test_tools.py +41 -0
- pvlib/tests/test_tracking.py +0 -149
- pvlib/tools.py +49 -25
- pvlib/tracking.py +1 -269
- pvlib-0.10.0.dist-info/AUTHORS.md +35 -0
- {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/LICENSE +5 -2
- {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/METADATA +3 -13
- {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/RECORD +80 -75
- {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/WHEEL +1 -1
- pvlib/data/adr-library-2013-10-01.csv +0 -1762
- pvlib/forecast.py +0 -1211
- pvlib/iotools/ecmwf_macc.py +0 -312
- pvlib/tests/iotools/test_ecmwf_macc.py +0 -162
- pvlib/tests/test_forecast.py +0 -228
- pvlib-0.9.4a1.dist-info/AUTHORS.md +0 -32
- {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/top_level.txt +0 -0
pvlib/pvsystem.py
CHANGED
|
@@ -10,16 +10,18 @@ import itertools
|
|
|
10
10
|
import os
|
|
11
11
|
from urllib.request import urlopen
|
|
12
12
|
import numpy as np
|
|
13
|
+
from scipy import constants
|
|
13
14
|
import pandas as pd
|
|
14
15
|
from dataclasses import dataclass
|
|
15
16
|
from abc import ABC, abstractmethod
|
|
16
17
|
from typing import Optional
|
|
17
18
|
|
|
18
|
-
from pvlib._deprecation import deprecated
|
|
19
|
+
from pvlib._deprecation import deprecated, warn_deprecated
|
|
19
20
|
|
|
20
21
|
from pvlib import (atmosphere, iam, inverter, irradiance,
|
|
21
|
-
singlediode as _singlediode, temperature)
|
|
22
|
+
singlediode as _singlediode, spectrum, temperature)
|
|
22
23
|
from pvlib.tools import _build_kwargs, _build_args
|
|
24
|
+
import pvlib.tools as tools
|
|
23
25
|
|
|
24
26
|
|
|
25
27
|
# a dict of required parameter names for each DC power model
|
|
@@ -67,37 +69,6 @@ def _unwrap_single_value(func):
|
|
|
67
69
|
return f
|
|
68
70
|
|
|
69
71
|
|
|
70
|
-
def _check_deprecated_passthrough(func):
|
|
71
|
-
"""
|
|
72
|
-
Decorator to warn or error when getting and setting the "pass-through"
|
|
73
|
-
PVSystem properties that have been moved to Array. Emits a warning for
|
|
74
|
-
PVSystems with only one Array and raises an error for PVSystems with
|
|
75
|
-
more than one Array.
|
|
76
|
-
"""
|
|
77
|
-
|
|
78
|
-
@functools.wraps(func)
|
|
79
|
-
def wrapper(self, *args, **kwargs):
|
|
80
|
-
pvsystem_attr = func.__name__
|
|
81
|
-
class_name = self.__class__.__name__ # PVSystem or SingleAxisTracker
|
|
82
|
-
overrides = { # some Array attrs aren't the same as PVSystem
|
|
83
|
-
'strings_per_inverter': 'strings',
|
|
84
|
-
}
|
|
85
|
-
array_attr = overrides.get(pvsystem_attr, pvsystem_attr)
|
|
86
|
-
alternative = f'{class_name}.arrays[i].{array_attr}'
|
|
87
|
-
|
|
88
|
-
if len(self.arrays) > 1:
|
|
89
|
-
raise AttributeError(
|
|
90
|
-
f'{class_name}.{pvsystem_attr} not supported for multi-array '
|
|
91
|
-
f'systems. Set {array_attr} for each Array in '
|
|
92
|
-
f'{class_name}.arrays instead.')
|
|
93
|
-
|
|
94
|
-
wrapped = deprecated('0.9', alternative=alternative, removal='0.10',
|
|
95
|
-
name=f"{class_name}.{pvsystem_attr}")(func)
|
|
96
|
-
return wrapped(self, *args, **kwargs)
|
|
97
|
-
|
|
98
|
-
return wrapper
|
|
99
|
-
|
|
100
|
-
|
|
101
72
|
# not sure if this belongs in the pvsystem module.
|
|
102
73
|
# maybe something more like core.py? It may eventually grow to
|
|
103
74
|
# import a lot more functionality from other modules.
|
|
@@ -217,7 +188,6 @@ class PVSystem:
|
|
|
217
188
|
See also
|
|
218
189
|
--------
|
|
219
190
|
pvlib.location.Location
|
|
220
|
-
pvlib.tracking.SingleAxisTracker
|
|
221
191
|
"""
|
|
222
192
|
|
|
223
193
|
def __init__(self,
|
|
@@ -635,44 +605,11 @@ class PVSystem:
|
|
|
635
605
|
in zip(self.arrays, effective_irradiance, temp_cell)
|
|
636
606
|
)
|
|
637
607
|
|
|
638
|
-
@deprecated('0.9', alternative='PVSystem.get_cell_temperature',
|
|
639
|
-
removal='0.10.0')
|
|
640
|
-
def sapm_celltemp(self, poa_global, temp_air, wind_speed):
|
|
641
|
-
"""Uses :py:func:`pvlib.temperature.sapm_cell` to calculate cell
|
|
642
|
-
temperatures.
|
|
643
|
-
|
|
644
|
-
Parameters
|
|
645
|
-
----------
|
|
646
|
-
poa_global : numeric or tuple of numeric
|
|
647
|
-
Total incident irradiance in W/m^2.
|
|
648
|
-
|
|
649
|
-
temp_air : numeric or tuple of numeric
|
|
650
|
-
Ambient dry bulb temperature in degrees C.
|
|
651
|
-
|
|
652
|
-
wind_speed : numeric or tuple of numeric
|
|
653
|
-
Wind speed in m/s at a height of 10 meters.
|
|
654
|
-
|
|
655
|
-
Returns
|
|
656
|
-
-------
|
|
657
|
-
numeric or tuple of numeric
|
|
658
|
-
values in degrees C.
|
|
659
|
-
|
|
660
|
-
Notes
|
|
661
|
-
-----
|
|
662
|
-
The `temp_air` and `wind_speed` parameters may be passed as tuples
|
|
663
|
-
to provide different values for each Array in the system. If not
|
|
664
|
-
passed as a tuple then the same value is used for input to each Array.
|
|
665
|
-
If passed as a tuple the length must be the same as the number of
|
|
666
|
-
Arrays.
|
|
667
|
-
"""
|
|
668
|
-
return self.get_cell_temperature(poa_global, temp_air, wind_speed,
|
|
669
|
-
model='sapm')
|
|
670
|
-
|
|
671
608
|
@_unwrap_single_value
|
|
672
609
|
def sapm_spectral_loss(self, airmass_absolute):
|
|
673
610
|
"""
|
|
674
|
-
Use the :py:func:`
|
|
675
|
-
parameters, and ``self.module_parameters`` to calculate F1.
|
|
611
|
+
Use the :py:func:`pvlib.spectrum.spectral_factor_sapm` function,
|
|
612
|
+
the input parameters, and ``self.module_parameters`` to calculate F1.
|
|
676
613
|
|
|
677
614
|
Parameters
|
|
678
615
|
----------
|
|
@@ -685,7 +622,8 @@ class PVSystem:
|
|
|
685
622
|
The SAPM spectral loss coefficient.
|
|
686
623
|
"""
|
|
687
624
|
return tuple(
|
|
688
|
-
|
|
625
|
+
spectrum.spectral_factor_sapm(airmass_absolute,
|
|
626
|
+
array.module_parameters)
|
|
689
627
|
for array in self.arrays
|
|
690
628
|
)
|
|
691
629
|
|
|
@@ -728,162 +666,10 @@ class PVSystem:
|
|
|
728
666
|
in zip(self.arrays, poa_direct, poa_diffuse, aoi)
|
|
729
667
|
)
|
|
730
668
|
|
|
731
|
-
@deprecated('0.9', alternative='PVSystem.get_cell_temperature',
|
|
732
|
-
removal='0.10.0')
|
|
733
|
-
def pvsyst_celltemp(self, poa_global, temp_air, wind_speed=1.0):
|
|
734
|
-
"""Uses :py:func:`pvlib.temperature.pvsyst_cell` to calculate cell
|
|
735
|
-
temperature.
|
|
736
|
-
|
|
737
|
-
Parameters
|
|
738
|
-
----------
|
|
739
|
-
poa_global : numeric or tuple of numeric
|
|
740
|
-
Total incident irradiance in W/m^2.
|
|
741
|
-
|
|
742
|
-
temp_air : numeric or tuple of numeric
|
|
743
|
-
Ambient dry bulb temperature in degrees C.
|
|
744
|
-
|
|
745
|
-
wind_speed : numeric or tuple of numeric, default 1.0
|
|
746
|
-
Wind speed in m/s measured at the same height for which the wind
|
|
747
|
-
loss factor was determined. The default value is 1.0, which is
|
|
748
|
-
the wind speed at module height used to determine NOCT.
|
|
749
|
-
|
|
750
|
-
Returns
|
|
751
|
-
-------
|
|
752
|
-
numeric or tuple of numeric
|
|
753
|
-
values in degrees C.
|
|
754
|
-
|
|
755
|
-
Notes
|
|
756
|
-
-----
|
|
757
|
-
The `temp_air` and `wind_speed` parameters may be passed as tuples
|
|
758
|
-
to provide different values for each Array in the system. If not
|
|
759
|
-
passed as a tuple then the same value is used for input to each Array.
|
|
760
|
-
If passed as a tuple the length must be the same as the number of
|
|
761
|
-
Arrays.
|
|
762
|
-
"""
|
|
763
|
-
return self.get_cell_temperature(poa_global, temp_air, wind_speed,
|
|
764
|
-
model='pvsyst')
|
|
765
|
-
|
|
766
|
-
@deprecated('0.9', alternative='PVSystem.get_cell_temperature',
|
|
767
|
-
removal='0.10.0')
|
|
768
|
-
def faiman_celltemp(self, poa_global, temp_air, wind_speed=1.0):
|
|
769
|
-
"""
|
|
770
|
-
Use :py:func:`pvlib.temperature.faiman` to calculate cell temperature.
|
|
771
|
-
|
|
772
|
-
Parameters
|
|
773
|
-
----------
|
|
774
|
-
poa_global : numeric or tuple of numeric
|
|
775
|
-
Total incident irradiance [W/m^2].
|
|
776
|
-
|
|
777
|
-
temp_air : numeric or tuple of numeric
|
|
778
|
-
Ambient dry bulb temperature [C].
|
|
779
|
-
|
|
780
|
-
wind_speed : numeric or tuple of numeric, default 1.0
|
|
781
|
-
Wind speed in m/s measured at the same height for which the wind
|
|
782
|
-
loss factor was determined. The default value 1.0 m/s is the wind
|
|
783
|
-
speed at module height used to determine NOCT. [m/s]
|
|
784
|
-
|
|
785
|
-
Returns
|
|
786
|
-
-------
|
|
787
|
-
numeric or tuple of numeric
|
|
788
|
-
values in degrees C.
|
|
789
|
-
|
|
790
|
-
Notes
|
|
791
|
-
-----
|
|
792
|
-
The `temp_air` and `wind_speed` parameters may be passed as tuples
|
|
793
|
-
to provide different values for each Array in the system. If not
|
|
794
|
-
passed as a tuple then the same value is used for input to each Array.
|
|
795
|
-
If passed as a tuple the length must be the same as the number of
|
|
796
|
-
Arrays.
|
|
797
|
-
"""
|
|
798
|
-
return self.get_cell_temperature(poa_global, temp_air, wind_speed,
|
|
799
|
-
model='faiman')
|
|
800
|
-
|
|
801
|
-
@deprecated('0.9', alternative='PVSystem.get_cell_temperature',
|
|
802
|
-
removal='0.10.0')
|
|
803
|
-
def fuentes_celltemp(self, poa_global, temp_air, wind_speed):
|
|
804
|
-
"""
|
|
805
|
-
Use :py:func:`pvlib.temperature.fuentes` to calculate cell temperature.
|
|
806
|
-
|
|
807
|
-
Parameters
|
|
808
|
-
----------
|
|
809
|
-
poa_global : pandas Series or tuple of Series
|
|
810
|
-
Total incident irradiance [W/m^2]
|
|
811
|
-
|
|
812
|
-
temp_air : pandas Series or tuple of Series
|
|
813
|
-
Ambient dry bulb temperature [C]
|
|
814
|
-
|
|
815
|
-
wind_speed : pandas Series or tuple of Series
|
|
816
|
-
Wind speed [m/s]
|
|
817
|
-
|
|
818
|
-
Returns
|
|
819
|
-
-------
|
|
820
|
-
temperature_cell : Series or tuple of Series
|
|
821
|
-
The modeled cell temperature [C]
|
|
822
|
-
|
|
823
|
-
Notes
|
|
824
|
-
-----
|
|
825
|
-
The Fuentes thermal model uses the module surface tilt for convection
|
|
826
|
-
modeling. The SAM implementation of PVWatts hardcodes the surface tilt
|
|
827
|
-
value at 30 degrees, ignoring whatever value is used for irradiance
|
|
828
|
-
transposition. If you want to match the PVWatts behavior you can
|
|
829
|
-
either leave ``surface_tilt`` unspecified to use the PVWatts default
|
|
830
|
-
of 30, or specify a ``surface_tilt`` value in the Array's
|
|
831
|
-
``temperature_model_parameters``.
|
|
832
|
-
|
|
833
|
-
The `temp_air`, `wind_speed`, and `surface_tilt` parameters may be
|
|
834
|
-
passed as tuples
|
|
835
|
-
to provide different values for each Array in the system. If not
|
|
836
|
-
passed as a tuple then the same value is used for input to each Array.
|
|
837
|
-
If passed as a tuple the length must be the same as the number of
|
|
838
|
-
Arrays.
|
|
839
|
-
"""
|
|
840
|
-
return self.get_cell_temperature(poa_global, temp_air, wind_speed,
|
|
841
|
-
model='fuentes')
|
|
842
|
-
|
|
843
|
-
@deprecated('0.9', alternative='PVSystem.get_cell_temperature',
|
|
844
|
-
removal='0.10.0')
|
|
845
|
-
def noct_sam_celltemp(self, poa_global, temp_air, wind_speed,
|
|
846
|
-
effective_irradiance=None):
|
|
847
|
-
"""
|
|
848
|
-
Use :py:func:`pvlib.temperature.noct_sam` to calculate cell
|
|
849
|
-
temperature.
|
|
850
|
-
|
|
851
|
-
Parameters
|
|
852
|
-
----------
|
|
853
|
-
poa_global : numeric or tuple of numeric
|
|
854
|
-
Total incident irradiance in W/m^2.
|
|
855
|
-
|
|
856
|
-
temp_air : numeric or tuple of numeric
|
|
857
|
-
Ambient dry bulb temperature in degrees C.
|
|
858
|
-
|
|
859
|
-
wind_speed : numeric or tuple of numeric
|
|
860
|
-
Wind speed in m/s at a height of 10 meters.
|
|
861
|
-
|
|
862
|
-
effective_irradiance : numeric, tuple of numeric, or None.
|
|
863
|
-
The irradiance that is converted to photocurrent. If None,
|
|
864
|
-
assumed equal to ``poa_global``. [W/m^2]
|
|
865
|
-
|
|
866
|
-
Returns
|
|
867
|
-
-------
|
|
868
|
-
temperature_cell : numeric or tuple of numeric
|
|
869
|
-
The modeled cell temperature [C]
|
|
870
|
-
|
|
871
|
-
Notes
|
|
872
|
-
-----
|
|
873
|
-
The `temp_air` and `wind_speed` parameters may be passed as tuples
|
|
874
|
-
to provide different values for each Array in the system. If not
|
|
875
|
-
passed as a tuple then the same value is used for input to each Array.
|
|
876
|
-
If passed as a tuple the length must be the same as the number of
|
|
877
|
-
Arrays.
|
|
878
|
-
"""
|
|
879
|
-
return self.get_cell_temperature(
|
|
880
|
-
poa_global, temp_air, wind_speed, model='noct_sam',
|
|
881
|
-
effective_irradiance=effective_irradiance)
|
|
882
|
-
|
|
883
669
|
@_unwrap_single_value
|
|
884
670
|
def first_solar_spectral_loss(self, pw, airmass_absolute):
|
|
885
671
|
"""
|
|
886
|
-
Use :py:func:`pvlib.
|
|
672
|
+
Use :py:func:`pvlib.spectrum.spectral_factor_firstsolar` to
|
|
887
673
|
calculate the spectral loss modifier. The model coefficients are
|
|
888
674
|
specific to the module's cell type, and are determined by searching
|
|
889
675
|
for one of the following keys in self.module_parameters (in order):
|
|
@@ -924,9 +710,8 @@ class PVSystem:
|
|
|
924
710
|
module_type = array._infer_cell_type()
|
|
925
711
|
coefficients = None
|
|
926
712
|
|
|
927
|
-
return
|
|
928
|
-
pw, airmass_absolute,
|
|
929
|
-
module_type, coefficients
|
|
713
|
+
return spectrum.spectral_factor_firstsolar(
|
|
714
|
+
pw, airmass_absolute, module_type, coefficients
|
|
930
715
|
)
|
|
931
716
|
return tuple(
|
|
932
717
|
itertools.starmap(_spectral_correction, zip(self.arrays, pw))
|
|
@@ -943,14 +728,17 @@ class PVSystem:
|
|
|
943
728
|
resistance_series, resistance_shunt, nNsVth,
|
|
944
729
|
ivcurve_pnts=ivcurve_pnts)
|
|
945
730
|
|
|
946
|
-
def i_from_v(self,
|
|
947
|
-
|
|
731
|
+
def i_from_v(self, voltage, photocurrent, saturation_current,
|
|
732
|
+
resistance_series, resistance_shunt, nNsVth):
|
|
948
733
|
"""Wrapper around the :py:func:`pvlib.pvsystem.i_from_v` function.
|
|
949
734
|
|
|
950
|
-
See :py:func:`pvsystem.i_from_v` for details
|
|
735
|
+
See :py:func:`pvlib.pvsystem.i_from_v` for details.
|
|
736
|
+
|
|
737
|
+
.. versionchanged:: 0.10.0
|
|
738
|
+
The function's arguments have been reordered.
|
|
951
739
|
"""
|
|
952
|
-
return i_from_v(
|
|
953
|
-
|
|
740
|
+
return i_from_v(voltage, photocurrent, saturation_current,
|
|
741
|
+
resistance_series, resistance_shunt, nNsVth)
|
|
954
742
|
|
|
955
743
|
def get_ac(self, model, p_dc, v_dc=None):
|
|
956
744
|
r"""Calculates AC power from p_dc using the inverter model indicated
|
|
@@ -1023,24 +811,6 @@ class PVSystem:
|
|
|
1023
811
|
model + ' is not a valid AC power model.',
|
|
1024
812
|
' model must be one of "sandia", "adr" or "pvwatts"')
|
|
1025
813
|
|
|
1026
|
-
@deprecated('0.9', alternative='PVSystem.get_ac', removal='0.10')
|
|
1027
|
-
def snlinverter(self, v_dc, p_dc):
|
|
1028
|
-
"""Uses :py:func:`pvlib.inverter.sandia` to calculate AC power based on
|
|
1029
|
-
``self.inverter_parameters`` and the input voltage and power.
|
|
1030
|
-
|
|
1031
|
-
See :py:func:`pvlib.inverter.sandia` for details
|
|
1032
|
-
"""
|
|
1033
|
-
return inverter.sandia(v_dc, p_dc, self.inverter_parameters)
|
|
1034
|
-
|
|
1035
|
-
@deprecated('0.9', alternative='PVSystem.get_ac', removal='0.10')
|
|
1036
|
-
def adrinverter(self, v_dc, p_dc):
|
|
1037
|
-
"""Uses :py:func:`pvlib.inverter.adr` to calculate AC power based on
|
|
1038
|
-
``self.inverter_parameters`` and the input voltage and power.
|
|
1039
|
-
|
|
1040
|
-
See :py:func:`pvlib.inverter.adr` for details
|
|
1041
|
-
"""
|
|
1042
|
-
return inverter.adr(v_dc, p_dc, self.inverter_parameters)
|
|
1043
|
-
|
|
1044
814
|
@_unwrap_single_value
|
|
1045
815
|
def scale_voltage_current_power(self, data):
|
|
1046
816
|
"""
|
|
@@ -1100,21 +870,6 @@ class PVSystem:
|
|
|
1100
870
|
self.losses_parameters)
|
|
1101
871
|
return pvwatts_losses(**kwargs)
|
|
1102
872
|
|
|
1103
|
-
@deprecated('0.9', alternative='PVSystem.get_ac', removal='0.10')
|
|
1104
|
-
def pvwatts_ac(self, pdc):
|
|
1105
|
-
"""
|
|
1106
|
-
Calculates AC power according to the PVWatts model using
|
|
1107
|
-
:py:func:`pvlib.inverter.pvwatts`, `self.module_parameters["pdc0"]`,
|
|
1108
|
-
and `eta_inv_nom=self.inverter_parameters["eta_inv_nom"]`.
|
|
1109
|
-
|
|
1110
|
-
See :py:func:`pvlib.inverter.pvwatts` for details.
|
|
1111
|
-
"""
|
|
1112
|
-
kwargs = _build_kwargs(['eta_inv_nom', 'eta_inv_ref'],
|
|
1113
|
-
self.inverter_parameters)
|
|
1114
|
-
|
|
1115
|
-
return inverter.pvwatts(pdc, self.inverter_parameters['pdc0'],
|
|
1116
|
-
**kwargs)
|
|
1117
|
-
|
|
1118
873
|
@_unwrap_single_value
|
|
1119
874
|
def dc_ohms_from_percent(self):
|
|
1120
875
|
"""
|
|
@@ -1126,127 +881,6 @@ class PVSystem:
|
|
|
1126
881
|
|
|
1127
882
|
return tuple(array.dc_ohms_from_percent() for array in self.arrays)
|
|
1128
883
|
|
|
1129
|
-
@property
|
|
1130
|
-
@_unwrap_single_value
|
|
1131
|
-
@_check_deprecated_passthrough
|
|
1132
|
-
def module_parameters(self):
|
|
1133
|
-
return tuple(array.module_parameters for array in self.arrays)
|
|
1134
|
-
|
|
1135
|
-
@module_parameters.setter
|
|
1136
|
-
@_check_deprecated_passthrough
|
|
1137
|
-
def module_parameters(self, value):
|
|
1138
|
-
for array in self.arrays:
|
|
1139
|
-
array.module_parameters = value
|
|
1140
|
-
|
|
1141
|
-
@property
|
|
1142
|
-
@_unwrap_single_value
|
|
1143
|
-
@_check_deprecated_passthrough
|
|
1144
|
-
def module(self):
|
|
1145
|
-
return tuple(array.module for array in self.arrays)
|
|
1146
|
-
|
|
1147
|
-
@module.setter
|
|
1148
|
-
@_check_deprecated_passthrough
|
|
1149
|
-
def module(self, value):
|
|
1150
|
-
for array in self.arrays:
|
|
1151
|
-
array.module = value
|
|
1152
|
-
|
|
1153
|
-
@property
|
|
1154
|
-
@_unwrap_single_value
|
|
1155
|
-
@_check_deprecated_passthrough
|
|
1156
|
-
def module_type(self):
|
|
1157
|
-
return tuple(array.module_type for array in self.arrays)
|
|
1158
|
-
|
|
1159
|
-
@module_type.setter
|
|
1160
|
-
@_check_deprecated_passthrough
|
|
1161
|
-
def module_type(self, value):
|
|
1162
|
-
for array in self.arrays:
|
|
1163
|
-
array.module_type = value
|
|
1164
|
-
|
|
1165
|
-
@property
|
|
1166
|
-
@_unwrap_single_value
|
|
1167
|
-
@_check_deprecated_passthrough
|
|
1168
|
-
def temperature_model_parameters(self):
|
|
1169
|
-
return tuple(array.temperature_model_parameters
|
|
1170
|
-
for array in self.arrays)
|
|
1171
|
-
|
|
1172
|
-
@temperature_model_parameters.setter
|
|
1173
|
-
@_check_deprecated_passthrough
|
|
1174
|
-
def temperature_model_parameters(self, value):
|
|
1175
|
-
for array in self.arrays:
|
|
1176
|
-
array.temperature_model_parameters = value
|
|
1177
|
-
|
|
1178
|
-
@property
|
|
1179
|
-
@_unwrap_single_value
|
|
1180
|
-
@_check_deprecated_passthrough
|
|
1181
|
-
def surface_tilt(self):
|
|
1182
|
-
return tuple(array.mount.surface_tilt for array in self.arrays)
|
|
1183
|
-
|
|
1184
|
-
@surface_tilt.setter
|
|
1185
|
-
@_check_deprecated_passthrough
|
|
1186
|
-
def surface_tilt(self, value):
|
|
1187
|
-
for array in self.arrays:
|
|
1188
|
-
array.mount.surface_tilt = value
|
|
1189
|
-
|
|
1190
|
-
@property
|
|
1191
|
-
@_unwrap_single_value
|
|
1192
|
-
@_check_deprecated_passthrough
|
|
1193
|
-
def surface_azimuth(self):
|
|
1194
|
-
return tuple(array.mount.surface_azimuth for array in self.arrays)
|
|
1195
|
-
|
|
1196
|
-
@surface_azimuth.setter
|
|
1197
|
-
@_check_deprecated_passthrough
|
|
1198
|
-
def surface_azimuth(self, value):
|
|
1199
|
-
for array in self.arrays:
|
|
1200
|
-
array.mount.surface_azimuth = value
|
|
1201
|
-
|
|
1202
|
-
@property
|
|
1203
|
-
@_unwrap_single_value
|
|
1204
|
-
@_check_deprecated_passthrough
|
|
1205
|
-
def albedo(self):
|
|
1206
|
-
return tuple(array.albedo for array in self.arrays)
|
|
1207
|
-
|
|
1208
|
-
@albedo.setter
|
|
1209
|
-
@_check_deprecated_passthrough
|
|
1210
|
-
def albedo(self, value):
|
|
1211
|
-
for array in self.arrays:
|
|
1212
|
-
array.albedo = value
|
|
1213
|
-
|
|
1214
|
-
@property
|
|
1215
|
-
@_unwrap_single_value
|
|
1216
|
-
@_check_deprecated_passthrough
|
|
1217
|
-
def racking_model(self):
|
|
1218
|
-
return tuple(array.mount.racking_model for array in self.arrays)
|
|
1219
|
-
|
|
1220
|
-
@racking_model.setter
|
|
1221
|
-
@_check_deprecated_passthrough
|
|
1222
|
-
def racking_model(self, value):
|
|
1223
|
-
for array in self.arrays:
|
|
1224
|
-
array.mount.racking_model = value
|
|
1225
|
-
|
|
1226
|
-
@property
|
|
1227
|
-
@_unwrap_single_value
|
|
1228
|
-
@_check_deprecated_passthrough
|
|
1229
|
-
def modules_per_string(self):
|
|
1230
|
-
return tuple(array.modules_per_string for array in self.arrays)
|
|
1231
|
-
|
|
1232
|
-
@modules_per_string.setter
|
|
1233
|
-
@_check_deprecated_passthrough
|
|
1234
|
-
def modules_per_string(self, value):
|
|
1235
|
-
for array in self.arrays:
|
|
1236
|
-
array.modules_per_string = value
|
|
1237
|
-
|
|
1238
|
-
@property
|
|
1239
|
-
@_unwrap_single_value
|
|
1240
|
-
@_check_deprecated_passthrough
|
|
1241
|
-
def strings_per_inverter(self):
|
|
1242
|
-
return tuple(array.strings for array in self.arrays)
|
|
1243
|
-
|
|
1244
|
-
@strings_per_inverter.setter
|
|
1245
|
-
@_check_deprecated_passthrough
|
|
1246
|
-
def strings_per_inverter(self, value):
|
|
1247
|
-
for array in self.arrays:
|
|
1248
|
-
array.strings = value
|
|
1249
|
-
|
|
1250
884
|
@property
|
|
1251
885
|
def num_arrays(self):
|
|
1252
886
|
"""The number of Arrays in the system."""
|
|
@@ -1597,9 +1231,7 @@ class Array:
|
|
|
1597
1231
|
func = temperature.pvsyst_cell
|
|
1598
1232
|
required = tuple()
|
|
1599
1233
|
optional = {
|
|
1600
|
-
|
|
1601
|
-
**_build_kwargs(['eta_m', 'module_efficiency',
|
|
1602
|
-
'alpha_absorption'],
|
|
1234
|
+
**_build_kwargs(['module_efficiency', 'alpha_absorption'],
|
|
1603
1235
|
self.module_parameters),
|
|
1604
1236
|
**_build_kwargs(['u_c', 'u_v'],
|
|
1605
1237
|
self.temperature_model_parameters)
|
|
@@ -1909,7 +1541,7 @@ def calcparams_desoto(effective_irradiance, temp_cell,
|
|
|
1909
1541
|
saturation_current : numeric
|
|
1910
1542
|
Diode saturation curent in amperes
|
|
1911
1543
|
|
|
1912
|
-
resistance_series :
|
|
1544
|
+
resistance_series : numeric
|
|
1913
1545
|
Series resistance in ohms
|
|
1914
1546
|
|
|
1915
1547
|
resistance_shunt : numeric
|
|
@@ -2004,8 +1636,8 @@ def calcparams_desoto(effective_irradiance, temp_cell,
|
|
|
2004
1636
|
Source: [4]
|
|
2005
1637
|
'''
|
|
2006
1638
|
|
|
2007
|
-
# Boltzmann constant in eV/K
|
|
2008
|
-
k =
|
|
1639
|
+
# Boltzmann constant in eV/K, 8.617332478e-05
|
|
1640
|
+
k = constants.value('Boltzmann constant in eV/K')
|
|
2009
1641
|
|
|
2010
1642
|
# reference temperature
|
|
2011
1643
|
Tref_K = temp_ref + 273.15
|
|
@@ -2032,9 +1664,21 @@ def calcparams_desoto(effective_irradiance, temp_cell,
|
|
|
2032
1664
|
# use errstate to silence divide by warning
|
|
2033
1665
|
with np.errstate(divide='ignore'):
|
|
2034
1666
|
Rsh = R_sh_ref * (irrad_ref / effective_irradiance)
|
|
1667
|
+
|
|
2035
1668
|
Rs = R_s
|
|
2036
1669
|
|
|
2037
|
-
|
|
1670
|
+
numeric_args = (effective_irradiance, temp_cell)
|
|
1671
|
+
out = (IL, I0, Rs, Rsh, nNsVth)
|
|
1672
|
+
|
|
1673
|
+
if all(map(np.isscalar, numeric_args)):
|
|
1674
|
+
return out
|
|
1675
|
+
|
|
1676
|
+
index = tools.get_pandas_index(*numeric_args)
|
|
1677
|
+
|
|
1678
|
+
if index is None:
|
|
1679
|
+
return np.broadcast_arrays(*out)
|
|
1680
|
+
|
|
1681
|
+
return tuple(pd.Series(a, index=index).rename(None) for a in out)
|
|
2038
1682
|
|
|
2039
1683
|
|
|
2040
1684
|
def calcparams_cec(effective_irradiance, temp_cell,
|
|
@@ -2113,7 +1757,7 @@ def calcparams_cec(effective_irradiance, temp_cell,
|
|
|
2113
1757
|
saturation_current : numeric
|
|
2114
1758
|
Diode saturation curent in amperes
|
|
2115
1759
|
|
|
2116
|
-
resistance_series :
|
|
1760
|
+
resistance_series : numeric
|
|
2117
1761
|
Series resistance in ohms
|
|
2118
1762
|
|
|
2119
1763
|
resistance_shunt : numeric
|
|
@@ -2230,7 +1874,7 @@ def calcparams_pvsyst(effective_irradiance, temp_cell,
|
|
|
2230
1874
|
saturation_current : numeric
|
|
2231
1875
|
Diode saturation current in amperes
|
|
2232
1876
|
|
|
2233
|
-
resistance_series :
|
|
1877
|
+
resistance_series : numeric
|
|
2234
1878
|
Series resistance in ohms
|
|
2235
1879
|
|
|
2236
1880
|
resistance_shunt : numeric
|
|
@@ -2262,10 +1906,10 @@ def calcparams_pvsyst(effective_irradiance, temp_cell,
|
|
|
2262
1906
|
'''
|
|
2263
1907
|
|
|
2264
1908
|
# Boltzmann constant in J/K
|
|
2265
|
-
k =
|
|
1909
|
+
k = constants.k
|
|
2266
1910
|
|
|
2267
1911
|
# elementary charge in coulomb
|
|
2268
|
-
q =
|
|
1912
|
+
q = constants.e
|
|
2269
1913
|
|
|
2270
1914
|
# reference temperature
|
|
2271
1915
|
Tref_K = temp_ref + 273.15
|
|
@@ -2289,7 +1933,18 @@ def calcparams_pvsyst(effective_irradiance, temp_cell,
|
|
|
2289
1933
|
|
|
2290
1934
|
Rs = R_s
|
|
2291
1935
|
|
|
2292
|
-
|
|
1936
|
+
numeric_args = (effective_irradiance, temp_cell)
|
|
1937
|
+
out = (IL, I0, Rs, Rsh, nNsVth)
|
|
1938
|
+
|
|
1939
|
+
if all(map(np.isscalar, numeric_args)):
|
|
1940
|
+
return out
|
|
1941
|
+
|
|
1942
|
+
index = tools.get_pandas_index(*numeric_args)
|
|
1943
|
+
|
|
1944
|
+
if index is None:
|
|
1945
|
+
return np.broadcast_arrays(*out)
|
|
1946
|
+
|
|
1947
|
+
return tuple(pd.Series(a, index=index).rename(None) for a in out)
|
|
2293
1948
|
|
|
2294
1949
|
|
|
2295
1950
|
def retrieve_sam(name=None, path=None):
|
|
@@ -2376,7 +2031,8 @@ def retrieve_sam(name=None, path=None):
|
|
|
2376
2031
|
csvdata = os.path.join(
|
|
2377
2032
|
data_path, 'sam-library-sandia-modules-2015-6-30.csv')
|
|
2378
2033
|
elif name == 'adrinverter':
|
|
2379
|
-
csvdata = os.path.join(
|
|
2034
|
+
csvdata = os.path.join(
|
|
2035
|
+
data_path, 'adr-library-cec-inverters-2019-03-05.csv')
|
|
2380
2036
|
elif name in ['cecinverter', 'sandiainverter']:
|
|
2381
2037
|
# Allowing either, to provide for old code,
|
|
2382
2038
|
# while aligning with current expectations
|
|
@@ -2537,8 +2193,8 @@ def sapm(effective_irradiance, temp_cell, module):
|
|
|
2537
2193
|
temp_ref = 25
|
|
2538
2194
|
irrad_ref = 1000
|
|
2539
2195
|
|
|
2540
|
-
q =
|
|
2541
|
-
kb =
|
|
2196
|
+
q = constants.e # Elementary charge in units of coulombs
|
|
2197
|
+
kb = constants.k # Boltzmann's constant in units of J/K
|
|
2542
2198
|
|
|
2543
2199
|
# avoid problem with integer input
|
|
2544
2200
|
Ee = np.array(effective_irradiance, dtype='float64') / irrad_ref
|
|
@@ -2597,43 +2253,10 @@ def sapm(effective_irradiance, temp_cell, module):
|
|
|
2597
2253
|
return out
|
|
2598
2254
|
|
|
2599
2255
|
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
Parameters
|
|
2605
|
-
----------
|
|
2606
|
-
airmass_absolute : numeric
|
|
2607
|
-
Absolute airmass
|
|
2608
|
-
|
|
2609
|
-
module : dict-like
|
|
2610
|
-
A dict, Series, or DataFrame defining the SAPM performance
|
|
2611
|
-
parameters. See the :py:func:`sapm` notes section for more
|
|
2612
|
-
details.
|
|
2613
|
-
|
|
2614
|
-
Returns
|
|
2615
|
-
-------
|
|
2616
|
-
F1 : numeric
|
|
2617
|
-
The SAPM spectral loss coefficient.
|
|
2618
|
-
|
|
2619
|
-
Notes
|
|
2620
|
-
-----
|
|
2621
|
-
nan airmass values will result in 0 output.
|
|
2622
|
-
"""
|
|
2623
|
-
|
|
2624
|
-
am_coeff = [module['A4'], module['A3'], module['A2'], module['A1'],
|
|
2625
|
-
module['A0']]
|
|
2626
|
-
|
|
2627
|
-
spectral_loss = np.polyval(am_coeff, airmass_absolute)
|
|
2628
|
-
|
|
2629
|
-
spectral_loss = np.where(np.isnan(spectral_loss), 0, spectral_loss)
|
|
2630
|
-
|
|
2631
|
-
spectral_loss = np.maximum(0, spectral_loss)
|
|
2632
|
-
|
|
2633
|
-
if isinstance(airmass_absolute, pd.Series):
|
|
2634
|
-
spectral_loss = pd.Series(spectral_loss, airmass_absolute.index)
|
|
2635
|
-
|
|
2636
|
-
return spectral_loss
|
|
2256
|
+
sapm_spectral_loss = deprecated(
|
|
2257
|
+
since='0.10.0',
|
|
2258
|
+
alternative='pvlib.spectrum.spectral_factor_sapm'
|
|
2259
|
+
)(spectrum.spectral_factor_sapm)
|
|
2637
2260
|
|
|
2638
2261
|
|
|
2639
2262
|
def sapm_effective_irradiance(poa_direct, poa_diffuse, airmass_absolute, aoi,
|
|
@@ -2693,11 +2316,11 @@ def sapm_effective_irradiance(poa_direct, poa_diffuse, airmass_absolute, aoi,
|
|
|
2693
2316
|
See also
|
|
2694
2317
|
--------
|
|
2695
2318
|
pvlib.iam.sapm
|
|
2696
|
-
pvlib.
|
|
2319
|
+
pvlib.spectrum.spectral_factor_sapm
|
|
2697
2320
|
pvlib.pvsystem.sapm
|
|
2698
2321
|
"""
|
|
2699
2322
|
|
|
2700
|
-
F1 =
|
|
2323
|
+
F1 = spectrum.spectral_factor_sapm(airmass_absolute, module)
|
|
2701
2324
|
F2 = iam.sapm(aoi, module)
|
|
2702
2325
|
|
|
2703
2326
|
Ee = F1 * (poa_direct * F2 + module['FD'] * poa_diffuse)
|
|
@@ -2709,7 +2332,7 @@ def singlediode(photocurrent, saturation_current, resistance_series,
|
|
|
2709
2332
|
resistance_shunt, nNsVth, ivcurve_pnts=None,
|
|
2710
2333
|
method='lambertw'):
|
|
2711
2334
|
r"""
|
|
2712
|
-
Solve the single
|
|
2335
|
+
Solve the single diode equation to obtain a photovoltaic IV curve.
|
|
2713
2336
|
|
|
2714
2337
|
Solves the single diode equation [1]_
|
|
2715
2338
|
|
|
@@ -2722,11 +2345,10 @@ def singlediode(photocurrent, saturation_current, resistance_series,
|
|
|
2722
2345
|
\frac{V + I R_s}{R_{sh}}
|
|
2723
2346
|
|
|
2724
2347
|
for :math:`I` and :math:`V` when given :math:`I_L, I_0, R_s, R_{sh},` and
|
|
2725
|
-
:math:`n N_s V_{th}` which are described later.
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
are Series (of the same length), multiple IV curves are calculated.
|
|
2348
|
+
:math:`n N_s V_{th}` which are described later. The five points on the I-V
|
|
2349
|
+
curve specified in [3]_ are returned. If :math:`I_L, I_0, R_s, R_{sh},` and
|
|
2350
|
+
:math:`n N_s V_{th}` are all scalars, a single curve is returned. If any
|
|
2351
|
+
are array-like (of the same length), multiple IV curves are calculated.
|
|
2730
2352
|
|
|
2731
2353
|
The input parameters can be calculated from meteorological data using a
|
|
2732
2354
|
function for a single diode model, e.g.,
|
|
@@ -2764,35 +2386,33 @@ def singlediode(photocurrent, saturation_current, resistance_series,
|
|
|
2764
2386
|
Number of points in the desired IV curve. If None or 0, no points on
|
|
2765
2387
|
the IV curves will be produced.
|
|
2766
2388
|
|
|
2389
|
+
.. deprecated:: 0.10.0
|
|
2390
|
+
Use :py:func:`pvlib.pvsystem.v_from_i` and
|
|
2391
|
+
:py:func:`pvlib.pvsystem.i_from_v` instead.
|
|
2392
|
+
|
|
2767
2393
|
method : str, default 'lambertw'
|
|
2768
2394
|
Determines the method used to calculate points on the IV curve. The
|
|
2769
2395
|
options are ``'lambertw'``, ``'newton'``, or ``'brentq'``.
|
|
2770
2396
|
|
|
2771
2397
|
Returns
|
|
2772
2398
|
-------
|
|
2773
|
-
|
|
2399
|
+
dict or pandas.DataFrame
|
|
2400
|
+
The returned dict-like object always contains the keys/columns:
|
|
2774
2401
|
|
|
2775
|
-
|
|
2402
|
+
* i_sc - short circuit current in amperes.
|
|
2403
|
+
* v_oc - open circuit voltage in volts.
|
|
2404
|
+
* i_mp - current at maximum power point in amperes.
|
|
2405
|
+
* v_mp - voltage at maximum power point in volts.
|
|
2406
|
+
* p_mp - power at maximum power point in watts.
|
|
2407
|
+
* i_x - current, in amperes, at ``v = 0.5*v_oc``.
|
|
2408
|
+
* i_xx - current, in amperes, at ``v = 0.5*(v_oc+v_mp)``.
|
|
2776
2409
|
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
* v_mp - voltage at maximum power point in volts.
|
|
2781
|
-
* p_mp - power at maximum power point in watts.
|
|
2782
|
-
* i_x - current, in amperes, at ``v = 0.5*v_oc``.
|
|
2783
|
-
* i_xx - current, in amperes, at ``V = 0.5*(v_oc+v_mp)``.
|
|
2410
|
+
A dict is returned when the input parameters are scalars or
|
|
2411
|
+
``ivcurve_pnts > 0``. If ``ivcurve_pnts > 0``, the output dictionary
|
|
2412
|
+
will also include the keys:
|
|
2784
2413
|
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
* i - IV curve current in amperes.
|
|
2789
|
-
* v - IV curve voltage in volts.
|
|
2790
|
-
|
|
2791
|
-
The output will be an OrderedDict if photocurrent is a scalar,
|
|
2792
|
-
array, or ivcurve_pnts is not None.
|
|
2793
|
-
|
|
2794
|
-
The output will be a DataFrame if photocurrent is a Series and
|
|
2795
|
-
ivcurve_pnts is None.
|
|
2414
|
+
* i - IV curve current in amperes.
|
|
2415
|
+
* v - IV curve voltage in volts.
|
|
2796
2416
|
|
|
2797
2417
|
See also
|
|
2798
2418
|
--------
|
|
@@ -2839,22 +2459,25 @@ def singlediode(photocurrent, saturation_current, resistance_series,
|
|
|
2839
2459
|
photovoltaic cell interconnection circuits" JW Bishop, Solar Cell (1988)
|
|
2840
2460
|
https://doi.org/10.1016/0379-6787(88)90059-2
|
|
2841
2461
|
"""
|
|
2462
|
+
if ivcurve_pnts:
|
|
2463
|
+
warn_deprecated('0.10.0', name='pvlib.pvsystem.singlediode',
|
|
2464
|
+
alternative=('pvlib.pvsystem.v_from_i and '
|
|
2465
|
+
'pvlib.pvsystem.i_from_v'),
|
|
2466
|
+
obj_type='parameter ivcurve_pnts',
|
|
2467
|
+
removal='0.11.0')
|
|
2468
|
+
args = (photocurrent, saturation_current, resistance_series,
|
|
2469
|
+
resistance_shunt, nNsVth) # collect args
|
|
2842
2470
|
# Calculate points on the IV curve using the LambertW solution to the
|
|
2843
2471
|
# single diode equation
|
|
2844
2472
|
if method.lower() == 'lambertw':
|
|
2845
|
-
out = _singlediode._lambertw(
|
|
2846
|
-
|
|
2847
|
-
resistance_shunt, nNsVth, ivcurve_pnts
|
|
2848
|
-
)
|
|
2849
|
-
i_sc, v_oc, i_mp, v_mp, p_mp, i_x, i_xx = out[:7]
|
|
2473
|
+
out = _singlediode._lambertw(*args, ivcurve_pnts)
|
|
2474
|
+
points = out[:7]
|
|
2850
2475
|
if ivcurve_pnts:
|
|
2851
2476
|
ivcurve_i, ivcurve_v = out[7:]
|
|
2852
2477
|
else:
|
|
2853
2478
|
# Calculate points on the IV curve using either 'newton' or 'brentq'
|
|
2854
2479
|
# methods. Voltages are determined by first solving the single diode
|
|
2855
2480
|
# equation for the diode voltage V_d then backing out voltage
|
|
2856
|
-
args = (photocurrent, saturation_current, resistance_series,
|
|
2857
|
-
resistance_shunt, nNsVth) # collect args
|
|
2858
2481
|
v_oc = _singlediode.bishop88_v_from_i(
|
|
2859
2482
|
0.0, *args, method=method.lower()
|
|
2860
2483
|
)
|
|
@@ -2870,6 +2493,7 @@ def singlediode(photocurrent, saturation_current, resistance_series,
|
|
|
2870
2493
|
i_xx = _singlediode.bishop88_i_from_v(
|
|
2871
2494
|
(v_oc + v_mp) / 2.0, *args, method=method.lower()
|
|
2872
2495
|
)
|
|
2496
|
+
points = i_sc, v_oc, i_mp, v_mp, p_mp, i_x, i_xx
|
|
2873
2497
|
|
|
2874
2498
|
# calculate the IV curve if requested using bishop88
|
|
2875
2499
|
if ivcurve_pnts:
|
|
@@ -2878,22 +2502,23 @@ def singlediode(photocurrent, saturation_current, resistance_series,
|
|
|
2878
2502
|
)
|
|
2879
2503
|
ivcurve_i, ivcurve_v, _ = _singlediode.bishop88(vd, *args)
|
|
2880
2504
|
|
|
2881
|
-
|
|
2882
|
-
out['i_sc'] = i_sc
|
|
2883
|
-
out['v_oc'] = v_oc
|
|
2884
|
-
out['i_mp'] = i_mp
|
|
2885
|
-
out['v_mp'] = v_mp
|
|
2886
|
-
out['p_mp'] = p_mp
|
|
2887
|
-
out['i_x'] = i_x
|
|
2888
|
-
out['i_xx'] = i_xx
|
|
2505
|
+
columns = ('i_sc', 'v_oc', 'i_mp', 'v_mp', 'p_mp', 'i_x', 'i_xx')
|
|
2889
2506
|
|
|
2890
|
-
if ivcurve_pnts:
|
|
2507
|
+
if all(map(np.isscalar, args)) or ivcurve_pnts:
|
|
2508
|
+
out = {c: p for c, p in zip(columns, points)}
|
|
2509
|
+
|
|
2510
|
+
if ivcurve_pnts:
|
|
2511
|
+
out.update(i=ivcurve_i, v=ivcurve_v)
|
|
2891
2512
|
|
|
2892
|
-
out
|
|
2893
|
-
out['i'] = ivcurve_i
|
|
2513
|
+
return out
|
|
2894
2514
|
|
|
2895
|
-
|
|
2896
|
-
|
|
2515
|
+
points = np.atleast_1d(*points) # convert scalars to 1d-arrays
|
|
2516
|
+
points = np.vstack(points).T # collect rows into DataFrame columns
|
|
2517
|
+
|
|
2518
|
+
# save the first available pd.Series index, otherwise set to None
|
|
2519
|
+
index = next((a.index for a in args if isinstance(a, pd.Series)), None)
|
|
2520
|
+
|
|
2521
|
+
out = pd.DataFrame(points, columns=columns, index=index)
|
|
2897
2522
|
|
|
2898
2523
|
return out
|
|
2899
2524
|
|
|
@@ -2934,7 +2559,7 @@ def max_power_point(photocurrent, saturation_current, resistance_series,
|
|
|
2934
2559
|
|
|
2935
2560
|
Returns
|
|
2936
2561
|
-------
|
|
2937
|
-
OrderedDict or pandas.
|
|
2562
|
+
OrderedDict or pandas.DataFrame
|
|
2938
2563
|
``(i_mp, v_mp, p_mp)``
|
|
2939
2564
|
|
|
2940
2565
|
Notes
|
|
@@ -2946,8 +2571,7 @@ def max_power_point(photocurrent, saturation_current, resistance_series,
|
|
|
2946
2571
|
"""
|
|
2947
2572
|
i_mp, v_mp, p_mp = _singlediode.bishop88_mpp(
|
|
2948
2573
|
photocurrent, saturation_current, resistance_series,
|
|
2949
|
-
resistance_shunt, nNsVth, d2mutau
|
|
2950
|
-
method=method.lower()
|
|
2574
|
+
resistance_shunt, nNsVth, d2mutau, NsVbi, method=method.lower()
|
|
2951
2575
|
)
|
|
2952
2576
|
if isinstance(photocurrent, pd.Series):
|
|
2953
2577
|
ivp = {'i_mp': i_mp, 'v_mp': v_mp, 'p_mp': p_mp}
|
|
@@ -2960,8 +2584,8 @@ def max_power_point(photocurrent, saturation_current, resistance_series,
|
|
|
2960
2584
|
return out
|
|
2961
2585
|
|
|
2962
2586
|
|
|
2963
|
-
def v_from_i(
|
|
2964
|
-
|
|
2587
|
+
def v_from_i(current, photocurrent, saturation_current, resistance_series,
|
|
2588
|
+
resistance_shunt, nNsVth, method='lambertw'):
|
|
2965
2589
|
'''
|
|
2966
2590
|
Device voltage at the given device current for the single diode model.
|
|
2967
2591
|
|
|
@@ -2975,18 +2599,34 @@ def v_from_i(resistance_shunt, resistance_series, nNsVth, current,
|
|
|
2975
2599
|
the caller's responsibility to ensure that the arguments are all float64
|
|
2976
2600
|
and within the proper ranges.
|
|
2977
2601
|
|
|
2602
|
+
.. versionchanged:: 0.10.0
|
|
2603
|
+
The function's arguments have been reordered.
|
|
2604
|
+
|
|
2978
2605
|
Parameters
|
|
2979
2606
|
----------
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2607
|
+
current : numeric
|
|
2608
|
+
The current in amperes under desired IV curve conditions.
|
|
2609
|
+
|
|
2610
|
+
photocurrent : numeric
|
|
2611
|
+
Light-generated current (photocurrent) in amperes under desired
|
|
2612
|
+
IV curve conditions. Often abbreviated ``I_L``.
|
|
2613
|
+
0 <= photocurrent
|
|
2614
|
+
|
|
2615
|
+
saturation_current : numeric
|
|
2616
|
+
Diode saturation current in amperes under desired IV curve
|
|
2617
|
+
conditions. Often abbreviated ``I_0``.
|
|
2618
|
+
0 < saturation_current
|
|
2984
2619
|
|
|
2985
2620
|
resistance_series : numeric
|
|
2986
2621
|
Series resistance in ohms under desired IV curve conditions.
|
|
2987
2622
|
Often abbreviated ``Rs``.
|
|
2988
2623
|
0 <= resistance_series < numpy.inf
|
|
2989
2624
|
|
|
2625
|
+
resistance_shunt : numeric
|
|
2626
|
+
Shunt resistance in ohms under desired IV curve conditions.
|
|
2627
|
+
Often abbreviated ``Rsh``.
|
|
2628
|
+
0 < resistance_shunt <= numpy.inf
|
|
2629
|
+
|
|
2990
2630
|
nNsVth : numeric
|
|
2991
2631
|
The product of three components. 1) The usual diode ideal factor
|
|
2992
2632
|
(n), 2) the number of cells in series (Ns), and 3) the cell
|
|
@@ -2997,19 +2637,6 @@ def v_from_i(resistance_shunt, resistance_series, nNsVth, current,
|
|
|
2997
2637
|
q is the charge of an electron (coulombs).
|
|
2998
2638
|
0 < nNsVth
|
|
2999
2639
|
|
|
3000
|
-
current : numeric
|
|
3001
|
-
The current in amperes under desired IV curve conditions.
|
|
3002
|
-
|
|
3003
|
-
saturation_current : numeric
|
|
3004
|
-
Diode saturation current in amperes under desired IV curve
|
|
3005
|
-
conditions. Often abbreviated ``I_0``.
|
|
3006
|
-
0 < saturation_current
|
|
3007
|
-
|
|
3008
|
-
photocurrent : numeric
|
|
3009
|
-
Light-generated current (photocurrent) in amperes under desired
|
|
3010
|
-
IV curve conditions. Often abbreviated ``I_L``.
|
|
3011
|
-
0 <= photocurrent
|
|
3012
|
-
|
|
3013
2640
|
method : str
|
|
3014
2641
|
Method to use: ``'lambertw'``, ``'newton'``, or ``'brentq'``. *Note*:
|
|
3015
2642
|
``'brentq'`` is limited to 1st quadrant only.
|
|
@@ -3026,8 +2653,8 @@ def v_from_i(resistance_shunt, resistance_series, nNsVth, current,
|
|
|
3026
2653
|
'''
|
|
3027
2654
|
if method.lower() == 'lambertw':
|
|
3028
2655
|
return _singlediode._lambertw_v_from_i(
|
|
3029
|
-
|
|
3030
|
-
|
|
2656
|
+
current, photocurrent, saturation_current, resistance_series,
|
|
2657
|
+
resistance_shunt, nNsVth
|
|
3031
2658
|
)
|
|
3032
2659
|
else:
|
|
3033
2660
|
# Calculate points on the IV curve using either 'newton' or 'brentq'
|
|
@@ -3048,33 +2675,49 @@ def v_from_i(resistance_shunt, resistance_series, nNsVth, current,
|
|
|
3048
2675
|
return V
|
|
3049
2676
|
|
|
3050
2677
|
|
|
3051
|
-
def i_from_v(
|
|
3052
|
-
|
|
2678
|
+
def i_from_v(voltage, photocurrent, saturation_current, resistance_series,
|
|
2679
|
+
resistance_shunt, nNsVth, method='lambertw'):
|
|
3053
2680
|
'''
|
|
3054
2681
|
Device current at the given device voltage for the single diode model.
|
|
3055
2682
|
|
|
3056
2683
|
Uses the single diode model (SDM) as described in, e.g.,
|
|
3057
|
-
|
|
2684
|
+
Jain and Kapoor 2004 [1]_.
|
|
3058
2685
|
The solution is per Eq 2 of [1] except when resistance_series=0,
|
|
3059
|
-
|
|
2686
|
+
in which case the explict solution for current is used.
|
|
3060
2687
|
Ideal device parameters are specified by resistance_shunt=np.inf and
|
|
3061
|
-
|
|
2688
|
+
resistance_series=0.
|
|
3062
2689
|
Inputs to this function can include scalars and pandas.Series, but it is
|
|
3063
|
-
|
|
3064
|
-
|
|
2690
|
+
the caller's responsibility to ensure that the arguments are all float64
|
|
2691
|
+
and within the proper ranges.
|
|
2692
|
+
|
|
2693
|
+
.. versionchanged:: 0.10.0
|
|
2694
|
+
The function's arguments have been reordered.
|
|
3065
2695
|
|
|
3066
2696
|
Parameters
|
|
3067
2697
|
----------
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
2698
|
+
voltage : numeric
|
|
2699
|
+
The voltage in Volts under desired IV curve conditions.
|
|
2700
|
+
|
|
2701
|
+
photocurrent : numeric
|
|
2702
|
+
Light-generated current (photocurrent) in amperes under desired
|
|
2703
|
+
IV curve conditions. Often abbreviated ``I_L``.
|
|
2704
|
+
0 <= photocurrent
|
|
2705
|
+
|
|
2706
|
+
saturation_current : numeric
|
|
2707
|
+
Diode saturation current in amperes under desired IV curve
|
|
2708
|
+
conditions. Often abbreviated ``I_0``.
|
|
2709
|
+
0 < saturation_current
|
|
3072
2710
|
|
|
3073
2711
|
resistance_series : numeric
|
|
3074
2712
|
Series resistance in ohms under desired IV curve conditions.
|
|
3075
2713
|
Often abbreviated ``Rs``.
|
|
3076
2714
|
0 <= resistance_series < numpy.inf
|
|
3077
2715
|
|
|
2716
|
+
resistance_shunt : numeric
|
|
2717
|
+
Shunt resistance in ohms under desired IV curve conditions.
|
|
2718
|
+
Often abbreviated ``Rsh``.
|
|
2719
|
+
0 < resistance_shunt <= numpy.inf
|
|
2720
|
+
|
|
3078
2721
|
nNsVth : numeric
|
|
3079
2722
|
The product of three components. 1) The usual diode ideal factor
|
|
3080
2723
|
(n), 2) the number of cells in series (Ns), and 3) the cell
|
|
@@ -3085,19 +2728,6 @@ def i_from_v(resistance_shunt, resistance_series, nNsVth, voltage,
|
|
|
3085
2728
|
q is the charge of an electron (coulombs).
|
|
3086
2729
|
0 < nNsVth
|
|
3087
2730
|
|
|
3088
|
-
voltage : numeric
|
|
3089
|
-
The voltage in Volts under desired IV curve conditions.
|
|
3090
|
-
|
|
3091
|
-
saturation_current : numeric
|
|
3092
|
-
Diode saturation current in amperes under desired IV curve
|
|
3093
|
-
conditions. Often abbreviated ``I_0``.
|
|
3094
|
-
0 < saturation_current
|
|
3095
|
-
|
|
3096
|
-
photocurrent : numeric
|
|
3097
|
-
Light-generated current (photocurrent) in amperes under desired
|
|
3098
|
-
IV curve conditions. Often abbreviated ``I_L``.
|
|
3099
|
-
0 <= photocurrent
|
|
3100
|
-
|
|
3101
2731
|
method : str
|
|
3102
2732
|
Method to use: ``'lambertw'``, ``'newton'``, or ``'brentq'``. *Note*:
|
|
3103
2733
|
``'brentq'`` is limited to 1st quadrant only.
|
|
@@ -3114,8 +2744,8 @@ def i_from_v(resistance_shunt, resistance_series, nNsVth, voltage,
|
|
|
3114
2744
|
'''
|
|
3115
2745
|
if method.lower() == 'lambertw':
|
|
3116
2746
|
return _singlediode._lambertw_i_from_v(
|
|
3117
|
-
|
|
3118
|
-
|
|
2747
|
+
voltage, photocurrent, saturation_current, resistance_series,
|
|
2748
|
+
resistance_shunt, nNsVth
|
|
3119
2749
|
)
|
|
3120
2750
|
else:
|
|
3121
2751
|
# Calculate points on the IV curve using either 'newton' or 'brentq'
|
|
@@ -3179,9 +2809,9 @@ def pvwatts_dc(g_poa_effective, temp_cell, pdc0, gamma_pdc, temp_ref=25.):
|
|
|
3179
2809
|
|
|
3180
2810
|
P_{dc} = \frac{G_{poa eff}}{1000} P_{dc0} ( 1 + \gamma_{pdc} (T_{cell} - T_{ref}))
|
|
3181
2811
|
|
|
3182
|
-
Note that
|
|
3183
|
-
:py:func:`pvlib.inverter.pvwatts`. pdc0 in this function refers to the DC
|
|
3184
|
-
power of the modules at reference conditions. pdc0 in
|
|
2812
|
+
Note that ``pdc0`` is also used as a symbol in
|
|
2813
|
+
:py:func:`pvlib.inverter.pvwatts`. ``pdc0`` in this function refers to the DC
|
|
2814
|
+
power of the modules at reference conditions. ``pdc0`` in
|
|
3185
2815
|
:py:func:`pvlib.inverter.pvwatts` refers to the DC power input limit of
|
|
3186
2816
|
the inverter.
|
|
3187
2817
|
|
|
@@ -3206,7 +2836,7 @@ def pvwatts_dc(g_poa_effective, temp_cell, pdc0, gamma_pdc, temp_ref=25.):
|
|
|
3206
2836
|
Returns
|
|
3207
2837
|
-------
|
|
3208
2838
|
pdc: numeric
|
|
3209
|
-
DC power.
|
|
2839
|
+
DC power. [W]
|
|
3210
2840
|
|
|
3211
2841
|
References
|
|
3212
2842
|
----------
|