def create_complex_bulk_reaction(self, is_kinetic=True, k_fwd_min=1): # Reactions # 0: NH4+(aq) <=> NH3(aq) + H+(aq) # 1: Lys2+(aq) <=> Lys+(aq) + H+(aq) # 2: Lys+(aq) <=> Lys(aq) + H+(aq) # 3: Lys(aq) <=> Lys-(aq) + H+(aq) # 4: Arg2+ <=> Arg+ + H+ # 5: Arg+ <=> Arg + H+ # 6: Arg <=> Arg- + H+ component_system = ComponentSystem() component_system.add_component('H+', charges=[1]) component_system.add_component( 'Ammonia', species=['NH4+', 'NH3'], charges=[1,0] ) component_system.add_component( 'Lysine', species=['Lys2+', 'Lys+', 'Lys', 'Lys-'], charges=[2,1,0,-1] ) component_system.add_component( 'Arginine', species=['Arg2+', 'Arg+', 'Arg', 'Arg-'], charges=[2,1,0,-1] ) reaction_model = MassActionLaw(component_system, 'complex') reaction_model.add_reaction( [1, 2, 0], [-1, 1, 1], 10**(-9.2)*1e3, is_kinetic=is_kinetic, k_fwd_min=k_fwd_min ) reaction_model.add_reaction( [3, 4, 0], [-1, 1, 1], 10**(-2.20)*1e3, is_kinetic=is_kinetic, k_fwd_min=k_fwd_min ) reaction_model.add_reaction( [4, 5, 0], [-1, 1, 1], 10**(-8.90)*1e3, is_kinetic=is_kinetic, k_fwd_min=k_fwd_min ) reaction_model.add_reaction( [5, 6, 0], [-1, 1, 1], 10**(-10.28)*1e3, is_kinetic=is_kinetic, k_fwd_min=k_fwd_min ) reaction_model.add_reaction( [7, 8, 0], [-1, 1, 1], 10**(-2.18)*1e3, is_kinetic=is_kinetic, k_fwd_min=k_fwd_min ) reaction_model.add_reaction( [8, 9, 0], [-1, 1, 1], 10**(-9.09)*1e3, is_kinetic=is_kinetic, k_fwd_min=k_fwd_min ) reaction_model.add_reaction( [9, 10, 0], [-1, 1, 1], 10**(-13.2)*1e3, is_kinetic=is_kinetic, k_fwd_min=k_fwd_min ) return reaction_model
def setUp(self): component_system = ComponentSystem() component_system.add_component('A') component_system.add_component('B') binding_model = Langmuir(component_system, name='test') binding_model.adsorption_rate = [0.02, 0.03] binding_model.desorption_rate = [1, 1] binding_model.saturation_capacity = [100, 100] self.binding_model = binding_model
class TestComponents(unittest.TestCase): def setUp(self): self.component_system = ComponentSystem() self.component_system.add_component( 'Ammonia', species=['NH4+', 'NH3'], charges=[1,0] ) self.component_system.add_component( 'Lysine', ['Lys2+', 'Lys+', 'Lys', 'Lys'], [2,1,0,-1] ) self.component_system.add_component( 'H+', charges=[1] ) self.component_system.add_component() def test_labels(self): labels_expected = [ 'NH4+', 'NH3', 'Lys2+', 'Lys+', 'Lys', 'Lys', 'H+', '7' ] labels = self.component_system.labels np.testing.assert_equal(labels, labels_expected) def test_n_comp(self): n_comp_expected = 8 n_comp = self.component_system.n_comp self.assertEqual(n_comp_expected, n_comp)
def setUp(self): self.component_system = ComponentSystem() self.component_system.add_component( 'Ammonia', species=['NH4+', 'NH3'], charges=[1,0] ) self.component_system.add_component( 'Lysine', ['Lys2+', 'Lys+', 'Lys', 'Lys'], [2,1,0,-1] ) self.component_system.add_component( 'H+', charges=[1] ) self.component_system.add_component()
def setUp(self): component_system = ComponentSystem() component_system.add_component('A') component_system.add_component('B') self.single_0 = MassActionLaw(component_system, name='simple') self.single_0.add_reaction([0, 1], [-1, 1], 2, k_bwd=2) self.single_1 = MassActionLaw(component_system, name='simple') self.single_1.add_reaction([0, 1], [-1, 1], 1, k_bwd=1) component_system = ComponentSystem() component_system.add_component('A') component_system.add_component('B') component_system.add_component('C') self.single_2 = MassActionLaw(n_comp=3, name='simple') self.single_2.add_reaction([0, 1], [-1, 1], 1, k_bwd=1) self.multi = MassActionLaw(n_comp=3, name='simple') self.multi.add_reaction([0, 1], [-1, 1], 1, k_bwd=1) self.multi.add_reaction([1, 2], [-1, 1], 1, k_bwd=1) self.multi = MassActionLaw(n_comp=3, name='simple') self.multi.add_reaction([0, 1], [-1, 1], 1, k_bwd=1) self.multi.add_reaction([1, 2], [-1, 1], 1, k_bwd=1) self.lysine = MassActionLaw(n_comp=5, name='Lysine') self.lysine.add_reaction([0, 1, -1], [-1, 1, 1], 10**(-2.20) * 1e3, is_kinetic=False) self.lysine.add_reaction([1, 2, -1], [-1, 1, 1], 10**(-8.90) * 1e3, is_kinetic=False) self.lysine.add_reaction([2, 3, -1], [-1, 1, 1], 10**(-10.28) * 1e3, is_kinetic=False)
def create_simple_bulk_reaction(self, is_kinetic=True, k_fwd_min=100): # 0: NH4+(aq) <=> NH3(aq) + H+(aq) component_system = ComponentSystem() component_system.add_component('H+', charges=[1]) component_system.add_component( 'Ammonia', species=['NH4+', 'NH3'], charges=[1,0] ) reaction_model = MassActionLaw(component_system, 'simple') reaction_model.add_reaction( [1, 2, 0], [-1, 1, 1], 10**(-9.2)*1e3, is_kinetic=is_kinetic, k_fwd_min=k_fwd_min ) return reaction_model
tags: steric mass action law lwe single column gradient """ from CADETProcess.processModel import ComponentSystem from CADETProcess.processModel import StericMassAction from CADETProcess.processModel import Source, GeneralRateModel, Sink from CADETProcess.processModel import FlowSheet from CADETProcess.processModel import Process # Component System component_system = ComponentSystem() component_system.add_component('A') component_system.add_component('B') # Binding Model binding_model = StericMassAction(component_system, name='SMA') binding_model.is_kinetic = True binding_model.adsorption_rate = [0.0, 0.3] binding_model.desorption_rate = [0.0, 1.5] binding_model.characteristic_charge = [0.0, 7.0] binding_model.steric_factor = [0.0, 50.0] binding_model.capacity = 225.0 # Unit Operations feed = Source(component_system, name='feed') feed.c = [180.0, 0.1]
def create_cross_phase_reaction(self): component_system = ComponentSystem() component_system.add_component( 'Ammonia', species=['NH4+', 'NH3'], charges=[1,0] ) component_system.add_component( 'Lysine', species=['Lys2+', 'Lys+', 'Lys', 'Lys-'], charges=[2,1,0,-1] ) component_system.add_component('H+', charges=[1]) reaction_model = MassActionLawParticle(component_system, 'complex') # Pore Liquid # 0: NH4+(aq) <=> NH3(aq) + H+(aq) # 1: Lys2+(aq) <=> Lys+(aq) + H+(aq) # 2: Lys+(aq) <=> Lys(aq) + H+(aq) # 3: Lys(aq) <=> Lys-(aq) + H+(aq) reaction_model.add_liquid_reaction( [1, 2, 0], [-1, 1, 1], 10**(-9.2)*1e3, is_kinetic=False ) reaction_model.add_liquid_reaction( [3, 4, 0], [-1, 1, 1], 10**(-2.20)*1e3, is_kinetic=False ) reaction_model.add_liquid_reaction( [4, 5, 0], [-1, 1, 1], 10**(-8.90)*1e3, is_kinetic=False ) reaction_model.add_liquid_reaction( [5, 6, 0], [-1, 1, 1], 10**(-10.28)*1e3, is_kinetic=False ) # Adsorption k_fwd_min_ads = 100 # 0: NH4+(aq) + H+(s) <=> NH4+(s) + H+(aq) # 1: NH4+(s) <=> NH3(aq) + H+(s) reaction_model.add_cross_phase_reaction( [1, 0, 1, 0], [-1, -1, 1, 1], [0, 1, 1, 0], 1/1.5, k_fwd_min=k_fwd_min_ads ) reaction_model.add_cross_phase_reaction( [1, 2, 0], [-1, 1, 1], [1, 0, 1], 1.5, k_fwd_min=k_fwd_min_ads ) # 2: Lys2+(aq) + 2H+(s) <=> Lys2+(s) + 2H+(aq) # 3: Lys2+(s) <=> Lys+(aq) + H+(s) reaction_model.add_cross_phase_reaction( [3, 0, 3, 0], [-1, -2, 1, 2], [0, 1, 1, 0], 1/5, k_fwd_min=k_fwd_min_ads ) reaction_model.add_cross_phase_reaction( [3, 2, 0], [-1, 1, 1], [1, 0, 1], 5, k_fwd_min=k_fwd_min_ads ) # 4: Lys+(aq) + H+(s) <=> Lys+(s) + H+(aq) # 5: Lys+(s) <=> Lys(aq) + H+(s) reaction_model.add_cross_phase_reaction( [4, 0, 4, 0], [-1, -1, 1, 1], [0, 1, 1, 0], 1/0.75, k_fwd_min=k_fwd_min_ads ) reaction_model.add_cross_phase_reaction( [4, 5, 0], [-1, 1, 1], [1, 0, 1], 0.75, k_fwd_min=k_fwd_min_ads ) return reaction_model
def setUp(self): self.component_system = ComponentSystem() self.component_system.add_component('A') self.component_system.add_component('B')
class Test_Unit_Operation(unittest.TestCase): def __init__(self, methodName='runTest'): super().__init__(methodName) def setUp(self): self.component_system = ComponentSystem() self.component_system.add_component('A') self.component_system.add_component('B') def create_source(self): source = Source(self.component_system, name='test') return source def create_cstr(self): cstr = Cstr(self.component_system, name='test') cstr.porosity = total_porosity cstr.V = volume cstr.flow_rate = 1 return cstr def create_tubular_reactor(self): tube = TubularReactor(self.component_system, name='test') tube.length = length tube.diameter = diameter tube.axial_dispersion = axial_dispersion return tube def create_lrmwop(self): lrmwop = LumpedRateModelWithoutPores(self.component_system, name='test') lrmwop.length = length lrmwop.diameter = diameter lrmwop.axial_dispersion = axial_dispersion lrmwop.total_porosity = total_porosity return lrmwop def create_lrmwp(self): lrmwp = LumpedRateModelWithPores(self.component_system, name='test') lrmwp.length = length lrmwp.diameter = diameter lrmwp.axial_dispersion = axial_dispersion lrmwp.bed_porosity = bed_porosity lrmwp.particle_porosity = particle_porosity return lrmwp def test_geometry(self): cstr = self.create_cstr() lrmwop = self.create_lrmwop() lrmwp = self.create_lrmwp() self.assertEqual(lrmwop.cross_section_area, cross_section_area) self.assertEqual(lrmwp.cross_section_area, cross_section_area) self.assertEqual(lrmwop.total_porosity, total_porosity) self.assertEqual(lrmwp.total_porosity, total_porosity) self.assertEqual(lrmwop.volume, volume) self.assertEqual(lrmwp.volume, volume) volume_interstitial = total_porosity * volume self.assertAlmostEqual(lrmwop.volume_interstitial, volume_interstitial) volume_interstitial = bed_porosity * volume self.assertAlmostEqual(lrmwp.volume_interstitial, volume_interstitial) volume_liquid = total_porosity * volume self.assertAlmostEqual(cstr.volume_liquid, volume_liquid) self.assertAlmostEqual(lrmwop.volume_liquid, volume_liquid) self.assertAlmostEqual(lrmwp.volume_liquid, volume_liquid) volume_solid = (1 - total_porosity) * volume self.assertAlmostEqual(cstr.volume_solid, volume_solid) self.assertAlmostEqual(lrmwop.volume_solid, volume_solid) self.assertAlmostEqual(lrmwp.volume_solid, volume_solid) lrmwop.cross_section_area = cross_section_area/2 self.assertAlmostEqual(lrmwop.diameter, diameter/(2**0.5)) def test_convection_dispersion(self): tube = self.create_tubular_reactor() lrmwp = self.create_lrmwp() flow_rate = 0 tube.length = 1 tube.cross_section_area = 1 tube.axial_dispersion = 0 with self.assertRaises(ZeroDivisionError): tube.u0(flow_rate) tube.NTP(flow_rate) flow_rate = 2 tube.axial_dispersion = 3 self.assertAlmostEqual(tube.u0(flow_rate), 2) self.assertAlmostEqual(tube.t0(flow_rate), 0.5) self.assertAlmostEqual(tube.NTP(flow_rate), 1/3) tube.set_axial_dispersion_from_NTP(1/3, 2) self.assertAlmostEqual(tube.axial_dispersion, 3) flow_rate = 2 lrmwp.length = 1 lrmwp.bed_porosity = 0.5 lrmwp.cross_section_area = 1 self.assertAlmostEqual(lrmwp.u0(flow_rate), 4) self.assertAlmostEqual(lrmwp.t0(flow_rate), 0.25) def test_poly_properties(self): source = self.create_source() ref = np.array([[1,0,0,0], [1,0,0,0]]) source.c = 1 np.testing.assert_equal(source.c, ref) source.c = [1,1] np.testing.assert_equal(source.c, ref) ref = np.array([[1,0,0,0], [2,0,0,0]]) source.c = [1,2] np.testing.assert_equal(source.c, ref) source.c = [[1,0], [2,0]] np.testing.assert_equal(source.c, ref) ref = np.array([[1,2,0,0], [3,4,0,0]]) source.c = [[1,2], [3,4]] np.testing.assert_equal(source.c, ref) source.c = ref np.testing.assert_equal(source.c, ref) cstr = self.create_cstr() ref = np.array([1,0,0,0]) cstr.flow_rate = 1 cstr.flow_rate_filter = 1 np.testing.assert_equal(cstr.flow_rate, ref) np.testing.assert_equal(cstr.flow_rate_filter, ref) cstr.flow_rate = [1,0] cstr.flow_rate_filter = [1,0] np.testing.assert_equal(cstr.flow_rate, ref) np.testing.assert_equal(cstr.flow_rate_filter, ref) ref = np.array([1,1,0,0]) cstr.flow_rate = [1,1] cstr.flow_rate_filter = [1,1] np.testing.assert_equal(cstr.flow_rate, ref) np.testing.assert_equal(cstr.flow_rate_filter, ref) cstr.flow_rate = ref cstr.flow_rate_filter = ref np.testing.assert_equal(cstr.flow_rate, ref) np.testing.assert_equal(cstr.flow_rate_filter, ref) def test_parameters(self): """ Note ---- Currently, only getting parameters is tested. Should also test if setting works. For this, adsorption parameters should be provided. """ cstr = self.create_cstr() parameters_expected = { 'flow_rate': np.array([1,0,0,0]), 'porosity': total_porosity, 'flow_rate_filter': np.array([0,0,0,0]), } np.testing.assert_equal(parameters_expected, cstr.parameters) sec_dep_parameters_expected = { 'flow_rate': np.array([1,0,0,0]), 'flow_rate_filter': np.array([0,0,0,0]), } np.testing.assert_equal( sec_dep_parameters_expected, cstr.section_dependent_parameters ) poly_parameters = { 'flow_rate': np.array([1,0,0,0]), 'flow_rate_filter': np.array([0,0,0,0]), } np.testing.assert_equal( poly_parameters, cstr.polynomial_parameters )
class Test_flow_sheet(unittest.TestCase): def __init__(self, methodName='runTest'): super().__init__(methodName) def setUp(self): self.component_system = ComponentSystem() self.component_system.add_component('A') self.component_system.add_component('B') def create_ssr_flow_sheet(self): flow_sheet = FlowSheet(self.component_system) feed = Source(self.component_system, name='feed') eluent = Source(self.component_system, name='eluent') cstr = Cstr(self.component_system, name='cstr') column = LumpedRateModelWithoutPores(self.component_system, name='column') outlet = Sink(self.component_system, name='outlet') flow_sheet.add_unit(feed) flow_sheet.add_unit(eluent) flow_sheet.add_unit(cstr) flow_sheet.add_unit(column) flow_sheet.add_unit(outlet) flow_sheet.add_connection(feed, cstr) flow_sheet.add_connection(cstr, column) flow_sheet.add_connection(eluent, column) flow_sheet.add_connection(column, cstr) flow_sheet.add_connection(column, outlet) flow_sheet.add_eluent_source(eluent) flow_sheet.add_feed_source(feed) flow_sheet.add_chromatogram_sink(outlet) return flow_sheet def test_unit_names(self): flow_sheet = self.create_ssr_flow_sheet() unit_names = ['feed', 'eluent', 'cstr', 'column', 'outlet'] self.assertEqual(list(flow_sheet.units_dict.keys()), unit_names) def test_sources(self): flow_sheet = self.create_ssr_flow_sheet() self.assertIn(flow_sheet.feed, flow_sheet.sources) self.assertIn(flow_sheet.eluent, flow_sheet.sources) self.assertIn(flow_sheet.cstr, flow_sheet.sources) def test_sinks(self): flow_sheet = self.create_ssr_flow_sheet() self.assertIn(flow_sheet.cstr, flow_sheet.sinks) self.assertIn(flow_sheet.outlet, flow_sheet.sinks) def test_connections(self): flow_sheet = self.create_ssr_flow_sheet() expected_connections = { 'feed': ['cstr'], 'eluent': ['column'], 'cstr': ['column'], 'column': ['cstr', 'outlet'], 'outlet': []} # self.assertDictEqual(flow_sheet.connections_out, expected_connections) def test_ssr_flow_rates(self): flow_sheet = self.create_ssr_flow_sheet() # Injection flow_sheet.feed.flow_rate = 0 flow_sheet.eluent.flow_rate = 0 flow_sheet.cstr.flow_rate = 1 flow_sheet.set_output_state('column', 1) expected_flow_rates = { 'feed': { 'total': (0, 0, 0, 0), 'destinations': { 'cstr': (0, 0, 0, 0), }, }, 'eluent': { 'total': (0, 0, 0, 0), 'destinations': { 'column': (0, 0, 0, 0), }, }, 'cstr': { 'total': (1.0, 0, 0, 0), 'destinations': { 'column': (1.0, 0, 0, 0), }, }, 'column': { 'total': (1.0, 0, 0, 0), 'destinations': { 'cstr': (0, 0, 0, 0), 'outlet': (1.0, 0, 0, 0), }, }, 'outlet': { 'total': (1.0, 0, 0, 0), }, } np.testing.assert_equal(flow_sheet.get_flow_rates(), expected_flow_rates) # Elution and Feed flow_sheet.feed.flow_rate = 1 flow_sheet.eluent.flow_rate = 1 flow_sheet.cstr.flow_rate = 0 flow_sheet.set_output_state('column', 1) expected_flow_rates = { 'feed': { 'total': (1.0, 0, 0, 0), 'destinations': { 'cstr': (1.0, 0, 0, 0), }, }, 'eluent': { 'total': (1.0, 0, 0, 0), 'destinations': { 'column': (1.0, 0, 0, 0), }, }, 'cstr': { 'total': (0, 0, 0, 0), 'destinations': { 'column': (0, 0, 0, 0), }, }, 'column': { 'total': (1.0, 0, 0, 0), 'destinations': { 'cstr': (0, 0, 0, 0), 'outlet': (1.0, 0, 0, 0), }, }, 'outlet': { 'total': (1.0, 0, 0, 0), }, } np.testing.assert_equal(flow_sheet.get_flow_rates(), expected_flow_rates) # Elution flow_sheet.feed.flow_rate = 0 flow_sheet.eluent.flow_rate = 1 flow_sheet.cstr.flow_rate = 0 flow_sheet.set_output_state('column', 1) expected_flow_rates = { 'feed': { 'total': (0, 0, 0, 0), 'destinations': { 'cstr': (0, 0, 0, 0), }, }, 'eluent': { 'total': (1.0, 0, 0, 0), 'destinations': { 'column': (1.0, 0, 0, 0), }, }, 'cstr': { 'total': (0, 0, 0, 0), 'destinations': { 'column': (0, 0, 0, 0), }, }, 'column': { 'total': (1.0, 0, 0, 0), 'destinations': { 'cstr': (0, 0, 0, 0), 'outlet': (1.0, 0, 0, 0), }, }, 'outlet': { 'total': (1.0, 0, 0, 0), }, } np.testing.assert_equal(flow_sheet.get_flow_rates(), expected_flow_rates) # Recycle flow_sheet.feed.flow_rate = 0 flow_sheet.eluent.flow_rate = 1 flow_sheet.cstr.flow_rate = 0 flow_sheet.set_output_state('column', 0) expected_flow_rates = { 'feed': { 'total': (0, 0, 0, 0), 'destinations': { 'cstr': (0, 0, 0, 0), }, }, 'eluent': { 'total': (1.0, 0, 0, 0), 'destinations': { 'column': (1.0, 0, 0, 0), }, }, 'cstr': { 'total': (0, 0, 0, 0), 'destinations': { 'column': (0, 0, 0, 0), }, }, 'column': { 'total': (1.0, 0, 0, 0), 'destinations': { 'cstr': (1.0, 0, 0, 0), 'outlet': (0, 0, 0, 0), }, }, 'outlet': { 'total': (0, 0, 0, 0), }, } np.testing.assert_equal(flow_sheet.get_flow_rates(), expected_flow_rates) def create_clr_flow_sheet(self): flow_sheet = FlowSheet(n_comp=2, name='test') feed = Source(n_comp=2, name='feed') column = LumpedRateModelWithoutPores(n_comp=2, name='column') outlet = Sink(n_comp=2, name='outlet') flow_sheet.add_unit(feed) flow_sheet.add_unit(column) flow_sheet.add_unit(outlet) flow_sheet.add_connection(feed, column) flow_sheet.add_connection(column, outlet) flow_sheet.add_connection(column, column) return flow_sheet def test_clr_flow_rates(self): """Currently not working in CADET-Process; Must be implemented with