@@ -272,106 +272,34 @@ def _process_results(S_ends, params, phys_props, dim_params):
272272 P_T2_out = y_T2_out * P_out
273273 P_T2_in = y_T2_in * P_in
274274
275- # Mass balance check
276- n_T_in_liquid = c_T_in * Q_l # mol/s
277- n_T_out_liquid = c_T_out * Q_l # mol/s
278- n_T2_in_gas = P_T2_in * Q_g / (R * T ) # mol/s
279- n_T_in_gas = n_T2_in_gas * 2 # mol/s
275+ # Tritium molar flows from the converged solution (mol/s). Each T2 molecule
276+ # carries two tritium atoms.
277+ n_T_in_liquid = c_T_in * Q_l
278+ n_T_in_gas = 2 * P_T2_in * Q_g / (R * T )
279+ n_T_out_liquid = c_T_out * Q_l
280280 Q_g_out = Q_g * (P_in / P_out ) # m3/s
281- n_T2_out_gas = P_T2_out * Q_g_out / (R * T ) # mol/s
282- n_T_out_gas = n_T2_out_gas * 2 # mol/s
281+ n_T_out_gas = 2 * P_T2_out * Q_g_out / (R * T )
283282
284- # Adjust for any mass balance error
285- mass_balance_error = (n_T_in_liquid + n_T_in_gas ) - (n_T_out_liquid + n_T_out_gas )
286- n_T_out_gas += mass_balance_error * efficiency
287- n_T_out_liquid += mass_balance_error * (1 - efficiency )
283+ n_T_in = n_T_in_liquid + n_T_in_gas
284+ n_T_out = n_T_out_liquid + n_T_out_gas
288285
289- results = {
290- "Total tritium in [mol/s]" : n_T_in_liquid + n_T_in_gas ,
291- "Total tritium out [mol/s]" : n_T_out_liquid + n_T_out_gas ,
292- "tritium_out_liquid [mol/s]" : n_T_out_liquid ,
293- "tritium_out_gas [mol/s]" : n_T_out_gas ,
294- "extraction_efficiency [fraction]" : efficiency ,
286+ # Mass-balance residual reported as a diagnostic. For closed-closed (C-C)
287+ # boundary conditions it is at numerical-noise level; for open-closed (O-C)
288+ # it reflects the dispersive flux neglected by the open inlet condition.
289+ return {
295290 "c_T_outlet [mol/m^3]" : c_T_out ,
296- "P_T2_inlet_gas [Pa]" : P_T2_in ,
297- "P_T2_outlet_gas [Pa]" : P_T2_out ,
298291 "y_T2_outlet_gas" : y_T2_out ,
299- "total_gas_P_inlet [Pa ]" : P_in ,
292+ "extraction_efficiency [fraction ]" : efficiency ,
300293 "total_gas_P_outlet [Pa]" : P_out ,
301294 "liquid_vol_flow [m^3/s]" : Q_l ,
302295 "gas_vol_flow_outlet [m^3/s]" : Q_g_out ,
296+ "tritium_out_liquid [mol/s]" : n_T_out_liquid ,
297+ "tritium_out_gas [mol/s]" : n_T_out_gas ,
298+ "Total tritium in [mol/s]" : n_T_in ,
299+ "Total tritium out [mol/s]" : n_T_out ,
300+ "mass_balance_residual [mol/s]" : n_T_in - n_T_out ,
303301 }
304302
305- # Add all calculated parameters to the results dictionary
306- results .update (phys_props )
307- results .update (dim_params )
308-
309- return results
310-
311-
312- def solve (params ):
313- """
314- Main solver function for the bubble column model.
315-
316- Builds the physical properties and dimensionless groups, then solves the
317- boundary value problem with the native :class:`~pathsim.blocks.BVP1D` block.
318-
319- Args:
320- params (dict): A dictionary of all input parameters for the model,
321- including operational conditions and geometry.
322-
323- Returns:
324- list: A list containing:
325- - dict: A dictionary containing the simulation results.
326- - pathsim.blocks.BVP1D: The BVP block, exposing the refined mesh
327- (``.x``) and the sampled solution (``.solution()``).
328-
329- Raises:
330- ValueError: If the calculated gas outlet pressure is non-positive.
331- RuntimeError: If the BVP solver fails to converge.
332- """
333- # Adjust inlet gas concentration to avoid numerical instability at zero
334- y_T2_in = max (params ["y_T2_in" ], 1e-20 )
335-
336- # 1. Calculate physical, hydrodynamic, and mass transfer properties
337- phys_props = _calculate_properties (params )
338-
339- # Pre-solver check for non-physical outlet pressure
340- P_out = params ["P_in" ] - (
341- phys_props ["rho_l" ] * (1 - phys_props ["epsilon_g" ]) * g * params ["L" ]
342- )
343- if P_out <= 0 :
344- raise ValueError (
345- f"Calculated gas outlet pressure is non-positive ({ P_out :.2e} Pa). "
346- "Check input parameters P_in, L, etc."
347- )
348-
349- # 2. Calculate dimensionless groups for the ODE system
350- dim_params = _calculate_dimensionless_groups (params , phys_props )
351-
352- # 3. Solve the boundary value problem with the native BVP1D block, sampling
353- # the two domain endpoints (xi=0 and xi=1)
354- bvp = BVP1D (
355- fun = lambda x , y , p , u : _ode_system (x , y , dim_params ),
356- bc = lambda ya , yb , p , u : _boundary_conditions (
357- ya , yb , dim_params , y_T2_in , params ["BCs" ]
358- ),
359- n = 4 ,
360- domain = (0.0 , 1.0 ),
361- n_nodes = params ["elements" ] + 1 ,
362- x_eval = np .array ([0.0 , 1.0 ]),
363- tol = 1e-5 ,
364- max_nodes = 10000 ,
365- )
366- bvp .update (0.0 )
367- if not bvp .success :
368- raise RuntimeError ("BVP solver failed to converge." )
369-
370- # 4. Process and return the results in a dimensional format
371- results = _process_results (bvp .solution (), params , phys_props , dim_params )
372-
373- return [results , bvp ]
374-
375303
376304class GLC (BVP1D ):
377305 r"""Counter-current bubble column gas-liquid contactor (GLC) for tritium extraction.
0 commit comments