I am currently trying to simulate acoustic resonators using OpenModelica, and I am wondering how to robustly/nicely calculate their resonance frequency.
As a simplified example (without Media, etc), I have implemented a dual Helmholtz resonator, in essence two volumes (compliances) connected by a pipe (inertance). The real system consists of more components connected together.
The oscillation of pressure and volume flow (both complex values) follow a sinusoidal expression, with a resonance angular frequency w
. This yields 8 equations for 4 pressures and 4 volume flows (at the end points and compliance-inertance connection points).
Here a Modelica code I am solving in OpenModelica nightly:
model Helmholtz_test "Simple test of double Helmholtz resonator"
constant Complex j = Modelica.ComplexMath.j;
ComplexU U_a, U_b, U_c, U_d "Oscillating volume flow rate";
ComplexPressure p_a, p_b, p_c, p_d "Oscillating pressure";
Modelica.SIunits.AngularFrequency w(start=2000, fixed=false);
Compliance C = 7.14e-9;
Inertance L = 80;
initial equation
p_a.re = 1e+2; //Simulation finishes, values reasonable, only during initialisation we get:
//Matrix singular!
//under-determined linear system not solvable!
//The initialization finished successfully without homotopy method.
equation
//BCs on ends
U_a = Complex(0);
U_d = Complex(0);
//Left compliance a-b;
p_a = p_b;
p_a = -1 / (j * w * C) * (U_b - U_a);
//Inertance b-c
U_b = U_c;
p_c - p_b = -j * w * L * U_b;
//Right compliance c-d
p_c = p_d;
p_c = -1 / (j * w * C) * (U_d - U_c);
//Additional condition for Eigenvalue
der(w) = 0;
//w^2 = 2/(L*C); //The "real" resonance frequency
annotation(
experiment(StartTime = 0, StopTime = 1, Tolerance = 1e-06, Interval = 0.002));
end Helmholtz_test;
with the additional definitions
operator record ComplexPressure =
Complex(redeclare Modelica.SIunits.Pressure re,
redeclare Modelica.SIunits.Pressure im)
"Complex pressure";
operator record ComplexU =
Complex(redeclare Modelica.SIunits.VolumeFlowRate re,
redeclare Modelica.SIunits.VolumeFlowRate im)
"Complex volume flow rate";
type Compliance = Real(final quantity = "Compliance", final unit = "m3.Pa-1");
type Inertance = Real(final quantity="Inertance", final unit="kg.m-4");
Calculating on paper, one arrives at a resonance angular frequency of w=\sqrt{\frac{2}{LC}}
(in this case ~1871 1/s) for the system to have a non-zero solution.
To avoid the solver going to the uninteresting solution of zero everything, I have to add some stimulation at one point, hence the initial equation p_a.re = 1e+2
.
Now, to simulate this, since the w
is an additional variable, I need to introduce an additional equation, choosing der(w) = 0;
as the resonance frequency is constant in this case.
Unfortunately, this makes it impossible to go to a more complex/realistic situation, where the resonance frequency changes over time e.g. with temperature or other changing values.
Q1: Is there a better way to supply the additional equation for the resonance frequency/calculate this eigenvalue of the system?
In addition, the success of simulation depends on the value of the initial stimulation (in some ranges this fails or I get singular equations at every time step). Also, in effect the problem is being solved in the initialisation phase. In the best case, I get the output
Simulation finishes, values reasonable, only during initialisation we get:
Matrix singular!
under-determined linear system not solvable!
The initialization finished successfully without homotopy method.
Q2: Is there a way to avoid the singularity and/or deal with this initialisation cleanly (e.g. with homotopy
)?
While this works adequately in the simplified example (and results in correct values for w
), I am concerned that for more complex/realistics models, I could encountered more problematic numeric difficulties.
I have looked into homotopy
, but I couldn't really see how to apply this here. I thought applying this to w
somehow, but the Fritzson book even seems to warn explicitly against using this on the derivative expression, and aside of that only the w.start
value seems to present itself.