Skip to content

Commit 0d30dd0

Browse files
author
Brad Carman
committed
added Cap and DynamicVolume
1 parent c27b203 commit 0d30dd0

File tree

3 files changed

+145
-108
lines changed

3 files changed

+145
-108
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
1111

1212
[compat]
1313
IfElse = "0.1"
14-
ModelingToolkit = "8.49" #8.49 required for the Domain feauture
14+
ModelingToolkit = "8.50"
1515
Symbolics = "4.9, 5"
1616
julia = "1.6"
1717

src/Hydraulic/IsothermalCompressible/components.jl

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,36 @@ Fixed pressure source
5151
ODESystem(eqs, t, vars, pars; name, systems)
5252
end
5353

54+
"""
55+
Cap(; p_int, name)
56+
57+
Caps a hydrualic port to prevent mass flow in or out.
58+
59+
# Parameters:
60+
- `p_int`: [Pa] initial pressure (set by `p_int` argument)
61+
62+
# Connectors:
63+
- `port`: hydraulic port
64+
"""
65+
@component function Cap(; p_int, name)
66+
pars = @parameters p_int = p_int
67+
68+
vars = @variables p(t) = p_int
69+
70+
systems = @named begin port = HydraulicPort(; p_int = p_int) end
71+
72+
eqs = [
73+
port.p ~ p
74+
port.dm ~ 0
75+
]
76+
77+
ODESystem(eqs, t, vars, pars; name, systems)
78+
end
79+
80+
81+
82+
83+
5484
"""
5585
FixedVolume(; vol, p_int, name)
5686
@@ -205,12 +235,17 @@ end
205235
DynamicVolume(; p_int, x_int=0, area, dead_volume=0, direction=+1, name)
206236
207237
Volume with moving wall. 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.
208-
_________
209-
| |
210-
--> d.v. |
211-
|_________|
212-
└─► x (= ∫ flange.v * direction)
213-
238+
```
239+
┌─────────────────┐ ───
240+
│ │ ▲
241+
│ │
242+
dm ────► dead volume │ │ area
243+
│ │
244+
│ │ ▼
245+
└─────────────────┤ ───
246+
247+
└─► x (= flange.v * direction)
248+
```
214249
215250
# Parameters:
216251
- `p_int`: [Pa] initial pressure (set by `p_int` argument)
@@ -233,25 +268,25 @@ Volume with moving wall. The `direction` argument aligns the mechanical port wi
233268
dead_volume = dead_volume
234269
end
235270

271+
systems = @named begin
272+
port = HydraulicPort(; p_int)
273+
flange = MechanicalPort()
274+
end
275+
236276
vars = @variables begin
237277
x(t) = x_int
238278
dx(t) = 0
239-
rho(t) = density(fluid, p_int)
279+
rho(t) = density(port, p_int)
240280
drho(t) = 0
241281
end
242282

243-
systems = @named begin
244-
port = HydraulicPort(; p_int)
245-
flange = MechanicalPort()
246-
end
247-
248283
# let -------------
249284
vol = dead_volume + area * x
250285

251286
eqs = [D(x) ~ dx
252287
D(rho) ~ drho
253288
dx ~ flange.v * direction
254-
rho ~ density(fluid, port.p)
289+
rho ~ density(port, port.p)
255290
port.dm ~ drho * vol + rho * area * dx
256291
flange.f ~ -port.p * area * direction]
257292

test/Hydraulic/isothermal_compressible.jl

Lines changed: 96 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -6,128 +6,130 @@ import ModelingToolkitStandardLibrary.Mechanical.Translational as T
66
@parameters t
77
D = Differential(t)
88

9-
function system(N; name, fluid)
10-
pars = @parameters begin fluid = fluid end
9+
function system(N; bulk_modulus, name)
10+
pars = @parameters begin
11+
bulk_modulus = bulk_modulus
12+
end
1113

1214
systems = @named begin
13-
stp = B.Step(; height = 10e5, offset = 0, start_time = 0.005, duration = Inf,
14-
smooth = 0)
15+
fluid = IC.HydraulicFluid(;bulk_modulus)
16+
stp = B.Step(; height = 10e5, offset = 0, start_time = 0.005, duration = Inf, smooth = true)
1517
src = IC.InputSource(; p_int = 0)
16-
vol = IC.FixedVolume(; p_int = 0, vol = 10.0, fluid)
18+
vol = IC.FixedVolume(; p_int = 0, vol = 10.0)
1719
end
1820

1921
if N == 1
20-
@named res = IC.PipeBase(; p_int = 0, area = 0.01, length = 500.0, fluid)
22+
@named res = IC.PipeBase(; p_int = 0, area = 0.01, length = 500.0)
2123
else
22-
@named res = IC.Pipe(N; p_int = 0, area = 0.01, length = 500.0, fluid)
24+
@named res = IC.Pipe(N; p_int = 0, area = 0.01, length = 500.0)
2325
end
2426
push!(systems, res)
2527

26-
eqs = [connect(stp.output, src.input)
27-
connect(src.port, res.port_a)
28-
connect(res.port_b, vol.port)]
28+
eqs = [ connect(stp.output, src.input)
29+
connect(fluid, src.port)
30+
connect(src.port, res.port_a)
31+
connect(res.port_b, vol.port)]
2932

3033
ODESystem(eqs, t, [], pars; name, systems)
3134
end
3235

33-
@named user_oil = IC.FluidType()
34-
user_oil_type = typeof(IC.get_fluid(user_oil))
35-
IC.density(::user_oil_type) = 876
36-
IC.bulk_modulus(::user_oil_type) = 1.2e9
37-
IC.viscosity(::user_oil_type) = 0.034
38-
39-
@named sys1 = system(1; fluid = IC.water_20C)
40-
@named sys2 = system(2; fluid = IC.water_20C)
41-
@named sys5 = system(5; fluid = IC.water_20C)
42-
@named sys25 = system(25; fluid = IC.water_20C)
43-
44-
cc1 = structural_simplify(sys1; allow_parameter = false)
45-
cc2 = structural_simplify(sys2; allow_parameter = false)
46-
cc5 = structural_simplify(sys5; allow_parameter = false)
47-
cc25 = structural_simplify(sys25; allow_parameter = false)
48-
49-
t_end = 0.2
50-
prob0 = ODEProblem(cc1, [], (0, t_end), [complete(sys1).fluid => user_oil])
51-
prob1 = ODEProblem(cc1, [], (0, t_end))
52-
prob2 = ODEProblem(cc2, [], (0, t_end))
53-
prob5 = ODEProblem(cc5, [], (0, t_end))
54-
prob25 = ODEProblem(cc25, [], (0, t_end))
36+
@named sys1_2 = system(1; bulk_modulus=2e9)
37+
@named sys1_1 = system(1; bulk_modulus=1e9)
38+
@named sys5_1 = system(5; bulk_modulus=1e9)
5539

56-
dt = 1e-4
5740
NEWTON = NLNewton(check_div = false, always_new = true, max_iter = 100, relax = 4 // 10)
58-
# sol0 = solve(prob0, ImplicitEuler(nlsolve=NEWTON); adaptive=false, dt, initializealg=NoInit())
59-
# sol1 = solve(prob1, ImplicitEuler(nlsolve=NEWTON); adaptive=false, dt, initializealg=NoInit())
60-
# sol2 = solve(prob2, ImplicitEuler(nlsolve=NEWTON); adaptive=false, dt, initializealg=NoInit())
61-
# sol5 = solve(prob5, ImplicitEuler(nlsolve=NEWTON); adaptive=false, dt, initializealg=NoInit())
62-
# sol25 = solve(prob25, ImplicitEuler(nlsolve=NEWTON); adaptive=false, dt, initializealg=NoInit())
6341

64-
# using GLMakie
42+
syss = structural_simplify.([sys1_2, sys1_1, sys5_1])
43+
probs = [ODEProblem(sys, [], (0, 0.2)) for sys in syss];
44+
sols = [solve(prob, ImplicitEuler(nlsolve=NEWTON); initializealg=NoInit()) for prob in probs];
45+
46+
s1_2 = complete(sys1_2)
47+
s1_1 = complete(sys1_1)
48+
s5_1 = complete(sys5_1)
49+
50+
# higher stiffness should compress more quickly and give a higher pressure
51+
@test sols[1][s1_2.vol.port.p][end] > sols[2][s1_1.vol.port.p][end]
52+
53+
# N=5 pipe is compressible, will pressurize more slowly
54+
@test sols[2][s1_1.vol.port.p][end] > sols[3][s5_1.vol.port.p][end]
55+
56+
# using CairoMakie
6557
# fig = Figure()
6658
# ax = Axis(fig[1,1])
67-
# lines!(ax, sol0.t, sol0[sys1.res.port_a.p] .- sol0[sys1.res.port_b.p]; label="pipe base, oil", linestyle=:dash)
68-
# lines!(ax, sol1.t, sol1[sys1.res.port_a.p] .- sol1[sys1.res.port_b.p]; label="pipe base")
69-
# lines!(ax, sol2.t, sol2[sys2.res.port_a.p] .- sol2[sys2.res.port_b.p]; label="pipe N=2")
70-
# lines!(ax, sol5.t, sol5[sys5.res.port_a.p] .- sol5[sys5.res.port_b.p]; label="pipe N=5")
71-
# lines!(ax, sol25.t, sol25[sys25.res.port_a.p] .- sol25[sys25.res.port_b.p]; label="pipe N=25")
72-
# axislegend(ax)
59+
# lines!(ax, sols[1].t, sols[1][s1_2.src.port.p]; label="sorce", color=:black)
60+
# # lines!(ax, sols[2].t, sols[2][s1_1.src.port.p])
61+
# scatterlines!(ax, sols[1].t, sols[1][s1_2.vol.port.p]; label="bulk=2e9")
62+
# scatterlines!(ax, sols[2].t, sols[2][s1_1.vol.port.p]; label="bulk=1e9")
63+
# scatterlines!(ax, sols[3].t, sols[3][s5_1.vol.port.p]; label="bulk=1e9, N=5")
64+
# Legend(fig[1,2], ax)
7365
# fig
7466

75-
function actuator_system(; name, fluid_a, fluid_b = fluid_a)
76-
pars = @parameters begin
77-
fluid_a = fluid_a
78-
fluid_b = fluid_b
79-
end
8067

81-
systems = @named begin
82-
stp = B.Step(; height = 10e5, offset = 0, start_time = 0.005, duration = Inf,
83-
smooth = 0)
8468

85-
src_a = IC.InputSource(; p_int = 0)
86-
res_a = IC.Pipe(5; p_int = 0, area = 0.01, length = 500.0, fluid = fluid_a)
87-
act_a = IC.Actuator(+1; fluid = fluid_a, p_int = 0, x_int = 0, area = 0.1,
88-
dead_volume = 100)
8969

90-
src_b = IC.InputSource(; p_int = 0)
91-
res_b = IC.Pipe(5; p_int = 0, area = 0.01, length = 500.0, fluid = fluid_b)
92-
act_b = IC.Actuator(-1; fluid = fluid_b, p_int = 0, x_int = 0, area = 0.1,
93-
dead_volume = 100)
70+
function system(; bulk_modulus, name)
71+
pars = @parameters begin
72+
bulk_modulus = bulk_modulus
73+
end
9474

95-
m = T.Mass(; m = 1000)
75+
systems = @named begin
76+
fluid = IC.HydraulicFluid(;bulk_modulus)
77+
stp = B.Step(; height = 10e5, offset = 0, start_time = 0.05, duration = Inf, smooth = 0.001)
78+
src = IC.InputSource(; p_int = 0)
79+
vol1 = IC.DynamicVolume(; p_int = 0, area=0.01, direction=+1)
80+
vol2 = IC.DynamicVolume(; p_int = 0, area=0.01, direction=-1, x_int=1.0)
81+
mass = T.Mass(; m=1000, s_0=0)
82+
res = IC.PipeBase(; p_int = 0, area = 0.001, length = 50.0)
83+
cap = IC.Cap(;p_int=0)
9684
end
9785

98-
eqs = [connect(stp.output, src_a.input, src_b.input)
99-
connect(src_a.port, res_a.port_a)
100-
connect(res_a.port_b, act_a.port)
101-
connect(src_b.port, res_b.port_a)
102-
connect(res_b.port_b, act_b.port)
103-
connect(act_a.flange, act_b.flange, m.flange)]
86+
eqs = [ connect(stp.output, src.input)
87+
connect(fluid, src.port, cap.port)
88+
connect(src.port, res.port_a)
89+
connect(res.port_b, vol1.port)
90+
connect(vol1.flange, mass.flange, vol2.flange)
91+
connect(vol2.port, cap.port)]
10492

10593
ODESystem(eqs, t, [], pars; name, systems)
10694
end
10795

108-
@named act_sys = actuator_system(; fluid_a = IC.water_20C)
109-
cc = structural_simplify(act_sys; allow_parameter = false)
110-
111-
t_end = 0.5
112-
prob1 = ODEProblem(cc, [], (0, t_end), [complete(act_sys).fluid_b => user_oil])
113-
prob2 = ODEProblem(cc, [], (0, t_end))
114-
115-
sol1 = solve(prob1, ImplicitEuler(nlsolve = NEWTON); adaptive = false, dt,
116-
initializealg = NoInit())
117-
sol2 = solve(prob2, ImplicitEuler(nlsolve = NEWTON); adaptive = false, dt,
118-
initializealg = NoInit())
119-
120-
using GLMakie
121-
fig = Figure()
122-
ax = Axis(fig[1, 1])
123-
lines!(ax, sol1.t, sol1[act_sys.act_a.x]; color = :red)
124-
lines!(ax, sol1.t, sol1[act_sys.act_b.x]; color = :red, linestyle = :dash)
125-
lines!(ax, sol2.t, sol2[act_sys.act_a.x]; color = :blue)
126-
lines!(ax, sol2.t, sol2[act_sys.act_b.x]; color = :blue, linestyle = :dash)
127-
128-
ax = Axis(fig[2, 1])
129-
lines!(ax, sol1.t, (sol1[act_sys.act_a.port.p] .- sol1[act_sys.act_b.port.p]) / 1e5;
130-
color = :red)
131-
lines!(ax, sol2.t, (sol2[act_sys.act_a.port.p] .- sol2[act_sys.act_b.port.p]) / 1e5;
132-
color = :blue)
133-
fig
96+
@named sys1 = system(; bulk_modulus=1e9)
97+
@named sys2 = system(; bulk_modulus=2e9)
98+
99+
syss = structural_simplify.([sys1, sys2])
100+
probs = [ODEProblem(sys, [], (0, 0.2)) for sys in syss];
101+
dt = 1e-4
102+
sols = [solve(prob, ImplicitEuler(nlsolve=NEWTON); adaptive=false, dt, initializealg=NoInit()) for prob in probs];
103+
104+
s1 = complete(sys1)
105+
s2 = complete(sys2)
106+
107+
# less stiff will compress more
108+
@test maximum(sols[1][s1.mass.s]) > maximum(sols[2][s2.mass.s])
109+
110+
111+
# fig = Figure()
112+
# ax = Axis(fig[1,1])
113+
# lines!(ax, sols[1].t, sols[1][s1.src.port.p]; label="sorce", color=:black)
114+
# # lines!(ax, sols[2].t, sols[2][s1_1.src.port.p])
115+
# scatterlines!(ax, sols[1].t, sols[1][s1.vol1.port.p]; label="bulk=1e9")
116+
# scatterlines!(ax, sols[2].t, sols[2][s2.vol1.port.p]; label="bulk=2e9")
117+
# Legend(fig[1,2], ax)
118+
# fig
119+
120+
121+
# fig = Figure()
122+
# ax = Axis(fig[1,1])
123+
# scatterlines!(ax, sols[1].t, sols[1][s1.mass.s]; label="bulk=1e9")
124+
# scatterlines!(ax, sols[2].t, sols[2][s2.mass.s]; label="bulk=2e9")
125+
# Legend(fig[1,2], ax)
126+
# fig
127+
128+
129+
# fig = Figure()
130+
# ax = Axis(fig[1,1])
131+
# lines!(ax, sols[1].t, sols[1][s1.vol1.dx]; label="bulk=2e9")
132+
# lines!(ax, sols[1].t, sols[1][s1.vol2.dx]; label="bulk=2e9")
133+
# lines!(ax, sols[1].t, sols[1][s1.mass.v]; label="bulk=2e9")
134+
# Legend(fig[1,2], ax)
135+
# fig

0 commit comments

Comments
 (0)