lunes, 9 de abril de 2018

Resolución de circuitos mediante Python

Python es un leguage interpretado que es muy popular actualmente.

Se usa en un amplio rango de aplicaciones incluyendo las asociadas a cálculos científicos, gracias a las librerias de SciPy.

Esra entrada del blog está ligada a un par de documentos de Google Colaboratory. Los documentos de Colaboratory son Jupyter Notebooks almacenados en una cuenta Google Drive que ejecutan el código en máquinas virtuales propiedad de Google.

De este modo no es necesario tener instalado Python para probar o modificar el código propuesto.

Resolución de circuitos con SymPy

SymPy es una de las librerias de SciPy. Ésta permite realizar cálculo matemáticos simbólicos. Ello es muy útil para resolver circuitos como el que se muestra a continuación:

Para resolver un circuito necesitamos obtener un conjunto de ecuaciones cuya solución es la magnitud que deseamos conocer. En el circuito mostrado, digamos que queremos conocer el valor de Vo en función de Vs, R1, R2 e Is.

Hemos de empezar definiendo simbolos para el circuito. Necesitamos símbolos para los valores de los componentes Vs, R1, R2 e Is y para la solución Vo.Como vamos a resolver el circuito empleando el método nodal que define ecuaciones de corriente en todos los nodos excepto masa, necesitaremos también símbolos para las tensiones nodales  V1 y V2.
Además, usando el método nodal completo, también necesitamos un símbolo, como iVs para la corriente en la fuente de tensión.


# Create the circuit symbols
Vs,iVs,R1,R2,Is,Vo, V1, V2 = sympy.symbols('Vs,iVs,R1,R2,Is,Vo,V1,V2')


Ara definimos las ecuaciones de los nodos 1 y 2. Para hacerlo, inicializamos una lista vacía de ecuaciones y añadimos las dos ecuaciones a la lista. Dado que estamos en el método nodal, esta ecuaciones consisten en aplicar La Ley de Kirchhoff KCL en ambos nodos:


# Create an empty list of equations
equations = []

# Nodal equations
equations.append(iVs-(V1-V2)/R1)       # Node 1
equations.append(Is-(V2-V1)/R1-V2/R2)  # Node 2


En SymPy se asume que todas las ecuacuiones son igual a cero.

En el método nodal también necesitamos añadir una ecuación para cada fuente de tensión que la relacione con las tensiones nodales.
En SymPy, Eq significa igual, por lo que Eq(Vs,V1) significa Vs = V1.

# Voltage source equations
equations.append(sympy.Eq(Vs,V1))


La última ecuación que hemos de añadir es la que contiene la magnitud que deseamos obtener:

# Measurement equations
equations.append(sympy.Eq(Vo,V2))



Con todo ello tenemos ya el conjunto de ecuaciones del circuito:

iVs - (V1 - V2)/R1
Is - V2/R2 - (-V1 + V2)/R1
Eq(Vs, V1)
Eq(Vo, V2)

Estas ecuaciones permiten obtener Vo pero no son necesariamente las mínimas ecuaciones que permiten halla esta solució. En concreto, dado que la primera ecuación contiene una incógnita iVs que no aparece en ninguna otra ecuación, la podemos eliminar de la lista si la única incógnita que deseamos obtener es Vo. En todo caso, no nos hace falta saber esto para resolver el sistema.

En las ecuaciones algunas variables son incógnitas. Haremos una lista de ellas:

unknowns = [V1,V2,iVs,Vo]

A partir de ello podemos resolver el sistema usando la función solve de la libreria SymPy :

# Solve the circuit
solution = sympy.solve(equations,unknowns)


Ello da lugar a la siguiente lista de soluciones para las incógnitas del circuito:

V1 = Vs
V2 = R2*(Is*R1 + Vs)/(R1 + R2)
iVs = (-Is*R2 + Vs)/(R1 + R2)
Vo = R2*(Is*R1 + Vs)/(R1 + R2)

Si deseas más detalles, más soluciones de circuitos o probar el código personalmente, abre este documento colaboratory.


Automatizando la solución

Como se ha visto, hemos seguido la receta del método nodal para resolver el circuito. Ello significa que el método puede ser automatizado. The módulo Python circuit se encarga precisamente de ello. Resuelve un circuito usando la receta del método nodal.

Recordemos otra vez el circuito a resolver:

Lo podemos describir con una lista de componentes y medidas a realizar:

# Circuit 1 definiton
c1 = circuit.circuit()  # New circuit
c1.addV('Vs',1,0,5)     # Vs between 1 and GND with 5 V value
c1.addR('R1',1,2,1000)  # R1 between 1 and 2 with 1000 Ohm value
c1.addR('R2',2,0,1000)  # R2 between 2 and GND with 1000 Ohm value
c1.addI('Is',2,0,0.01)  # Is going from GND to 2 with 10 mA value
c1.addVM('Vo',2,0)      # Measurement Vo between 2 and GND


Una vez definido el circuito podemos resolverlo para la incógnita Vo:

# Symbolic solution
print('Vo =',c1.solution['Vo'],'  (Symbolic)')


Ello da lugar a:

Vo = R2*(Is*R1 + Vs)/(R1 + R2)   (Symbolic)

Obsérvese que esta es exactamente la  misma solución que obtuvimos previamente usando el módulo SymPy aislado.


Dado que hemos indicado los valores de los componentes, podemos obtener también una solución numérica:

# Numeric solution
print('Vo =',c1.particular['Vo'],'V   (Particular)')


Ello da lugar a:

Vo = 7.5 V   (Particular)

Si deseas saber más sobre el módulo circuit, ver otras soluciones o probar tu propio código, abre este documento de google colaboratory.