Source code for pathsim.blocks.adder

#########################################################################################
##
##                                      ADDER BLOCK 
##                                   (blocks/adder.py)
##
##                                   Milan Rother 2024
##
#########################################################################################

# IMPORTS ===============================================================================

import numpy as np

from ._block import Block

from ..utils.utils import dict_to_array
from ..optim.operator import Operator


# MISO BLOCKS ===========================================================================

[docs] class Adder(Block): """Summs / adds up all input signals to a single output signal (MISO) This is how it works in the default case .. math:: y(t) = \\sum_i u_i(t) and like this when additional operations are defined .. math:: y(t) = \\sum_i \\mathrm{op}_i \\cdot u_i(t) Example ------- This is the default initialization that just adds up all the inputs: .. code-block:: python A = Adder() and this is the initialization with specific operations that subtracts the second from first input and neglects all others: .. code-block:: python A = Adder('+-') Parameters ---------- operations : str, optional optional string of operations to be applied before summation, i.e. '+-' will compute the difference, 'None' will just perform regular sum Attributes ---------- _ops : dict dict that maps string operations to numerical op_alg : Operator internal algebraic operator """ def __init__(self, operations=None): super().__init__() #allowed arithmetic operations self._ops = {"+":1.0, "-":-1.0, "0":0.0} #input validation if operations is not None: if not isinstance(operations, str): raise ValueError("'operations' must be string or 'None'") for op in operations: if op not in self._ops: raise ValueError(f"operation '{op}' not in {self._ops}") self.operations = operations def sum_ops(X): return sum(x*self._ops[op] for op, x in zip(self.operations, X)) def jac_ops(X): return np.array([self._ops[op] for op in self.operations]) #create internal algebraic operator self.op_alg = Operator( func=sum if self.operations is None else sum_ops, jac=lambda x: np.ones(len(x)) if self.operations is None else jac_ops )
[docs] def update(self, t): """update system equation in fixed point loop Parameters ---------- t : float evaluation time Returns ------- error : float absolute error to previous iteration for convergence control """ u = dict_to_array(self.inputs) _out, self.outputs[0] = self.outputs[0], self.op_alg(u) return abs(_out - self.outputs[0])