Ask Your Question

solve() fails for 3 simple linear equations

asked 2021-10-14 20:24:40 +0100

tjrob gravatar image

I am doing basic circuit analysis, which involves solving multiple algebraic equations. solve() fails for a simple linear circuit (image does not work -- see circuit description below).

Vi, Vo, Vm, Vx, R1, R2, R3, C, A, s = var('Vi,Vo,Vm,Vx,R1,R2,R3,C,A,s')
# Three Kirchoff equations at nodes Vm, Vx, Vo
eq_at_Vm = (Vi-Vm)/R1 + (Vx-Vm)/R2 == 0
eq_at_Vx = (Vm-Vx)/R2 + (Vo-Vx)/R3 + (0-Vx)/(1/(C*s)) == 0
eq_at_Vo = Vo == -A*Vm
# solving for Vo FAILS

The output is just [].

Am I doing something wrong, or is this a limitation of solve()?

I did find a workaround, solving each equation individually, which in this case is easy, but in general is not:

Vi, Vo, Vm, Vx, R1, R2, R3, C, A, s = var('Vi,Vo,Vm,Vx,R1,R2,R3,C,A,s')
# Three Kirchoff equations at nodes Vm, Vx, Vo
eq_at_Vm = (Vi-Vm)/R1 + (Vx-Vm)/R2 == 0
eq_at_Vx = (Vm-Vx)/R2 + (Vo-Vx)/R3 + (0-Vx)/(1/(C*s)) == 0
eq_at_Vo = Vo == -A*Vm
# eliminate Vm
Vm_eq = solve(eq_at_Vo,Vm)[0]
eq_at_Vm = eq_at_Vm.substitute(Vm_eq)
eq_at_Vx = eq_at_Vx.substitute(Vm_eq)
# eliminate Vx
Vx_eq = solve(eq_at_Vm,Vx)[0]
eq_at_Vx = eq_at_Vx.substitute(Vx_eq)
# final transfer function

The output is: Vo/Vi == -(A*C*R2*R3*s + A*R2 + A*R3)/((C*R1 + C*R2)*R3*s + (A + 1)*R1 + R2 + R3)

Circuit Description: This is an inverting OpAmp with a R2-C-R3 Tee network as feedback. The OpAmp has gain=A with in+ grounded, so Vo=-A*in-. Nodes are labeled Vi, Vm, Vx, Vo: Vi is the input, Vo is the OpAmp output, Vm is the OpAmp in-, and Vx is inside the Tee. R1 is Vi to Vm, R2 is Vm to Vx, R3 is Vx to Vo, and C is Vx to ground.

edit retag flag offensive close merge delete


Note that many asterisks got omitted in the output Vo/Vi, even after editing to indicate it is preformatted.

tjrob gravatar imagetjrob ( 2021-10-14 20:22:50 +0100 )edit

1 Answer

Sort by ยป oldest newest most voted

answered 2021-10-15 21:48:46 +0100

tmonteil gravatar image

updated 2021-10-15 21:53:50 +0100

By solving against Vo only, you do as if every other symbols involved in the equations were constants. However, Vi, Vm, Vx are also unknown.

Imagine that the solver would return [Vo == -A*Vm] as a solution, i bet you will not be very happy.

So, what you have to do is to put all unknowns, and let only the constants outside:

sage: solve([eq_at_Vm, eq_at_Vx, eq_at_Vo],[Vo, Vi, Vm, Vx])
[[Vo == (A*R3*r1 + (A*C*R3*r1*s + A*r1)*R2)/(A*R2 - R3), Vi == -((C*R3*r1*s + A*r1 + r1)*R1 + (C*R3*r1*s + r1)*R2 + R3*r1)/(A*R2 - R3), Vm == -((C*R3*r1*s + r1)*R2 + R3*r1)/(A*R2 - R3), Vx == r1]]

Now, as you can see, there is one degree of freedom : Vx can take any value, so Sage added a free parameter r1 and gave you all the solutions using the constants and this free parameter r1.

Now, i see in your workaround that you want to solve for Vo/Vi, so let me assume that you want Vi being the free parameter, not Vx.

Hence, you can solve as if Vi is also a constant:

sage: solve([eq_at_Vm, eq_at_Vx, eq_at_Vo],[Vo, Vm, Vx])
[[Vo == -((A*C*R3*s + A)*R2 + A*R3)*Vi/((C*R3*s + A + 1)*R1 + (C*R3*s + 1)*R2 + R3), Vm == ((C*R3*s + 1)*R2 + R3)*Vi/((C*R3*s + A + 1)*R1 + (C*R3*s + 1)*R2 + R3), Vx == -(A*R2 - R3)*Vi/((C*R3*s + A + 1)*R1 + (C*R3*s + 1)*R2 + R3)]]
edit flag offensive delete link more


Thanks. This makes sense.

tjrob gravatar imagetjrob ( 2021-10-22 17:17:26 +0100 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower


Asked: 2021-10-14 20:18:17 +0100

Seen: 121 times

Last updated: Oct 15 '21