1+ from __future__ import annotations
12from mpi4py import MPI
23import dolfinx
34import basix
2425
2526if TYPE_CHECKING :
2627 import pint
28+ from collections .abc import Callable
2729
2830hours_to_seconds = 3600
2931days_to_seconds = 24 * hours_to_seconds
@@ -140,9 +142,9 @@ def profiles_to_csv(self, output_path: Path):
140142class 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