Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
fa86c1e
Test protected record locals set by modifiers and field defaults
JKRT Oct 13, 2026
21bc0f8
Test an initial equation reading a negated parameter
JKRT Oct 13, 2026
6a5ec42
Test the semiLinear chain rule
JKRT Oct 13, 2026
ed11199
Test MSL SimpleNaturalGas against omc
JKRT Oct 13, 2026
0b8387f
Test tuple equations with a record output and MSL Spice3 Graetz
JKRT Oct 13, 2026
12f41ac
Test record-array function locals, nested initial if-equations, termi…
JKRT Oct 13, 2026
4c30597
Test a bound record in a partial application
JKRT Oct 13, 2026
53e2779
Test a 3-D constant table read in an algorithm
JKRT Oct 13, 2026
8ea0ccd
Test an element of an array call of parameters
JKRT Oct 13, 2026
2241791
Test noEvent guarding the branch it does not take
JKRT Oct 13, 2026
80f8fee
Test a relation's hysteresis on its own operands
JKRT Oct 13, 2026
2061baa
Test x = 1/y with y in no other equation
JKRT Oct 13, 2026
688ddf3
Test free parameters from coupled initial equations
JKRT Oct 13, 2026
ed58679
Test an assert at its boundary at the start
JKRT Oct 13, 2026
bd38f29
Test parameters the observedFilter asks for
JKRT Oct 13, 2026
506365d
Test enumeration inputs as indices
JKRT Oct 13, 2026
c029c23
Test a function error at a step's re-evaluation
JKRT Oct 14, 2026
f70ba28
Test a zero numerator in a derivative's coefficient
JKRT Oct 14, 2026
046ae7d
Test two models' tables of one name in one process
JKRT Oct 14, 2026
05091f1
OM.jl 0.5.2: OMBackend 0.5.5, OMFrontend 1.7.3
JKRT Oct 14, 2026
d41b1be
Test a tuple initial equation of an array output for free parameters
JKRT Oct 14, 2026
e154997
Release workflow: tag and release a version bump of Project.toml
JKRT Oct 14, 2026
de30d07
Test a build's tables freed with the build
JKRT Oct 14, 2026
ec042e2
Test tables in structural modes and recompiled models, the agentic sw…
JKRT Oct 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Release

# A version bump of Project.toml merged to master: tag it vX.Y.Z with a GitHub
# release. Runs only when Project.toml changes, and does nothing unless its version
# changed. (This package is not in the OpenModelica registry: its Project.toml has
# a [sources] block, which the registry's auto-update skips.)

on:
push:
branches:
- master
paths:
- Project.toml

permissions:
contents: write

concurrency:
group: release
cancel-in-progress: false

jobs:
release:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2

- name: Version change
id: version
run: |
new=$(sed -n 's/^version = "\(.*\)"/\1/p' Project.toml | head -1)
old=$(git show HEAD^:Project.toml 2>/dev/null | sed -n 's/^version = "\(.*\)"/\1/p' | head -1)
echo "new=$new" >> "$GITHUB_OUTPUT"
if [ -n "$new" ] && [ "$new" != "$old" ] && ! git ls-remote --exit-code --tags origin "refs/tags/v$new" > /dev/null; then
echo "release=true" >> "$GITHUB_OUTPUT"
echo "Version $old -> $new"
else
echo "release=false" >> "$GITHUB_OUTPUT"
echo "No new version (Project.toml $new, before $old, or v$new is tagged already)"
fi

- name: Tag and GitHub release
if: steps.version.outputs.release == 'true'
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.version.outputs.new }}
run: |
gh release create "v$VERSION" --target "$GITHUB_SHA" --title "v$VERSION" \
--notes "$(git log -1 --format=%s "$GITHUB_SHA")"
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "OM"
uuid = "2f925a0b-2436-437b-858e-49aee461894b"
version = "0.5.1"
version = "0.5.2"
authors = ["John Tinnerholm <john.tinnerholm@liu.se>"]

[deps]
Expand Down Expand Up @@ -52,8 +52,8 @@ DoubleEnded = "0.2.3"
ImmutableList = "0.4.2"
ListUtil = "0.4.1"
MetaModelica = "0.4.2"
OMBackend = "0.5.4"
OMFrontend = "1.6"
OMBackend = "0.5.5"
OMFrontend = "1.7.3"
OMParser = "0.2.2"
OMRuntimeExternalC = "0.3.5"
SCode = "1.3"
Expand Down
6 changes: 3 additions & 3 deletions test/Agentic/agenticTests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ end SimpleAgenticTest;
MSL = true, MSL_Version = "MSL:3.2.3")
flat_with_consts = OM.OMFrontend.Frontend.collectConstants(fm[1], fm[2])
flat_str = OM.toString(flat_with_consts)
@test occursin("Real 'Modelica.Mechanics.MultiBody.Types.Defaults.FrameHeadLengthFraction' =", flat_str)
@test occursin("Real 'Modelica.Mechanics.MultiBody.Types.Defaults.FrameHeadWidthFraction' =", flat_str)
@test occursin("Real 'Modelica.Mechanics.MultiBody.Types.Defaults.ArrowHeadLengthFraction' =", flat_str)
@test occursin("constant Real Modelica.Mechanics.MultiBody.Types.Defaults.FrameHeadLengthFraction =", flat_str)
@test occursin("constant Real Modelica.Mechanics.MultiBody.Types.Defaults.FrameHeadWidthFraction =", flat_str)
@test occursin("constant Real Modelica.Mechanics.MultiBody.Types.Defaults.ArrowHeadLengthFraction =", flat_str)
end

end
19 changes: 19 additions & 0 deletions test/Models/ArrayCallElementParam.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ArrayCallElementParam
function normalized "an output whose size follows the input (MSL normalizeWithAssert)"
input Real e[:];
output Real r[size(e, 1)];
algorithm
assert(sqrt(e*e) > 0, "a zero vector");
r := e/sqrt(e*e);
end normalized;
model M "a parameter array bound to the call of a parameter computed at initialization (MSL PlanarLoops_analytic's revolute.e = normalizeWithAssert(n)): x(1) = 0.6 + 0.8 = 1.4"
parameter Real n0[3](each fixed = false);
parameter Real n[3] = n0;
parameter Real e[3] = normalized(n);
Real x(start = 0, fixed = true);
initial equation
n0 = {0, 3, 4};
equation
der(x) = e[2] + e[3];
end M;
end ArrayCallElementParam;
22 changes: 22 additions & 0 deletions test/Models/AssertAtBoundary.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package AssertAtBoundary
model AtBoundary "an assert on a level that starts at its boundary, past it by rounding (MSL TanksWithEmptyingPipe1: level_start = height, the level from the mass): level(0) = 0.3 m/(A d) = 0.30000000000000004 > 0.3, then the tank drains"
parameter Real height = 0.3;
parameter Real A = 0.7;
parameter Real d = 997.3;
Real m(start = height*A*d, fixed = true);
Real level = m/(A*d);
equation
der(m) = -1;
assert(level <= height, "Tank starts to overflow");
end AtBoundary;
model Violated "the same assert violated at the start: reported"
parameter Real height = 0.3;
parameter Real A = 0.7;
parameter Real d = 997.3;
Real m(start = 1.1*height*A*d, fixed = true);
Real level = m/(A*d);
equation
der(m) = -1;
assert(level <= height, "Tank starts to overflow");
end Violated;
end AssertAtBoundary;
16 changes: 16 additions & 0 deletions test/Models/CoupledFreeParameters.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
model CoupledFreeParameters "free parameters from two coupled initial equations that start states (MSL 4 SMPM_ResistiveBraking's idq_sr): a + b = 3 and a - b = 1, so a = 2, b = 1; y(0) = a, z(0) = b, x(1) = a b = 2"
parameter Real a(fixed = false, start = 0);
parameter Real b(fixed = false, start = 0);
Real x(start = 0, fixed = true);
Real y;
Real z;
initial equation
0 = a + b - 3;
0 = a - b - 1;
y = a;
z = b;
equation
der(x) = a*b;
der(y) = -y + a;
der(z) = -z + b;
end CoupledFreeParameters;
32 changes: 32 additions & 0 deletions test/Models/EnumIndexInput.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package EnumIndexInput
type Level = enumeration(low, mid, high);
function weight "a table indexed by an enumeration input (MSL Digital's Logic tables)"
input Level l;
output Real w;
protected
Real table[3] = {1, 10, 100};
algorithm
w := table[Integer(l)];
end weight;
function weights "an array of enumeration inputs"
input Level l[2];
output Real w;
protected
Real table[3] = {1, 10, 100};
algorithm
w := table[Integer(l[1])] + table[Integer(l[2])];
end weights;
model M "w = weight(l) at the ticks: 1 at 0.25 (low), 100 at 0.75 (high); v = 2 then 200"
discrete Level l(start = Level.low, fixed = true);
discrete Real w(start = 0, fixed = true);
discrete Real v(start = 0, fixed = true);
equation
when time > 0.5 then
l = Level.high;
end when;
when {time > 0.25, time > 0.75} then
w = weight(l);
v = weights({l, l});
end when;
end M;
end EnumIndexInput;
34 changes: 34 additions & 0 deletions test/Models/InitialEquationTests.mo
Original file line number Diff line number Diff line change
Expand Up @@ -793,4 +793,38 @@ package InitialEquationTests
der(x) = -2;
y = homotopy(actual = x, simplified = ieq57Positive(x));
end IEQ57_HomotopySimplifiedOnlyAtInit;
model IEQ58_PreFromNegatedParameter "pre(y) = ystart = not q0 (MSL Blocks' RSFlipFlop: pre_u_start = not Qini): x(1) = 0.5 (OpenModelica)"
parameter Boolean q0 = false;
parameter Boolean ystart = not q0;
discrete Boolean y;
Real x(start = 0, fixed = true);
initial equation
pre(y) = ystart;
equation
when time > 0.5 then
y = not pre(y);
end when;
der(x) = if y then 1 else 0;
end IEQ58_PreFromNegatedParameter;
model IEQ59_NestedInitialIf "an if-equation nested in an initial if-equation (MSL 4 SoftStarter): x(0) = 3, x(1) = 4 (OpenModelica)"
Boolean b = time < 0.5;
Real p = 2 + time;
Real x;
initial equation
if b then
if p < 1 then
x = 1;
else
x = 3;
end if;
else
if p > 0 then
x = 5;
else
x = 7;
end if;
end if;
equation
der(x) = 1;
end IEQ59_NestedInitialIf;
end InitialEquationTests;
5 changes: 5 additions & 0 deletions test/Models/NoEventGuard.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
model NoEventGuard "noEvent(if c then a else b) takes only the chosen branch (MSL ContinuousMean's der(mu) = noEvent(if time >= t_0 + t_eps then (u - mu)/(time - t_0) else 0)): the other branch is 1/0 at t = 0; x = 0 until t = 0.1, then x(1) = 1 - 0.1/1 = 0.9"
Real x(start = 0, fixed = true);
equation
der(x) = noEvent(if time >= 0.1 then (1 - x)/time else 0);
end NoEventGuard;
36 changes: 36 additions & 0 deletions test/Models/PartialRecordArg.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package PartialRecordArg
record Coef
Real a;
Real b;
end Coef;
partial function PF
input Real x;
output Real y;
end PF;
function lin
extends PF;
input Coef c;
algorithm
y := c.a * x + c.b;
end lin;
function evalAt
input PF f;
input Real x;
output Real y;
algorithm
y := f(x);
end evalAt;
function useIt "a function argument with a bound record (MSL 4 Inverse_sh_T's f_nonlinear(data = ...)): 2 u + 1"
input Real u;
output Real y;
protected
Coef c = Coef(2, 1);
algorithm
y := evalAt(function lin(c = c), u);
end useIt;
model M "der(x) = 2 time + 1: x(1) = 2"
Real x(start = 0, fixed = true);
equation
der(x) = useIt(time);
end M;
end PartialRecordArg;
14 changes: 14 additions & 0 deletions test/Models/PulseHysteresis.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
model PulseHysteresis "an if-condition of several relations, one with a huge operand (MSL Spice3 V_pulse: PW = 1e60): v = time - 0.5 after t = 0.5, v(1) = 0.5"
parameter Real TD = 0.5;
parameter Real Tfalling = 1e60;
discrete Real T0(start = TD, fixed = true);
Integer counter2(start = -1, fixed = true);
Real v;
Real x(start = 0, fixed = true);
equation
when sample(TD, 1e60) then
T0 = time;
end when;
v = if (time < TD or counter2 == 0) or time >= T0 + Tfalling then 0 else time - T0;
der(x) = v;
end PulseHysteresis;
11 changes: 11 additions & 0 deletions test/Models/ReciprocalVariable.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
model ReciprocalVariable "x = 1/y with y in no other equation (MSL FluxTubes' LeakageWithCoefficient: R_m = 1/G_m): G = 1/(9 Rtot), G(0) = 1.3963e-7, G(1) = G(0)/2"
parameter Real c = 0.9;
Real Rtot = 795774.715459477*(1 + time);
Real R;
Real G;
Real phi(start = 0, fixed = true);
equation
(1 - c)*R = c*Rtot;
R = 1/G;
der(phi) = 1 - 1e-7*R*phi;
end ReciprocalVariable;
96 changes: 96 additions & 0 deletions test/Models/RecordFunctionTest.mo
Original file line number Diff line number Diff line change
Expand Up @@ -538,4 +538,100 @@ package RecordFunctionTest
der(x) = secondOfPairIf(time);
end RecordIfAssignment;

record SatPair "MSL R134a SaturationProperties"
Real psat;
Real Tsat;
end SatPair;

record FieldDefault "a field default reading another field"
Real a;
Real b = 2 * a;
end FieldDefault;

function satSum
input SatPair s;
output Real y;
algorithm
y := s.psat + 2 * s.Tsat;
end satSum;

function recordLocalModifiers "a protected record set by modifiers (MSL R134a getPhase_ph): 2 p"
input Real p;
output Real y;
protected
SatPair sat(psat = p, Tsat = 0);
Real hl = satSum(sat);
algorithm
y := hl + sat.psat;
end recordLocalModifiers;

function recordLocalDefaults "a field default reading another field, a record binding: 3 p + 3"
input Real p;
output Real y;
protected
FieldDefault w(a = p);
SatPair s2 = SatPair(p, 3);
algorithm
y := w.a + w.b + s2.Tsat;
end recordLocalDefaults;

model RecordLocalBindings "der(x) = 2 (time + 2): x(1) = 5; der(z) = 3 (time + 2) + 3: z(1) = 10.5"
Real x(start = 0, fixed = true);
Real z(start = 0, fixed = true);
equation
der(x) = recordLocalModifiers(time + 2);
der(z) = recordLocalDefaults(time + 2);
end RecordLocalBindings;

function tupleWithRecord "a record output first (MSL Spice3 diodeNoBypassCode)"
input Real u;
output SatPair r;
output Real y2;
algorithm
r.psat := 2 * u;
r.Tsat := 0;
y2 := 3 * u;
end tupleWithRecord;

model TupleWithRecordOutput "(r, y2) = tupleWithRecord(time): der(x) = r.psat + y2 = 5 time, x(1) = 2.5"
SatPair r;
Real y2;
Real x(start = 0, fixed = true);
equation
(r, y2) = tupleWithRecord(time);
der(x) = r.psat + y2;
end TupleWithRecordOutput;

function addPairs
input SatPair a;
input SatPair b;
output SatPair c;
algorithm
c.psat := a.psat + b.psat;
c.Tsat := a.Tsat + b.Tsat;
end addPairs;

function recordArrayLocals "arrays of records as locals (MSL ReferenceAir's Ice09 Gibbs): 25 + u"
input Real u;
output Real y;
protected
SatPair[3] r = {SatPair(1, 2), SatPair(3, 4), SatPair(5, 6)};
SatPair acc;
SatPair o[2];
algorithm
acc := r[1];
for k in 2:3 loop
acc := addPairs(acc, r[k]);
end for;
o[1] := addPairs(acc, SatPair(u, 0));
o[2] := r[2];
y := o[1].psat + o[2].Tsat + acc.Tsat;
end recordArrayLocals;

model RecordArrayLocals "der(x) = recordArrayLocals(time) = 25 + time: x(1) = 25.5 (OpenModelica)"
Real x(start = 0, fixed = true);
equation
der(x) = recordArrayLocals(time);
end RecordArrayLocals;

end RecordFunctionTest;
8 changes: 8 additions & 0 deletions test/Models/RequestedParameter.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
model RequestedParameter "a variable bound to a parameter expression, and a parameter, asked for by the observedFilter (MSL ShowTransferFunction's const.y): y = q = 2 k = 6"
parameter Real k = 3;
parameter Real q = 2*k;
Real y = q;
Real x(start = 0, fixed = true);
equation
der(x) = k;
end RequestedParameter;
Loading
Loading