Exemple #1
0
    def test_work_flow_me2(self):
        model = Dummy_FMUModelME2([],
                                  "bouncingBall.fmu",
                                  os.path.join(file_path, "files", "FMUs",
                                               "XML", "ME2.0"),
                                  _connect_dll=False)
        model.setup_experiment()
        model.initialize()

        bouncingBall = ResultHandlerCSV(model)

        bouncingBall.set_options(model.simulate_options())
        bouncingBall.simulation_start()
        bouncingBall.initialize_complete()
        bouncingBall.integration_point()
        bouncingBall.simulation_end()

        res = ResultCSVTextual('bouncingBall_result.csv')

        h = res.get_variable_data('h')
        derh = res.get_variable_data('der(h)')
        g = res.get_variable_data('g')

        nose.tools.assert_almost_equal(h.x, 1.000000, 5)
        nose.tools.assert_almost_equal(derh.x, 0.000000, 5)
class SciEstAlg(AlgorithmBase):
    """
    Estimation algortihm for FMUs.
    """

    def __init__(self,
                 parameters,
                 measurements,
                 input,
                 model,
                 options):
        """
        Estimation algortihm for FMUs .

        Parameters::

            model --
                fmi.FMUModel* object representation of the model.

            options --
                The options that should be used in the algorithm. For details on
                the options, see:

                * model.simulate_options('SciEstAlgOptions')

                or look at the docstring with help:

                * help(pyfmi.fmi_algorithm_drivers.SciEstAlgAlgOptions)

                Valid values are:
                - A dict that overrides some or all of the default values
                  provided by SciEstAlgOptions. An empty dict will thus
                  give all options with default values.
                - SciEstAlgOptions object.
        """
        self.model = model

        # set start time, final time and input trajectory
        self.parameters = parameters
        self.measurements = measurements
        self.input = input
        
        # handle options argument
        if isinstance(options, dict) and not \
            isinstance(options, SciEstAlgOptions):
            # user has passed dict with options or empty dict = default
            self.options = SciEstAlgOptions(options)
        elif isinstance(options, SciEstAlgOptions):
            # user has passed FMICSAlgOptions instance
            self.options = options
        else:
            raise InvalidAlgorithmOptionException(options)

        # set options
        self._set_options()
        
        self.result_handler = ResultHandlerCSV(self.model)
        self.result_handler.set_options(self.options)
        self.result_handler.initialize_complete()

    def _set_options(self):
        """
        Helper function that sets options for FMICS algorithm.
        """
        self.options["filter"] = self.parameters
        
        if isinstance(self.options["scaling"], str) and self.options["scaling"] == "Default":
            scale = []
            for i,parameter in enumerate(self.parameters):
                scale.append(self.model.get_variable_nominal(parameter))
            self.options["scaling"] = N.array(scale)
        
        if self.options["simulate_options"] == "Default":
            self.options["simulate_options"] = self.model.simulate_options()
            
        #Modifiy necessary options:
        self.options["simulate_options"]['ncp']    = self.measurements[1].shape[0] - 1 #Store at the same points as measurment data
        self.options["simulate_options"]['filter'] = self.measurements[0] #Only store the measurement variables (efficiency)
        
        if "solver" in self.options["simulate_options"]:
            solver = self.options["simulate_options"]["solver"]
            
            self.options["simulate_options"][solver+"_options"]["verbosity"] = 50 #Disable printout (efficiency)
            self.options["simulate_options"][solver+"_options"]["store_event_points"] = False #Disable extra store points

    def _set_solver_options(self):
        """
        Helper function that sets options for the solver.
        """
        pass

    def solve(self):
        """
        Runs the estimation.
        """
        import scipy as sci
        import scipy.optimize as sciopt
        from pyfmi.fmi_util import parameter_estimation_f
        
        #Define callback
        global niter
        niter = 0
        def parameter_estimation_callback(y):
            global niter
            if niter % 10 == 0:
                print("  iter    parameters ")
            #print '{:>5d} {:>15e}'.format(niter+1, parameter_estimation_f(y, self.parameters, self.measurements, self.model, self.input, self.options))
            print('{:>5d} '.format(niter+1) + str(y))
            niter += 1
        
        #End of simulation, stop the clock
        time_start = timer()
        
        p0 = []
        for i,parameter in enumerate(self.parameters):
            p0.append(self.model.get(parameter)/self.options["scaling"][i])
            
        print('\nRunning solver: ' + self.options["method"])
        print(' Initial parameters (scaled): ' + str(N.array(p0).flatten()))
        print(' ')
        
        res = sciopt.minimize(parameter_estimation_f, p0, 
                                args=(self.parameters, self.measurements, self.model, self.input, self.options), 
                                method=self.options["method"],
                                bounds=None, 
                                constraints=(), 
                                tol=self.options["tolerance"],
                                callback=parameter_estimation_callback)
        
        for i in range(len(self.parameters)):
            res["x"][i] = res["x"][i]*self.options["scaling"][i]
        
        self.res = res
        self.status = res["success"]
        
        #End of simulation, stop the clock
        time_stop = timer()
        
        if not res["success"]:
            print('Estimation failed: ' + res["message"])
        else:
            print('\nEstimation terminated successfully!')
            print(' Found parameters: ' + str(res["x"]))
        
        print('Elapsed estimation time: ' + str(time_stop-time_start) + ' seconds.\n')

    def get_result(self):
        """
        Write result to file, load result data and create an SciEstResult
        object.

        Returns::

            The SciEstResult object.
        """
        for i,parameter in enumerate(self.parameters):
            self.model.set(parameter, self.res["x"][i])
        
        self.result_handler.simulation_start()
        
        self.model.time = self.measurements[1][0,0]
        self.result_handler.integration_point()

        self.result_handler.simulation_end()
        
        self.model.reset()
        
        for i,parameter in enumerate(self.parameters):
            self.model.set(parameter, self.res["x"][i])
            
        return FMIResult(self.model, self.options["result_file_name"], None,
            self.result_handler.get_result(), self.options, status=self.status)

    @classmethod
    def get_default_options(cls):
        """
        Get an instance of the options class for the SciEstAlg algorithm,
        prefilled with default values. (Class method.)
        """
        return SciEstAlgOptions()
Exemple #3
0
class SciEstAlg(AlgorithmBase):
    """
    Estimation algortihm for FMUs.
    """

    def __init__(self,
                 parameters,
                 measurements,
                 input,
                 model,
                 options):
        """
        Estimation algortihm for FMUs .

        Parameters::

            model --
                fmi.FMUModel* object representation of the model.

            options --
                The options that should be used in the algorithm. For details on
                the options, see:

                * model.simulate_options('SciEstAlgOptions')

                or look at the docstring with help:

                * help(pyfmi.fmi_algorithm_drivers.SciEstAlgAlgOptions)

                Valid values are:
                - A dict that overrides some or all of the default values
                  provided by SciEstAlgOptions. An empty dict will thus
                  give all options with default values.
                - SciEstAlgOptions object.
        """
        self.model = model

        # set start time, final time and input trajectory
        self.parameters = parameters
        self.measurements = measurements
        self.input = input
        
        # handle options argument
        if isinstance(options, dict) and not \
            isinstance(options, SciEstAlgOptions):
            # user has passed dict with options or empty dict = default
            self.options = SciEstAlgOptions(options)
        elif isinstance(options, SciEstAlgOptions):
            # user has passed FMICSAlgOptions instance
            self.options = options
        else:
            raise InvalidAlgorithmOptionException(options)

        # set options
        self._set_options()
        
        self.result_handler = ResultHandlerCSV(self.model)
        self.result_handler.set_options(self.options)
        self.result_handler.initialize_complete()

    def _set_options(self):
        """
        Helper function that sets options for FMICS algorithm.
        """
        self.options["filter"] = self.parameters
        
        if isinstance(self.options["scaling"], str) and self.options["scaling"] == "Default":
            scale = []
            for i,parameter in enumerate(self.parameters):
                scale.append(self.model.get_variable_nominal(parameter))
            self.options["scaling"] = N.array(scale)
        
        if self.options["simulate_options"] == "Default":
            self.options["simulate_options"] = self.model.simulate_options()
            
        #Modifiy necessary options:
        self.options["simulate_options"]['ncp']    = self.measurements[1].shape[0] - 1 #Store at the same points as measurment data
        self.options["simulate_options"]['filter'] = self.measurements[0] #Only store the measurement variables (efficiency)
        
        if "solver" in self.options["simulate_options"]:
            solver = self.options["simulate_options"]["solver"]
            
            self.options["simulate_options"][solver+"_options"]["verbosity"] = 50 #Disable printout (efficiency)
            self.options["simulate_options"][solver+"_options"]["store_event_points"] = False #Disable extra store points

    def _set_solver_options(self):
        """
        Helper function that sets options for the solver.
        """
        pass

    def solve(self):
        """
        Runs the estimation.
        """
        import scipy as sci
        import scipy.optimize as sciopt
        from pyfmi.fmi_util import parameter_estimation_f
        
        #Define callback
        global niter
        niter = 0
        def parameter_estimation_callback(y):
            global niter
            if niter % 10 == 0:
                print("  iter    parameters ")
            #print '{:>5d} {:>15e}'.format(niter+1, parameter_estimation_f(y, self.parameters, self.measurements, self.model, self.input, self.options))
            print('{:>5d} '.format(niter+1) + str(y))
            niter += 1
        
        #End of simulation, stop the clock
        time_start = timer()
        
        p0 = []
        for i,parameter in enumerate(self.parameters):
            p0.append(self.model.get(parameter)/self.options["scaling"][i])
            
        print('\nRunning solver: ' + self.options["method"])
        print(' Initial parameters (scaled): ' + str(N.array(p0).flatten()))
        print(' ')
        
        res = sciopt.minimize(parameter_estimation_f, p0, 
                                args=(self.parameters, self.measurements, self.model, self.input, self.options), 
                                method=self.options["method"],
                                bounds=None, 
                                constraints=(), 
                                tol=self.options["tolerance"],
                                callback=parameter_estimation_callback)
        
        for i in range(len(self.parameters)):
            res["x"][i] = res["x"][i]*self.options["scaling"][i]
        
        self.res = res
        self.status = res["success"]
        
        #End of simulation, stop the clock
        time_stop = timer()
        
        if not res["success"]:
            print('Estimation failed: ' + res["message"])
        else:
            print('\nEstimation terminated successfully!')
            print(' Found parameters: ' + str(res["x"]))
        
        print('Elapsed estimation time: ' + str(time_stop-time_start) + ' seconds.\n')

    def get_result(self):
        """
        Write result to file, load result data and create an SciEstResult
        object.

        Returns::

            The SciEstResult object.
        """
        for i,parameter in enumerate(self.parameters):
            self.model.set(parameter, self.res["x"][i])
        
        self.result_handler.simulation_start()
        
        self.model.time = self.measurements[1][0,0]
        self.result_handler.integration_point()

        self.result_handler.simulation_end()
        
        self.model.reset()
        
        for i,parameter in enumerate(self.parameters):
            self.model.set(parameter, self.res["x"][i])
            
        return FMIResult(self.model, self.options["result_file_name"], None,
            self.result_handler.get_result(), self.options, status=self.status)

    @classmethod
    def get_default_options(cls):
        """
        Get an instance of the options class for the SciEstAlg algorithm,
        prefilled with default values. (Class method.)
        """
        return SciEstAlgOptions()
Exemple #4
0
class FMICSAlg(AlgorithmBase):
    """
    Simulation algortihm for FMUs (Co-simulation).
    """
    def __init__(self, start_time, final_time, input, model, options):
        """
        Simulation algortihm for FMUs (Co-simulation).

        Parameters::

            model --
                fmi.FMUModelCS1 object representation of the model.

            options --
                The options that should be used in the algorithm. For details on
                the options, see:

                * model.simulate_options('FMICSAlgOptions')

                or look at the docstring with help:

                * help(pyfmi.fmi_algorithm_drivers.FMICSAlgOptions)

                Valid values are:
                - A dict that overrides some or all of the default values
                  provided by FMICSAlgOptions. An empty dict will thus
                  give all options with default values.
                - FMICSAlgOptions object.
        """
        self.model = model

        # set start time, final time and input trajectory
        self.start_time = start_time
        self.final_time = final_time
        self.input = input

        self.status = 0

        # handle options argument
        if isinstance(options, dict) and not \
            isinstance(options, FMICSAlgOptions):
            # user has passed dict with options or empty dict = default
            self.options = FMICSAlgOptions(options)
        elif isinstance(options, FMICSAlgOptions):
            # user has passed FMICSAlgOptions instance
            self.options = options
        else:
            raise InvalidAlgorithmOptionException(options)

        # set options
        self._set_options()

        input_traj = None
        if self.input:
            if hasattr(self.input[1], "__call__"):
                input_traj = (self.input[0],
                              TrajectoryUserFunction(self.input[1]))
            else:
                input_traj = (self.input[0],
                              TrajectoryLinearInterpolation(
                                  self.input[1][:, 0], self.input[1][:, 1:]))
            #Sets the inputs, if any
            self.model.set(input_traj[0],
                           input_traj[1].eval(self.start_time)[0, :])
        self.input_traj = input_traj

        if self.options["result_handling"] == "file":
            self.result_handler = ResultHandlerFile(self.model)
        elif self.options["result_handling"] == "memory":
            self.result_handler = ResultHandlerMemory(self.model)
        elif self.options["result_handling"] == "csv":
            self.result_handler = ResultHandlerCSV(self.model, delimiter=",")
        elif self.options["result_handling"] == "custom":
            self.result_handler = self.options["result_handler"]
            if self.result_handler == None:
                raise Exception(
                    "The result handler needs to be specified when using a custom result handling."
                )
            if not isinstance(self.result_handler, ResultHandler):
                raise Exception(
                    "The result handler needs to be a subclass of ResultHandler."
                )
        else:
            raise Exception("Unknown option to result_handling.")

        self.result_handler.set_options(self.options)

        # Initialize?
        if self.options['initialize']:
            if isinstance(self.model, fmi.FMUModelCS1) or isinstance(
                    self.model, fmi_extended.FMUModelME1Extended):
                self.model.initialize(start_time,
                                      final_time,
                                      StopTimeDefined=True)

            elif isinstance(self.model, fmi.FMUModelCS2):
                self.model.setup_experiment(start_time=start_time,
                                            stop_time_defined=True,
                                            stop_time=final_time)
                self.model.initialize()

            else:
                raise Exception("Unknown model.")

            self.result_handler.initialize_complete()

        elif self.model.time == None and isinstance(self.model,
                                                    fmi.FMUModelCS2):
            raise Exception(
                "Setup Experiment has not been called, this has to be called prior to the initialization call."
            )

        self.result_handler.simulation_start()

    def _set_options(self):
        """
        Helper function that sets options for FMICS algorithm.
        """
        # no of communication points
        self.ncp = self.options['ncp']

        self.write_scaled_result = self.options['write_scaled_result']

        # result file name
        if self.options['result_file_name'] == '':
            self.result_file_name = self.model.get_identifier() + '_result.txt'
        else:
            self.result_file_name = self.options['result_file_name']

    def _set_solver_options(self):
        """
        Helper function that sets options for the solver.
        """
        pass  #No solver options

    def solve(self):
        """
        Runs the simulation.
        """
        result_handler = self.result_handler
        h = (self.final_time - self.start_time) / self.ncp
        grid = N.linspace(self.start_time, self.final_time, self.ncp + 1)[:-1]

        status = 0
        final_time = 0.0

        #For result writing
        result_handler.integration_point()

        #Start of simulation, start the clock
        time_start = time.clock()

        for t in grid:
            status = self.model.do_step(t, h)
            self.status = status

            if status != 0:

                if status == fmi.FMI_ERROR:
                    result_handler.simulation_end()
                    raise Exception(
                        "The simulation failed. See the log for more information. Return flag %d."
                        % status)

                elif status == fmi.FMI_DISCARD and isinstance(
                        self.model, fmi.FMUModelCS1):

                    try:
                        last_time = self.model.get_real_status(
                            fmi.FMI1_LAST_SUCCESSFUL_TIME)
                        if last_time > t:  #Solver succeeded in taken a step a little further than the last time
                            self.model.time = last_time
                            final_time = last_time
                            result_handler.integration_point()
                    except fmi.FMUException:
                        pass
                break
                #result_handler.simulation_end()
                #raise Exception("The simulation failed. See the log for more information. Return flag %d"%status)

            final_time = t + h

            result_handler.integration_point()

            if self.input_traj != None:
                self.model.set(self.input_traj[0],
                               self.input_traj[1].eval(t + h)[0, :])

        #End of simulation, stop the clock
        time_stop = time.clock()

        result_handler.simulation_end()

        if self.status != 0:
            print(
                'Simulation terminated prematurely. See the log for possibly more information. Return flag %d.'
                % status)

        #Log elapsed time
        print('Simulation interval    : ' + str(self.start_time) + ' - ' +
              str(final_time) + ' seconds.')
        print('Elapsed simulation time: ' + str(time_stop - time_start) +
              ' seconds.')

    def get_result(self):
        """
        Write result to file, load result data and create an FMICSResult
        object.

        Returns::

            The FMICSResult object.
        """
        # Get the result
        res = self.result_handler.get_result()

        # create and return result object
        return FMIResult(self.model,
                         self.result_file_name,
                         None,
                         res,
                         self.options,
                         status=self.status)

    @classmethod
    def get_default_options(cls):
        """
        Get an instance of the options class for the FMICSAlg algorithm,
        prefilled with default values. (Class method.)
        """
        return FMICSAlgOptions()
class FMICSAlg(AlgorithmBase):
    """
    Simulation algortihm for FMUs (Co-simulation).
    """

    def __init__(self,
                 start_time,
                 final_time,
                 input,
                 model,
                 options):
        """
        Simulation algortihm for FMUs (Co-simulation).

        Parameters::

            model --
                fmi.FMUModelCS1 object representation of the model.

            options --
                The options that should be used in the algorithm. For details on
                the options, see:

                * model.simulate_options('FMICSAlgOptions')

                or look at the docstring with help:

                * help(pyfmi.fmi_algorithm_drivers.FMICSAlgOptions)

                Valid values are:
                - A dict that overrides some or all of the default values
                  provided by FMICSAlgOptions. An empty dict will thus
                  give all options with default values.
                - FMICSAlgOptions object.
        """
        self.model = model

        # set start time, final time and input trajectory
        self.start_time = start_time
        self.final_time = final_time
        self.input = input
        
        self.status = 0

        # handle options argument
        if isinstance(options, dict) and not \
            isinstance(options, FMICSAlgOptions):
            # user has passed dict with options or empty dict = default
            self.options = FMICSAlgOptions(options)
        elif isinstance(options, FMICSAlgOptions):
            # user has passed FMICSAlgOptions instance
            self.options = options
        else:
            raise InvalidAlgorithmOptionException(options)

        # set options
        self._set_options()

        input_traj = None
        if self.input:
            if hasattr(self.input[1],"__call__"):
                input_traj=(self.input[0],
                        TrajectoryUserFunction(self.input[1]))
            else:
                input_traj=(self.input[0],
                        TrajectoryLinearInterpolation(self.input[1][:,0],
                                                      self.input[1][:,1:]))
            #Sets the inputs, if any
            self.model.set(input_traj[0], input_traj[1].eval(self.start_time)[0,:])
        self.input_traj = input_traj

        if self.options["result_handling"] == "file":
            self.result_handler = ResultHandlerFile(self.model)
        elif self.options["result_handling"] == "memory":
            self.result_handler = ResultHandlerMemory(self.model)
        elif self.options["result_handling"] == "csv":
            self.result_handler = ResultHandlerCSV(self.model, delimiter=",")
        elif self.options["result_handling"] == "custom":
            self.result_handler = self.options["result_handler"]
            if self.result_handler == None:
                raise Exception("The result handler needs to be specified when using a custom result handling.")
            if not isinstance(self.result_handler, ResultHandler):
                raise Exception("The result handler needs to be a subclass of ResultHandler.")
        else:
            raise Exception("Unknown option to result_handling.")

        self.result_handler.set_options(self.options)

        # Initialize?
        if self.options['initialize']:
            if isinstance(self.model, fmi.FMUModelCS1) or isinstance(self.model, fmi_extended.FMUModelME1Extended):
                self.model.initialize(start_time, final_time, StopTimeDefined=True)

            elif isinstance(self.model, fmi.FMUModelCS2):
                self.model.setup_experiment(start_time=start_time, stop_time_defined=True, stop_time=final_time)
                self.model.initialize()
                
            else:
                raise Exception("Unknown model.")
                
            self.result_handler.initialize_complete()
            
        elif self.model.time == None and isinstance(self.model, fmi.FMUModelCS2):
            raise Exception("Setup Experiment has not been called, this has to be called prior to the initialization call.")
            
        self.result_handler.simulation_start()

    def _set_options(self):
        """
        Helper function that sets options for FMICS algorithm.
        """
        # no of communication points
        self.ncp = self.options['ncp']

        self.write_scaled_result = self.options['write_scaled_result']

        # result file name
        if self.options['result_file_name'] == '':
            self.result_file_name = self.model.get_identifier()+'_result.txt'
        else:
            self.result_file_name = self.options['result_file_name']

    def _set_solver_options(self):
        """
        Helper function that sets options for the solver.
        """
        pass #No solver options

    def solve(self):
        """
        Runs the simulation.
        """
        result_handler = self.result_handler
        h = (self.final_time-self.start_time)/self.ncp
        grid = N.linspace(self.start_time,self.final_time,self.ncp+1)[:-1]

        status = 0
        final_time = 0.0

        #For result writing
        result_handler.integration_point()

        #Start of simulation, start the clock
        time_start = time.clock()

        for t in grid:
            status = self.model.do_step(t,h)
            self.status = status

            if status != 0:
                
                if status == fmi.FMI_ERROR:
                    result_handler.simulation_end()
                    raise Exception("The simulation failed. See the log for more information. Return flag %d."%status)

                elif status == fmi.FMI_DISCARD and isinstance(self.model, fmi.FMUModelCS1):
                
                    try:
                        last_time = self.model.get_real_status(fmi.FMI1_LAST_SUCCESSFUL_TIME)
                        if last_time > t: #Solver succeeded in taken a step a little further than the last time
                            self.model.time = last_time
                            final_time = last_time
                            result_handler.integration_point()
                    except fmi.FMUException:
                        pass
                break
                #result_handler.simulation_end()
                #raise Exception("The simulation failed. See the log for more information. Return flag %d"%status)
            
            final_time = t+h

            result_handler.integration_point()

            if self.input_traj != None:
                self.model.set(self.input_traj[0], self.input_traj[1].eval(t+h)[0,:])

        #End of simulation, stop the clock
        time_stop = time.clock()

        result_handler.simulation_end()
        
        if self.status != 0:
            print('Simulation terminated prematurely. See the log for possibly more information. Return flag %d.'%status)
        
        #Log elapsed time
        print('Simulation interval    : ' + str(self.start_time) + ' - ' + str(final_time) + ' seconds.')
        print('Elapsed simulation time: ' + str(time_stop-time_start) + ' seconds.')

    def get_result(self):
        """
        Write result to file, load result data and create an FMICSResult
        object.

        Returns::

            The FMICSResult object.
        """
        # Get the result
        res = self.result_handler.get_result()

        # create and return result object
        return FMIResult(self.model, self.result_file_name, None,
            res, self.options, status=self.status)

    @classmethod
    def get_default_options(cls):
        """
        Get an instance of the options class for the FMICSAlg algorithm,
        prefilled with default values. (Class method.)
        """
        return FMICSAlgOptions()