Source code for CADETProcess.modelBuilder.clrBuilder

import warnings

from CADETProcess.processModel import (
    ChromatographicColumnBase,
    Cstr,
    FlowSheet,
    Inlet,
    Outlet,
    Process,
)


[docs] class CLR(Process): """ Closed loop recycling (CLR) process. The flowsheet includes: - feed: Inlet - eluent: Inlet - column: ChromatographicColumnBase - pump: Cstr (auxiliary pump unit) - outlet: Outlet The process is configured with the following events: - Feed injection (duration: `feed_duration`). - Recycling (ends at `t_recycle_off`). - Elution after recycling. """ def __init__( self, column: ChromatographicColumnBase, c_feed: list[float], flow_rate: float, feed_duration: float, t_recycle_off: float, cycle_time: float, c_eluent: list[float] | float = 0.0, pump_volume: float = 1e-9, ) -> None: """ Initialize CLR process. Parameters ---------- column : ChromatographicColumnBase Chromatographic column object. c_feed : list[float] Feed concentration. flow_rate : float Flow rate. feed_duration : float Feed injection duration. t_recycle_off : float Time at which recycling ends. cycle_time : float Total cycle time. c_eluent : list[float] | float | None, optional Eluent concentration. Defaults to 0.0. pump_volume : float, optional Volume of the auxiliary pump unit. Defaults to 1e-9. """ if not isinstance(column, ChromatographicColumnBase): raise TypeError("Expected ChromatographicColumnBase.") if not column.name == "column": warnings.warn("Renaming column to `column` for consistency") column.name = "column" flow_sheet = self._build_flow_sheet( column=column, c_feed=c_feed, c_eluent=c_eluent, pump_volume=pump_volume, ) super().__init__(flow_sheet, "CLR") self.cycle_time = cycle_time # 0: Start feeding, no eluent, no recycle self.add_event("feed_on", "flow_sheet.feed.flow_rate", flow_rate, 0.0) self.add_event("eluent_off", "flow_sheet.eluent.flow_rate", 0.0) self.add_event_dependency("eluent_off", ["feed_on"]) # t_inj / t_rec_start: End feeding, no eluent, start recycle self.add_event("feed_off", "flow_sheet.feed.flow_rate", 0.0) self.add_duration("feed_duration", feed_duration) self.add_event_dependency("feed_off", ["feed_on", "feed_duration"], [1, 1]) self.add_event( "recycle_on_output_state", f"flow_sheet.output_states.{column.name}", {"pump": 1}, ) self.add_event_dependency("recycle_on_output_state", ["feed_off"]) self.add_event("recycle_on_pump", "flow_sheet.pump.flow_rate", flow_rate) self.add_event_dependency("recycle_on_pump", ["recycle_on_output_state"]) # t_rec_end: End recycle, start eluent self.add_event( "recycle_off_output_state", f"flow_sheet.output_states.{column.name}", {"outlet": 1}, t_recycle_off, ) self.add_event("recycle_off_pump", "flow_sheet.pump.flow_rate", 0) self.add_event_dependency("recycle_off_pump", ["recycle_off_output_state"]) self.add_event("eluent_on", "flow_sheet.eluent.flow_rate", flow_rate) self.add_event_dependency("eluent_on", ["recycle_off_output_state"]) def _build_flow_sheet( self, column: ChromatographicColumnBase, c_feed: list[float], c_eluent: list[float] | float = 0.0, pump_volume: float = 1e-9, ) -> FlowSheet: """Build and return the flow sheet for CLR process.""" component_system = column.component_system # Unit Operations feed = Inlet(component_system, name="feed") feed.c = c_feed eluent = Inlet(component_system, name="eluent") eluent.c = c_eluent if c_eluent is not None else 0.0 pump = Cstr(component_system, name="pump") pump.V = pump_volume outlet = Outlet(component_system, name="outlet") # Flow Sheet flow_sheet = FlowSheet(component_system) flow_sheet.add_unit(feed, feed_inlet=True) flow_sheet.add_unit(eluent, eluent_inlet=True) flow_sheet.add_unit(pump) flow_sheet.add_unit(column) flow_sheet.add_unit(outlet, product_outlet=True) flow_sheet.add_connection(feed, column) flow_sheet.add_connection(eluent, column) flow_sheet.add_connection(column, outlet) flow_sheet.add_connection(column, pump) flow_sheet.add_connection(pump, column) return flow_sheet