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'
Exemplo n.º 2
0
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']
Exemplo n.º 5
0
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'
    ]    
Exemplo n.º 8
0
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)