|
| 1 | +# Sign Convention |
| 2 | + |
| 3 | +A sign convention is recommended for this library that implements the following rule: |
| 4 | + |
| 5 | +> An input component that specifies the *through* variable should be such that an oppossite equality is written such that when connected to a conserved quantity component (i.e. a mass or capacitor component) a positive value for a flow variable represents the accumulation of that conserved quantity over time in the component. |
| 6 | +
|
| 7 | +Note: that this implements the same convention as applied in Modelica Standard Library. |
| 8 | + |
| 9 | +For example, the following would be the *correct* sign convention for the `Mechanical.Translational` force variable `f` |
| 10 | + |
| 11 | +```julia |
| 12 | +@mtkmodel ConstantForce begin |
| 13 | + @parameters begin |
| 14 | + f = 0 |
| 15 | + end |
| 16 | + @components begin |
| 17 | + flange = MechanicalPort() |
| 18 | + end |
| 19 | + @equations begin |
| 20 | + # connectors |
| 21 | + flange.f ~ -f # <-- force is leaving |
| 22 | + end |
| 23 | +end |
| 24 | +``` |
| 25 | + |
| 26 | +And writing the following would be the *incorrect* sign convention. |
| 27 | + |
| 28 | +```julia |
| 29 | +@equations begin |
| 30 | + # connectors |
| 31 | + flange.f ~ f # <-- wrong through variable input sign! |
| 32 | +end |
| 33 | +``` |
| 34 | + |
| 35 | +<!-- To visualize the sign convention, one can draw the orientation of the connector port *across* and *through* variables and the subsequent component variables. For example, the `Mechanical.Translation` mass component would look like |
| 36 | +
|
| 37 | + |
| 38 | +
|
| 39 | +In this case we know from Newton that mass times acceleration equals force, therefore the direction of movement is in the opposite direction of the force. In other words, if we push the mass from left to right (i.e. in the positive direction), then the mass will generate a force in the negative direction. This would be the general rule for a single port component of any domain. The exception is for a *through* variable **input** component, which should align the component and port connection *through* variables. For example, a force input diagram would look like this: |
| 40 | +
|
| 41 | + |
| 42 | +
|
| 43 | +For a 2 port connection component, then the *through* variable is exiting each connection port in opposing directions. Using a damper as an example, if the positive direction is to the right, then the force of the damper is pushing left (i.e. in the negative direction) on connection port `a` and right (positive direction) on connection port `b`. |
| 44 | +
|
| 45 | + --> |
| 46 | +# Discussion |
| 47 | + |
| 48 | +The energy dissipation equation that governs the acausal connection definitions should be such that a positive *through* variable input will lead to an increasing *across* variable value. |
| 49 | + |
| 50 | +```math |
| 51 | +\frac{\partial \blue across}{\partial t} = \text{ {\green through} input} |
| 52 | +``` |
| 53 | + |
| 54 | +This is demonstrated in the following domains of `Mechanical`, `Electrical`, and `Hydraulic`. |
| 55 | + |
| 56 | +## Mechanical |
| 57 | + |
| 58 | +The flow variable (i.e. force) input component for the `Mechanical` domain is |
| 59 | + |
| 60 | +```@example sign_convention |
| 61 | +using ModelingToolkit |
| 62 | +using ModelingToolkitStandardLibrary.Mechanical.Translational |
| 63 | +
|
| 64 | +@mtkmodel ConstantForce begin |
| 65 | + @parameters begin |
| 66 | + f |
| 67 | + end |
| 68 | + @components begin |
| 69 | + flange = MechanicalPort() |
| 70 | + end |
| 71 | + @equations begin |
| 72 | + # connectors |
| 73 | + flange.f ~ -f |
| 74 | + end |
| 75 | +end |
| 76 | +``` |
| 77 | + |
| 78 | +Here we can see that a positive input force results in an increasing velocity. |
| 79 | + |
| 80 | +```@example sign_convention |
| 81 | +@mtkmodel System begin |
| 82 | + @components begin |
| 83 | + mass = Mass(; m = 10) |
| 84 | + force = ConstantForce(; f = 1) |
| 85 | + end |
| 86 | + @equations begin |
| 87 | + connect(mass.flange, force.flange) |
| 88 | + end |
| 89 | +end |
| 90 | +@mtkbuild sys = System() |
| 91 | +full_equations(sys) |
| 92 | +``` |
| 93 | + |
| 94 | +## Electrical |
| 95 | + |
| 96 | +The flow variable (i.e. current) input component for the `Electrical` domain is |
| 97 | + |
| 98 | +```@example sign_convention |
| 99 | +using ModelingToolkitStandardLibrary.Electrical |
| 100 | +
|
| 101 | +@mtkmodel ConstantCurrent begin |
| 102 | + @parameters begin |
| 103 | + i |
| 104 | + end |
| 105 | + @components begin |
| 106 | + p = Pin() |
| 107 | + n = Pin() |
| 108 | + end |
| 109 | + @equations begin |
| 110 | + 0 ~ p.i + n.i |
| 111 | + i ~ -n.i # can also be written as i ~ p.i |
| 112 | + end |
| 113 | +end |
| 114 | +``` |
| 115 | + |
| 116 | +Here we can see that a positive input current results in an increasing voltage. Note that the electrical domain uses pins `p` and `n` at each side of the source and energy storage components. The direction of connection is not important here, only that a positive connector `p` connects with a negative connector `n`. |
| 117 | + |
| 118 | +```@example sign_convention |
| 119 | +@mtkmodel System begin |
| 120 | + @components begin |
| 121 | + capacitor = Capacitor(; C = 10) |
| 122 | + current = ConstantCurrent(; i = 1) |
| 123 | + ground = Ground() |
| 124 | + end |
| 125 | + @equations begin |
| 126 | + connect(current.n, capacitor.p) |
| 127 | + connect(capacitor.n, current.p, ground.g) |
| 128 | + end |
| 129 | +end |
| 130 | +@mtkbuild sys = System() |
| 131 | +full_equations(sys) |
| 132 | +``` |
| 133 | + |
| 134 | +Reversing the pins gives the same result |
| 135 | + |
| 136 | +```@example sign_convention |
| 137 | +@mtkmodel System begin |
| 138 | + @components begin |
| 139 | + capacitor = Capacitor(; C = 10) |
| 140 | + current = ConstantCurrent(; i = 1) |
| 141 | + ground = Ground() |
| 142 | + end |
| 143 | + @equations begin |
| 144 | + connect(current.p, capacitor.n) |
| 145 | + connect(capacitor.p, current.n, ground.g) |
| 146 | + end |
| 147 | +end |
| 148 | +@mtkbuild sys = System() |
| 149 | +full_equations(sys) |
| 150 | +``` |
| 151 | + |
| 152 | +## Hydraulic |
| 153 | + |
| 154 | +The flow variable (i.e. mass flow) input component for the `Hydraulic` domain is |
| 155 | + |
| 156 | +```@example sign_convention |
| 157 | +using ModelingToolkitStandardLibrary.Hydraulic.IsothermalCompressible |
| 158 | +
|
| 159 | +@mtkmodel ConstantMassFlow begin |
| 160 | + @parameters begin |
| 161 | + p_int |
| 162 | + dm |
| 163 | + end |
| 164 | + @components begin |
| 165 | + port = HydraulicPort(; p_int) |
| 166 | + end |
| 167 | + @equations begin |
| 168 | + port.dm ~ -dm |
| 169 | + end |
| 170 | +end |
| 171 | +``` |
| 172 | + |
| 173 | +A positive input mass flow leads to an increasing pressure (in this case we get increasing density (`rho`), which is directly related to an increasing pressure). |
| 174 | + |
| 175 | +```@example sign_convention |
| 176 | +@mtkmodel System begin |
| 177 | + @components begin |
| 178 | + volume = FixedVolume(; vol = 10.0, p_int = 0.0) |
| 179 | + flow = ConstantMassFlow(; dm = 1) |
| 180 | + fluid = HydraulicFluid() |
| 181 | + end |
| 182 | + @equations begin |
| 183 | + connect(flow.port, volume.port) |
| 184 | + connect(fluid, flow.port) |
| 185 | + end |
| 186 | +end |
| 187 | +@mtkbuild sys = System() |
| 188 | +full_equations(sys) |> first |
| 189 | +``` |
0 commit comments