Exemple #1
0
    def connect(self, connection):
        """Connect something to the junction. This is a lot like a Connector, but there is no limit on the number of things, and the rule Connector -> junction is of course reversed here."""
        if connection in self.connections:
            debug.verbose(self, "already connected to", connection)
            return

        # Connect directly to connections, that's the name of the game.
        if isinstance(connection, Connector.Connector):
            self.connections.add(connection)
            connection.connect(self)
            return

        # We can connect to other Junctions (even if that is a bit pointless, it might end up making some circuits neater), but we need to create a connection to go between them.
        if isinstance(connection, Junction):

            conn = Connector.Connector(connection,
                                       self,
                                       name="AutoGeneratedConnection",
                                       label="")
            # Hopefully that constructor has done everything needed
            return

        # If we reach this point then we haven't known how to connect to whatever it is, which means either somebody is trying to do something really weird, or we just haven't implemented that yet
        raise NotImplementedError("Don't know how to add a connection from " +
                                  str(connection) + " to " + str(self) +
                                  ". Maybe try the other way around?")
    def connect(self, connection):
        """Connect one end of a connection to the object 'connection' """
        # Don't doubly connect. This doesn't prevent us from doing anything as the only real use case for that would be to connect both ends of the resistor to the same junction, which shorts out the resistor and so is not an important situation. If we do really want to short out a resistor for whatever reason we can use two junctions and a wire (or 0Ohm resistor)
        # In cases like that the thing in self.connections will be the junction, so this will pass by here anyway
        debug.verbose("In ", self, ".connect(", connection, ")")

        if connection in self.connections:
            debug.verbose(self, "already connected to", connection)
            return

        # Resistors can only connect to two places. Those places should be junctions, which can connect to arbitrarily many things, but a resistor itself has two ends.
        if len(self.connections) == 2:
            raise CircuitExceptions.ConnectionError(
                "Connector " + str(self) +
                " cannot connect to more than two places.")

        # Ok, we want to connect. Great. How should we connect?

        # Connect directly to junctions, that's what they're for
        if isinstance(connection, Junction.Junction):
            self.connections.add(connection)
            connection.connect(self)
            return

        # We can connect to other Connectors, but we need to create a junction at which to do so
        if isinstance(connection, Connector):
            junc = Junction.Junction(self,
                                     connection,
                                     name="AutoGeneratedJunction",
                                     label="")
            return
        # If we reach this point then we haven't known how to connect to whatever it is, which means either somebody is trying to do something really weird, or we just haven't implemented that yet
        raise NotImplementedError("Don't know how to add a connection from " +
                                  str(connection) + " to " + str(self) +
                                  ". Maybe try the other way around?")
Exemple #3
0
  def getTheveninEquiv(self, exclude=None):
    """ 
    The Thevenin equivalent of a source is ... the source.

    Returns two values, the effective voltage and resistance.
    """
    debug.verbose("Generating Thevenin equiv for", self, "- 0V via inf Ohms")
    return 0.0, np.inf
Exemple #4
0
    def getTheveninEquiv(self, exclude=None):
        """ 
    The Thevenin equivalent of a source is ... the source.

    Returns two values, the effective voltage and resistance.
    """
        debug.verbose("Generating Thevenin equiv for", self,
                      "- fixed voltage of", self.voltage(), "V")
        return self.voltage(), 0.0
  def connect(self, connection, connectionName=None):
    """A voltage source has two special connections, +ve and negative. As such this function should never be called by anything but the end user, who should probably only call it via a helper or init function anyway"""
    debug.verbose( "In ", self, ".connect(", connection, ", ",connectionName,")")
    debug.indent()
    debug.verbose("Has connections :  ",self.connections)
    debug.unindent()
    
    if isinstance(connectionName , str):
      try:
        conenctionName=self.avaliableConnections[connectionName]
      except KeyError:
        raise ConnectionError(str(self)+" does not have a connection \""+connectionName+"\"")
      
    
    # Check to see if we're already connected
    if connection in self.connections:
      debug.verbose( self, "already connected to", connection)
      # If we're already connected to the same polarity (or if we've not been told which polarity) then assume we're ok to leave it as is. This is mainly so the reverse connection is gracefully ignored
      if connectionName is None:
        return
      
      
      if self.connectionMap[connectionName] != connection:
        # Not just trying to reconnect, trying to short us out or similar. Bad times.
        raise ConnectionError("Trying to connect "+str(connection)+" to "+str(self)+", but that looks like it would be a short!")
      return

    #Not already connected, no name specified, what can we do?
    if connectionName is None:
      raise ConnectionError("Tried to connected to a polarized device without specifying a polarity.")

    # Connect directly to connections, that's the name of the game.
    if isinstance(connection, Junction.Junction):
      self.connectionMap[connectionName]=connection
      # Also maintain the standard connection system
      self.connections.add(connection)
      connection.connect(self)
      return

    # We can connect to other Connectors, but we need to create a junction at which to do so
    if isinstance(connection, Connector.Connector):
      junc = Junction.Junction(name="AutoGeneratedJunction")
      connection.connect(junc)
      self.connect(junc, connectionName)
      return
    # If we reach this point then we haven't known how to connect to whatever it is, which means either somebody is trying to do something really weird, or we just haven't implemented that yet
    raise NotImplementedError("Don't know how to add a connection from "+str(connection)+" to "+str(self))
    def getTheveninEquiv(self, excluded=[]):
        """ 
    Traverse the graph to determine the voltage of this node, and the output impedance 
    If excluded is specified as either an object or a iterable of objects connections that lead to these objects are ignored, to prevent cycles.

    """
        debug.verbose("Generating Thevenin equiv for", self)

        # Make sure excluded is iterable
        if not hasattr(excluded, "__iter__"):
            excluded = [excluded]

        if len(excluded) > 0:
            entryPoint = excluded[-1]
        else:
            entryPoint = None
        # Keep track of the properties of what we're connected to in a set.
        connectedDevices = set(())

        # We can tot up the total conductance easily
        conductance = 0.0

        # i is a counter that we can use to ensure that every connection is unique. This is needed as we're using a  set, which really simplifies the calculation at the end, but has the problem that if multiple connections return the same properties all but the first are ignored
        i = 0

        # Follow every link
        for connection in self.connections:
            debug.verbose("At", self, "considering connection to", connection)

            if not connection in excluded:
                # If we've not been told to exclude it follow the link to a simplified source.
                v, r = connection.getTheveninEquiv(excluded + [self])
                # Add the resistance of this link. Everything has a resistance, and it's zero if it hasn't been explicitly set, so we can do this without worrying if it makes any particular physical sense or not

                debug.verbose("--Adding", v, "V via", r, "Ohms")
                # Add the result (and the counter) to the set of connections
                connectedDevices.add((v, r, i))

                # If the resistance of the source is non zero add its reciprocal (the conductance) to the accumulator
                conductance += np.float64(1.0) / r
            else:
                debug.verbose("--Connection Excluded")
            debug.verbose("Connection list :  ", connectedDevices)
            i += 1

        connectedDevices = {x for x in connectedDevices if not x[1] == np.inf}
        debug.verbose("Remove inf resistances :  ", connectedDevices)

        voltageNumerator = 0.0
        voltageDenominator = 0.0

        # Calculate the equivalent voltage:
        #   V1*R2..Rn + V2*R1R3..Rn + ... Vn*R1..R[n-1]
        # V=  ___________________________________________
        #     R2R3..Rn + R1R3..Rn + ... + R1R2..R[n-1]

        for device in connectedDevices:  # For everything we're connected to
            resistanceProduct = 1.0
            # Find the product of all the other resistances. This is why we use a set, it's really easy to get the list of everything that isn't the current connection
            # Consider everything else as a voltage and resistance
            for v, r, _ in connectedDevices.difference(set([device])):
                resistanceProduct *= r

            # We can sum the two parts of the fraction and divide at the end.
            voltageDenominator += resistanceProduct
            voltageNumerator += device[0] * resistanceProduct

        # And now the results are easy to get
        outputVoltage = np.float64(voltageNumerator) / voltageDenominator
        outputResistance = np.float64(1.0) / conductance

        outputResistance += self.resistance(fromConnection=entryPoint)
        outputVoltage += self.voltage(fromConnection=entryPoint)

        return outputVoltage, outputResistance