First let’s import a version of the provided model with some descriptions and details added:
In[]:=
model=ImportString
,"MO";
Let's keep track of the start and parameter values of interest as integers and rationals. This will be useful for the analytical solution:
In[]:=
parVals={"r"->22,"l"->1/5,"c"->1/100000};​​initVals={"inductor1.i"->6/5,"capacitor1.v"->24};
Let’s set those parameter and initial values in the model:
In[]:=
model=SetSystemModel[model,<|"ParameterValues"->parVals,"InitialValues"->initVals|>];
Let’s extract the equations of the model with a method that specifies elimination:
In[]:=
eqs=SystemModel[model,"SystemEquations",Method->{"Elimination"->All,"ReduceIndex"->True}];
Further simplifications and eliminations are needed to turn these equations into something that the Wolfram Language (WL) can process easily. Let’s start by eliminating some variables that are not of much interest:
In[]:=
eliminVars=
resistor1.R_actual
t.,
resistor1.T_heatPort
t.,
resistor1.LossPower
t.,
ground1.p.i
t.,
switch1.LossPower
t.,
switch1.s
t.,
switch1.v
t.,
switch1.i
t.,
switch.LossPower
t.,
switch.s
t.,
switch.i
t.,
switch.v
t.;
In[]:=
reducedEquations=List@@Eliminate[eqs,eliminVars]//Simplify
Out[]=

capacitor1.i
t.+
resistor1.i
t.
inductor1.i
t.,
resistor1.R
(1+
resistor1.alpha
(
resistor1.T
-
resistor1.T_ref
))
resistor1.i
t.
capacitor1.v
t.,
capacitor1.v
t.
Vc
t.,If[
booleanConstant1.k
,1,
switch.Ron
]If[
booleanConstant2.k
,
switch1.Goff
,1]
capacitor1.v
t.+
inductor1.v
t.+If[
booleanConstant2.k
,1,
switch1.Ron
]
capacitor1.i
t.+
resistor1.i
t.+If[
booleanConstant1.k
,
switch.Goff
,1]If[
booleanConstant2.k
,1,
switch1.Ron
]
capacitor1.v
t.+
inductor1.v
t.-
Vi
t.0,
capacitor1.i
t.
capacitor1.C
′
capacitor1.v
t.,
inductor1.v
t.
inductor1.L
′
inductor1.i
t.
This is already more readable. Let’s set some parameter values to find an even cleaner presentation of the equations in the model:
In[]:=
nonNumPars=Select[SystemModel[model,"ParameterValues"],!MemberQ[{
r
,
c
,
l
},#[[1]]]&]
Out[]=
{
k1
True,
k2
False,
inductor1.L

l
,
capacitor1.C

c
,
resistor1.R

r
,
resistor1.T_ref
300.15,
resistor1.alpha
0,
resistor1.T

resistor1.T_ref
,
switch.Ron
0,
switch.Goff
0,
switch1.Ron
0,
switch1.Goff
0,
booleanConstant1.k

k1
,
booleanConstant2.k

k2
}
In[]:=
reducedEquationsEval=reducedEquations//.nonNumPars;​​%//TableForm
Out[]//TableForm=
capacitor1.i
t.+
resistor1.i
t.
inductor1.i
t.
r
resistor1.i
t.
capacitor1.v
t.
capacitor1.v
t.
Vc
t.
capacitor1.v
t.+
inductor1.v
t.0
capacitor1.i
t.
c
′
capacitor1.v
t.
inductor1.v
t.
l
′
inductor1.i
t.
Let’s change variable names to make them more WL-friendly and set the parameters to the values we chose at the start:
In[]:=
wlEqs=reducedEquationsEval/.
capacitor1.i
->Function[t,ci[t]],
capacitor1.v
->Function[t,cv[t]],
inductor1.i
->Function[t,ii[t]],
inductor1.v
->Function[t,iv[t]],
resistor1.i
->Function[t,ri[t]],
Vc
->Function[t,vc[t]],
r
->r,
c
->c,
l
->l,t.->t/.Thread[{r,l,c}->parVals[[All,2]]]
Out[]=
ci[t]+ri[t]ii[t],22ri[t]cv[t],cv[t]vc[t],cv[t]+iv[t]0,ci[t]
′
cv
[t]
100000
,iv[t]
′
ii
[t]
5

Now we can pass this to DSolve, adding the initial conditions that we chose at the start, to find the analytical solution:
In[]:=
initEqs=MapThread[Equal,{{ii[0],cv[0]},initVals[[All,2]]}];​​sol=DSolve[Join[wlEqs,initEqs],{cv[t],ii[t],ci[t],iv[t],ri[t],vc[t]},t]//First//FullSimplify
Out[]=
ci[t]
-
500
11
(50+
2258
)t

33870+1113
2258
+(33870-1113
2258
)
1000
2258
t
11

620950
,cv[t]
12
-
500
11
(50+
2258
)t

1129-30
2258
+(1129+30
2258
)
1000
2258
t
11

1129
,ii[t]
-
500
11
(50+
2258
)t

33870-717
2258
+(33870+717
2258
)
1000
2258
t
11

56450
,iv[t]-
12
-
500
11
(50+
2258
)t

1129-30
2258
+(1129+30
2258
)
1000
2258
t
11

1129
,ri[t]
6
-
500
11
(50+
2258
)t

1129-30
2258
+(1129+30
2258
)
1000
2258
t
11

12419
,vc[t]
12
-
500
11
(50+
2258
)t

1129-30
2258
+(1129+30
2258
)
1000
2258
t
11

1129

Now we only need to simulate the model with a specific simulation method. “Euler” is generally not the default method for simulation but we can pick it in the SystemModelSimulate function. As mentioned by Henrik, this is explicit Euler’s method, no the inverse Euler method. Check the documentation for more details:
https://reference.wolfram.com/language/ref/SystemModelSimulate.html
Notice that we are also free to pick method suboptions like step size, which naturally affects the simulation results. We also pick here a simulation interval from 0 to tMax = 0.04, since most of the difference to the analytical solution seems to appear at the start of the simulation. Notice that for the “Euler” method, the choice of step size can affect substantially the time it takes to finish the simulation for a given time interval:
In[]:=
tMax=0.04;​​sim=SystemModelSimulate[model,tMax,Method->{"Euler","StepSize"->
-6
10
}];​​cvSim=sim["capacitor1.v",t];​​cvDSolve=cv[t]/.sol;​​absDiff=Abs[cvSim-cvDSolve];
If we plot the two solutions with these specific choices, we notice that it is hard to see the difference at first sight:
In[]:=
Plot[{cvSim,cvDSolve},{t,0,tMax},PlotStyle->{Dashed,Directive[Darker[Green],Opacity[0.3]]},PlotRange->All,PlotLegends->{"Simulation","DSolve"},PlotLabel->"Voltage of capacitor",AxesLabel->{"t",QuantityForm["Volts","Abbreviation"]}]
Out[]=
Simulation
DSolve
But we can instead plot the absolute value of the error, here plotted in log scale with LogPlot:
In[]:=
LogPlot[absDiff,{t,0,tMax},PlotRange->All,PlotLabel->"Absolute value of error",AxesLabel->{"t",QuantityForm["Volts","Abbreviation"]}]
Out[]=
We can also easily find the maximum of the absolute value of the error in the given simulation time interval:
In[]:=
NMaximize[{absDiff,0<=t<=tMax},t]
Out[]=
{0.00253696,{t0.000222008}}
For interesting applications of circuit simulation and the use of System Modeler and Mathematica take a look at these blogs
https://blog.wolfram.com/author/leonardo-laguna-ruiz/