Search code examples
modelicadymolafmi

How could I use 'fmi2GetDirectionalDerivative'?


I am trying to get the model Jacobian matrix from FMU, according to the following literature, I could use fmi2GetDirectionalDerivative to do this, but I am not sure what I need to do exactly.

My question is:

  1. Could I call this function in Dymola or MATLAB?
  2. A screenshot or an example would be very helpful.

https://ep.liu.se/ecp/132/091/ecp17132831.pdf

enter image description here


Solution

  • I am not familiar with calling DLL functions in MATLAB but this is an example in Python. FMPy (https://github.com/CATIA-Systems/FMPy) has these wrappers for running FMUs in python.

    I've tested this for a simple model I've written here(How to access model jacobian from FMU or Dymola without analytical jacobian). In this case, knowns are value references of either states or inputs, unknowns are value references of derivatives or outputs.

    I have had success extracting the Jacobian when exported through Dymola as Model Exchange FMU but not Co-Simulation FMU.

    def get_jacobian(fmu, vr_knowns, vr_unknowns):
        """
        populates jacobian from list of knowns and unknowns
        can be only called after the current sim time and inputs are set
        """
        jacobian = []
        try:
            for vr_known in vr_knowns:
                for vr_unknown in vr_unknowns:
                    jacobian.extend(
                        fmu.getDirectionalDerivative(
                            vUnknown_ref=[vr_unknown],
                            vKnown_ref=[vr_known],
                            dvKnown=[1.0]
                        ))
            print_status(f'Jacobian Elements: {jacobian}')
        except Exception as e:
            print("[ERROR] cannot compute jacobian at current timestep")
            print(f"[ERROR] {e}")
    

    I use this code snippet to collect the value references for states and derivatives using FMPy:

    # get FMU model description object
    model_description = fmpy.read_model_description(
        os.path.join(fmu_path, fmu_filename)
    )
    
    # collect the value references
    vrs = {}
    for variable in model_description.modelVariables:
        vrs[variable.name] = variable.valueReference
    
    # collect list of states and derivatives
    states = []
    derivatives = []
    for derivative in model_description.derivatives:
        derivatives.append(derivative.variable.name)
        states.append(re.findall('^der\((.*)\)$',derivative.variable.name)[0])
    
    # collect the value references for states and derivatives
    vr_states = [vrs[x] for x in states]
    vr_derivatives = [vrs[x] for x in derivatives]