pvlib 0.13.1a1__py3-none-any.whl → 0.14.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/pvarray.py CHANGED
@@ -9,8 +9,9 @@ Supporting functions and parameter fitting functions may also be found here.
9
9
  """
10
10
 
11
11
  import numpy as np
12
+ import pandas as pd
12
13
  from scipy.optimize import curve_fit
13
- from scipy.special import exp10
14
+ from scipy.special import exp10, lambertw
14
15
 
15
16
 
16
17
  def pvefficiency_adr(effective_irradiance, temp_cell,
@@ -394,3 +395,131 @@ def huld(effective_irradiance, temp_mod, pdc0, k=None, cell_type=None,
394
395
  k[5] * tprime**2
395
396
  )
396
397
  return pdc
398
+
399
+
400
+ def batzelis(effective_irradiance, temp_cell,
401
+ v_mp, i_mp, v_oc, i_sc, alpha_sc, beta_voc):
402
+ """
403
+ Compute maximum power point, open circuit, and short circuit
404
+ values using Batzelis's method.
405
+
406
+ Batzelis's method (described in Section III of [1]_) is a fast method
407
+ of computing the maximum power current and voltage. The calculations
408
+ are rooted in the De Soto single-diode model, but require only typical
409
+ datasheet information.
410
+
411
+ Parameters
412
+ ----------
413
+ effective_irradiance : numeric, non-negative
414
+ Effective irradiance incident on the PV module. [Wm⁻²]
415
+ temp_cell : numeric
416
+ PV module operating temperature. [°C]
417
+ v_mp : float
418
+ Maximum power point voltage at STC. [V]
419
+ i_mp : float
420
+ Maximum power point current at STC. [A]
421
+ v_oc : float
422
+ Open-circuit voltage at STC. [V]
423
+ i_sc : float
424
+ Short-circuit current at STC. [A]
425
+ alpha_sc : float
426
+ Short-circuit current temperature coefficient at STC. [A/K]
427
+ beta_voc : float
428
+ Open-circuit voltage temperature coefficient at STC. [V/K]
429
+
430
+ Returns
431
+ -------
432
+ dict
433
+ The returned dict-like object contains the keys/columns:
434
+
435
+ * ``p_mp`` - power at maximum power point. [W]
436
+ * ``i_mp`` - current at maximum power point. [A]
437
+ * ``v_mp`` - voltage at maximum power point. [V]
438
+ * ``i_sc`` - short circuit current. [A]
439
+ * ``v_oc`` - open circuit voltage. [V]
440
+
441
+ Notes
442
+ -----
443
+ This method is the combination of three sub-methods for:
444
+
445
+ 1. estimating single-diode model parameters from datasheet information
446
+ 2. translating SDM parameters from STC to operating conditions
447
+ (taken from the De Soto model)
448
+ 3. estimating the MPP, OC, and SC points on the resulting I-V curve.
449
+
450
+ At extremely low irradiance (e.g. 1e-10 Wm⁻²), this model can produce
451
+ negative voltages. This function clips any negative voltages to zero.
452
+
453
+ References
454
+ ----------
455
+ .. [1] E. I. Batzelis, "Simple PV Performance Equations Theoretically Well
456
+ Founded on the Single-Diode Model," Journal of Photovoltaics vol. 7,
457
+ no. 5, pp. 1400-1409, Sep 2017, :doi:`10.1109/JPHOTOV.2017.2711431`
458
+
459
+ Examples
460
+ --------
461
+ >>> params = {'i_sc': 15.98, 'v_oc': 50.26, 'i_mp': 15.27, 'v_mp': 42.57,
462
+ ... 'alpha_sc': 0.007351, 'beta_voc': -0.120624}
463
+ >>> batzelis(np.array([1000, 800]), np.array([25, 30]), **params)
464
+ {'p_mp': array([650.0439 , 512.99199048]),
465
+ 'i_mp': array([15.27 , 12.23049303]),
466
+ 'v_mp': array([42.57 , 41.94368856]),
467
+ 'i_sc': array([15.98 , 12.813404]),
468
+ 'v_oc': array([50.26 , 49.26532902])}
469
+ """
470
+ # convert temp coeffs from A/K and V/K to 1/K
471
+ alpha_sc = alpha_sc / i_sc
472
+ beta_voc = beta_voc / v_oc
473
+
474
+ t0 = 298.15
475
+ delT = temp_cell - (t0 - 273.15)
476
+ lamT = (temp_cell + 273.15) / t0
477
+ g = effective_irradiance / 1000
478
+ # for zero/negative irradiance, use lnG=large negative number so that
479
+ # computed voltages are negative and then clipped to zero
480
+ with np.errstate(divide='ignore'): # needed for pandas for some reason
481
+ lnG = np.log(g, out=np.full_like(g, -9e9), where=(g > 0))
482
+ lnG = np.where(np.isfinite(g), lnG, np.nan) # also preserve nans
483
+
484
+ # Eq 9-10
485
+ del0 = (1 - beta_voc * t0) / (50.1 - alpha_sc * t0)
486
+ w0 = np.real(lambertw(np.exp(1/del0 + 1)))
487
+
488
+ # Eqs 27-28
489
+ alpha_imp = alpha_sc + (beta_voc - 1/t0) / (w0 - 1)
490
+ beta_vmp = (v_oc / v_mp) * (
491
+ beta_voc / (1 + del0) +
492
+ (del0 * (w0 - 1) - 1/(1 + del0)) / t0
493
+ )
494
+
495
+ # Eq 26
496
+ eps0 = (del0 / (1 + del0)) * (v_oc / v_mp)
497
+ eps1 = del0 * (w0 - 1) * (v_oc / v_mp) - 1
498
+
499
+ # Eqs 22-25
500
+ isc = g * i_sc * (1 + alpha_sc * delT)
501
+ voc = v_oc * (1 + del0 * lamT * lnG + beta_voc * delT)
502
+ imp = g * i_mp * (1 + alpha_imp * delT)
503
+ vmp = v_mp * (1 + eps0 * lamT * lnG + eps1 * (1 - g) + beta_vmp * delT)
504
+
505
+ # handle negative voltages from zero and extremely small irradiance
506
+ vmp = np.clip(vmp, a_min=0, a_max=None)
507
+ voc = np.clip(voc, a_min=0, a_max=None)
508
+
509
+ out = {
510
+ 'p_mp': vmp * imp,
511
+ 'i_mp': imp,
512
+ 'v_mp': vmp,
513
+ 'i_sc': isc,
514
+ 'v_oc': voc,
515
+ }
516
+
517
+ # if pandas in, ensure pandas out
518
+ pandas_inputs = [
519
+ x for x in [effective_irradiance, temp_cell]
520
+ if isinstance(x, pd.Series)
521
+ ]
522
+ if pandas_inputs:
523
+ out = pd.DataFrame(out, index=pandas_inputs[0].index)
524
+
525
+ return out
pvlib/pvsystem.py CHANGED
@@ -2498,7 +2498,11 @@ def singlediode(photocurrent, saturation_current, resistance_series,
2498
2498
 
2499
2499
  method : str, default 'lambertw'
2500
2500
  Determines the method used to calculate points on the IV curve. The
2501
- options are ``'lambertw'``, ``'newton'``, or ``'brentq'``.
2501
+ options are ``'lambertw'``, ``'newton'``, ``'brentq'``, or
2502
+ ``'chandrupatla'``.
2503
+
2504
+ .. note::
2505
+ ``'chandrupatla'`` requires scipy 1.15 or greater.
2502
2506
 
2503
2507
  Returns
2504
2508
  -------
@@ -2530,28 +2534,35 @@ def singlediode(photocurrent, saturation_current, resistance_series,
2530
2534
  explicit function of :math:`V=f(I)` and :math:`I=f(V)` as shown in [2]_.
2531
2535
 
2532
2536
  If the method is ``'newton'`` then the root-finding Newton-Raphson method
2533
- is used. It should be safe for well behaved IV-curves, but the ``'brentq'``
2534
- method is recommended for reliability.
2537
+ is used. It should be safe for well-behaved IV curves, otherwise the
2538
+ ``'chandrupatla``` or ``'brentq'`` methods are recommended for reliability.
2535
2539
 
2536
2540
  If the method is ``'brentq'`` then Brent's bisection search method is used
2537
2541
  that guarantees convergence by bounding the voltage between zero and
2538
- open-circuit.
2542
+ open-circuit. ``'brentq'`` is generally slower than the other options.
2543
+
2544
+ If the method is ``'chandrupatla'`` then Chandrupatla's method is used
2545
+ that guarantees convergence.
2539
2546
 
2540
2547
  References
2541
2548
  ----------
2542
- .. [1] S.R. Wenham, M.A. Green, M.E. Watt, "Applied Photovoltaics" ISBN
2543
- 0 86758 909 4
2549
+ .. [1] S. R. Wenham, M. A. Green, M. E. Watt, "Applied Photovoltaics",
2550
+ Centre for Photovoltaic Devices and Systems, 1995. ISBN
2551
+ 0867589094
2544
2552
 
2545
2553
  .. [2] A. Jain, A. Kapoor, "Exact analytical solutions of the
2546
2554
  parameters of real solar cells using Lambert W-function", Solar
2547
- Energy Materials and Solar Cells, 81 (2004) 269-277.
2555
+ Energy Materials and Solar Cells, vol. 81 no. 2, pp. 269-277, Feb. 2004.
2556
+ :doi:`10.1016/j.solmat.2003.11.018`.
2548
2557
 
2549
- .. [3] D. King et al, "Sandia Photovoltaic Array Performance Model",
2550
- SAND2004-3535, Sandia National Laboratories, Albuquerque, NM
2558
+ .. [3] D. L. King, E. E. Boyson and J. A. Kratochvil "Photovoltaic Array
2559
+ Performance Model", Sandia National Laboratories, Albuquerque, NM, USA.
2560
+ Report SAND2004-3535, 2004.
2551
2561
 
2552
- .. [4] "Computer simulation of the effects of electrical mismatches in
2553
- photovoltaic cell interconnection circuits" JW Bishop, Solar Cell (1988)
2554
- https://doi.org/10.1016/0379-6787(88)90059-2
2562
+ .. [4] J.W. Bishop, "Computer simulation of the effects of electrical
2563
+ mismatches in photovoltaic cell interconnection circuits" Solar Cells,
2564
+ vol. 25 no. 1, pp. 73-89, Oct. 1988.
2565
+ :doi:`doi.org/10.1016/0379-6787(88)90059-2`
2555
2566
  """
2556
2567
  args = (photocurrent, saturation_current, resistance_series,
2557
2568
  resistance_shunt, nNsVth) # collect args
@@ -2561,8 +2572,9 @@ def singlediode(photocurrent, saturation_current, resistance_series,
2561
2572
  out = _singlediode._lambertw(*args)
2562
2573
  points = out[:7]
2563
2574
  else:
2564
- # Calculate points on the IV curve using either 'newton' or 'brentq'
2565
- # methods. Voltages are determined by first solving the single diode
2575
+ # Calculate points on the IV curve using Bishop's algorithm and solving
2576
+ # with 'newton', 'brentq' or 'chandrupatla' method.
2577
+ # Voltages are determined by first solving the single diode
2566
2578
  # equation for the diode voltage V_d then backing out voltage
2567
2579
  v_oc = _singlediode.bishop88_v_from_i(
2568
2580
  0.0, *args, method=method.lower()
@@ -2630,7 +2642,11 @@ def max_power_point(photocurrent, saturation_current, resistance_series,
2630
2642
  cells ``Ns`` and the builtin voltage ``Vbi`` of the intrinsic layer.
2631
2643
  [V].
2632
2644
  method : str
2633
- either ``'newton'`` or ``'brentq'``
2645
+ either ``'newton'``, ``'brentq'``, or ``'chandrupatla'``.
2646
+
2647
+ .. note::
2648
+ ``'chandrupatla'`` requires scipy 1.15 or greater.
2649
+
2634
2650
 
2635
2651
  Returns
2636
2652
  -------
@@ -2713,8 +2729,13 @@ def v_from_i(current, photocurrent, saturation_current, resistance_series,
2713
2729
  0 < nNsVth
2714
2730
 
2715
2731
  method : str
2716
- Method to use: ``'lambertw'``, ``'newton'``, or ``'brentq'``. *Note*:
2717
- ``'brentq'`` is limited to 1st quadrant only.
2732
+ Method to use: ``'lambertw'``, ``'newton'``, ``'brentq'``, or
2733
+ ``'chandrupatla'``. *Note*: ``'brentq'`` is limited to
2734
+ non-negative current.
2735
+
2736
+ .. note::
2737
+ ``'chandrupatla'`` requires scipy 1.15 or greater.
2738
+
2718
2739
 
2719
2740
  Returns
2720
2741
  -------
@@ -2795,8 +2816,13 @@ def i_from_v(voltage, photocurrent, saturation_current, resistance_series,
2795
2816
  0 < nNsVth
2796
2817
 
2797
2818
  method : str
2798
- Method to use: ``'lambertw'``, ``'newton'``, or ``'brentq'``. *Note*:
2799
- ``'brentq'`` is limited to 1st quadrant only.
2819
+ Method to use: ``'lambertw'``, ``'newton'``, ``'brentq'``, or
2820
+ ``'chandrupatla'``. *Note*: ``'brentq'`` is limited to
2821
+ non-negative current.
2822
+
2823
+ .. note::
2824
+ ``'chandrupatla'`` requires scipy 1.15 or greater.
2825
+
2800
2826
 
2801
2827
  Returns
2802
2828
  -------
@@ -2860,53 +2886,117 @@ def scale_voltage_current_power(data, voltage=1, current=1):
2860
2886
 
2861
2887
  @renamed_kwarg_warning(
2862
2888
  "0.13.0", "g_poa_effective", "effective_irradiance")
2863
- def pvwatts_dc(effective_irradiance, temp_cell, pdc0, gamma_pdc, temp_ref=25.):
2889
+ def pvwatts_dc(effective_irradiance, temp_cell, pdc0, gamma_pdc, temp_ref=25.,
2890
+ k=None, cap_adjustment=False):
2864
2891
  r"""
2865
- Implements NREL's PVWatts DC power model. The PVWatts DC model [1]_ is:
2866
-
2867
- .. math::
2868
-
2869
- P_{dc} = \frac{G_{poa eff}}{1000} P_{dc0} ( 1 + \gamma_{pdc} (T_{cell} - T_{ref}))
2870
-
2871
- Note that ``pdc0`` is also used as a symbol in
2872
- :py:func:`pvlib.inverter.pvwatts`. ``pdc0`` in this function refers to the DC
2873
- power of the modules at reference conditions. ``pdc0`` in
2874
- :py:func:`pvlib.inverter.pvwatts` refers to the DC power input limit of
2875
- the inverter.
2892
+ Implement NREL's PVWatts (Version 5) DC power model.
2876
2893
 
2877
2894
  Parameters
2878
2895
  ----------
2879
2896
  effective_irradiance: numeric
2880
- Irradiance transmitted to the PV cells. To be
2881
- fully consistent with PVWatts, the user must have already
2882
- applied angle of incidence losses, but not soiling, spectral,
2883
- etc. [W/m^2]
2897
+ Irradiance transmitted to the PV cells. To be fully consistent with
2898
+ PVWatts, the user must have already applied angle of incidence losses,
2899
+ but not soiling, spectral, etc. [Wm⁻²]
2884
2900
  temp_cell: numeric
2885
2901
  Cell temperature [C].
2886
2902
  pdc0: numeric
2887
- Power of the modules at 1000 W/m^2 and cell reference temperature. [W]
2903
+ Power of the modules at 1000 Wm⁻² and cell reference temperature. [W]
2888
2904
  gamma_pdc: numeric
2889
- The temperature coefficient of power. Typically -0.002 to
2890
- -0.005 per degree C. [1/C]
2905
+ The temperature coefficient of power. Typically -0.002 to -0.005 per
2906
+ degree C. [1C]
2891
2907
  temp_ref: numeric, default 25.0
2892
- Cell reference temperature. PVWatts defines it to be 25 C and
2893
- is included here for flexibility. [C]
2908
+ Cell reference temperature. PVWatts defines it to be 25 °C and is
2909
+ included here for flexibility. [°C]
2910
+ k: numeric, optional
2911
+ Irradiance correction factor, defined in [2]_. Typically positive.
2912
+ [unitless]
2913
+ cap_adjustment: Boolean, default False
2914
+ If True, only apply the optional adjustment at and below 1000 Wm⁻²
2894
2915
 
2895
2916
  Returns
2896
2917
  -------
2897
2918
  pdc: numeric
2898
2919
  DC power. [W]
2899
2920
 
2921
+ Notes
2922
+ -----
2923
+ The PVWatts Version 5 DC model [1]_ is:
2924
+
2925
+ .. math::
2926
+
2927
+ P_{dc} = \frac{G_{poa eff}}{1000} P_{dc0} ( 1 + \gamma_{pdc} (T_{cell} - T_{ref}))
2928
+
2929
+ This model has also been referred to as the power temperature coefficient
2930
+ model.
2931
+
2932
+ An optional adjustment can be applied to :math:`P_{dc}` as described in
2933
+ [2]_. The adjustment accounts for the variation in module efficiency with
2934
+ irradiance. The piece-wise adjustment to power is parameterized by `k`,
2935
+ where `k` is the reduction in actual power at 200 Wm⁻² relative to power
2936
+ calculated at 200 Wm⁻² as 0.2*`pdc0`. For example, a module that is rated
2937
+ at 500 W at STC but produces 95 W at 200 Wm⁻² (a 5% relative reduction in
2938
+ efficiency) would have a value of `k` = 0.01.
2939
+
2940
+ .. math::
2941
+
2942
+ k=\frac{0.2P_{dc0}-P_{200}}{P_{dc0}}
2943
+
2944
+ For positive `k` values, and `k` is typically positive, this adjustment
2945
+ would also increase relative efficiency when irradiance is above 1000 Wm⁻².
2946
+ This may not be desired, as modules with nonlinear irradiance response
2947
+ often have peak efficiency near 1000 Wm⁻², and it is either flat or
2948
+ declining at higher irradiance. An optional parameter, `cap_adjustment`,
2949
+ can address this by modifying the adjustment from [2]_ to only apply below
2950
+ 1000 Wm⁻².
2951
+
2952
+ Note that ``pdc0`` is also used as a symbol in
2953
+ :py:func:`pvlib.inverter.pvwatts`. ``pdc0`` in this function refers to the
2954
+ DC power of the modules at reference conditions. ``pdc0`` in
2955
+ :py:func:`pvlib.inverter.pvwatts` refers to the DC power input limit of
2956
+ the inverter.
2957
+
2900
2958
  References
2901
2959
  ----------
2902
- .. [1] A. P. Dobos, "PVWatts Version 5 Manual"
2903
- http://pvwatts.nrel.gov/downloads/pvwattsv5.pdf
2904
- (2014).
2960
+ .. [1] A. P. Dobos, "PVWatts Version 5 Manual", NREL, Golden, CO, USA,
2961
+ Technical Report NREL/TP-6A20-62641, 2014, :doi:`10.2172/1158421`.
2962
+ .. [2] B. Marion, "Comparison of Predictive Models for Photovoltaic
2963
+ Module Performance," In Proc. 33rd IEEE Photovoltaic Specialists
2964
+ Conference (PVSC), San Diego, CA, USA, 2008, pp. 1-6,
2965
+ :doi:`10.1109/PVSC.2008.4922586`.
2966
+ Pre-print: https://docs.nrel.gov/docs/fy08osti/42511.pdf
2905
2967
  """ # noqa: E501
2906
2968
 
2907
2969
  pdc = (effective_irradiance * 0.001 * pdc0 *
2908
2970
  (1 + gamma_pdc * (temp_cell - temp_ref)))
2909
2971
 
2972
+ # apply Marion's correction if k is provided
2973
+ if k is not None:
2974
+
2975
+ # preserve input types
2976
+ index = pdc.index if isinstance(pdc, pd.Series) else None
2977
+ is_scalar = np.isscalar(pdc)
2978
+
2979
+ # calculate error adjustments
2980
+ err_1 = k * (1 - (1 - effective_irradiance / 200)**4)
2981
+ err_2 = k * (1000 - effective_irradiance) / (1000 - 200)
2982
+ err = np.where(effective_irradiance <= 200, err_1, err_2)
2983
+
2984
+ # cap adjustment, if needed
2985
+ if cap_adjustment:
2986
+ err = np.where(effective_irradiance >= 1000, 0, err)
2987
+
2988
+ # make error adjustment
2989
+ pdc = pdc - pdc0 * err
2990
+
2991
+ # set negative power to zero
2992
+ pdc = np.where(pdc < 0, 0, pdc)
2993
+
2994
+ # preserve input types
2995
+ if index is not None:
2996
+ pdc = pd.Series(pdc, index=index)
2997
+ elif is_scalar:
2998
+ pdc = float(pdc)
2999
+
2910
3000
  return pdc
2911
3001
 
2912
3002
 
@@ -2945,9 +3035,8 @@ def pvwatts_losses(soiling=2, shading=3, snow=0, mismatch=2, wiring=2,
2945
3035
 
2946
3036
  References
2947
3037
  ----------
2948
- .. [1] A. P. Dobos, "PVWatts Version 5 Manual"
2949
- http://pvwatts.nrel.gov/downloads/pvwattsv5.pdf
2950
- (2014).
3038
+ .. [1] A. P. Dobos, "PVWatts Version 5 Manual", NREL, Golden, CO, USA,
3039
+ Technical Report NREL/TP-6A20-62641, 2014, :doi:`10.2172/1158421`.
2951
3040
  """
2952
3041
 
2953
3042
  params = [soiling, shading, snow, mismatch, wiring, connections, lid,