def v(resistances, r_i, applied_voltages, **kwargs):
    """Solves matrix equation `gv = i`.

    Parameters
    ----------
    resistances : ndarray
        Resistances of crossbar devices.
    r_i : named tuple of (int or float)
        Interconnect resistances along the word and bit line segments.
    applied_voltages : ndarray
        Applied voltages.

    Returns
    -------
    ndarray
        Matrix containing potentials at each of the nodes.
    """
    if r_i.word_line > 0 or r_i.bit_line > 0:
        g = fill.g(resistances, r_i)
        i = fill.i(applied_voltages, resistances, r_i)

        utils.message('Started solving for v.', **kwargs)
        v_matrix = linalg.spsolve(g.tocsc(), i)
        utils.message('Solved for v.', **kwargs)

        # if `num_examples == 1`, it can result in 1D array.
        if v_matrix.ndim == 1:
            v_matrix = v_matrix.reshape(v_matrix.shape[0], 1)

        # if one of the interconnect resistances is zero, only half of the
        # matrix_v had to be solved. The other half can be filled without
        # solving because the node voltages are known.
        if r_i.word_line == 0:
            new_v_matrix = np.zeros(
                (2*resistances.size, applied_voltages.shape[1]))
            new_v_matrix[:resistances.size, ] = np.repeat(
                applied_voltages, resistances.shape[1], axis=0)
            new_v_matrix[resistances.size:, ] = v_matrix
            v_matrix = new_v_matrix
        if r_i.bit_line == 0:
            new_v_matrix = np.zeros(
                (2*resistances.size, applied_voltages.shape[1]))
            new_v_matrix[:resistances.size, ] = v_matrix
            v_matrix = new_v_matrix
    else:
        # if both interconnect resistances are zero, all node voltages are
        # known.
        v_matrix = np.zeros(
                (2*resistances.size, applied_voltages.shape[1]))
        v_matrix[:resistances.size, ] = np.repeat(
                applied_voltages, resistances.shape[1], axis=0)

    return v_matrix
Beispiel #2
0
def currents(extracted_voltages, resistances, r_i, applied_voltages, **kwargs):
    """Extracts crossbar branch currents in a convenient format.
    
    Parameters
    ----------
    extracted_voltages : named tuple
        Crossbar node voltages. It has fields `word_line` and `bit_line` that
        contain the potentials at the nodes on the word and bit lines.
    resistances : ndarray
        Resistances of crossbar devices.
    r_i : named tuple of (int or float)
        Interconnect resistances along the word and bit line segments.
    applied_voltages : ndarray
        Applied voltages.
    **kwargs
        all_currents : bool, optional
            If False, only output currents are returned, while all the other
            ones are set to None.

    Returns
    -------
    named tuple
        Crossbar branch currents. Named tuple has fields `output`, `device`,
        `word_line` and `bit_line` that contain output currents, as well as
        currents flowing through the devices and interconnect segments of the
        word and bit lines.
    """
    device_i = device_currents(extracted_voltages, resistances)
    output_i = output_currents(extracted_voltages, device_i, r_i)
    if kwargs.get('all_currents'):
        word_line_i = word_line_currents(extracted_voltages, device_i, r_i,
                                         applied_voltages)
        bit_line_i = bit_line_currents(extracted_voltages, device_i, r_i)
        utils.message('Extracted currents from all branches in the crossbar.',
                      **kwargs)
    else:
        device_i = word_line_i = bit_line_i = None
        utils.message('Extracted output currents.', **kwargs)

    extracted_currents = Currents(output_i, device_i, word_line_i, bit_line_i)
    return extracted_currents
Beispiel #3
0
def voltages(v, resistances, **kwargs):
    """Extracts crossbar node voltages in a convenient format.

    Parameters
    ----------
    v : ndarray
        Solution to gv = i in a flattened form.
    resistances : ndarray
        Resistances of crossbar devices.

    Returns
    -------
    named tuple
        Crossbar node voltages. It has fields `word_line` and `bit_line` that
        contain the potentials at the nodes on the word and bit lines.
    """
    word_line_v = word_line_voltages(v, resistances)
    bit_line_v = bit_line_voltages(v, resistances)
    extracted_voltages = Voltages(word_line_v, bit_line_v)
    if kwargs.get('node_voltages'):
        utils.message('Extracted node voltages.', **kwargs)
    return extracted_voltages
Beispiel #4
0
def insulating_interconnect_solution(resistances, applied_voltages, **kwargs):
    """Extracts solution when all interconnects are perfectly insulating.

    Parameters
    ----------
    resistances : ndarray
        Resistances of crossbar devices.
    applied_voltages : ndarray
        Applied voltages.
    **kwargs
        all_currents : bool, optional
            If False, only output currents are returned, while all the other
            ones are set to None.
        verbose : int
            If 2, makes sure that warning is displayed.

    Returns
    -------
    named tuple
        Branch currents and node voltages of the crossbar.
    """
    extracted_voltages = Voltages(None, None)
    if kwargs.get('node_voltages'):
        initial_verbose = kwargs.get('verbose')

        if initial_verbose == 2:
            kwargs['verbose'] = 1

        utils.message(
            'Warning: all interconnects are perfectly insulating! Node '
            'voltages are undefined!', **kwargs)

        if initial_verbose == 2:
            kwargs['verbose'] = 2

    output_i = np.zeros((applied_voltages.shape[1], resistances.shape[1]))
    if kwargs.get('all_currents', True):
        same_i = np.zeros((resistances.shape[0], resistances.shape[1],
                           applied_voltages.shape[1]))
        same_i = utils.squeeze_third_axis(same_i)
        device_i = word_line_i = bit_line_i = same_i
        utils.message('Extracted currents from all branches in the crossbar.',
                      **kwargs)
    else:
        device_i = word_line_i = bit_line_i = None
        utils.message('Extracted output currents.', **kwargs)

    extracted_currents = Currents(output_i, device_i, word_line_i, bit_line_i)
    extracted_solution = Solution(extracted_currents, extracted_voltages)

    return extracted_solution
def compute(
        applied_voltages, resistances, r_i=None,
        r_i_word_line=None, r_i_bit_line=None, **kwargs):
    """Computes branch currents and node voltages of a crossbar.

    Parameters
    ----------
    applied_voltages : array_like
        Applied voltages. Voltages must be supplied in an array of shape `m x
        p`, where `m` is the number of word lines and `p` is the number of
        examples (sets of voltages applied one by one).
    resistances : array_like
        Resistances of crossbar devices. Resistances must be supplied in an
        array of shape `m x n`, where `n` is the number of bit lines.
    r_i : int or float, optional
        Interconnect resistance of the word and bit line segments. If None,
        `r_i_word_line` and `r_i_bit_line` are used instead.
    r_i_word_line : int or float, optional
        Interconnect resistance of the word line segments.
    r_i_bit_line : int or float, optional
        Interconnect resistance of the bit line segments.
    **kwargs
        node_voltages : bool, optional
            If False, None is returned instead of node voltages.
        all_currents : bool, optional
            If False, only output currents are returned, while all the other
            ones are set to None.
        verbose : {1, 2, 0}, optional
            If 1, all messages are shown. If 2, only warnings are shown. If
            0, no messages are shown.
        show_time : bool, optional
            If True, includes current time when the messages are printed.
        gap_size : int, optional
            Number of whitespace characters to be printed between current
            time and the message.

    Returns
    -------
    named tuple
        Branch currents and node voltages of the crossbar. Field `currents`
        is a named tuple itself with fields `output`, `device`, `word_line`
        and `bit_line` and contains output currents, as well as currents
        flowing through the devices and interconnect segments of the word and
        bit lines. Field `voltages` is a named tuple itself with fields
        `word_line` and `bit_line` and contains the voltages at the nodes on
        the word and bit lines. `currents.output` is an array of shape `p x n`,
        while all the others are arrays of shape `m x n` if `p == 1`,
        or arrays of shape `m x n x p` if `p > 1`.
    """
    kwargs.setdefault('node_voltages', True)
    kwargs.setdefault('all_currents', True)
    kwargs.setdefault('verbose', 1)
    kwargs.setdefault('show_time', True)
    kwargs.setdefault('gap_size', 5)

    if r_i is not None:
        r_i_word_line = r_i_bit_line = r_i

    resistances, applied_voltages = check.crossbar_requirements(
        resistances, applied_voltages, r_i_word_line, r_i_bit_line)

    utils.message('Initialising simulation.', **kwargs)

    solution = computing.extract.solution(
            resistances, r_i_word_line, r_i_bit_line,
            applied_voltages, **kwargs)

    return solution