Archived OpenModelica forums. Posting is disabled.

Alternative forums include GitHub discussions or StackOverflow (make sure to read the Stack Overflow rules; you need to have well-formed questions)


Forgot password? | Forgot username? | Register

Parameter Sweep Optimization with OpenModelica

Parameter Sweep Optimization with OpenModelica

Hi folks,

I am currently looking for a possibility to perform a static parameter sweep optimization on a Modelica model. I've started with the onboard OMOptim tool. Unfortunatly, it seems like the tool itself as well as the documentation are no longer maintained. For OM v1.17, I couldn't manage to get it started at all, while for OM v1.16, the tool does work for me, but I can't define a optimization problem, since no parameters appear in the list of variables after loading the model according to the documentation.

My questions:

1) Does OMOptim generally not work in the new versions or is the error on my side? I've inculded the very basic model which
I've used for testing OMOptim. It inculdes a single parameter (Param) and a single objective to be minimized (Error.y)

OptimTest.mo

2) If OMOptim is not longer maintained/used by the community, what is the current "state of the art" for solving such a optimization problem with OpenModelica? Do you use the Python or the Matlab interface?

Thank you very very much for your help!!


Cheers


Attachments:

Re: Parameter Sweep Optimization with OpenModelica

a possible solution is to export the modelica model as an fmu and do the parameter sweep / optimization using any tool that can load fmus and do optimization (check out fmi-standard.org)
here a solution using python (based on the great example provided by t-sommer on https://github.com/CATIA-Systems/FMPy/b … _input.py)

remark1: I've created another modelica example, as the purpose of the original example with the tables wasn't clear to me...
remark2: the method presented here only works for quasi-steady state models, but modification for transient modes should be easy
remark3: fmu export is done by right-clicking on the model in the navigator, and choosing export/FMU;
               use FMI setting 'Version 2.0' and 'Co-Simulation' in Tools/Options/FMI !
               in the Messages-pane you'll see the path where the fmu is stored (usually C:\Users\USERNAME\AppData\Local\Temp\OpenModelica\OMEdit\)


test-parVar.mo

somehow uploading the python script doesn't work, thus I include the plain text


""" This example demonstrates how to use the FMU.get*() and FMU.set*() functions
to set custom input and get the output after each simulation step """

# based on:
# source: https://github.com/CATIA-Systems/FMPy/b … m_input.py


from fmpy import read_model_description, extract
from fmpy.fmi2 import FMU2Slave
import matplotlib.pyplot as plt
import shutil
import numpy as np

FMU_FILENAME = 'test_parVar.fmu'
INPUT_NAME   = 'param'
OUTPUT_NAME  = 'error'


def simulate(lower_bound, upper_bound):

    # define the model name and simulation parameters
   
    start_time = 0.0
    stop_time  = 2.0
    step_size  = 1e-2

    # read the model description
    model_description = read_model_description(FMU_FILENAME)

    # collect the value references
    vrs = {}
    for variable in model_description.modelVariables:
        vrs[variable.name] = variable.valueReference

    # get the value references for the variables we want to get/set
    vr_input  = vrs[INPUT_NAME]  # real input block name
    vr_output = vrs[OUTPUT_NAME]  # real output block name

    # extract the FMU
    unzipdir = extract(FMU_FILENAME)

    fmu = FMU2Slave(guid=model_description.guid,
                    unzipDirectory=unzipdir,
                    modelIdentifier=model_description.coSimulation.modelIdentifier,
                    instanceName='instance1')

    # initialize
    fmu.instantiate()
    fmu.setupExperiment(startTime=start_time)
    fmu.enterInitializationMode()
    fmu.exitInitializationMode()

    time = start_time

    results = []  # list to record the results

    # simulation loop
    while time <= stop_time:

        # NOTE: the FMU.get*() and FMU.set*() functions take lists of
        # value references as arguments and return lists of values

        # calculate the input
        x = lower_bound + (upper_bound-lower_bound)/(stop_time-start_time)*(time-start_time)
       
        # set the input
        fmu.setReal([vr_input], [x])

        # perform one step
        fmu.doStep(currentCommunicationPoint=time, communicationStepSize=step_size)

        # advance the time
        time += step_size

        # get the value for 'error'
        output = fmu.getReal([vr_output])[0] # return value of getReal is a list, we need just the value

        # append the results
        results.append([time, x, output])

    fmu.terminate()
    fmu.freeInstance()

    # clean up
    shutil.rmtree(unzipdir, ignore_errors=True)

    return results


if __name__ == '__main__':
    results = simulate(-5, 5) # range for parameter sweep
    results_np = np.array(results)
    plt.plot(results_np[:,1], results_np[:,2])
    plt.show()

Edited by: glang - Jan-11-22 08:41:49
Attachments:
There are 0 guests and 0 other users also viewing this topic
You are here: