# Getting the symbolic solution of system of equations using ModelingToolKit

**URL:** https://discourse.julialang.org/t/getting-the-symbolic-solution-of-system-of-equations-using-modelingtoolkit/122786
**Category:** Modelling & Simulations
**Tags:** modelingtoolkit, symbolics
**Created:** [November 18, 2024, 8:22pm UTC](https://discourse.julialang.org/t/getting-the-symbolic-solution-of-system-of-equations-using-modelingtoolkit/122786 "2024-11-18T20:22:31Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![Ricardo\_Borges](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ricardo_borges/32/19918_2.png) [@Ricardo\_Borges](https://discourse.julialang.org/u/Ricardo_Borges)
#### Post date: [November 18, 2024, 8:22pm UTC](https://discourse.julialang.org/t/getting-the-symbolic-solution-of-system-of-equations-using-modelingtoolkit/122786/1 "2024-11-18T20:22:31Z")

</div>

Hi,

I have the following circuit, which is used to estimate the isolation resistance of high-voltage battery packs to the chassis / low-voltage reference. The switch SW is turned on and off, so there are 2 equations, to solve for RisoP and RisoN, and all the other values are known (the voltage Vadc is sensed by a microncontroller for each state of SW).

 ![image](https://global.discourse-cdn.com/julialang/original/3X/e/2/e27b3e259b5d514b63b53cfdf1c7ff02312e070f.png)

I want to get the symbolic equation for bith RisoP and RisoN. I can have the answer using SymPy:

```julia
using SymPy

Vpack, Vadc_off, Vadc_on, R1, R2, R3, RisoP, RisoN = symbols("Vpack, Vadc_off, Vadc_on, R1, R2, R3, RisoP, RisoN")

# RisoN || (R2+R3)
A = 1/(1/RisoN + 1/(R2+R3))
# RisoP || R1
B = 1/(1/RisoP + 1/R1)
# R3 / (R2+R3)
Vadc_ratio = R3/(R2+R3)

Vchassis_off = Vpack * (A / (RisoP + A))
Vchassis_on = Vpack * (A / (A+B))

eq1 = Vadc_off ~ Vchassis_off * Vadc_ratio
eq2 = Vadc_on ~ Vchassis_on * Vadc_ratio

ret = solve((eq1, eq2), (RisoP, RisoN))

RisoP_hat = ret[1][1]
RisoN_hat = ret[1][2]

println(RisoP_hat)
println(RisoN_hat)

----
R1*R3*Vpack*(Vadc_off - Vadc_on)/(Vadc_off*(R2*Vadc_on + R3*Vadc_on - R3*Vpack))
R1*R3*Vpack*(-R2*Vadc_off + R2*Vadc_on - R3*Vadc_off + R3*Vadc_on)/(R1*R3*Vadc_off*Vpack - R1*R3*Vadc_on*Vpack + R2^2*Vadc_off*Vadc_on + 2*R2*R3*Vadc_off*Vadc_on - R2*R3*Vadc_off*Vpack - R2*R3*Vadc_on*Vpack + R3^2*Vadc_off*Vadc_on - R3^2*Vadc_off*Vpack - R3^2*Vadc_on*Vpack + R3^2*Vpack^2)

```

As I’m trying to use MTK/SciML/Symbolics more extensively, I would like to use it to solve this problem. So, I have 2 questions:

1. Can SciML’s Symbolics solve that? When I try the following:

```julia
using ModelingToolkit
using Groebner

@variables Vpack R1 RisoP RisoN R2 R3 
@variables Vadc_off Vadc_on

# RisoN || (R2+R3)
A = 1/(1/RisoN + 1/(R2+R3))
# RisoP || R1
B = 1/(1/RisoP + 1/R1)
# R3 / (R2+R3)
Vadc_ratio = R3/(R2+R3)

Vchassis_off = Vpack * (A / (RisoP + A))
Vchassis_on = Vpack * (A / (A+B))

eq1 = Vadc_off ~ Vchassis_off * Vadc_ratio
eq2 = Vadc_on ~ Vchassis_on * Vadc_ratio

symbolic_solve([eq1, eq2], (RisoP, RisoN))

```

I get

```julia
┌ Info: Assuming (R2*RisoN + R2*RisoP + R3*RisoN + R3*RisoP + RisoN*RisoP) != 0
└ @ Symbolics /home/ricardo/.julia/packages/Symbolics/6CYZh/src/solver/preprocess.jl:53
┌ Info: Assuming (R1*R2*RisoN + R1*R2*RisoP + R1*R3*RisoN + R1*R3*RisoP + R1*RisoN*RisoP + R2*RisoN*RisoP + R3*RisoN*RisoP) != 0
└ @ Symbolics /home/ricardo/.julia/packages/Symbolics/6CYZh/src/solver/preprocess.jl:53
"Groebner bases engine is required. Execute `using Groebner` to enable this functionality."

```

1. If I model that circuit using @mtkmodel:

```julia
using ModelingToolkit, OrdinaryDiffEq, Plots
using ModelingToolkitStandardLibrary.Electrical
using ModelingToolkitStandardLibrary.Blocks: Constant
using ModelingToolkit: t_nounits as t

@mtkmodel simple_resistor begin
    @parameters begin
        Vpack = 800.0
        R1 = 4.0*499.0e3
        R2 = 4.0*499.0e3
        R3 = 1/3*60.4e3
        RisoP = 50e3
        RisoN = 100e3
    end
    @components begin
        r1 = Resistor(R = R1)
        r2 = Resistor(R = R2)
        r3 = Resistor(R = R3)
        risop = Resistor(R = RisoP)
        rison = Resistor(R = RisoN)
        source = Voltage()
        constant = Constant(k = Vpack)
        ground = Ground()
    end
    @equations begin
        connect(constant.output, source.V)
        connect(source.p, r1.p)
        connect(r1.n, r2.p)
        connect(r2.n, r3.p)

        connect(source.p, risop.p)
        connect(risop.n, rison.p)
        connect(risop.n, r2.p) # connects the resistor network with the chassis

        connect(source.n, r3.n, rison.n, ground.g)
    end
end

@mtkbuild sys_ON = simple_resistor()
@mtkbuild sys_OFF = simple_resistor(R1 = 1e18)

```

is there a way to get the symbolic solution for a variable, like sys\_ON.r3.v and sys\_OFF.r3.v (which would be the Vadc when SW is ON and OFF, respecitvely)? With those solutions, I can iterate one more time to solve for RisoP and RisoN.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [November 18, 2024, 8:46pm UTC](https://discourse.julialang.org/t/getting-the-symbolic-solution-of-system-of-equations-using-modelingtoolkit/122786/2 "2024-11-18T20:46:30Z")

</div>

> [@Ricardo\_Borges](#):
>
> ```julia
> "Groebner bases engine is required. Execute `using Groebner` to enable this functionality."
> 
> ```

Did you do this? I assume in your script you did execute that, so did it not load for you?

---

<div class="post-metadata">

### Author: ![Ricardo\_Borges](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ricardo_borges/32/19918_2.png) [@Ricardo\_Borges](https://discourse.julialang.org/u/Ricardo_Borges)
#### Post date: [November 19, 2024, 1:21pm UTC](https://discourse.julialang.org/t/getting-the-symbolic-solution-of-system-of-equations-using-modelingtoolkit/122786/3 "2024-11-19T13:21:18Z")

</div>

Yes, I run “using Groebner”, and I can see it’s loaded by:

```julia
using Pkg
Pkg.status()
Status `~/.julia/environments/v1.11/Project.toml`
  [6e4b80f9] BenchmarkTools v1.5.0
  [a93c6f00] DataFrames v1.7.0
⌃ [82cc6244] DataInterpolations v6.5.2
⌃ [0c46a032] DifferentialEquations v7.14.0
  [0b43b601] Groebner v0.8.2
⌃ [7073ff75] IJulia v1.25.0
  [a98d9a8b] Interpolations v0.15.1
⌃ [961ee093] ModelingToolkit v9.49.0
  [16a59e39] ModelingToolkitStandardLibrary v2.17.0
⌅ [8913a72c] NonlinearSolve v3.15.1
⌃ [1dea7af3] OrdinaryDiffEq v6.89.0
⌃ [f0f68f2c] PlotlyJS v0.18.14
⌃ [91a5bcdd] Plots v1.40.8
  [24249f21] SymPy v2.2.0
  [2efcf032] SymbolicIndexingInterface v0.3.34

```

The full error stack is:

```julia
┌ Info: Assuming (R2*RisoN + R2*RisoP + R3*RisoN + R3*RisoP + RisoN*RisoP) != 0
└ @ Symbolics /home/ricardo/.julia/packages/Symbolics/6CYZh/src/solver/preprocess.jl:53
┌ Info: Assuming (R1*R2*RisoN + R1*R2*RisoP + R1*R3*RisoN + R1*R3*RisoP + R1*RisoN*RisoP + R2*RisoN*RisoP + R3*RisoN*RisoP) != 0
└ @ Symbolics /home/ricardo/.julia/packages/Symbolics/6CYZh/src/solver/preprocess.jl:53

"Groebner bases engine is required. Execute `using Groebner` to enable this functionality."

Stacktrace:
 [1] solve_multivar(eqs::Vector{Num}, vars::Tuple{Num, Num}; dropmultiplicity::Bool, warns::Bool)
   @ Symbolics ~/.julia/packages/Symbolics/6CYZh/src/solver/main.jl:328
 [2] symbolic_solve(expr::Vector{Equation}, x::Tuple{Num, Num}; dropmultiplicity::Bool, warns::Bool)
   @ Symbolics ~/.julia/packages/Symbolics/6CYZh/src/solver/main.jl:204
 [3] symbolic_solve(expr::Vector{Equation}, x::Tuple{Num, Num})
   @ Symbolics ~/.julia/packages/Symbolics/6CYZh/src/solver/main.jl:145
 [4] top-level scope
   @ ~/jupyter/isolation_sensing/jl_notebook_cell_df34fa98e69747e1a8f8a730347b8e2f_W1sZmlsZQ==.jl:1

```

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [November 19, 2024, 3:30pm UTC](https://discourse.julialang.org/t/getting-the-symbolic-solution-of-system-of-equations-using-modelingtoolkit/122786/4 "2024-11-19T15:30:55Z")

</div>

Open an issue on Symbolics. That is a bug.

---

<div class="post-metadata">

### Author: ![Bart\_van\_de\_Lint](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bart_van_de_lint/32/212161_2.png) [@Bart\_van\_de\_Lint](https://discourse.julialang.org/u/Bart_van_de_Lint)
#### Post date: [November 20, 2024, 10:06am UTC](https://discourse.julialang.org/t/getting-the-symbolic-solution-of-system-of-equations-using-modelingtoolkit/122786/5 "2024-11-20T10:06:30Z")

</div>

I ran into the same problem and opened an issue.

> <https://github.com/JuliaSymbolics/Symbolics.jl/issues/1370>
>
> https://discourse.julialang.org/t/getting-the-symbolic-solution-of-system-of-equ…ations-using-modelingtoolkit/122786/3
> 
> solve\_multivar using Groebner is broken
> 
> \`\`\`julia
> using Symbolics
> using Groebner
> 
> @variables Vpack R1 RisoP RisoN R2 R3 
> @variables Vadc\_off Vadc\_on
> 
> \# RisoN || (R2+R3)
> A = 1/(1/RisoN + 1/(R2+R3))
> \# RisoP || R1
> B = 1/(1/RisoP + 1/R1)
> \# R3 / (R2+R3)
> Vadc\_ratio = R3/(R2+R3)
> 
> Vchassis\_off = Vpack \* (A / (RisoP + A))
> Vchassis\_on = Vpack \* (A / (A+B))
> 
> eq1 = Vadc\_off ~ Vchassis\_off \* Vadc\_ratio
> eq2 = Vadc\_on ~ Vchassis\_on \* Vadc\_ratio
> 
> symbolic\_solve(\[eq1, eq2\], (RisoP, RisoN))
> \`\`\`
> \`\`\`julia
> \[ Info: Assuming (R2\*RisoN + R2\*RisoP + R3\*RisoN + R3\*RisoP + RisoN\*RisoP) != 0
> \[ Info: Assuming (R1\*R2\*RisoN + R1\*R2\*RisoP + R1\*R3\*RisoN + R1\*R3\*RisoP + R1\*RisoN\*RisoP + R2\*RisoN\*RisoP + R3\*RisoN\*RisoP) != 0
> ERROR: LoadError: "Groebner bases engine is required. Execute \`using Groebner\` to enable this functionality."
> Stacktrace:
> \[1\] solve\_multivar(eqs::Vector{Num}, vars::Tuple{Num, Num}; dropmultiplicity::Bool, warns::Bool)
> @ Symbolics ~/.julia/packages/Symbolics/GYV9b/src/solver/main.jl:326
> \[2\] symbolic\_solve(expr::Vector{Equation}, x::Tuple{Num, Num}; dropmultiplicity::Bool, warns::Bool)
> @ Symbolics ~/.julia/packages/Symbolics/GYV9b/src/solver/main.jl:204
> \[3\] symbolic\_solve(expr::Vector{Equation}, x::Tuple{Num, Num})
> @ Symbolics ~/.julia/packages/Symbolics/GYV9b/src/solver/main.jl:145
> \[4\] top-level scope
> @ ~/Code/Tethers.jl/mwes/mwe06.jl:20
> \[5\] include(fname::String)
> @ Base.MainInclude ./client.jl:494
> \[6\] top-level scope
> @ REPL\[1\]:1
> \`\`\`
> 
> \` \[0c5d862f\] Symbolics v6.21.0 \`

---

<div class="post-metadata">

### Author: ![Ricardo\_Borges](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ricardo_borges/32/19918_2.png) [@Ricardo\_Borges](https://discourse.julialang.org/u/Ricardo_Borges)
#### Post date: [November 20, 2024, 11:56am UTC](https://discourse.julialang.org/t/getting-the-symbolic-solution-of-system-of-equations-using-modelingtoolkit/122786/6 "2024-11-20T11:56:29Z")

</div>

Many thanks for that!

Besides the bug, is it possible to get the analytical solution for a symbol in a @mtkmodel? @ChrisRackauckas

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [November 20, 2024, 12:06pm UTC](https://discourse.julialang.org/t/getting-the-symbolic-solution-of-system-of-equations-using-modelingtoolkit/122786/7 "2024-11-20T12:06:03Z")

</div>

That would be how you do it. And we need to expose more interfaces for better analytical solutions and will do so in the future.
