From c5ca585134153788d468c7fa4b4f1b11906dcb2b Mon Sep 17 00:00:00 2001 From: Joppe Blondel Date: Sun, 19 Jul 2026 13:44:33 +0200 Subject: [PATCH] Added simple piston with gas test --- thermtest.mo | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 thermtest.mo diff --git a/thermtest.mo b/thermtest.mo new file mode 100644 index 0000000..65879a9 --- /dev/null +++ b/thermtest.mo @@ -0,0 +1,212 @@ +model thermtest + model c_gas + BondGraph.BondPort p_thermal "Thermal port" + annotation( + Placement( + transformation( + origin = {-44, 18}, + extent = {{-10, -10}, {10, 10}}), + iconTransformation( + origin = {-80, 0}, + extent = {{-10, -10}, {10, 10}}))); + + BondGraph.BondPort p_pneumatic "Pneumatic port" + annotation( + Placement( + transformation( + origin = {44, 18}, + extent = {{-10, -10}, {10, 10}}), + iconTransformation( + origin = {80, 0}, + extent = {{-10, -10}, {10, 10}}))); + + /* + * Gas properties + */ + + parameter Modelica.Units.SI.SpecificHeatCapacity cv = 312 + "Specific heat capacity at constant volume"; + + parameter Modelica.Units.SI.MolarMass molarMass = 0.039948 + "Molar mass of argon"; + + final parameter Modelica.Units.SI.SpecificHeatCapacity Rs = + Modelica.Constants.R / molarMass + "Mass-specific gas constant"; + + /* + * Reference state + */ + + parameter Modelica.Units.SI.Volume V0 = 6e-3 + "Initial expanded volume"; + + parameter Modelica.Units.SI.Pressure p0 = 1e5 + "Pressure at the reference state"; + + parameter Modelica.Units.SI.Temperature T0 = 283 + "Temperature at the reference state"; + + /* + * Derived reference quantities + */ + + final parameter Modelica.Units.SI.Mass m = + p0 * V0 / (Rs * T0) + "Mass of working gas"; + + final parameter Modelica.Units.SI.SpecificVolume v0 = + V0 / m + "Specific volume at the reference state"; + + final parameter Modelica.Units.SI.SpecificEntropy s0 = 0 + "Reference specific entropy"; + + /* + * Thermodynamic states + */ + + Modelica.Units.SI.SpecificEntropy s( + start = s0, + fixed = true) + "Specific entropy"; + + Modelica.Units.SI.SpecificVolume v( + start = v0, + fixed = true) + "Specific volume"; + + /* + * Diagnostic quantities + */ + + Modelica.Units.SI.Volume V + "Total gas volume"; + + Modelica.Units.SI.Entropy S + "Total gas entropy relative to reference"; + + Modelica.Units.SI.Temperature T + "Gas temperature"; + + Modelica.Units.SI.Pressure p + "Gas pressure"; + + equation + /* + * State balances + * + * p_thermal.f: + * entropy flow into the gas, W/K + * + * p_pneumatic.f: + * volume flow associated with the gas, m3/s + */ + + m * der(s) = p_thermal.f; + m * der(v) = p_pneumatic.f; + + /* + * Total quantities + */ + + V = m * v; + S = m * s; + + /* + * Ideal-gas constitutive equations expressed in + * terms of specific entropy and specific volume. + */ + + T = + T0 + * (v / v0)^(-Rs / cv) + * exp((s - s0) / cv); + + p = + p0 + * (v / v0)^(-(Rs / cv + 1)) + * exp((s - s0) / cv); + + /* + * Bond-port efforts + */ + + p_thermal.e = T; + p_pneumatic.e = p; + + /* + * Prevent the thermodynamic model from entering + * a nonphysical negative-volume state. + */ + + assert( + v > 0, + "The gas specific volume must remain positive."); + + annotation( + Icon(graphics = {Text(extent = {{-100, 100}, {100, -100}}, textString = "C"), Text(origin = {50, 80}, textColor = {0, 0, 255}, extent = {{-50, 20}, {50, -20}}, textString = "%name"), Rectangle(origin = {-8, 5}, fillPattern = FillPattern.Solid, extent = {{-4, -51}, {4, 51}})})); + end c_gas; + + c_gas cgas annotation( + Placement(transformation(origin = {-40, 80}, extent = {{-10, -10}, {10, 10}}))); + BondGraph.J0 Tgas(N = 1, s = {-1}) annotation( + Placement(transformation(origin = {-80, 80}, extent = {{-10, -10}, {10, 10}}))); + BondGraph.J0 Pgas(s = {-1, -1}) annotation( + Placement(transformation(origin = {0, 80}, extent = {{-10, -10}, {10, 10}}))); + BondGraph.J0 Penv(s = {-1, 1}) annotation( + Placement(transformation(origin = {80, 80}, extent = {{-10, -10}, {10, 10}}))); + BondGraph.J1 Pdiff(N = 3, s = {1, -1, 1}) annotation( + Placement(transformation(origin = {40, 80}, extent = {{-10, -10}, {10, 10}}))); + BondGraph.Se Se_Penv(e0 = 1e5) annotation( + Placement(transformation(origin = {120, 80}, extent = {{-10, -10}, {10, 10}}, rotation = 180))); + BondGraph.TF A_piston(n = 0.007) annotation( + Placement(transformation(origin = {40, 40}, extent = {{-10, -10}, {10, 10}}, rotation = 90))); + BondGraph.J1 v_piston(N = 2, s = {1, -1}) annotation( + Placement(transformation(origin = {40, 0}, extent = {{-10, -10}, {10, 10}}))); + BondGraph.mTF crankshaft annotation( + Placement(transformation(origin = {40, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 90))); + BondGraph.J1 w_shaft(s = {1, -1}) annotation( + Placement(transformation(origin = {40, -80}, extent = {{-10, -10}, {10, 10}}))); + BondGraph.Sf shaft_drive(f0 = 3.14) annotation( + Placement(transformation(origin = {0, -80}, extent = {{-10, -10}, {10, 10}}))); + Modelica.Blocks.Continuous.Integrator w_to_alpha annotation( + Placement(transformation(origin = {80, -80}, extent = {{-10, -10}, {10, 10}}))); + Modelica.Blocks.Math.Gain l_crankshaft(k = 0.05) annotation( + Placement(transformation(origin = {80, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 180))); + Modelica.Blocks.Math.Sin sin annotation( + Placement(transformation(origin = {120, -40}, extent = {{-10, -10}, {10, 10}}, rotation = 180))); +equation + connect(Pgas.P[1], cgas.p_pneumatic) annotation( + Line(points = {{0, 80}, {-32, 80}}, color = {0, 0, 127}, arrow = {Arrow.None, Arrow.Half})); + connect(Tgas.P[1], cgas.p_thermal) annotation( + Line(points = {{-80, 80}, {-48, 80}}, color = {0, 0, 127}, arrow = {Arrow.None, Arrow.Half})); + connect(Pgas.P[2], Pdiff.P[1]) annotation( + Line(points = {{0, 80}, {40, 80}}, color = {0, 0, 127}, thickness = 0.5, arrow = {Arrow.None, Arrow.Half})); + connect(Pdiff.P[2], Penv.P[1]) annotation( + Line(points = {{40, 80}, {80, 80}}, color = {0, 0, 127}, thickness = 0.5, arrow = {Arrow.None, Arrow.Half})); + connect(Se_Penv.p, Penv.P[2]) annotation( + Line(points = {{112, 80}, {80, 80}}, color = {0, 0, 127}, arrow = {Arrow.None, Arrow.Half})); + connect(A_piston.p2, Pdiff.P[3]) annotation( + Line(points = {{40, 48}, {40, 80}}, color = {0, 0, 127}, arrow = {Arrow.None, Arrow.Half})); + connect(v_piston.P[2], A_piston.p1) annotation( + Line(points = {{40, 0}, {40, 32}}, color = {0, 0, 127}, arrow = {Arrow.None, Arrow.Half})); + connect(crankshaft.p2, v_piston.P[1]) annotation( + Line(points = {{40, -32}, {40, 0}}, color = {0, 0, 127}, arrow = {Arrow.None, Arrow.Half})); + connect(w_shaft.P[2], crankshaft.p1) annotation( + Line(points = {{40, -80}, {40, -48}}, color = {0, 0, 127}, arrow = {Arrow.None, Arrow.Half})); + connect(shaft_drive.p, w_shaft.P[1]) annotation( + Line(points = {{8, -80}, {40, -80}}, color = {0, 0, 127}, arrow = {Arrow.None, Arrow.Half})); + connect(w_shaft.f, w_to_alpha.u) annotation( + Line(points = {{46, -86}, {50, -86}, {50, -80}, {68, -80}}, color = {0, 0, 127})); + connect(l_crankshaft.y, crankshaft.m) annotation( + Line(points = {{70, -40}, {48, -40}}, color = {0, 0, 127})); + connect(sin.y, l_crankshaft.u) annotation( + Line(points = {{110, -40}, {92, -40}}, color = {0, 0, 127})); + connect(w_to_alpha.y, sin.u) annotation( + Line(points = {{92, -80}, {144, -80}, {144, -40}, {132, -40}}, color = {0, 0, 127})); + +annotation( + uses(Modelica(version = "4.1.0")), + experiment(StartTime = 0, StopTime = 10, Tolerance = 1e-06, Interval = 0.02)); +end thermtest; \ No newline at end of file