class TrustConstr(SciPyInterface): """Class from scipy for optimization with trust-constr as method for the solver. This class is a wrapper for the method trust-constr from the optimization suite of the scipy interface. It defines the solver options in the local variable options as a dictionary and implements the abstract method run for running the optimization. """ gtol = UnsignedFloat(default=1e-6) xtol = UnsignedFloat(default=1e-8) barrier_tol = UnsignedFloat(default=1e-8) initial_constr_penalty = UnsignedFloat(default=1.0) initial_tr_radius = UnsignedFloat(default=1.0) initial_barrier_parameter = UnsignedFloat(default=0.01) initial_barrier_tolerance = UnsignedFloat(default=0.01) factorization_method = None maxiter = UnsignedInteger(default=1000) verbose = UnsignedInteger(default=0) disp = Bool(default=False) _options = [ 'gtol', 'xtol', 'barrier_tol', 'finite_diff_rel_step', 'initial_constr_penalty', 'initial_tr_radius', 'initial_barrier_parameter', 'initial_barrier_tolerance', 'factorization_method', 'maxiter','verbose', 'disp' ] jac = Switch(default='3-point', valid=['2-point', '3-point', 'cs']) def __str__(self): return 'trust-constr'
class TestPerformer(metaclass=StructMeta): param_1 = Float(default=0) param_2 = SizedTuple(minlen=2, maxlen=2, default=(1, 1)) param_3 = Switch(valid=[-1, 1], default=1) _parameters = ['param_1', 'param_2', 'param_3'] _section_dependent_parameters = ['param_1', 'param_2'] @property def section_dependent_parameters(self): parameters = { param: getattr(self, param) for param in self._section_dependent_parameters } return parameters @property def parameters(self): parameters = { param: getattr(self, param) for param in self._parameters } return parameters @parameters.setter def parameters(self, parameters): for param, value in parameters.items(): if param not in self._parameters: raise CADETProcessError('Not a valid parameter') if value is not None: setattr(self, param, value)
class LRMDiscretizationFV(DiscretizationParametersBase): ncol = UnsignedInteger(default=100) use_analytic_jacobian = Bool(default=True) reconstruction = Switch(default='WENO', valid=['WENO']) _parameters = DiscretizationParametersBase._parameters + [ 'ncol', 'use_analytic_jacobian', 'reconstruction', ] _dimensionality = ['ncol']
class LRMPDiscretizationFV(DiscretizationParametersBase): ncol = UnsignedInteger(default=100) par_geom = Switch( default='SPHERE', valid=['SPHERE', 'CYLINDER', 'SLAB'] ) use_analytic_jacobian = Bool(default=True) reconstruction = Switch(default='WENO', valid=['WENO']) gs_type = Bool(default=True) max_krylov = UnsignedInteger(default=0) max_restarts = UnsignedInteger(default=10) schur_safety = UnsignedFloat(default=1.0e-8) _parameters = DiscretizationParametersBase._parameters + [ 'ncol', 'par_geom', 'use_analytic_jacobian', 'reconstruction', 'gs_type', 'max_krylov', 'max_restarts', 'schur_safety' ] _dimensionality = ['ncol']
class SensitivityParametersGroup(ParametersGroup): """Class for defining the sensitivity parameters. The sensitivity parameters NSENS and SENS_METHOD are defined with default values. See also -------- ParametersGroup """ nsens = UnsignedInteger(default=0) sens_method = Switch(default='ad1', valid=['ad1'])
class GRMDiscretizationFV(DiscretizationParametersBase): ncol = UnsignedInteger(default=100) npar = UnsignedInteger(default=5) par_geom = Switch( default='SPHERE', valid=['SPHERE', 'CYLINDER', 'SLAB'] ) par_disc_type = Switch( default='EQUIDISTANT_PAR', valid=['EQUIDISTANT_PAR', 'EQUIVOLUME_PAR', 'USER_DEFINED_PAR'] ) par_disc_vector = DependentlySizedRangedList(lb=0, ub=1, dep='par_disc_vector_length') par_boundary_order = RangedInteger(lb=1, ub=2, default=2) use_analytic_jacobian = Bool(default=True) reconstruction = Switch(default='WENO', valid=['WENO']) gs_type = Bool(default=True) max_krylov = UnsignedInteger(default=0) max_restarts = UnsignedInteger(default=10) schur_safety = UnsignedFloat(default=1.0e-8) fix_zero_surface_diffusion = Bool(default=False) _parameters = DiscretizationParametersBase._parameters + [ 'ncol', 'npar', 'par_geom', 'par_disc_type', 'par_disc_vector', 'par_boundary_order', 'use_analytic_jacobian', 'reconstruction', 'gs_type', 'max_krylov', 'max_restarts', 'schur_safety', 'fix_zero_surface_diffusion', ] _dimensionality = ['ncol', 'npar'] @property def par_disc_vector_length(self): return self.npar + 1
class ConsistencySolverParametersGroup(ParametersGroup): """Class for defining the consistency solver parameters for cadet. See also -------- ParametersGroup """ solver_name = Switch( default='LEVMAR', valid=['LEVMAR', 'ATRN_RES', 'ARTN_ERR', 'COMPOSITE'] ) init_damping = UnsignedFloat(default=0.01) min_damping = UnsignedFloat(default=0.0001) max_iterations = UnsignedInteger(default=50) subsolvers = Switch( default='LEVMAR', valid=['LEVMAR', 'ATRN_RES', 'ARTN_ERR'] ) _parameters = [ 'solver_name', 'init_damping', 'min_damping', 'max_iterations', 'subsolvers' ]
class TubularReactor(UnitBaseClass): """Class for tubular reactors. Class can be used for a regular tubular reactor. Also serves as parent for other tubular models like the GRM by providing methods for calculating geometric properties such as the cross section area and volume, as well as methods for convective and dispersive properties like mean residence time or NTP. Notes ----- For subclassing, check that the total porosity and interstitial cross section area are computed correctly depending on the model porosities! Attributes ---------- length : UnsignedFloat Length of column. diameter : UnsignedFloat Diameter of column. axial_dispersion : UnsignedFloat Dispersion rate of compnents in axial direction. c : List of unsinged floats. Length depends on n_comp Initial concentration of the reactor. """ supports_bulk_reaction = True length = UnsignedFloat(default=0) diameter = UnsignedFloat(default=0) axial_dispersion = UnsignedFloat() total_porosity = 1 flow_direction = Switch(valid=[-1, 1], default=1) _parameter_names = UnitBaseClass._parameter_names + [ 'length', 'diameter', 'axial_dispersion', 'flow_direction' ] _section_dependent_parameters = UnitBaseClass._section_dependent_parameters + [ 'axial_dispersion', 'flow_direction' ] c = DependentlySizedUnsignedList(dep='n_comp', default=0) _initial_state = UnitBaseClass._initial_state + ['c'] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._discretization = LRMDiscretizationFV() @property def cross_section_area(self): """float: Cross section area of a Column. See also -------- volume cross_section_area_interstitial cross_section_area_liquid cross_section_area_solid """ return math.pi / 4 * self.diameter**2 @cross_section_area.setter def cross_section_area(self, cross_section_area): self.diameter = (4 * cross_section_area / math.pi)**0.5 def set_diameter_from_interstitial_velicity(self, Q, u0): """Set diamter from flow rate and interstitial velocity. In literature, often only the interstitial velocity is given. This method, the diameter / cross section area can be inferred from the flow rate, velocity, and porosity. Parameters ---------- Q : float Volumetric flow rate. u0 : float Interstitial velocity. Notes ----- Needs to be overwritten depending on the model porosities! """ self.cross_section_area = Q / (u0 * self.total_porosity) @property def cross_section_area_interstitial(self): """float: Interstitial area between particles. Notes ----- Needs to be overwritten depending on the model porosities! See also -------- cross_section_area cross_section_area_liquid cross_section_area_solid """ return self.total_porosity * self.cross_section_area @property def cross_section_area_liquid(self): """float: Liquid fraction of column cross section area. See also -------- cross_section_area cross_section_area_interstitial cross_section_area_solid volume """ return self.total_porosity * self.cross_section_area @property def cross_section_area_solid(self): """float: Liquid fraction of column cross section area. See also -------- cross_section_area cross_section_area_interstitial cross_section_area_liquid """ return (1 - self.total_porosity) * self.cross_section_area @property def volume(self): """float: Volume of the TubularReactor. See also -------- cross_section_area """ return self.cross_section_area * self.length @property def volume_interstitial(self): """float: Interstitial volume between particles. See also -------- cross_section_area """ return self.cross_section_area_interstitial * self.length @property def volume_liquid(self): """float: Volume of the liquid phase. """ return self.cross_section_area_liquid * self.length @property def volume_solid(self): """float: Volume of the solid phase. """ return self.cross_section_area_solid * self.length def t0(self, flow_rate): """Mean residence time of a (non adsorbing) volume element. Parameters ---------- flow_rate : float volumetric flow rate Returns ------- t0 : float Mean residence time See also -------- u0 """ return self.volume_interstitial / flow_rate def u0(self, flow_rate): """Flow velocity of a (non adsorbint) volume element. Parameters ---------- flow_rate : float volumetric flow rate Returns ------- u0 : float interstitial flow velocity See also -------- t0 NTP """ return self.length / self.t0(flow_rate) def NTP(self, flow_rate): """Number of theoretical plates. Parameters ---------- flow_rate : float volumetric flow rate Calculated using the axial dispersion coefficient: :math: NTP = \frac{u \cdot L_{Column}}{2 \cdot D_a} Returns ------- NTP : float Number of theretical plates """ return self.u0(flow_rate) * self.length / (2 * self.axial_dispersion) def set_axial_dispersion_from_NTP(self, NTP, flow_rate): """ Parameters ---------- NTP : float Number of theroetical plates flow_rate : float volumetric flow rate Calculated using the axial dispersion coefficient: :math: NTP = \frac{u \cdot L_{Column}}{2 \cdot D_a} Returns ------- NTP : float Number of theretical plates See also -------- u0 NTP """ self.axial_dispersion = self.u0(flow_rate) * self.length / (2 * NTP)