Skip to content

Commit f8d0dc3

Browse files
committed
u_g is a profile now
1 parent 6d7a7da commit f8d0dc3

4 files changed

Lines changed: 80 additions & 77 deletions

File tree

examples/sparging_standard.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
dispersion_on=True,
4040
constant_profiles=False,
4141
)
42-
4342
if __name__ == "__main__":
4443
# my_simulation.exports = ["pressure", "J_T2"]
4544
output = my_simulation.solve(fast_solve=True)
@@ -49,7 +48,7 @@
4948
# P = output.exported_fields["pressure"]
5049
# plt.plot(output.x_ct, P)
5150
# output.exports_to_csv(FOLDER)
52-
output.export = ["pressure, "]
51+
# output.export = ["pressure, "]
5352

5453
output.profiles_to_csv(FOLDER)
5554
output.profiles_to_cdf(FOLDER)

src/sparging/correlations.py

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class CorrelationType(enum.Enum): # TODO do we really use it ?
2828
MORTON_NUMBER = "Mo"
2929
SCHMIDT_NUMBER = "Sc"
3030
REYNOLDS_NUMBER = "Re"
31-
SUPERFICIAL_GAS_VELOCITY = "u_g0"
31+
SUPERFICIAL_GAS_VELOCITY = "u_g"
3232
BUBBLE_VELOCITY = "v_g0"
3333
GAS_PHASE_DISPERSION = "E_g"
3434
LIQUID_PHASE_DISPERSION = "E_l"
@@ -308,16 +308,6 @@ def get_list(self, corr_type: CorrelationType) -> list[Correlation]:
308308
)
309309
all_correlations.append(v_g0)
310310

311-
# superficial gas velocity at the inlet
312-
u_g0 = Correlation(
313-
identifier="u_g0",
314-
function=lambda Vdot_g0, area: (Vdot_g0 / area).to("m/s"),
315-
corr_type=CorrelationType.SUPERFICIAL_GAS_VELOCITY,
316-
input_units=["m^3/s", "m^2"],
317-
output_units="m/s",
318-
)
319-
all_correlations.append(u_g0)
320-
321311

322312
h_l_higbie = Correlation(
323313
identifier="h_l_higbie",
@@ -361,27 +351,28 @@ def get_list(self, corr_type: CorrelationType) -> list[Correlation]:
361351
# liquid phase axial dispersion coefficient
362352
E_l = Correlation(
363353
identifier="E_l",
364-
function=lambda tank_diameter, u_g0: ureg.Quantity(
365-
0.678 * tank_diameter.magnitude**1.4 * u_g0.magnitude**0.3, "m**2/s"
354+
function=lambda tank_diameter, u_g: ureg.Quantity(
355+
0.678 * tank_diameter.magnitude**1.4 * u_g(0 * ureg.m).magnitude ** 0.3,
356+
"m**2/s",
366357
),
367358
corr_type=CorrelationType.LIQUID_PHASE_DISPERSION,
368359
source="Deckwer 1974",
369360
description="liquid phase axial dispersion coefficient, assumed equal to diffusivity of tritium in liquid FLiBe",
370-
input_units=["m", "m/s"],
361+
input_units=["m", PROFILE],
371362
output_units="m**2/s",
372363
)
373364
all_correlations.append(E_l)
374365

375366
# gas phase axial dispersion coefficient
376367
E_g = Correlation(
377368
identifier="E_g",
378-
function=lambda tank_diameter, u_g0: (
379-
0.2 * ureg("1/m") * tank_diameter**2 * u_g0
369+
function=lambda tank_diameter, u_g: (
370+
0.2 * ureg("1/m") * tank_diameter**2 * u_g(0 * ureg.m)
380371
), # gas phase axial dispersion coefficient
381372
corr_type=CorrelationType.GAS_PHASE_DISPERSION,
382373
source="Malara 1995",
383374
description="gas phase axial dispersion coefficient [m2/s], Malara 1995",
384-
input_units=["m", "m/s"],
375+
input_units=["m", PROFILE],
385376
output_units="m**2/s",
386377
)
387378
all_correlations.append(E_g)
@@ -585,3 +576,15 @@ def get_h_briggs(Re: float, Sc: float, D_l: float, d_b: float) -> float:
585576
description="specific interfacial area profile",
586577
)
587578
all_correlations.append(a)
579+
580+
u_g = Profile(
581+
identifier="u_g",
582+
function=lambda Vdot_g0, area, P_g: (
583+
lambda z: (Vdot_g0 / area).to("m/s") * (P_g(0 * ureg.m) / P_g(z))
584+
),
585+
corr_type=CorrelationType.SUPERFICIAL_GAS_VELOCITY,
586+
input_units=["m^3/s", "m^2", PROFILE],
587+
output_units="m/s",
588+
description="superficial gas velocity profile",
589+
)
590+
all_correlations.append(u_g)

src/sparging/inputs.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ def copy(self):
6565
class SpargingParameters:
6666
h_l: pint.Quantity | Correlation
6767
eps_g: pint.Quantity | Correlation | None = None
68-
u_g0: pint.Quantity | Correlation | None = None
6968
d_b: pint.Quantity | Correlation | None = None
7069
rho_g: pint.Quantity | Correlation | None = None
7170
E_g: pint.Quantity | Correlation | None = None
@@ -80,7 +79,6 @@ def copy(self):
8079
class SimulationInput:
8180
height: pint.Quantity
8281
area: pint.Quantity
83-
u_g0: pint.Quantity
8482
temperature: pint.Quantity
8583
h_l: pint.Quantity
8684
K_s: pint.Quantity
@@ -100,7 +98,6 @@ class SimulationInput:
10098
required_keys = (
10199
"height",
102100
"area",
103-
"u_g0",
104101
"temperature",
105102
"h_l",
106103
"K_s",
@@ -114,6 +111,7 @@ class SimulationInput:
114111
"P_g",
115112
"eps_g",
116113
"a",
114+
"u_g",
117115
) # these parameters will be used to solve the model
118116
graph: nx.Graph | None = None
119117
""" Stores the intermediate parameters and their relationships that built the SimulationInput.
@@ -128,6 +126,7 @@ class SimulationInput:
128126
P_g: Callable[[pint.Quantity], pint.Quantity] | None = None
129127
eps_g: Callable[[pint.Quantity], pint.Quantity] | None = None
130128
a: Callable[[pint.Quantity], pint.Quantity] | None = None
129+
u_g: Callable[[pint.Quantity], pint.Quantity] | None = None
131130

132131
@property
133132
def volume(self):
@@ -138,21 +137,25 @@ def a_0(self):
138137
return self.a(0 * ureg.m)
139138

140139
@property
141-
def eps_g_0(self):
140+
def eps_g0(self):
142141
return self.eps_g(0 * ureg.m)
143142

144143
@property
145-
def eps_l_0(self):
146-
return 1 - self.eps_g_0
144+
def eps_l0(self):
145+
return 1 - self.eps_g0
147146

148147
@property
149-
def P_l_0(self):
148+
def P_l0(self):
150149
return self.P_l(0 * ureg.m)
151150

152151
@property
153-
def P_g_0(self):
152+
def P_g0(self):
154153
return self.P_g(0 * ureg.m)
155154

155+
@property
156+
def u_g0(self):
157+
return self.u_g(0 * ureg.m)
158+
156159
def set_S_T(self, val: pint.Quantity):
157160
self.Q_T = (val.to("molT/m**3/s") * self.volume).to("molT/s")
158161

@@ -161,7 +164,7 @@ def get_S_T(self) -> pint.Quantity:
161164

162165
def get_tau(self) -> pint.Quantity:
163166
"""characteristic time of the sparger under the small partial pressure (SPP) approximation"""
164-
return (self.eps_l_0 / (self.h_l * self.a_0)).to("seconds")
167+
return (self.eps_l0 / (self.h_l * self.a_0)).to("seconds")
165168

166169
def get_c_T2_SS(self) -> pint.Quantity:
167170
return (self.get_S_T() * 1 / (self.h_l * self.a_0)).to("molT2/m^3")
@@ -177,7 +180,7 @@ def get_Pi_number(self) -> pint.Quantity:
177180
* self.height
178181
* self.h_l
179182
* self.a_0
180-
/ (self.eps_g_0 * self.graph.nodes["v_g0"]["value"])
183+
/ (self.eps_g0 * self.graph.nodes["v_g0"]["value"])
181184
).to("dimensionless")
182185

183186
def get_dP_dx(self) -> pint.Quantity:
@@ -196,16 +199,13 @@ def get_Bo(self) -> pint.Quantity:
196199
returns Bodenstein number = ratio of convective to dispersive transport for the gas phase
197200
corresponds to Peclet number at the scale of the tank
198201
"""
199-
# return (self.eps_g * self.u_g0 * self.height / self.E_g).to("dimensionless")
200-
return (
201-
(self.graph.nodes["Vdot_g0"]["value"] / self.area) * self.height / self.E_g
202-
).to("dimensionless")
202+
return (self.u_g0 * self.height / self.E_g).to("dimensionless")
203203

204204
def test_eps_g(
205205
self,
206206
): # to see if the two definitions of superficial velocity are consistent -> TODO remove
207207
print(
208-
f"{self.eps_g_0 * self.graph.nodes['v_g0']['value']} vs {self.graph.nodes['Vdot_g0']['value'] / self.area} vs {self.graph.nodes['u_g0']['value']}"
208+
f"{self.eps_g0 * self.graph.nodes['v_g0']['value']} vs {self.graph.nodes['Vdot_g0']['value'] / self.area} vs {self.u_g0}"
209209
)
210210

211211
def __post_init__(self):

src/sparging/model.py

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,6 @@ def solve(
307307
T = self.sim_input.temperature.to("K").magnitude
308308
E_g = self.sim_input.E_g.to("m**2/s").magnitude
309309
E_l = self.sim_input.E_l.to("m**2/s").magnitude
310-
u_g0 = self.sim_input.u_g0.to("m/s").magnitude
311310
Q_T2 = self.sim_input.Q_T.to("molT2/s").magnitude
312311

313312
dt = (
@@ -337,40 +336,13 @@ def solve(
337336
u_n = dolfinx.fem.Function(V)
338337
v_c, v_y = ufl.TestFunctions(V)
339338

340-
# set initial concentration
341-
c_T2_0_ufl_expr = dolfinx.fem.Constant(
342-
mesh, self.sim_input.c_T2_0.to("molT2/m**3").magnitude
343-
) * self.normalize_profile(
344-
self.sim_input.profile_c_T2_0, tank_height, mesh, V_profile
345-
)
346-
u_n.sub(0).interpolate(
347-
dolfinx.fem.Expression(
348-
c_T2_0_ufl_expr, V.sub(0).element.interpolation_points
349-
)
350-
)
351-
352-
c_T2, y_T2 = ufl.split(u)
353-
c_T2_n, y_T2_n = ufl.split(u_n)
354-
355-
vel_x = u_g0 # TODO velocity should vary with hydrostatic pressure
356-
vel = dolfinx.fem.Constant(mesh, PETSc.ScalarType([vel_x]))
357-
358-
h_l_const = dolfinx.fem.Constant(mesh, PETSc.ScalarType(h_l))
359-
360-
gen_T2_ave = dolfinx.fem.Constant(
361-
mesh, Q_T2 / tank_volume * self.sim_input.signal_irr(0 * ureg.s)
362-
) # magnitude of the generation term
363-
364-
gen_T2 = gen_T2_ave * self.normalize_profile(
365-
self.sim_input.profile_source_T, tank_height, mesh, V_profile
366-
)
367-
368339
# define spatially varying profiles
369340
if not self.constant_profiles:
370341
eps_g = dolfinx.fem.Function(V_profile)
371342
eps_l = dolfinx.fem.Function(V_profile)
372343
a = dolfinx.fem.Function(V_profile)
373344
P_g = dolfinx.fem.Function(V_profile)
345+
u_g = dolfinx.fem.Function(V_profile)
374346

375347
eps_g.interpolate(
376348
lambda x: (
@@ -387,16 +359,49 @@ def solve(
387359
P_g.interpolate(
388360
lambda x: self.sim_input.P_g(x[0] * ureg.m).to("Pa").magnitude
389361
)
362+
u_g.interpolate(
363+
lambda x: self.sim_input.u_g(x[0] * ureg.m).to("m/s").magnitude
364+
)
390365
else:
391366
# use values at z=0 for constant profiles
392-
eps_g_0 = self.sim_input.eps_g_0.to("dimensionless").magnitude
367+
eps_g0 = self.sim_input.eps_g0.to("dimensionless").magnitude
393368
a_0 = self.sim_input.a_0.to("1/m").magnitude
394-
P_g_0 = self.sim_input.P_g_0.to("Pa").magnitude
369+
P_g0 = self.sim_input.P_g0.to("Pa").magnitude
370+
u_g0 = self.sim_input.u_g0.to("m/s").magnitude
395371

396-
eps_g = dolfinx.fem.Constant(mesh, PETSc.ScalarType(eps_g_0))
397-
eps_l = dolfinx.fem.Constant(mesh, PETSc.ScalarType(1 - eps_g_0))
372+
eps_g = dolfinx.fem.Constant(mesh, PETSc.ScalarType(eps_g0))
373+
eps_l = dolfinx.fem.Constant(mesh, PETSc.ScalarType(1 - eps_g0))
398374
a = dolfinx.fem.Constant(mesh, PETSc.ScalarType(a_0))
399-
P_g = dolfinx.fem.Constant(mesh, PETSc.ScalarType(P_g_0))
375+
P_g = dolfinx.fem.Constant(mesh, PETSc.ScalarType(P_g0))
376+
u_g = dolfinx.fem.Constant(mesh, PETSc.ScalarType(u_g0))
377+
378+
# set initial concentration
379+
c_T2_0_ufl_expr = dolfinx.fem.Constant(
380+
mesh, self.sim_input.c_T2_0.to("molT2/m**3").magnitude
381+
) * self.normalize_profile(
382+
self.sim_input.profile_c_T2_0, tank_height, mesh, V_profile
383+
)
384+
u_n.sub(0).interpolate(
385+
dolfinx.fem.Expression(
386+
c_T2_0_ufl_expr, V.sub(0).element.interpolation_points
387+
)
388+
)
389+
390+
c_T2, y_T2 = ufl.split(u)
391+
c_T2_n, y_T2_n = ufl.split(u_n)
392+
393+
# vel_x = u_g0 # TODO velocity should vary with hydrostatic pressure
394+
# vel = dolfinx.fem.Constant(mesh, PETSc.ScalarType([vel_x]))
395+
396+
h_l_const = dolfinx.fem.Constant(mesh, PETSc.ScalarType(h_l))
397+
398+
gen_T2_ave = dolfinx.fem.Constant(
399+
mesh, Q_T2 / tank_volume * self.sim_input.signal_irr(0 * ureg.s)
400+
) # magnitude of the generation term
401+
402+
gen_T2 = gen_T2_ave * self.normalize_profile(
403+
self.sim_input.profile_source_T, tank_height, mesh, V_profile
404+
)
400405

401406
# VARIATIONAL FORMULATION
402407

@@ -431,7 +436,9 @@ def solve(
431436
F += (
432437
1
433438
/ (const.R * T)
434-
* ufl.inner(ufl.dot(ufl.grad(P_g * y_T2), vel), v_y)
439+
# * ufl.inner(ufl.dot(ufl.grad(P_g * y_T2), vel), v_y)
440+
* ufl.grad(u_g * P_g * y_T2)[0]
441+
* v_y
435442
* ufl.dx
436443
)
437444

@@ -458,13 +465,7 @@ def solve(
458465

459466
# Danckwert BC at gas inlet
460467
P_T2_inlet = 0
461-
F += (
462-
1
463-
/ (const.R * T)
464-
* vel_x
465-
* ufl.inner((P_g * y_T2 - P_T2_inlet), v_y)
466-
* ds(1)
467-
)
468+
F += 1 / (const.R * T) * u_g * ufl.inner((P_g * y_T2 - P_T2_inlet), v_y) * ds(1)
468469

469470
# n = ufl.FacetNormal(mesh)
470471

@@ -527,7 +528,7 @@ def post_process(t):
527528

528529
flux_T2 = dolfinx.fem.assemble_scalar(
529530
dolfinx.fem.form(
530-
vel_x * P_g / (const.R * T) * y_T2_post * tank_area * ds(2)
531+
u_g * P_g / (const.R * T) * y_T2_post * tank_area * ds(2)
531532
)
532533
)
533534
flux_T2_2 = dolfinx.fem.assemble_scalar(

0 commit comments

Comments
 (0)