def add_connection(self, origin, destination):
        """Add connection between units 'origin' and 'destination'.

        Parameters
        ----------
        origin : UnitBaseClass
            UnitBaseClass from which the connection originates.
        destination : UnitBaseClass
            UnitBaseClass where the connection terminates.

        Raises
        ------
        CADETProcessError
            If origin OR destination do not exist in the current flow sheet.
            If connection already exists in the current flow sheet.

        See Also
        --------
        connections
        remove_connection
        output_state
        """
        if origin not in self._units:
            raise CADETProcessError('Origin not in flow sheet')
        if destination not in self._units:
            raise CADETProcessError('Destination not in flow sheet')
        
        if destination in self.connections[origin].destinations:
            raise CADETProcessError('Connection already exists')

        self._connections[origin].destinations.append(destination)
        self._connections[destination].origins.append(origin)        
        
        self.set_output_state(origin, 0)
Esempio n. 2
0
    def check_cadet(self):
        """Wrapper around a basic CADET example for testing functionality"""
        if platform.system() == 'Windows':
            lwe_path = self.install_path / "bin" / "createLWE.exe"
        else:
            lwe_path = self.install_path / "bin" / "createLWE"
        ret = subprocess.run(
            [lwe_path.as_posix()],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            cwd=self.temp_dir
        )
        if ret.returncode != 0:
            if ret.stdout:
                print('Output', ret.stdout.decode('utf-8'))
            if ret.stderr:
                print('Errors', ret.stderr.decode('utf-8'))
            raise CADETProcessError(
                "Failure: Creation of test simulation ran into problems"
            )

        lwe_hdf5_path = Path(self.temp_dir) / 'LWE.h5'

        sim = CadetAPI()
        sim.filename = lwe_hdf5_path.as_posix()
        data = sim.run()
        os.remove(sim.filename)

        if data.returncode == 0:
            print("Test simulation completed successfully")
        else:
            print(data)
            raise CADETProcessError(
                "Simulation failed"
            )
    def add_section(self, section, entry_index=None):
        """Add section to TimeLine.

        Parameters
        ----------
        section : Section
            Section to be added.

        Raises
        ------
        TypeError
            If section is not instance of Section.
        CADETProcessError
            If polynomial degree does not match.
        CADETProcessError
            If section introduces a gap.
        """
        if not isinstance(section, Section):
            raise TypeError('Expected Section')
        if len(self.sections) > 0:
            if section.degree != self.degree:
                raise CADETProcessError('Polynomial degree does not match')

            if not (section.start == self.end or section.end == self.start):
                raise CADETProcessError('Sections times must be without gaps')

        self._sections.append(section)
        self._sections = sorted(self._sections, key=lambda sec: sec.start)

        self.update_piecewise_poly()
    def remove_connection(self, origin, destination):
        """Remove connection between units 'origin' and 'destination'.

        Parameters
        ----------
        origin : UnitBaseClass
            UnitBaseClass from which the connection originates.
        destination : UnitBaseClass
            UnitBaseClass where the connection terminates.

        Raises
        ------
        CADETProcessError
            If origin OR destination do not exist in the current flow sheet.
            If connection does not exists in the current flow sheet.

        See Also
        --------
        connections
        add_connection
        """
        if origin not in self._units:
            raise CADETProcessError('Origin not in flow sheet')
        if destination not in self._units:
            raise CADETProcessError('Destination not in flow sheet')

        try:
            self._connections[origin].destinations.remove(destination)
            self._connections[destination].origins.remove(origin)
        except KeyError:
            raise CADETProcessError('Connection does not exist.')
    def add_fraction(self, fraction):
        if not isinstance(fraction, Fraction):
            raise CADETProcessError('Expected Fraction')

        if fraction.n_comp != self.n_comp:
            raise CADETProcessError('Number of components does not match.')

        self._fractions.append(fraction)
Esempio n. 6
0
    def temp_dir(self, temp_dir):
        if temp_dir is not None:
            try:
                exists = Path(temp_dir).exists()
            except TypeError:
                raise CADETProcessError('Not a valid path')
            if not exists:
                raise CADETProcessError('Not a valid path')

        tempfile.tempdir = temp_dir
Esempio n. 7
0
    def bulk_reaction_model(self, bulk_reaction_model):
        if not isinstance(bulk_reaction_model, ReactionBaseClass):
            raise TypeError('Expected ReactionBaseClass')
        if not self.supports_bulk_reaction:
            raise CADETProcessError('Unit does not support bulk reactions.')

        if bulk_reaction_model.component_system is not self.component_system \
                and not isinstance(bulk_reaction_model, NoReaction):
            raise CADETProcessError('Component systems do not match.')

        self._bulk_reaction_model = bulk_reaction_model
Esempio n. 8
0
    def __init__(self, wrapped_object):
        if not isinstance(wrapped_object, self._baseClass):
            raise CADETProcessError("Expected {}".format(self._baseClass))

        model = wrapped_object.model
        try:
            self.model_parameters = self._model_parameters[model]
        except KeyError:
            raise CADETProcessError("Model Type not defined")

        self._wrapped_object = wrapped_object
    def add_unit(
            self, unit, 
            feed_source=False, eluent_source=False, chromatogram_sink=False
        ):
        """Add unit to the flow sheet.

        Parameters
        ----------
        unit : UnitBaseClass
            UnitBaseClass object to be added to the flow sheet.
        feed_source : bool
            If True, add unit to feed sources.
        eluent_source : bool
            If True, add unit to eluent sources.
        chromatogram_sink : bool
            If True, add unit to chromatogram sinks.

        Raises
        ------
        TypeError
            If unit is no instance of UnitBaseClass.
        CADETProcessError
            If unit already exists in flow sheet.
            If n_comp does not match with FlowSheet.

        See Also
        --------
        remove_unit
        """
        if not isinstance(unit, UnitBaseClass):
            raise TypeError('Expected UnitOperation')

        if unit in self._units:
            raise CADETProcessError('Unit already part of System')

        if unit.component_system is not self.component_system:
            raise CADETProcessError('Component systems do not match.')

        self._units.append(unit)
        self._connections[unit] = Dict({
            'origins': [], 
            'destinations': [],
        })
        self._output_states[unit] = []
        self._flow_rates[unit] = []
        
        super().__setattr__(unit.name, unit)

        if feed_source:
            self.add_feed_source(unit)
        if eluent_source:
            self.add_eluent_source(unit)
        if chromatogram_sink:
            self.add_chromatogram_sink(unit)
Esempio n. 10
0
    def parameters(self, parameters):
        try:
            self.binding_model.parameters = parameters.pop('binding_model')
        except KeyError:
            pass
        try:
            self.bulk_reaction_model.parameters = parameters.pop(
                'bulk_reaction_model')
        except KeyError:
            pass
        try:
            self.particle_reaction_model.parameters = parameters.pop(
                'particle_reaction_model')
        except KeyError:
            pass
        try:
            self.discretization.parameters = parameters.pop('discretization')
        except KeyError:
            pass

        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)
Esempio n. 11
0
    def setup_optimization_problem(self, frac):
        opt = OptimizationProblem(frac)
        opt.logger.setLevel(logging.WARNING)

        opt.add_objective(self.obj_fun)
        opt.add_nonlinear_constraint(
            nonlin_bounds_decorator(self.purity_required)(purity))

        for evt in frac.events:
            opt.add_variable(evt.name + '.time', evt.name)

        for chrom_index, chrom in enumerate(frac.chromatograms):
            chrom_events = frac.chromatogram_events[chrom]
            evt_names = [evt.name for evt in chrom_events]
            for evt_index, evt in enumerate(chrom_events):
                if evt_index < len(chrom_events) - 1:
                    opt.add_linear_constraint(
                        [evt_names[evt_index], evt_names[evt_index + 1]],
                        [1, -1])
                else:
                    opt.add_linear_constraint([evt_names[0], evt_names[-1]],
                                              [-1, 1], frac.cycle_time)

        opt.x0 = [evt.time for evt in frac.events]

        if not opt.check_nonlinear_constraints(opt.x0):
            raise CADETProcessError("No areas found with sufficient purity.")

        return opt
    def remove_event(self, evt_name):
        """Remove event from the EventHandler.

        Parameters
        ----------
        evt_name : str
            Name of the event to be removed

        Raises
        ------
        CADETProcessError
            If Event is not found.

        Note
        ----
        !!! Check remove_event_dependencies

        See also
        --------
        add_event
        remove_event_dependency
        Event
        """
        try:
            evt = self.events_dict[evt_name]
        except KeyError:
            raise CADETProcessError("Event does not exist")

        self._events.remove(evt)
        self.__dict__.pop(evt_name)
Esempio n. 13
0
    def add_inlet_profile(self, unit, time, c, component_index=None, s=1e-6):
        if not isinstance(unit, Source):
            raise TypeError('Expected Source')

        if max(time) > self.cycle_time:
            raise ValueError('Inlet profile exceeds cycle time')

        if component_index == -1:
            # Assume same profile for all components
            if c.ndim > 1:
                raise ValueError('Expected single concentration profile')

            c = np.column_stack([c] * 2)

        elif component_index is None and c.shape[1] != self.n_comp:
            # Assume c is given for all components
            raise CADETProcessError('Number of components does not match')

        for comp in range(self.n_comp):
            tck = interpolate.splrep(time, c[:, comp], s=s)
            ppoly = interpolate.PPoly.from_spline(tck)

            for i, (t, sec) in enumerate(zip(ppoly.x, ppoly.c.T)):
                if i < 3:
                    continue
                elif i > len(ppoly.x) - 5:
                    continue
                evt = self.add_event(f'{unit}_inlet_{comp}_{i-3}',
                                     f'flow_sheet.{unit}.c', np.flip(sec), t,
                                     comp)
    def add_duration(self, name, time=0.0):
        """Add duration to the EventHandler.

        Parameters
        ----------
        name: str
            Name of the event.
        time : float
            Time point for perfoming the event.

        Raises
        ------
        CADETProcessError
            If Duration already exists.

        See also
        --------
        durations
        remove_duration
        Duration
        add_event
        add_event_dependency
        """
        if name in self.events_dict:
            raise CADETProcessError("Duration already exists")

        dur = Duration(name, self, time)

        self._durations.append(dur)
        super().__setattr__(name, dur)
    def remove_duration(self, duration_name):
        """Remove duration from list of durations.

        Parameters
        ----------
        duration : str
            Name of the duration be removed from the EventHandler.

        Raises
        ------
        CADETProcessError
            If Duration is not found.

        See also
        --------
        Duration
        add_duration
        remove_event_dependency
        """
        try:
            dur = self.events_dict[duration_name]
        except KeyError:
            raise CADETProcessError("Duration does not exist")

        self._durations.remove(dur)
        self.__dict__.pop(duration_name)
Esempio n. 16
0
def set_style(style='medium'):
    """Defines the sytle of a plot.

    Can set the sytle of a plot for small, medium and large plots. The
    figuresize of the figure, the linewitdth and color of the lines and the
    size of the font can be changed by switching the style.

    Parameters
    ----------
    style : str
        Style of a figure plot, default set to small.

    Raises
    ------
    CADETProcessError
        If no valid style has been chosen as parameter.
    """
    if style == 'small':
        plt.rcParams['figure.figsize'] = (5, 3)
        plt.rcParams['lines.linewidth'] = 2
        plt.rcParams['font.size'] = 12
        plt.rcParams['axes.prop_cycle'] = chromapy_cycler
    elif style == 'medium':
        plt.rcParams['figure.figsize'] = (10, 6)
        plt.rcParams['lines.linewidth'] = 4
        plt.rcParams['font.size'] = 24
        plt.rcParams['axes.prop_cycle'] = chromapy_cycler
    elif style == 'large':
        plt.rcParams['figure.figsize'] = (15, 9)
        plt.rcParams['lines.linewidth'] = 6
        plt.rcParams['font.size'] = 30
        plt.rcParams['axes.prop_cycle'] = chromapy_cycler
    else:
        raise CADETProcessError('Not a valid style')
    def parameters(self, parameters):
        try:
            self.cycle_time = parameters.pop('cycle_time')
        except KeyError:
            pass

        for evt_name, evt_parameters in parameters.items():
            try:
                evt = self.events_dict[evt_name]
            except AttributeError:
                raise CADETProcessError('Not a valid event')
            if evt not in self.independent_events + self.durations:
                raise CADETProcessError('{} is not a valid event'.format(
                    str(evt)))

            evt.parameters = evt_parameters
Esempio n. 18
0
    def binding_model(self, binding_model):
        if not isinstance(binding_model, BindingBaseClass):
            raise TypeError('Expected BindingBaseClass')

        if binding_model.component_system is not self.component_system:
            raise CADETProcessError('Component systems do not match.')

        self._binding_model = binding_model
 def parameters(self, parameters):
     if isinstance(parameters, (float, int)):
         self.time = parameters
     else:
         for param, value in parameters.items():
             if param not in self._parameters:
                 raise CADETProcessError('Not a valid parameter')
             setattr(self, param, value)
    def time(self, time):
        if not isinstance(time, (int, float, np.int64, np.float64)):
            raise TypeError("Expected {}".format(float))

        if self.isIndependent:
            self._time = time
        else:
            raise CADETProcessError("Cannot set time for dependent events")
    def entry_index(self, entry_index):
        if entry_index is not None:
            parameter = get_nested_value(self.event_handler.parameters,
                                         self.parameter_sequence)

            if entry_index > len(parameter) - 1:
                raise CADETProcessError('Index exceeds components')
        self._entry_index = entry_index
Esempio n. 22
0
    def component_index(self, component_index):
        if component_index is not None:
            parameter = get_nested_value(self.evaluation_object.parameters,
                                         self.parameter_sequence)

            if component_index > len(parameter) - 1:
                raise CADETProcessError('Index exceeds components')
        self._component_index = component_index
 def wrapper(self, unit, *args, **kwargs):
     """Enable calling functions with unit object or unit name.
     """
     if isinstance(unit, str):
         try:
             unit = self.units_dict[unit]
         except KeyError:
             raise CADETProcessError('Not a valid unit')
     return func(self, unit, *args, **kwargs)
    def set_output_state(self, unit, state):
        """Set split ratio of outgoing streams for UnitOperation.
        
        Parameters
        ----------
        unit : UnitBaseClass
            UnitOperation of flowsheet.
        state : int or list of floats
            new output state of the unit. 

        Raises
        ------
        CADETProcessError
            If unit not in flowSheet
            If state is integer and the state >= the state_length.
            If the length of the states is unequal the state_length.
            If the sum of the states is not equal to 1.
        """
        if unit not in self._units:
            raise CADETProcessError('Unit not in flow sheet')
            
        state_length = len(self.connections[unit].destinations)

        if state_length == 0:
            output_state = []

        if isinstance(state, (int, np.int64)):
            if state >= state_length:
                raise CADETProcessError('Index exceeds destinations')

            output_state = [0] * state_length
            output_state[state] = 1

        else:
            if len(state) != state_length:
                raise CADETProcessError(
                    'Expected length {}.'.format(state_length))

            elif sum(state) != 1:
                raise CADETProcessError('Sum of fractions must be 1')

            output_state = state

        self._output_states[unit] = output_state                    
Esempio n. 25
0
    def initial_state(self, initial_state):
        try:
            self.flow_sheet.initial_state = initial_state.pop('flow_sheet')
        except KeyError:
            pass

        for state_name, state_value in initial_state.items():
            if state_name not in self._initial_state:
                raise CADETProcessError('Not an valid state')
            setattr(self, state_name, state_value)
    def add_eluent_source(self, eluent_source):
        """Add source to list of units to be considered for eluent consumption.

        Parameters
        ----------
        eluent_source : SourceMixin
            Unit to be added to list of eluent sources.

        Raises
        ------
        CADETProcessError
            If unit is not in a source object
            If unit is already marked as eluent source
        """
        if eluent_source not in self.sources:
            raise CADETProcessError('Expected Source')
        if eluent_source in self._eluent_sources:
            raise CADETProcessError('{} is already eluent source'.format(
                    eluent_source))
        self._eluent_sources.append(eluent_source)
    def initial_state(self, initial_state):
        if initial_state is None:
            self._initial_state = initial_state
            return

        if not isinstance(initial_state, list):
            initial_state = self.n_columns * [initial_state]

        if len(initial_state) != self.n_columns:
            raise CADETProcessError(f"Expected size {self.n_columns}")
        self._initial_state = initial_state
Esempio n. 28
0
    def set_variables(self, x, make_copy=False):
        """Sets the values from the x-vector to the OptimizationVariables.

        Parameters
        ----------
         x : array_like
            Value of the optimization variables

        make_copy : Bool
            If True, a copy of the evaluation_object attribute is made on which
            the values are set. Otherwise, the values are set on the attribute.

        Returns
        -------
        evaluation_object : object
            Returns copy of evaluation object if make_copy is True, else returns
            the attribute evaluation_object with the values set.

        Raises
        ------
        ValueError
            If value of variable exceeds bounds

        See also
        --------
        OptimizationVariable
        evaluate
        """
        if len(x) != self.n_variables:
            raise CADETProcessError('Expected {} variables'.format(
                self.n_variables))
        if make_copy:
            evaluation_object = copy.deepcopy(self.evaluation_object)
        else:
            evaluation_object = self.evaluation_object

        for variable, value in zip(self.variables, x):
            if value < variable.lb:
                raise ValueError("Exceeds lower bound")
            if value > variable.ub:
                raise ValueError("Exceeds upper bound")

            if variable.component_index is not None:
                value_list = get_nested_value(evaluation_object.parameters,
                                              variable.parameter_path)
                value_list[variable.component_index] = value
                parameters = generate_nested_dict(variable.parameter_path,
                                                  value_list)
            else:
                parameters = generate_nested_dict(variable.parameter_path,
                                                  value)
            evaluation_object.parameters = parameters

        return evaluation_object
Esempio n. 29
0
    def setup_fractionator(self, process_meta, chromatograms):
        frac = Fractionator(process_meta)

        for chrom in chromatograms:
            frac.add_chromatogram(chrom)

        frac.initial_values(self.purity_required)

        if len(frac.events) == 0:
            raise CADETProcessError("No areas found with sufficient purity.")
        return frac
    def __init__(self, performance, ranking=1.0):
        if not isinstance(performance, Performance):
            raise TypeError('Expected Performance')

        self._performance = performance

        if isinstance(ranking, (float, int)):
            ranking = [ranking] * performance.n_comp
        elif len(ranking) != performance.n_comp:
            raise CADETProcessError('Number of components does not match.')

        self._ranking = ranking