如何用Python的FMPY库初始化OpenModelica热力学模型参数
使用FMPY修改OpenModelica热力学模型的初始压力参数
我想了解如何用Python的FMPY库修改OpenModelica模型的内部参数,当前使用的是一个热力学模型,希望直接在Python中初始化压力参数。

现有代码
# define the model name and simulation parameters # fmu_filename = 'Stockage_1.fmu' fmu_filename = 'Stockage350.fmu' start_time = 0 #threshold = 150.0 stop_time = 8000 step_size = 1 #step_size = 0.5 # download the FMU #download_test_file('2.0', 'CoSimulation', 'MapleSim', '2016.2', 'CoupledClutches', fmu_filename) # 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 in_consommation_H2 = vrs['Conso_Kg_s'] # normalized force on the 3rd clutch in_cmd_1_R1 = vrs['cmd_1_R1'] in_cmd_1_R2 = vrs['cmd_1_R2'] in_cmd_1_R3 = vrs['cmd_1_R3'] in_cmd_1_R4 = vrs['cmd_1_R4'] in_cmd_1_R5 = vrs['cmd_1_R5'] in_cmd_1_R6 = vrs['cmd_1_R6'] in_cmd_1_R7 = vrs['cmd_1_R7'] in_cmd_1_R8 = vrs['cmd_1_R8'] in_cmd_2_R1 = vrs['cmd_2_R1'] in_cmd_2_R2 = vrs['cmd_2_R2'] in_cmd_2_R3 = vrs['cmd_2_R3'] in_cmd_2_R4 = vrs['cmd_2_R4'] in_cmd_2_R5 = vrs['cmd_2_R5'] in_cmd_2_R6 = vrs['cmd_2_R6'] in_cmd_2_R7 = vrs['cmd_2_R7'] in_cmd_2_R8 = vrs['cmd_2_R8'] out_Masse_H2 = vrs['Masse_H2'] out_P1 = vrs['P1'] out_P2 = vrs['P2'] out_P3 = vrs['P3'] out_P4 = vrs['P4'] out_P5 = vrs['P5'] out_P6 = vrs['P6'] out_P7 = vrs['P6'] out_P8 = vrs['P8'] out_P_1 = vrs['P_1'] out_P_2 = vrs['P_2'] out_P_3 = vrs['P_3'] out_P_4 = vrs['P_4'] out_P_5 = vrs['P_5'] out_P_6 = vrs['P_6'] out_P_7 = vrs['P_7'] out_P_8 = vrs['P_8'] out_P_HP = vrs['P_HP'] out_P_MP = vrs['P_MP'] out_T1 = vrs['T1'] out_T2 = vrs['T2'] out_T3 = vrs['T3'] out_T4 = vrs['T4'] out_T5 = vrs['T5'] out_T6 = vrs['T6'] out_T7 = vrs['T6'] out_T8 = vrs['T8'] out_T_1 = vrs['T_1'] out_T_2 = vrs['T_2'] out_T_3 = vrs['T_3'] out_T_4 = vrs['T_4'] out_T_5 = vrs['T_5'] out_T_6 = vrs['T_6'] out_T_7 = vrs['T_7'] out_T_8 = vrs['T_8'] out_T_HP = vrs['T_HP'] out_m_flow = vrs['m_Flow'] # 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 rows = [] # 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 print("\n\n\n\n\nwhile() time: " + str(time)) # set the input fmu.setReal([in_consommation_H2], [0.00678 if time < 0.0 else 0.00678]) # set the input fmu.setBoolean([in_cmd_1_R1], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_1_R2], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_1_R3], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_1_R4], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_1_R5], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_1_R6], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_1_R7], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_1_R8], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_2_R1], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_2_R2], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_2_R3], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_2_R4], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_2_R5], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_2_R6], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_2_R7], [1 if time < 1.0 else 1]) fmu.setBoolean([in_cmd_2_R8], [1 if time < 1.0 else 1]) print("\nwhile() 2 time: " + str(time)) # perform one step fmu.doStep(currentCommunicationPoint=time, communicationStepSize=step_size) print("\nwhile() 3 time: " + str(time)) # advance the time time += step_size # get the values for 'inputs' and 'outputs[4]' resultat_FMU = fmu.getReal([out_Masse_H2, out_P1, out_P2, out_P3, out_P4, out_P5, out_P6, out_P7, out_P8, out_P_1, out_P_2, out_P_3, out_P_4, out_P_5, out_P_6, out_P_7, out_P_8, out_T1, out_T2, out_T3, out_T4, out_T5, out_T6, out_T7, out_T8, out_T_1, out_T_2, out_T_3, out_T_4, out_T_5, out_T_6, out_T_7, out_T_8, out_P_HP, out_P_MP, out_T_HP, out_m_flow]) print("Sortie du FMU: " + str(resultat_FMU)) # append the results rows.append((time, resultat_FMU[0], resultat_FMU[1], resultat_FMU[2], resultat_FMU[3], resultat_FMU[4], resultat_FMU[5], resultat_FMU[6], resultat_FMU[7], resultat_FMU[8], resultat_FMU[9], resultat_FMU[10], resultat_FMU[11], resultat_FMU[12], resultat_FMU[13], resultat_FMU[14], resultat_FMU[15], resultat_FMU[16], resultat_FMU[17], resultat_FMU[18], resultat_FMU[19], resultat_FMU[20], resultat_FMU[21], resultat_FMU[22], resultat_FMU[23], resultat_FMU[24], resultat_FMU[25], resultat_FMU[26], resultat_FMU[27], resultat_FMU[28], resultat_FMU[29], resultat_FMU[30], resultat_FMU[31], resultat_FMU[32], resultat_FMU[33], resultat_FMU[34], resultat_FMU[35], resultat_FMU[36], )) # use the threshold to terminate the simulation # if outputs4 > threshold: # print("Threshold reached at t = %g s" % time) # break fmu.terminate() fmu.freeInstance() # clean up shutil.rmtree(unzipdir, ignore_errors=True) # convert the results to a structured NumPy array result = np.array(rows, dtype=np.dtype([('time', np.float64), ('Masse H2', np.float64), ('Pression 1', np.float64), ('Pression 2', np.float64), ('Pression 3', np.float64), ('Pression 4', np.float64), ('Pression 5', np.float64), ('Pression 6', np.float64), ('Pression 7', np.float64), ('Pression 8', np.float64), ('Pression 2-1', np.float64), ('Pression 2-2', np.float64), ('Pression 2-3', np.float64), ('Pression 2-4', np.float64), ('Pression 2-5', np.float64), ('Pression 2-6', np.float64), ('Pression 2-7', np.float64), ('Pression 2-8', np.float64), ('Température 1', np.float64), ('Température 2', np.float64), ('Température 3', np.float64), ('Température 4', np.float64), ('Température 5', np.float64), ('Température 6', np.float64), ('Température 7', np.float64), ('Température 8', np.float64), ('Température 2-1', np.float64), ('Température 2-2', np.float64), ('Température 2-3', np.float64), ('Température 2-4', np.float64), ('Température 2-5', np.float64), ('Température 2-6', np.float64), ('Température 2-7', np.float64), ('Température 2-8', np.float64), ('Pression HP', np.float64), ('Pression MP', np.float64), ('Température HP', np.float64), ('Flux', np.float64) ])) # plot the results if show_plot: plot_result(result) return time
修改方法
要初始化压力参数,核心是在FMU初始化阶段设置参数,而不是仿真循环中(后者是运行时输入),具体步骤如下:
- 定位初始参数变量
OpenModelica导出FMU时,状态变量的初始值通常会生成带_start后缀的变量(比如截图中的P1_start)。你可以遍历model_description.modelVariables确认所有可修改的初始变量:
# 打印所有变量名,找到对应压力的初始变量 for variable in model_description.modelVariables: if 'start' in variable.name and 'P' in variable.name: print(variable.name)
- 获取变量的Value Reference
在收集vrs字典时,加入目标初始参数的引用:
# 比如获取P1、P2的初始值变量引用 p1_start_vr = vrs['P1_start'] p2_start_vr = vrs['P2_start'] # 按需添加其他压力参数
- 在初始化阶段设置参数
修改初始化代码块,在enterInitializationMode()之后、exitInitializationMode()之前调用setReal()设置初始值:
# initialize fmu.instantiate() fmu.setupExperiment(startTime=start_time) fmu.enterInitializationMode() # 设置初始压力值,注意单位匹配(示例为350bar转Pa) fmu.setReal([p1_start_vr, p2_start_vr], [350e5, 350e5]) fmu.exitInitializationMode()
注意事项
- 单位一致性:确保设置的数值单位与模型内部单位一致(如Pa、bar),否则会导致仿真结果异常。
- 变量可写性:确认目标变量的
variability属性为fixed或tunable,这类变量才能通过FMPY修改初始值。 - 批量设置:可以一次性传入多个变量的valueReference和对应值,提高效率。
内容的提问来源于stack exchange,提问作者Yaya356
相关产品推荐
相关产品推荐

