Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ docs/site/
# It records a fixed state of all packages used by the project. As such, it should not be
# committed for packages, but should be committed for applications that require a static
# environment.
Manifest.toml
Manifest.toml
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a new line at the end (to keep Git-diff rendering happy).

200 changes: 94 additions & 106 deletions src/Hydraulic/IsothermalCompressible/components.jl
Original file line number Diff line number Diff line change
@@ -1,55 +1,59 @@

"""
Cap(; p_int, name)
Cap(; name)

Caps a hydraulic port to prevent mass flow in or out.

# Parameters:
- `p_int`: [Pa] initial pressure (set by `p_int` argument)

# Connectors:
- `port`: hydraulic port
"""
@component function Cap(; name)
vars = @variables p(t), [guess = 0]
@mtkmodel Cap begin

systems = @named begin
@parameters begin
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be dropped. @parameters and @variable blocks aren't compulsory; mtkmodel handles such cases robustly.


@variables begin
p(t), [guess = 0]
end

@components begin
port = HydraulicPort()
end

eqs = [port.p ~ p
port.dm ~ 0]
@equations begin
port.p ~ p
port.dm ~ 0
end

ODESystem(eqs, t, vars, []; name, systems)
end

"""
Open(; p_int, name)
Open(; name)

Provides an "open" boundary condition for a hydraulic port such that mass flow `dm` is non-zero. This is opposite from an un-connected hydraulic port or the `Cap` boundary component which sets the mass flow `dm` to zero.

# Parameters:
- `p_int`: [Pa] initial pressure (set by `p_int` argument)

# Connectors:
- `port`: hydraulic port
"""
@component function Open(; name)
pars = []
@mtkmodel Open begin

@parameters begin
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be dropped


vars = @variables begin
@variables begin
p(t), [guess = 0]
dm(t), [guess = 0]
end

systems = @named begin
@components begin
port = HydraulicPort()
end

eqs = [port.p ~ p
port.dm ~ dm]
@equations begin
port.p ~ p
port.dm ~ dm
end

ODESystem(eqs, t, vars, pars; name, systems)
end

"""
Expand Down Expand Up @@ -226,45 +230,44 @@ end
@deprecate Pipe Tube

"""
FlowDivider(;p_int, n, name)
FlowDivider(; n, name)

Reduces the flow from `port_a` to `port_b` by `n`. Useful for modeling parallel tubes efficiently by placing a `FlowDivider` on each end of a tube.

# Parameters:
- `p_int`: [Pa] initial pressure
- `n`: divide flow from `port_a` to `port_b` by `n`

# Connectors:
- `port_a`: full flow hydraulic port
- `port_b`: part flow hydraulic port
"""
@component function FlowDivider(; n, name)
@mtkmodel FlowDivider begin

#TODO: assert n >= 1

pars = @parameters begin
@parameters begin
n = n
end

vars = @variables begin
@variables begin
dm_a(t), [guess = 0]
dm_b(t), [guess = 0]
end

systems = @named begin
@components begin
port_a = HydraulicPort()
port_b = HydraulicPort()
open = Open()
end

eqs = [connect(port_a, port_b, open.port)
dm_a ~ port_a.dm
dm_b ~ dm_a / n
open.dm ~ dm_a - dm_b # extra flow dumps into an open port
# port_b.dm ~ dm_b # divided flow goes to port_b
]
@equations begin
connect(port_a, port_b, open.port)
dm_a ~ port_a.dm
dm_b ~ dm_a / n
open.dm ~ dm_a - dm_b # extra flow dumps into an open port
# port_b.dm ~ dm_b # divided flow goes to port_b
end

ODESystem(eqs, t, vars, pars; name, systems)
end

@component function ValveBase(
Expand Down Expand Up @@ -313,14 +316,11 @@ end
end

"""
Valve(reversible = false; p_a_int, p_b_int, area_int, Cd, Cd_reverse = Cd, minimum_area = 0, name)
Valve(reversible = false; Cd, Cd_reverse = Cd, minimum_area = 0, name)

Valve with `area` input and discharge coefficient `Cd` defined by https://en.wikipedia.org/wiki/Discharge_coefficient. The `Cd_reverse` parameter allows for directional flow restriction, making it possible to define a check valve.

# Parameters:
- `p_a_int`: [Pa] initial pressure for `port_a`
- `p_b_int`: [Pa] initial pressure for `port_b`
- `area_int`: [m^2] initial valve opening
- `Cd`: discharge coefficient flowing from `a → b`
- `Cd_reverse`: discharge coefficient flowing from `b → a`
- `minimum_area`: when `reversible = false` applies a forced minimum area
Expand Down Expand Up @@ -357,36 +357,37 @@ Valve with `area` input and discharge coefficient `Cd` defined by https://en.wik
ODESystem(eqs, t, vars, pars; name, systems)
end

@component function VolumeBase(; area, dead_volume = 0, Χ1 = 1, Χ2 = 1,
name)
pars = @parameters begin
@mtkmodel VolumeBase begin

@parameters begin
area = area
dead_volume = dead_volume
x1 = 1
x2 = 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x1 x2 were @structural_parameters. These could be just @parameters. However, that would need fixing these scoping here: https://github.com/SciML/ModelingToolkitStandardLibrary.jl/blob/main/src/Hydraulic/IsothermalCompressible/components.jl#L648-L650 in DynamicVolume

Probably adding them as structural_parameters is easier.

end

systems = @named begin
port = HydraulicPort()
end

vars = @variables begin
@variables begin
x(t)
dx(t), [guess = 0]
rho(t), [guess = liquid_density(port)]
drho(t), [guess = 0]
vol(t)
end

# let
dm = port.dm
p = port.p
@components begin
port = HydraulicPort()
end

eqs = [vol ~ dead_volume + area * x
D(x) ~ dx
D(rho) ~ drho
rho ~ full_density(port, p)
dm ~ drho * vol * Χ1 + rho * area * dx * Χ2]
@equations begin
dm = port.dm
p = port.p
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be added to a

begin
...
end

(outside @equations)
As dm and p are not defined as variables, these equations will throw errors.

vol ~ dead_volume + area * x
D(x) ~ dx
D(rho) ~ drho
rho ~ full_density(port, p)
dm ~ drho * vol * Χ1 + rho * area * dx * Χ2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo:

Suggested change
dm ~ drho * vol * Χ1 + rho * area * dx * Χ2
dm ~ drho * vol * x1 + rho * area * dx * x2

end

ODESystem(eqs, t, vars, pars; name, systems)
end

"""
Expand All @@ -400,29 +401,29 @@ Fixed fluid volume.
# Connectors:
- `port`: hydraulic port
"""
@component function FixedVolume(; vol, name)
pars = @parameters begin
vol = vol
end
@mtkmodel FixedVolume begin

systems = @named begin
port = HydraulicPort(;)
@parameters begin
Volume
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Volume
vol

end

vars = @variables begin
@variables begin
rho(t), [guess = liquid_density(port)]
drho(t), [guess = 0]
end

# let
dm = port.dm
p = port.p
@components begin
port = HydraulicPort()
end

eqs = [D(rho) ~ drho
rho ~ full_density(port, p)
dm ~ drho * vol]
@equations begin
dm = port.dm
p = port.p
Copy link
Member

@ven-k ven-k Mar 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be added to a

begin
...
end

(outside @equations)

As dm and p are not defined as variables, these equations will throw errors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like accessing values from subcomponent can't be added to begin...end. My bad.

Alternative fix would be, define dm and p as @variables.
And move these back to @equations .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems simplest?

    @equations begin
        D(rho) ~ drho
        rho ~ full_density(port, port.p)
        port.dm ~ drho * vol
    end

D(rho) ~ drho
rho ~ full_density(port, p)
dm ~ drho * vol
end

ODESystem(eqs, t, vars, pars; name, systems)
end

"""
Expand Down Expand Up @@ -463,16 +464,14 @@ dm ────► │ │ area

See also [`FixedVolume`](@ref), [`DynamicVolume`](@ref)
"""
@component function Volume(;
@mtkmodel Volume begin

#parameters
area,
direction = +1, name)
pars = @parameters begin
area = area
@parameters begin
area
direction = +1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

direction could be of type @structurtal_parameters.

Is this intentionally promoted to a @parameters?

While here, could you change +1 to 1?

end

vars = @variables begin
@variables begin
x(t)
dx(t)
p(t)
Expand All @@ -482,32 +481,33 @@ See also [`FixedVolume`](@ref), [`DynamicVolume`](@ref)
dm(t)
end

systems = @named begin
@components begin
port = HydraulicPort()
flange = MechanicalPort()
end

eqs = [
# connectors
port.p ~ p
port.dm ~ dm
flange.v * direction ~ dx
flange.f * direction ~ -f
@equations begin
# connectors
port.p ~ p
port.dm ~ dm
flange.v * direction ~ dx
flange.f * direction ~ -f

# differentials
D(x) ~ dx
D(rho) ~ drho
# differentials
D(x) ~ dx
D(rho) ~ drho

# physics
rho ~ liquid_density(port, p)
f ~ p * area
dm ~ drho * x * area + rho * dx * area
end

# physics
rho ~ liquid_density(port, p)
f ~ p * area
dm ~ drho * x * area + rho * dx * area]

ODESystem(eqs, t, vars, pars; name, systems, defaults = [rho => liquid_density(port)])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defaults = [rho => liquid_density(port)]

can be added via the @defaults block https://docs.sciml.ai/ModelingToolkit/stable/basics/MTKLanguage/#@defaults-begin-block

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this correct?

    @defaults begin
        rho => liquid_density(port)
    end

end

"""
DynamicVolume(N, add_inertia=true; p_int, area, x_int = 0, x_max, x_min = 0, x_damp = x_min, direction = +1, perimeter = 2 * sqrt(area * pi), shape_factor = 64, head_factor = 1, Cd = 1e2, Cd_reverse = Cd, name)
DynamicVolume(N, add_inertia=true, reversible=false; area, x_int = 0, x_max, x_min = 0, x_damp = x_min, direction = +1, perimeter = 2 * sqrt(area * pi), shape_factor = 64, head_factor = 1, Cd = 1e2, Cd_reverse = Cd, name)

Volume with moving wall with `flange` connector for converting hydraulic energy to 1D mechanical. The `direction` argument aligns the mechanical port with the hydraulic port, useful when connecting two dynamic volumes together in oppsing directions to create an actuator.

Expand Down Expand Up @@ -680,14 +680,11 @@ dm ────► │ │ area
end

"""
SpoolValve(reversible = false; p_a_int, p_b_int, x_int, Cd, d, name)
SpoolValve(reversible = false; Cd, d, name)

Spool valve with `x` valve opening input as mechanical flange port and `d` diameter of orifice. See `Valve` for more information.

# Parameters:
- `p_a_int`: [Pa] initial pressure for `port_a`
- `p_b_int`: [Pa] initial pressure for `port_b`
- `x_int`: [m] initial valve opening
- `d`: [m] orifice diameter
- `Cd`: discharge coefficient flowing from `a → b`

Expand Down Expand Up @@ -727,18 +724,13 @@ See [`Valve`](@ref) for more information.
end

"""
SpoolValve2Way(reversible = false; p_s_int, p_a_int, p_b_int, p_r_int, m, g, x_int, Cd, d, name)
SpoolValve2Way(reversible = false; m, g, Cd, d, name)

2-ways spool valve with 4 ports and spool mass. Fluid flow direction S → A and B → R when `x` is positive and S → B and A → R when `x` is negative.

# Parameters:
- `p_s_int`: [Pa] initial pressure for `port_s`
- `p_a_int`: [Pa] initial pressure for `port_a`
- `p_b_int`: [Pa] initial pressure for `port_b`
- `p_r_int`: [Pa] initial pressure for `port_r`
- `m`: [kg] mass of the spool
- `g`: [m/s²] gravity field acting on the spool, positive value acts in the positive direction
- `x_int`: [m] initial valve opening
- `d`: [m] orifice diameter
- `Cd`: discharge coefficient flowing from `s → a` and `b → r`

Expand Down Expand Up @@ -788,8 +780,6 @@ end

"""
Actuator(N, add_inertia = true, reversible = false;
p_a_int,
p_b_int,
area_a,
area_b,
perimeter_a = 2 * sqrt(area_a * pi),
Expand Down Expand Up @@ -819,8 +809,6 @@ Actuator made of two DynamicVolumes connected in opposite direction with body ma

# Parameters:
## volume
- `p_a_int`: [Pa] initial pressure for `port_a`
- `p_b_int`: [Pa] initial pressure for `port_b`
- `area_a`: [m^2] moving wall area of volume `A`
- `area_b`: [m^2] moving wall area of volume `B`
- `length_a_int`: [m] initial wall position for `A`
Expand Down
Loading
Loading