diff --git a/.github/workflows/Tests.yml b/.github/workflows/Tests.yml index 77c95b2..27fb81a 100644 --- a/.github/workflows/Tests.yml +++ b/.github/workflows/Tests.yml @@ -34,5 +34,5 @@ jobs: uses: "SciML/.github/.github/workflows/tests.yml@v1" with: group: "${{ matrix.group }}" - julia-version: "${{ matrix.julia-version }}" + julia-version: "${{ matrix.version }}" secrets: "inherit" diff --git a/src/parser.jl b/src/parser.jl index 1efb8c5..3228a2c 100644 --- a/src/parser.jl +++ b/src/parser.jl @@ -10,7 +10,7 @@ BaseModelicaArray(type, length) BaseModelicaString(string) BaseModelicaTypeSpecifier(type) - BaseModelicaTypePrefix(dpc, io) + BaseModelicaTypePrefix(final_flag, dpc, io) BaseModelicaDeclaration(ident, array_subs, modification) BaseModelicaComponentDeclaration(declaration, comment) BaseModelicaComponentClause(type_prefix, type_specifier, component_list) @@ -220,16 +220,19 @@ function BaseModelicaFunctionCall(input) end function BaseModelicaTypePrefix(input_list) + final_flag = nothing dpc = nothing io = nothing for input in input_list - if input == "parameter" || input == "discrete" || input == "constant" + if input == "final" + final_flag = input + elseif input == "parameter" || input == "discrete" || input == "constant" dpc = input elseif input == ("input") || input == ("output") io = input end end - BaseModelicaTypePrefix(dpc, io) + BaseModelicaTypePrefix(final_flag, dpc, io) end function BaseModelicaSimpleEquation(input_list) @@ -348,7 +351,7 @@ spc = Drop(Star(Space())) name = Not(Lookahead(e"end")) + Not(Lookahead(E"equation")) + Not(Lookahead(E"initial equation")) + (IDENT + Star(e"." + IDENT)) |> list2string # Not(Lookahead(foo)) tells it that names can't be foo type_specifier = E"."[0:1] + name > BaseModelicaTypeSpecifier - type_prefix = ((e"discrete" | e"parameter" | e"constant")[0:1] + spc + + type_prefix = ((e"final")[0:1] + spc + (e"discrete" | e"parameter" | e"constant")[0:1] + spc + (e"input" | e"output")[0:1]) |> BaseModelicaTypePrefix array_subscripts = Delayed() modification = Delayed() @@ -374,7 +377,7 @@ spc = Drop(Star(Space())) element_modification_or_replaceable = element_modification decoration = E"@" + UNSIGNED_INTEGER argument = decoration[0:1] + element_modification_or_replaceable - argument_list = argument + Star(E"," + argument) + argument_list = argument + Star(E"," + spc + argument) class_modification = E"(" + argument_list[0:1] + E")" expression = Delayed() modification.matcher = (class_modification + (spc + E"=" + spc + expression)[0:1]) | @@ -429,7 +432,7 @@ spc = Drop(Star(Space())) array_subscripts.matcher = E"[" + subscript + Star(E"," + subscript) + E"]" |> BaseModelicaArraySubscripts annotation_comment = E"annotation" + class_modification - comment.matcher = string_comment + annotation_comment[0:1] + comment.matcher = (string_comment + annotation_comment[0:1]) |> (x -> length(x) == 1 ? x[1] : BaseModelicaString(join([string(elem) for elem in x], " "))) enumeration_literal = IDENT + comment enum_list = enumeration_literal + Star(E"," + enumeration_literal) @@ -513,13 +516,13 @@ spc = Drop(Star(Space())) output_expression_list.matcher = expression[0:1] + Star(E"," + expression[0:1]) expression_list.matcher = expression + Star(E"," + expression) - if_expression = Delayed() + # Simple if_expression supporting both "elseif" and "else if" + if_expression = e"if" + simple_expression + e"then" + + simple_expression + + Star((e"elseif" | (e"else" + e"if")) + simple_expression + e"then" + + simple_expression) + + e"else" + simple_expression |> BaseModelicaIfExpression expression_no_decoration = simple_expression | if_expression - if_expression.matcher = e"if" + expression_no_decoration + e"then" + - expression_no_decoration + - Star(e"elseif" + expression_no_decoration + e"then" + - expression_no_decoration) + - e"else" + expression_no_decoration |> BaseModelicaIfExpression expression.matcher = expression_no_decoration + decoration[0:1] @@ -585,7 +588,7 @@ spc = Drop(Star(Space())) (spc + E"=" + spc + expression)[0:1]) |> BaseModelicaSimpleEquation) + comment > BaseModelicaAnyEquation - base_modelica = (spc + E"package" + spc + IDENT + spc + + base_modelica = (Star(LINE_COMMENT) + spc + E"package" + spc + IDENT + spc + Star((decoration[0:1] + spc + class_definition + spc + E";") | (decoration[0:1] + global_constant + E";")) + spc + decoration[0:1] + spc + diff --git a/test_chua.mo b/test_chua.mo new file mode 100644 index 0000000..c1fedee --- /dev/null +++ b/test_chua.mo @@ -0,0 +1,113 @@ +//! base 0.1.0 +package 'ChuaCircuit' + model 'ChuaCircuit' "Chua's circuit, ns, V, A" + Real 'L.v'(unit = "V", quantity = "ElectricPotential") "Voltage drop of the two pins (= p.v - n.v)"; + Real 'L.p.v'(unit = "V", quantity = "ElectricPotential") "Potential at the pin"; + Real 'L.p.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing into the pin"; + Real 'L.n.v'(unit = "V", quantity = "ElectricPotential") "Potential at the pin"; + Real 'L.n.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing into the pin"; + Real 'L.i'(fixed = true, start = 0.0, unit = "A", quantity = "ElectricCurrent") "Current flowing from pin p to pin n"; + parameter Real 'L.L'(start = 1.0, unit = "H", quantity = "Inductance") = 18.0 "Inductance"; + parameter Real 'Ro.R'(start = 1.0, unit = "Ohm", quantity = "Resistance") = 0.0125 "Resistance at temperature T_ref"; + parameter Real 'Ro.T_ref'(nominal = 300.0, start = 288.15, min = 0.0, displayUnit = "degC", unit = "K", quantity = "ThermodynamicTemperature") = 300.15 "Reference temperature"; + parameter Real 'Ro.alpha'(unit = "1/K", quantity = "LinearTemperatureCoefficient") = 0.0 "Temperature coefficient of resistance (R_actual = R*(1 + alpha*(T_heatPort - T_ref))"; + Real 'Ro.v'(unit = "V", quantity = "ElectricPotential") "Voltage drop of the two pins (= p.v - n.v)"; + Real 'Ro.p.v'(unit = "V", quantity = "ElectricPotential") "Potential at the pin"; + Real 'Ro.p.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing into the pin"; + Real 'Ro.n.v'(unit = "V", quantity = "ElectricPotential") "Potential at the pin"; + Real 'Ro.n.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing into the pin"; + Real 'Ro.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing from pin p to pin n"; + final parameter Boolean 'Ro.useHeatPort' = false "= true, if heatPort is enabled" annotation(Evaluate = true); + parameter Real 'Ro.T'(nominal = 300.0, start = 288.15, min = 0.0, displayUnit = "degC", unit = "K", quantity = "ThermodynamicTemperature") = 'Ro.T_ref' "Fixed device temperature if useHeatPort = false"; + Real 'Ro.LossPower'(unit = "W", quantity = "Power") "Loss power leaving component via heatPort"; + Real 'Ro.T_heatPort'(nominal = 300.0, start = 288.15, min = 0.0, displayUnit = "degC", unit = "K", quantity = "ThermodynamicTemperature") "Temperature of heatPort"; + Real 'Ro.R_actual'(unit = "Ohm", quantity = "Resistance") "Actual resistance = R*(1 + alpha*(T_heatPort - T_ref))"; + parameter Real 'G.G'(start = 1.0, unit = "S", quantity = "Conductance") = 0.565 "Conductance at temperature T_ref"; + parameter Real 'G.T_ref'(nominal = 300.0, start = 288.15, min = 0.0, displayUnit = "degC", unit = "K", quantity = "ThermodynamicTemperature") = 300.15 "Reference temperature"; + parameter Real 'G.alpha'(unit = "1/K", quantity = "LinearTemperatureCoefficient") = 0.0 "Temperature coefficient of conductance (G_actual = G_ref/(1 + alpha*(T_heatPort - T_ref))"; + Real 'G.v'(unit = "V", quantity = "ElectricPotential") "Voltage drop of the two pins (= p.v - n.v)"; + Real 'G.p.v'(unit = "V", quantity = "ElectricPotential") "Potential at the pin"; + Real 'G.p.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing into the pin"; + Real 'G.n.v'(unit = "V", quantity = "ElectricPotential") "Potential at the pin"; + Real 'G.n.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing into the pin"; + Real 'G.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing from pin p to pin n"; + final parameter Boolean 'G.useHeatPort' = false "= true, if heatPort is enabled" annotation(Evaluate = true); + parameter Real 'G.T'(nominal = 300.0, start = 288.15, min = 0.0, displayUnit = "degC", unit = "K", quantity = "ThermodynamicTemperature") = 'G.T_ref' "Fixed device temperature if useHeatPort = false"; + Real 'G.LossPower'(unit = "W", quantity = "Power") "Loss power leaving component via heatPort"; + Real 'G.T_heatPort'(nominal = 300.0, start = 288.15, min = 0.0, displayUnit = "degC", unit = "K", quantity = "ThermodynamicTemperature") "Temperature of heatPort"; + Real 'G.G_actual'(unit = "S", quantity = "Conductance") "Actual conductance = G_ref/(1 + alpha*(T_heatPort - T_ref))"; + Real 'C1.v'(fixed = true, start = 4.0, unit = "V", quantity = "ElectricPotential") "Voltage drop of the two pins (= p.v - n.v)"; + Real 'C1.p.v'(unit = "V", quantity = "ElectricPotential") "Potential at the pin"; + Real 'C1.p.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing into the pin"; + Real 'C1.n.v'(unit = "V", quantity = "ElectricPotential") "Potential at the pin"; + Real 'C1.n.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing into the pin"; + Real 'C1.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing from pin p to pin n"; + parameter Real 'C1.C'(start = 1.0, min = 0.0, unit = "F", quantity = "Capacitance") = 10.0 "Capacitance"; + Real 'C2.v'(fixed = true, start = 0.0, unit = "V", quantity = "ElectricPotential") "Voltage drop of the two pins (= p.v - n.v)"; + Real 'C2.p.v'(unit = "V", quantity = "ElectricPotential") "Potential at the pin"; + Real 'C2.p.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing into the pin"; + Real 'C2.n.v'(unit = "V", quantity = "ElectricPotential") "Potential at the pin"; + Real 'C2.n.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing into the pin"; + Real 'C2.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing from pin p to pin n"; + parameter Real 'C2.C'(start = 1.0, min = 0.0, unit = "F", quantity = "Capacitance") = 100.0 "Capacitance"; + Real 'Nr.v'(unit = "V", quantity = "ElectricPotential") "Voltage drop of the two pins (= p.v - n.v)"; + Real 'Nr.p.v'(unit = "V", quantity = "ElectricPotential") "Potential at the pin"; + Real 'Nr.p.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing into the pin"; + Real 'Nr.n.v'(unit = "V", quantity = "ElectricPotential") "Potential at the pin"; + Real 'Nr.n.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing into the pin"; + Real 'Nr.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing from pin p to pin n"; + parameter Real 'Nr.Ga'(min = -1.0, unit = "S", quantity = "Conductance") = -0.757576 "Conductance in inner voltage range"; + parameter Real 'Nr.Gb'(min = -1.0, unit = "S", quantity = "Conductance") = -0.409091 "Conductance in outer voltage range"; + parameter Real 'Nr.Ve'(unit = "V", quantity = "ElectricPotential") = 1.0 "Inner voltage range limit"; + Real 'Gnd.p.v'(unit = "V", quantity = "ElectricPotential") "Potential at the pin"; + Real 'Gnd.p.i'(unit = "A", quantity = "ElectricCurrent") "Current flowing into the pin"; + equation + 'L.n.v' = 'Ro.p.v'; + 'L.p.v' = 'G.p.v'; + 'L.p.v' = 'C2.p.v'; + 'C1.p.v' = 'G.n.v'; + 'C1.p.v' = 'Nr.p.v'; + 'Gnd.p.v' = 'Nr.n.v'; + 'Gnd.p.v' = 'C1.n.v'; + 'Gnd.p.v' = 'C2.n.v'; + 'Gnd.p.v' = 'Ro.n.v'; + 'Ro.p.i' + 'L.n.i' = 0.0; + 'Gnd.p.i' + 'Nr.n.i' + 'C2.n.i' + 'C1.n.i' + 'Ro.n.i' = 0.0; + 'C2.p.i' + 'G.p.i' + 'L.p.i' = 0.0; + 'Nr.p.i' + 'C1.p.i' + 'G.n.i' = 0.0; + 'L.L' * der('L.i') = 'L.v'; + 0.0 = 'L.p.i' + 'L.n.i'; + 'L.i' = 'L.p.i'; + 'L.v' = 'L.p.v' - 'L.n.v'; + assert(1.0 + 'Ro.alpha' * ('Ro.T_heatPort' - 'Ro.T_ref') >= 2.220446049250313e-16, "Temperature outside scope of model!", AssertionLevel.error); + 'Ro.R_actual' = 'Ro.R' * (1.0 + 'Ro.alpha' * ('Ro.T_heatPort' - 'Ro.T_ref')); + 'Ro.v' = 'Ro.R_actual' * 'Ro.i'; + 'Ro.LossPower' = 'Ro.v' * 'Ro.i'; + 'Ro.T_heatPort' = 'Ro.T'; + 0.0 = 'Ro.p.i' + 'Ro.n.i'; + 'Ro.i' = 'Ro.p.i'; + 'Ro.v' = 'Ro.p.v' - 'Ro.n.v'; + assert(1.0 + 'G.alpha' * ('G.T_heatPort' - 'G.T_ref') >= 2.220446049250313e-16, "Temperature outside scope of model!", AssertionLevel.error); + 'G.G_actual' = 'G.G' / (1.0 + 'G.alpha' * ('G.T_heatPort' - 'G.T_ref')); + 'G.i' = 'G.G_actual' * 'G.v'; + 'G.LossPower' = 'G.v' * 'G.i'; + 'G.T_heatPort' = 'G.T'; + 0.0 = 'G.p.i' + 'G.n.i'; + 'G.i' = 'G.p.i'; + 'G.v' = 'G.p.v' - 'G.n.v'; + 'C1.i' = 'C1.C' * der('C1.v'); + 0.0 = 'C1.p.i' + 'C1.n.i'; + 'C1.i' = 'C1.p.i'; + 'C1.v' = 'C1.p.v' - 'C1.n.v'; + 'C2.i' = 'C2.C' * der('C2.v'); + 0.0 = 'C2.p.i' + 'C2.n.i'; + 'C2.i' = 'C2.p.i'; + 'C2.v' = 'C2.p.v' - 'C2.n.v'; + 'Nr.i' = if 'Nr.v' < (-'Nr.Ve') then 'Nr.Gb' * ('Nr.v' + 'Nr.Ve') - 'Nr.Ga' * 'Nr.Ve' else if 'Nr.v' > 'Nr.Ve' then 'Nr.Gb' * ('Nr.v' - 'Nr.Ve') + 'Nr.Ga' * 'Nr.Ve' else 'Nr.Ga' * 'Nr.v'; + 0.0 = 'Nr.p.i' + 'Nr.n.i'; + 'Nr.i' = 'Nr.p.i'; + 'Nr.v' = 'Nr.p.v' - 'Nr.n.v'; + 'Gnd.p.v' = 0.0; + annotation(experiment(StopTime = 5e4, Interval = 1)); + end 'ChuaCircuit'; +end 'ChuaCircuit'; \ No newline at end of file