Skip to content

Commit 5edb024

Browse files
committed
cleaner J_T2 post processing + retrocompatibility with python 3.12 to use with autoemulate
1 parent c3ea741 commit 5edb024

5 files changed

Lines changed: 48 additions & 11 deletions

File tree

autoemulate_env.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: autoemulate_env
2+
channels:
3+
- conda-forge
4+
dependencies:
5+
- python=3.12
6+
- fenics-dolfinx
7+
- matplotlib
8+
- pyvista
9+
- pyyaml
10+
- numpy
11+
- scipy
12+
- pandas
13+
- pint
14+
- pip:
15+
- autoemulate

sparging101.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from __future__ import annotations
12
from sparging.config import ureg
23
from sparging import all_correlations
34
from sparging import animation
@@ -78,21 +79,20 @@ def profile_source_T(z: pint.Quantity | list[float], height: pint.Quantity = Non
7879
# return 0.5 * (1 + np.cos(0.5 * np.pi / (1 * ureg.m) * z))
7980

8081

81-
T_99 = 1 * ureg.hour
82+
T_99 = my_input.get_tau()
8283
my_simulation = Simulation(
8384
my_input,
8485
t_final=2 * T_99,
8586
signal_irr=lambda t: 1 if t < T_99 else 0,
86-
signal_sparging=lambda t: 0,
87+
signal_sparging=lambda t: 1,
8788
profile_pressure_hydrostatic=False,
8889
profile_source_T=profile_source_T,
89-
dispersion_on=False,
9090
)
9191

9292
if __name__ == "__main__":
9393
# my_simulation.sim_input.E_g *= 1e5
9494
# my_simulation.sim_input.E_l *= 1e-5
95-
output = my_simulation.solve(fast_solve=True)
95+
output = my_simulation.solve()
9696

9797
# # save output to file
9898
# output.profiles_to_csv(f"output_{tank_height}m.csv")

src/sparging/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
ureg.define(f"molT = {const.N_A} * triton")
1010
ureg.define(f"molT2 = 2 * {const.N_A} * triton")
1111
ureg.define("neutron = [neutron] = n")
12-
ureg.define("sccm = 7.44e-7 mol/s")
12+
ureg.define("sccm = 7.44e-7 mol/s") # holds for an ideal gas
1313

1414

1515
const_R = const.R * ureg("J/K/mol") # ideal gas constant

src/sparging/inputs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class SimulationInput:
7979
D_l: pint.Quantity
8080
Q_T: pint.Quantity
8181
# normalize_source_T: bool = True
82+
# TODO refactoring, put signals in this class
8283

8384
@property
8485
def volume(self):

src/sparging/model.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from __future__ import annotations
12
from mpi4py import MPI
23
import dolfinx
34
import basix
@@ -24,6 +25,7 @@
2425

2526
if TYPE_CHECKING:
2627
import pint
28+
from collections.abc import Callable
2729

2830
hours_to_seconds = 3600
2931
days_to_seconds = 24 * hours_to_seconds
@@ -140,9 +142,9 @@ def profiles_to_csv(self, output_path: Path):
140142
class Simulation:
141143
sim_input: SimulationInput
142144
t_final: pint.Quantity
143-
signal_irr: callable[pint.Quantity]
144-
signal_sparging: callable[pint.Quantity]
145-
profile_source_T: callable[pint.Quantity] | None = None
145+
signal_irr: Callable[[pint.Quantity], float]
146+
signal_sparging: Callable[[pint.Quantity], float]
147+
profile_source_T: Callable[[float], float] | None = None
146148
"""callable = f:[0,1] -> R+, it takes a dimensionless coordinate: (z / height)"""
147149
profile_pressure_hydrostatic: bool = False
148150
dispersion_on: bool = True
@@ -313,6 +315,11 @@ def solve(
313315
)
314316

315317
# initialise post processing
318+
319+
# we define a function and an expression for J_T2 for use in post processing
320+
J_T2_func = dolfinx.fem.Function(V_profile)
321+
J_T2_expr = dolfinx.fem.Expression(J_T2, V_profile.element.interpolation_points)
322+
316323
V0_ct, ct_dofs = u.function_space.sub(0).collapse()
317324
coords = V0_ct.tabulate_dof_coordinates()[:, 0]
318325
ct_sort_coords = np.argsort(coords)
@@ -323,14 +330,28 @@ def solve(
323330
y_sort_coords = np.argsort(coords)
324331
x_y = coords[y_sort_coords]
325332

333+
coords_profile = V_profile.tabulate_dof_coordinates()[:, 0]
334+
num_profile_dofs = (
335+
V_profile.dofmap.index_map.size_local
336+
) * V_profile.dofmap.index_map_bs
337+
338+
profile_dofs = np.arange(num_profile_dofs)
339+
profile_sort_coords = np.argsort(coords_profile)
340+
# NOTE currently we don't use x_profile and use another x in the plotting script
341+
x_profile = coords_profile[profile_sort_coords]
342+
343+
# NOTE maybe we could take this function out and it would take a SimulationResults object as input + u + other things...
326344
def post_process(t):
345+
"""
346+
Post-process the solution at time t.
347+
Extract solution profiles, compute fluxes and inventories, and store them in lists for later analysis.
348+
"""
327349
c_T2_post, y_T2_post = u.split()
328350

329351
c_T2_vals = u.x.array[ct_dofs][ct_sort_coords]
330352
y_T2_vals = u.x.array[y_dofs][y_sort_coords]
331-
J_T2_vals = (
332-
a * h_l_const.value * (c_T2_vals - K_s * (P.x.array * y_T2_vals + EPS))
333-
) # TODO there is a clever way of getting J_T2 for sure
353+
J_T2_func.interpolate(J_T2_expr)
354+
J_T2_vals = J_T2_func.x.array[profile_dofs][ct_sort_coords]
334355
times.append(t)
335356
c_T2_solutions.append(c_T2_vals.copy())
336357
y_T2_solutions.append(y_T2_vals.copy())

0 commit comments

Comments
 (0)