def adrinverter(v_dc, p_dc, inverter, vtol=0.10):
    r'''
    Converts DC power and voltage to AC power using Anton Driesse's
    Grid-Connected PV Inverter efficiency model

    Parameters
    ----------
    v_dc : numeric
        A scalar or pandas series of DC voltages, in volts, which are provided
        as input to the inverter. If Vdc and Pdc are vectors, they must be
        of the same size. v_dc must be >= 0. (V)

    p_dc : numeric
        A scalar or pandas series of DC powers, in watts, which are provided
        as input to the inverter. If Vdc and Pdc are vectors, they must be
        of the same size. p_dc must be >= 0. (W)

    inverter : dict-like
        A dict-like object defining the inverter to be used, giving the
        inverter performance parameters according to the model
        developed by Anton Driesse [1].
        A set of inverter performance parameters may be loaded from the
        supplied data table using retrievesam.
        See Notes for required keys.

    vtol : numeric, default 0.1
        A unit-less fraction that determines how far the efficiency model is
        allowed to extrapolate beyond the inverter's normal input voltage
        operating range. 0.0 <= vtol <= 1.0

    Returns
    -------
    ac_power : numeric
        A numpy array or pandas series of modeled AC power output given the
        input DC voltage, v_dc, and input DC power, p_dc. When ac_power would
        be greater than pac_max, it is set to p_max to represent inverter
        "clipping". When ac_power would be less than -p_nt (energy consumed
        rather  than produced) then ac_power is set to -p_nt to represent
        nightly power losses. ac_power is not adjusted for maximum power point
        tracking (MPPT) voltage windows or maximum current limits of the
        inverter.

    Notes
    -----

    Required inverter keys are:

    =======   ============================================================
    Column    Description
    =======   ============================================================
    p_nom     The nominal power value used to normalize all power values,
              typically the DC power needed to produce maximum AC power
              output, (W).

    v_nom     The nominal DC voltage value used to normalize DC voltage
              values, typically the level at which the highest efficiency
              is achieved, (V).

    pac_max   The maximum AC output power value, used to clip the output
              if needed, (W).

    ce_list   This is a list of 9 coefficients that capture the influence
              of input voltage and power on inverter losses, and thereby
              efficiency.

    p_nt      ac-power consumed by inverter at night (night tare) to
              maintain circuitry required to sense PV array voltage, (W).
    =======   ============================================================

    References
    ----------
    [1] Beyond the Curves: Modeling the Electrical Efficiency
        of Photovoltaic Inverters, PVSC 2008, Anton Driesse et. al.

    See also
    --------
    sapm
    singlediode
    '''

    p_nom = inverter['Pnom']
    v_nom = inverter['Vnom']
    pac_max = inverter['Pacmax']
    p_nt = inverter['Pnt']
    ce_list = inverter['ADRCoefficients']
    v_max = inverter['Vmax']
    v_min = inverter['Vmin']
    vdc_max = inverter['Vdcmax']
    mppt_hi = inverter['MPPTHi']
    mppt_low = inverter['MPPTLow']

    v_lim_upper = float(np.nanmax([v_max, vdc_max, mppt_hi]) * (1 + vtol))
    v_lim_lower = float(np.nanmax([v_min, mppt_low]) * (1 - vtol))

    pdc = p_dc / p_nom
    vdc = v_dc / v_nom
    # zero voltage will lead to division by zero, but since power is
    # set to night time value later, these errors can be safely ignored
    with np.errstate(invalid='ignore', divide='ignore'):
        poly = np.array([pdc**0,  # replace with np.ones_like?
                         pdc,
                         pdc**2,
                         vdc - 1,
                         pdc * (vdc - 1),
                         pdc**2 * (vdc - 1),
                         1. / vdc - 1,  # divide by 0
                         pdc * (1. / vdc - 1),  # invalid 0./0. --> nan
                         pdc**2 * (1. / vdc - 1)])  # divide by 0
    p_loss = np.dot(np.array(ce_list), poly)
    ac_power = p_nom * (pdc-p_loss)
    p_nt = -1 * np.absolute(p_nt)

    # set output to nan where input is outside of limits
    # errstate silences case where input is nan
    with np.errstate(invalid='ignore'):
        invalid = (v_lim_upper < v_dc) | (v_dc < v_lim_lower)
    ac_power = np.where(invalid, np.nan, ac_power)

    # set night values
    ac_power = np.where(vdc == 0, p_nt, ac_power)
    ac_power = np.maximum(ac_power, p_nt)

    # set max ac output
    ac_power = np.minimum(ac_power, pac_max)

    if isinstance(p_dc, pd.Series):
        ac_power = pd.Series(ac_power, index=pdc.index)

    return ac_power