Source code for simudo.example.fourlayer.IV_Analysis

import numpy as np
from scipy.interpolate import interp1d
from scipy.interpolate import UnivariateSpline

__all__ = ["IV_params"]

# From Matt Wilkins


def ordertest(A):
    """Test if list ``A`` is strictly ascending."""
    return all(A[k] <= A[k + 1] for k in range(len(A) - 1))


[docs]class IV_params: """ Takes arrays of current and voltage, and interpolates Voc, Isc, and Pmax. ``voc`` and ``isc`` are linearly interpolated, ``pmax`` is found with a spline fit. If v and i are in V and A respectively, then pmax is in W. If the the power quadrant has negative I (as for Simudo), use optional argument ``powersign=-1.0``. Example ------- :: p = iv_params(current_array, voltage_array) print(p.voc, p.isc, p.pmax, p.ff, p.mppv, p.mppi) """ def __init__(self, i, v, powersign=1.0): self.i = np.array(i) self.v = np.array(v) assert len(i) == len(v), "Unequal length arrays" if ordertest(v) == False: self.i = self.i[::-1] self.v = self.v[::-1] assert ordertest( self.v ), "Voltage array out of order, must be monotonic" assert ( max(i) >= 0.0 and min(i) <= 0.0 and max(i) > min(i) ), "Current array does not cross zero" assert ( max(v) >= 0.0 and min(v) <= 0.0 and max(v) > min(v) ), "Voltage array does not cross zero" interp_i = interp1d(self.v, self.i, kind="linear") self.isc = float(interp_i(0.0)) interp_v = interp1d(self.i, self.v, kind="linear", bounds_error=False) self.voc = float(interp_v(0.0)) spline_P = UnivariateSpline( self.v, powersign * self.i * self.v, k=4, s=0 ) dPdV = spline_P.derivative() roots = dPdV.roots() Pmax = -1e10 for k in range(len(roots)): P = spline_P(roots[k]) if P > Pmax: Pmax = P self.mppv = roots[k] self.mppi = interp_i(self.mppv) self.pmax = spline_P(self.mppv) # self.mppi*self.mppv self.ff = self.pmax / (self.voc * self.isc)