diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..5a1981d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +* linguist-vendored +*.py linguist-vendored=false diff --git a/pyDMPC/ControlFramework/Init.py b/pyDMPC/ControlFramework/Init.py index 8628ce2..d07c28d 100644 --- a/pyDMPC/ControlFramework/Init.py +++ b/pyDMPC/ControlFramework/Init.py @@ -16,10 +16,10 @@ """ Settings for BExMoC algorithm """ # So far: For all subsystems the same settings -factors_BCs = [5, 0.03] # order: BC1, BC2, ... -center_vals_BCs = [15, 0.001] -amount_lower_vals = [2, 0] -amount_upper_vals = [2, 1] +factors_BCs = [1.5, 0.03] # order: BC1, BC2, ... +center_vals_BCs = [30, 0.001] +amount_lower_vals = [9, 0] +amount_upper_vals = [9, 1] exp_BCs = [1, 1] amount_vals_BCs = [1, 1] @@ -40,7 +40,7 @@ sim_time_global = 10000 # -> not used yet sync_rate = 5*60 # Synchronisation rate in seconds optimization_interval = 10*60 # After one interval the optimization is repeated -prediction_horizon = 86400 #Common prediction horizon in seconds +prediction_horizon = 3600 #Common prediction horizon in seconds """ Directories and Modelica libraries """ # Path where the main working directory shall be created @@ -122,29 +122,48 @@ IDs_inputs = [] T_set = [] Q_set = [] +variation = [] """ Subsystems """ -# Ground -name.append('Geothermal_Field') -position.append(2) +#Ground_long +name.append('Field_long') +position.append(1) type_subSyst.append('generator') num_DecVars.append(0) -num_VarsOut.append(2) +num_VarsOut.append(1) bounds_DVs.append([0,0]) -model_path.append('ModelicaModels.SubsystemModels.DetailedModels.Geo.Field') +model_path.append('ModelicaModels.SubsystemModels.DetailedModels.Geo.Field_new') names_DVs.append(None) -output_vars.append(["supplyTemperature.T","massFlow.m_flow"]) +output_vars.append(["supplyTemperature.T"]) initial_names.append([]) IDs_initial_values.append([]) -IDs_inputs.append(["fieldTemperature_in","fieldMassflow_in"]) -cost_par.append("decisionVariables.y[1]") +IDs_inputs.append(["fieldTemperature_in"]) +cost_par.append("") T_set.append(285) Q_set.append(2200) +variation.append(False) + +## Ground_short +#name.append('Field_short') +#position.append(2) +#type_subSyst.append('generator') +#num_DecVars.append(0) +#num_VarsOut.append(2) +#bounds_DVs.append([0,0]) +#model_path.append('ModelicaModels.SubsystemModels.DetailedModels.Geo.Field') +#names_DVs.append(None) +#output_vars.append(["supplyTemperature.T","massFlow.m_flow"]) +#initial_names.append([]) +#IDs_initial_values.append([]) +#IDs_inputs.append(["fieldTemperature_in","fieldMassflow_in"]) +#cost_par.append("decisionVariables.y[1]") +#T_set.append(285) +#Q_set.append(2200) +#variation.append(True) - # Building name.append('Building') -position.append(1) +position.append(2) type_subSyst.append('consumer') num_DecVars.append(1) num_VarsOut.append(2) @@ -158,3 +177,4 @@ cost_par.append("decisionVariables.y[1]") T_set.append(295) Q_set.append(0) +variation.append(True) \ No newline at end of file diff --git a/pyDMPC/ControlFramework/__pycache__/Init.cpython-36.pyc b/pyDMPC/ControlFramework/__pycache__/Init.cpython-36.pyc index f822afc..40a64dd 100644 Binary files a/pyDMPC/ControlFramework/__pycache__/Init.cpython-36.pyc and b/pyDMPC/ControlFramework/__pycache__/Init.cpython-36.pyc differ diff --git a/pyDMPC/ControlFramework/__pycache__/Objective_Function.cpython-36.pyc b/pyDMPC/ControlFramework/__pycache__/Objective_Function.cpython-36.pyc index 52c86bd..8db9117 100644 Binary files a/pyDMPC/ControlFramework/__pycache__/Objective_Function.cpython-36.pyc and b/pyDMPC/ControlFramework/__pycache__/Objective_Function.cpython-36.pyc differ diff --git a/pyDMPC/ControlFramework/__pycache__/Subsystem.cpython-36.pyc b/pyDMPC/ControlFramework/__pycache__/Subsystem.cpython-36.pyc index ef6f56f..6e96408 100644 Binary files a/pyDMPC/ControlFramework/__pycache__/Subsystem.cpython-36.pyc and b/pyDMPC/ControlFramework/__pycache__/Subsystem.cpython-36.pyc differ diff --git a/pyDMPC/ControlFramework/__pycache__/System.cpython-36.pyc b/pyDMPC/ControlFramework/__pycache__/System.cpython-36.pyc index 71a3b8b..f9fd370 100644 Binary files a/pyDMPC/ControlFramework/__pycache__/System.cpython-36.pyc and b/pyDMPC/ControlFramework/__pycache__/System.cpython-36.pyc differ diff --git a/pyDMPC/ControlFramework/algorithm/__pycache__/BExMoC.cpython-36.pyc b/pyDMPC/ControlFramework/algorithm/__pycache__/BExMoC.cpython-36.pyc index 98e5dbd..963db3a 100644 Binary files a/pyDMPC/ControlFramework/algorithm/__pycache__/BExMoC.cpython-36.pyc and b/pyDMPC/ControlFramework/algorithm/__pycache__/BExMoC.cpython-36.pyc differ diff --git a/pyDMPC/ControlFramework/field_long.py b/pyDMPC/ControlFramework/field_long.py index 45b12a0..28fc573 100644 --- a/pyDMPC/ControlFramework/field_long.py +++ b/pyDMPC/ControlFramework/field_long.py @@ -1,79 +1,105 @@ import numpy as np -import matplotlib.pyplot as plt +#import matplotlib.pyplot as plt import pandas as pd -import xlrd -import scipy -from scipy.integrate import simps +#import xlrd +#import scipy +#from scipy.integrate import simps import pickle import os import sys - +import scipy.io as sio +import Init +# sys.path.insert(0, os.path.join('C:\\', 'Program Files (x86)', 'Dymola 2018', 'Modelica', 'Library', 'python_interface', 'dymola.egg')) #Simulation of field model #Import dymola package from dymola.dymola_interface import DymolaInterface - +from modelicares import SimRes # Start the interface dymola = DymolaInterface() # Location of your libraries -path_lib1 = r'C:\mst\pyDMPC\pyDMPC\ModelicaModels\ModelicaModels' -path_lib2 = r'C:\mst\modelica-buildings\Buildings' -path_lib3 = r'C:\mst\AixLib\Aixlib' +path_lib1 = r'C:\\mst\\pyDMPC\\pyDMPC\\ModelicaModels\\ModelicaModels' +path_lib2 = r'C:\\mst\\modelica-buildings\\Buildings' +path_lib3 = r'C:\\mst\\AixLib\\Aixlib' path_lib = [path_lib1, path_lib2, path_lib3] # Location where to store the results -path_res = r'C:\mst\dymola\Geo_long' +path_res = r'C:\\mst\\dymola\\Geo_long\\' # Name of the main working directory import time timestr = time.strftime("%Y%m%d_%H%M%S") name_wkdir = r'pyDMPC_' + 'wkdir' + timestr -# Open AixLib +# Open AixLib, Buildings & pyDMPC Modlica Models dymola.openModel(path=os.path.join(path_lib3, 'package.mo')) +dymola.openModel(path=os.path.join(path_lib2, 'package.mo')) +dymola.openModel(path=os.path.join(path_lib1, 'package.mo')) # Translate any model you'd like to simulate dymola.translateModel('ModelicaModels.SubsystemModels.DetailedModels.Geo.Field') +#obj_fnc_val = 'objectiveFunction' #parameters of the field model #Input: combiTable "variation": heatflow of the houses need, m_flow -Q0_heat = np.array([500, 600, 300, 100, 50, 10, 0, 5, 80, 250, 300, 450]) -Q0_cold = np.array([25, 25, 110, 200, 400, 600, 650, 600, 450, 300, 150, 50]) +Q0_heat = np.array([5000, 6000, 3000, 1000, 500, 100, 0, 50, 800, 2500, 3000, 4500]) #in kWh +Q0_cold = np.array([250, 250, 1100, 2000, 4000, 6000, 6500, 6000, 4500, 3000, 1500, 500]) #in kWh days = np.array([31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]) -dQ = np.array(Q0_heat/days - Q0_cold/days) #in kWh +dQ = np.array(Q0_heat/days - Q0_cold/days) #in kWh/day dt = 24 Q_flow = np.divide(dQ*1000,dt) #in W -#Q_set as needed heatflow every hour a year +#Q_set as needed heatflow every hour a year in W Q_set = [Q_flow[0]] *days[0] *24 + [Q_flow[1]] *days[1] *24 + [Q_flow[2]] *days[2] *24 + \ [Q_flow[3]] *days[3] *24 + [Q_flow[4]] *days[4] *24 + [Q_flow[5]] *days[5] *24 + \ [Q_flow[6]] *days[6] *24 + [Q_flow[7]] *days[7] *24 + [Q_flow[8]] *days[8] *24 + \ [Q_flow[9]] *days[9] *24 + [Q_flow[10]] *days[10] *24 + [Q_flow[11]] *days[11] *24 -m_flow = [0.00025]*365 #in m³/s +V_flow = 0.00025 #in m³/s +rho = 1000 +m_flow = [V_flow*rho]*8760 #in kg/s + +starttime = 0.0 +stoptime = 1*365*24*3600 +time = np.arange(0, stoptime, 3600) + +tab = np.array([time] + [Q_set] + [m_flow]) +BC_array = tab.transpose(1,0) -tab1 = np.array([Q_set], [m_flow]) +sio.savemat((path_res +'\\'+ Init.fileName_BCsInputTable + '.mat'), {Init.tableName_BCsInputTable :BC_array}) + +#testList = [variation.column[1],variation.column[2]] +#testValues = [BC_array[1],BC_array[2]] +testList = [''] +testValues = [None] +variable_name=[''] +final_names = ['supplyTemperature.T'] # Simulate the model output = dymola.simulateExtendedModel( - problem='', - startTime=0.0, - stopTime=94608000, - outputInterval=3600, - method="Dassl", - tolerance=0.0001, - resultFile=os.path.join(dir_result, 'demo_results'), - finalNames=[''], -) - + problem = 'ModelicaModels.SubsystemModels.DetailedModels.Geo.Field_new', + startTime = starttime, + stopTime = stoptime, + outputInterval = 3600, + method = "Dassl", + tolerance = 1, + resultFile = path_res +'dsres', + finalNames = final_names, + initialNames = testList, + initialValues = testValues + ) dymola.close() -#field temperature regarding the longterm set temperature = trajectory -T0 = 285 #ungestörte Erdreichtemperatur -T_set = T0*np.ones(3*365*24) #Vorlauftemperatur ins Feld (Soll) -pickle_out = open("T_set.pickle","wb") -pickle.dump(T_set, pickle_out) +sim = SimRes(path_res + 'dsres' + '.mat') +sol = sim.to_pandas(variable_name) + +#pickling field temperature +#T0 = 285 #ungestörte Erdreichtemperatur +#T_set = T0*np.ones(3*365*24) #Vorlauftemperatur ins Feld (Soll) + +#pickle_out = open(path_res + "\\" + "T_out.pickle","wb") +#pickle.dump(T_out, pickle_out) \ No newline at end of file diff --git a/pyDMPC/ModelicaModels/ModelicaModels/ControlledSystems/SimpleModelGeo.mo b/pyDMPC/ModelicaModels/ModelicaModels/ControlledSystems/SimpleModelGeo.mo index 576f89b..a8563f8 100644 --- a/pyDMPC/ModelicaModels/ModelicaModels/ControlledSystems/SimpleModelGeo.mo +++ b/pyDMPC/ModelicaModels/ModelicaModels/ControlledSystems/SimpleModelGeo.mo @@ -146,7 +146,10 @@ model SimpleModelGeo "extends Modelica.Icons.Example;extends ModelicaModels.Base Placement(transformation( extent={{-4,-4},{4,4}}, rotation=90, - origin={12,100}))); + origin={12,100}), iconTransformation( + extent={{-4,-4},{4,4}}, + rotation=90, + origin={0,16}))); Modelica.Blocks.Interfaces.RealOutput fieldMassflow_in annotation (Placement( transformation( extent={{-4,-4},{4,4}}, diff --git a/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/CoolerML.mo b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/CoolerML.mo new file mode 100644 index 0000000..2e584c1 --- /dev/null +++ b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/CoolerML.mo @@ -0,0 +1,103 @@ +within ModelicaModels.SubsystemModels.DetailedModels; +model CoolerML "Detailed model of the cooler for machine learning" + + extends ModelicaModels.Subsystems.BaseClasses.CoolerBaseClass; + Modelica.Fluid.Sources.MassFlowSource_T IntakeAirSource( + nPorts=1, + m_flow=0.5, + redeclare package Medium = MediumAir, + X={0.03,0.97}, + T=30 + 273.15, + use_X_in=true, + use_T_in=true, + use_m_flow_in=true) + annotation (Placement(transformation(extent={{-60,60},{-40,80}}))); + Modelica.Fluid.Sources.Boundary_pT IntakeAirSink( + nPorts=1, + redeclare package Medium = MediumAir, + use_T_in=false, + use_X_in=false, + use_p_in=false, + p(displayUnit="Pa") = 101300) + annotation (Placement(transformation(extent={{120,60},{100,80}}))); + AixLib.Utilities.Psychrometrics.ToTotalAir toTotAir + annotation (Placement(transformation(extent={{-110,56},{-90,76}}))); + AixLib.Fluid.Sensors.Temperature supplyAirTemperature(redeclare package + Medium = MediumAir) "Temperature of supply air" + annotation (Placement(transformation(extent={{32,88},{52,108}}))); + Modelica.Blocks.Sources.RealExpression realExpression3[4](y=hex.ele[:].mas.T) + annotation (Placement(transformation(extent={{52,-124},{72,-104}}))); + Modelica.Blocks.Interfaces.RealOutput hexele1masT "Value of Real output" + annotation (Placement(transformation(extent={{92,-108},{112,-88}}))); + Modelica.Blocks.Interfaces.RealOutput hexele2masT "Value of Real output" + annotation (Placement(transformation(extent={{92,-118},{112,-98}}))); + Modelica.Blocks.Interfaces.RealOutput hexele3masT "Value of Real output" + annotation (Placement(transformation(extent={{92,-128},{112,-108}}))); + Modelica.Blocks.Interfaces.RealOutput hexele4masT "Value of Real output" + annotation (Placement(transformation(extent={{92,-138},{112,-118}}))); + Modelica.Blocks.Interfaces.RealOutput supplyTemp "Temperature in port medium" + annotation (Placement(transformation(extent={{126,88},{146,108}}))); + Modelica.Blocks.Interfaces.RealInput valveOpening "Input signal connector" + annotation (Placement(transformation(extent={{-160,-70},{-120,-30}}))); + Modelica.Blocks.Sources.Constant x(k=0.007) annotation (Placement( + transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={-130,66}))); + Modelica.Blocks.Sources.Constant mflow(k=0.35) annotation (Placement( + transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={-100,100}))); + Modelica.Blocks.Interfaces.RealInput inflowTemp + "Prescribed fluid temperature" + annotation (Placement(transformation(extent={{-160,0},{-120,40}}))); + Modelica.Thermal.HeatTransfer.Celsius.ToKelvin toKelvin annotation ( + Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={-84,20}))); + Modelica.Thermal.HeatTransfer.Celsius.FromKelvin + fromKelvin + annotation ( + Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={82,98}))); +equation + connect(toTotAir.XiTotalAir, IntakeAirSource.X_in[1]) + annotation (Line(points={{-89,66},{-62,66}}, color={0,0,127})); + connect(toTotAir.XNonVapor, IntakeAirSource.X_in[2]) annotation (Line(points= + {{-89,62},{-82,62},{-82,66},{-62,66}}, color={0,0,127})); + connect(IntakeAirSource.ports[1], hex.port_a2) + annotation (Line(points={{-40,70},{-12,70}}, color={0,127,255})); + connect(hex.port_b2, IntakeAirSink.ports[1]) + annotation (Line(points={{8,70},{100,70}}, color={0,127,255})); + connect(realExpression3[1].y, hexele1masT) annotation (Line(points={{73,-114}, + {84,-114},{84,-98},{102,-98}}, color={0,0,127})); + connect(realExpression3[2].y, hexele2masT) annotation (Line(points={{73,-114}, + {84,-114},{84,-108},{102,-108}}, color={0,0,127})); + connect(realExpression3[3].y, hexele3masT) annotation (Line(points={{73,-114}, + {82,-114},{82,-118},{102,-118}}, color={0,0,127})); + connect(realExpression3[4].y, hexele4masT) annotation (Line(points={{73,-114}, + {84,-114},{84,-128},{102,-128}}, color={0,0,127})); + connect(hex.port_b2, supplyAirTemperature.port) annotation (Line(points={{8, + 70},{26,70},{26,88},{42,88}}, color={0,127,255})); + connect(convertCommand.u, valveOpening) + annotation (Line(points={{-103.2,-50},{-140,-50}}, color={0,0,127})); + connect(toTotAir.XiDry, x.y) + annotation (Line(points={{-111,66},{-119,66}}, color={0,0,127})); + connect(mflow.y, IntakeAirSource.m_flow_in) annotation (Line(points={{-89,100}, + {-74,100},{-74,78},{-60,78}}, color={0,0,127})); + connect(inflowTemp, toKelvin.Celsius) + annotation (Line(points={{-140,20},{-96,20}}, color={0,0,127})); + connect(toKelvin.Kelvin, IntakeAirSource.T_in) annotation (Line(points={{-73, + 20},{-70,20},{-70,74},{-62,74}}, color={0,0,127})); + connect(supplyAirTemperature.T, fromKelvin.Kelvin) + annotation (Line(points={{49,98},{70,98}}, color={0,0,127})); + connect(fromKelvin.Celsius, supplyTemp) + annotation (Line(points={{93,98},{136,98}}, color={0,0,127})); + annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false)), + experiment(StopTime=100000, Interval=10)); +end CoolerML; diff --git a/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/Building.mo b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/Building.mo index 572dd14..6c6366a 100644 --- a/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/Building.mo +++ b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/Building.mo @@ -8,7 +8,7 @@ model Building "Simplified building model" energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial, m_flow_small=50, p_start=100000, - nPorts=3) annotation ( + nPorts=2) annotation ( Placement(transformation( extent={{-10,-10},{10,10}}, rotation=0, @@ -22,6 +22,25 @@ model Building "Simplified building model" extent={{-6,-6},{6,6}}, rotation=0, origin={-80,-58}))); + AixLib.Fluid.Geothermal.Borefields.TwoUTubes borFie(redeclare package Medium + = Water, + borFieDat( + filDat=AixLib.Fluid.Geothermal.Borefields.Data.Filling.Bentonite(), + soiDat=AixLib.Fluid.Geothermal.Borefields.Data.Soil.SandStone(), + conDat=AixLib.Fluid.Geothermal.Borefields.Data.Configuration.Example( + borCon=AixLib.Fluid.Geothermal.Borefields.Types.BoreholeConfiguration.DoubleUTubeParallel, + cooBor=[0,0; 0,6; 6,0; 6,6; 0,12; 12,0; 12,12; 0,18; 18,0; 18,18; 6, + 12; 6,18; 12,6; 18,6; 18,12; 12,18; 24,0; 0,24; 6,24; 12,24; 18,24; + 24,24; 24,18; 24,12; 24,6; 0,30; 6,30; 12,30; 18,30; 24,30; 30,30; 30, + 24; 30,18; 30,12; 30,6; 30,0; 0,36; 6,36; 12,36; 18,36; 24,36; 30,36; + 36,36; 36,30; 36,24; 36,18; 36,12; 36,6; 36,0])), + show_T=false, + TExt0_start=285.15) + annotation (Placement( + transformation( + extent={{-27,-26},{27,26}}, + rotation=0, + origin={63,12}))); equation connect(prescribedHeatFlow.port, vol1.heatPort) annotation (Line(points={{-40, -58},{-26,-58},{-26,42},{-16,42}}, color={191,0,0})); @@ -29,10 +48,12 @@ equation annotation (Line(points={{-64,-58},{-73.4,-58}}, color={0,0,127})); connect(decisionVariables.y[1], maxHeatFlowRate.u) annotation (Line(points={{ -99,-110},{-92,-110},{-92,-58},{-87.2,-58}}, color={0,0,127})); - connect(IntakeAirSource.ports[1], vol1.ports[1]) annotation (Line(points={{ - -100,12},{-74,12},{-74,32},{-8.66667,32}}, color={0,127,255})); - connect(supplyTemperature.port, vol1.ports[2]) annotation (Line(points={{104, - 38},{104,12},{28,12},{28,32},{-6,32}}, color={0,127,255})); - connect(vol1.ports[3], massFlow.port_a) annotation (Line(points={{-3.33333,32}, - {28,32},{28,12},{116,12}}, color={0,127,255})); + connect(IntakeAirSource.ports[1], vol1.ports[1]) annotation (Line(points={{-100,12}, + {-74,12},{-74,32},{-8,32}}, color={0,127,255})); + connect(vol1.ports[2], borFie.port_a) annotation (Line(points={{-4,32},{14,32}, + {14,12},{36,12}}, color={0,127,255})); + connect(borFie.port_b, supplyTemperature.port) annotation (Line(points={{90, + 12},{90,25},{104,25},{104,38}}, color={0,127,255})); + connect(supplyTemperature.port, massFlow.port_a) + annotation (Line(points={{104,38},{104,12},{116,12}}, color={0,127,255})); end Building; diff --git a/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/Field.mo b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/Field.mo index 728ec44..007bc8d 100644 --- a/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/Field.mo +++ b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/Field.mo @@ -1,19 +1,41 @@ within ModelicaModels.SubsystemModels.DetailedModels.Geo; model Field "Simplified model of geothermal field" - extends HeatExchangerCommunicationBaseClass(IntakeAirSource(nPorts=1)); + extends HeatExchangerCommunicationBaseClass2( + cp_water(k=4180000), + IntakeAirSource(nPorts=1), + variation( + table=[0,1,1; 1,2,2; 2,3,3], + tableOnFile=true, + fileName="C:/mst/dymola/Geo_long/variation.mat", + columns=1:3), + decisionVariables(table=[1,2,0.0; 2,3,0.0; 4,5,0.0; 6,6,0.0], tableOnFile= + false), + MeasuredData( + columns=1:2, + table=[0,12; 3600,12.1; 7200,12.15; 10800,12.1; 14400,12.15; 18000,12; + 21600,12; 25200,12; 28800,12; 32400,12; 36000,12; 39600,12; 43200,12; + 46800,12; 50400,12; 54000,12; 57600,12; 61200,12; 64800,12; 68400,12; + 72000,12; 75600,12; 79200,12; 82800,12; 86400,12; 90000,12; 93600,12; + 97200,12; 100800,12; 104400,12; 108000,12; 111600,12; 115200,12; + 118800,12; 122400,12; 126000,12; 129600,12; 133200,12; 136800,12; + 140400,12; 144000,12; 147600,12; 151200,12; 154800,12; 158400,12; + 162000,12; 165600,12; 169200,12; 172800,12], + tableOnFile=false), + supplyTemperature(T(start=285))); + replaceable package Water = AixLib.Media.Water; AixLib.Fluid.MixingVolumes.MixingVolume vol(redeclare package Medium = Water, m_flow_nominal=100, m_flow_small=50, - V=900000, nPorts=3, p_start=150000, - T_start=283.15) annotation ( + T_start=285.15, + V=900) annotation ( Placement(transformation( extent={{-10,-10},{10,10}}, rotation=0, - origin={10,38}))); + origin={8,38}))); Modelica.Thermal.HeatTransfer.Sources.FixedTemperature fixedTemperature(T=283.15) annotation (Placement(transformation( extent={{-6,-6},{6,6}}, @@ -26,13 +48,15 @@ model Field "Simplified model of geothermal field" origin={-24,62}))); equation connect(thermalResistor.port_b,vol. heatPort) annotation (Line(points={{-18,62}, - {-10,62},{-10,38},{0,38}}, color={191,0,0})); + {-10,62},{-10,38},{-2,38}}, color={191,0,0})); connect(fixedTemperature.port, thermalResistor.port_a) annotation (Line(points={{-40,62},{-30,62}}, color={191,0,0})); - connect(IntakeAirSource.ports[1], vol.ports[1]) annotation (Line(points={{-100,12}, - {-54,12},{-54,28},{7.33333,28}}, color={0,127,255})); - connect(supplyTemperature.port, vol.ports[2]) annotation (Line(points={{104, - 38},{58,38},{58,28},{10,28}}, color={0,127,255})); - connect(vol.ports[3], massFlow.port_a) annotation (Line(points={{12.6667,28}, + connect(IntakeAirSource.ports[1], vol.ports[1]) annotation (Line(points={{-58,12}, + {-54,12},{-54,28},{5.33333,28}}, color={0,127,255})); + connect(supplyTemperature.port, vol.ports[2]) annotation (Line(points={{104,38}, + {58,38},{58,28},{8,28}}, color={0,127,255})); + connect(vol.ports[3], massFlow.port_a) annotation (Line(points={{10.6667,28}, {64,28},{64,12},{116,12}}, color={0,127,255})); + connect(fromKelvin.Kelvin, add.u1) annotation (Line(points={{174,48},{112,48}, + {112,84},{-112,84},{-112,66},{-180,66},{-180,62}}, color={0,0,127})); end Field; diff --git a/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/Field_new.mo b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/Field_new.mo index d1c858f..6ed2ab1 100644 --- a/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/Field_new.mo +++ b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/Field_new.mo @@ -1,23 +1,49 @@ within ModelicaModels.SubsystemModels.DetailedModels.Geo; model Field_new "Simplified model of geothermal field" - extends HeatExchangerCommunicationBaseClass(IntakeAirSource(nPorts=1)); + extends HeatExchangerCommunicationBaseClass2( + cp_water(k=4180), + variation(fileName="C:/mst/dymola/Geo_long/variation.mat", columns=1:3), + MeasuredData(tableOnFile=false, table=[0.0,0.0,0.0; 0.0,0.0,0.0; 0.0,0.0, + 0.0; 0.0,0.0,0.0; 0.0,0.0,0.0; 0.0,0.0,0.0; 0.0,0.0,0.0]), + decisionVariables(tableOnFile=false, table=[0.0,0.0,0.0; 0.0,0.0,0.0; 0.0, + 0.0,0.0; 0.0,0.0,0.0; 0.0,0.0,0.0; 0.0,0.0,0.0]), + add1(k2=-1), + Kelvin(k=273.15), + supplyTemperature(T(start=285.15, fixed=true)), + IntakeAirSource(nPorts=1)); replaceable package Water = AixLib.Media.Water; + AixLib.Fluid.Geothermal.Borefields.TwoUTubes borFie(redeclare package Medium = Water, - TExt0_start=285.15, - z0=10, - dT_dz=0.01) + borFieDat( + filDat=AixLib.Fluid.Geothermal.Borefields.Data.Filling.Bentonite(), + soiDat=AixLib.Fluid.Geothermal.Borefields.Data.Soil.SandStone(), + conDat=AixLib.Fluid.Geothermal.Borefields.Data.Configuration.Example( + borCon=AixLib.Fluid.Geothermal.Borefields.Types.BoreholeConfiguration.DoubleUTubeParallel, + cooBor=[0,0; 0,6; 6,0; 6,6; 0,12; 12,0; 12,12; 0,18; 18,0; 18,18; 6, + 12; 6,18; 12,6; 18,6; 18,12; 12,18; 24,0; 0,24; 6,24; 12,24; 18,24; + 24,24; 24,18; 24,12; 24,6; 0,30; 6,30; 12,30; 18,30; 24,30; 30,30; 30, + 24; 30,18; 30,12; 30,6; 30,0; 0,36; 6,36; 12,36; 18,36; 24,36; 30,36; + 36,36; 36,30; 36,24; 36,18; 36,12; 36,6; 36,0])), + show_T=false, + TExt0_start=285.15) annotation (Placement( transformation( - extent={{-26,-25},{26,25}}, + extent={{-27,-26},{27,26}}, rotation=0, - origin={-16,11}))); + origin={5,12}))); + + Modelica.Blocks.Sources.RealExpression realExpression(y=borFie.borFieDat.conDat.nBor) + annotation (Placement(transformation(extent={{-162,66},{-142,86}}))); equation - connect(IntakeAirSource.ports[1], borFie.port_a) annotation (Line(points={{-100,12}, - {-42,12},{-42,11}}, color={0,127,255})); - connect(borFie.port_b, massFlow.port_a) annotation (Line(points={{10,11},{22,11}, - {22,10},{116,10},{116,12}}, color={0,127,255})); - connect(supplyTemperature.port, massFlow.port_a) annotation (Line(points={{ - 104,38},{100,38},{100,8},{96,8},{96,6},{116,6},{116,12}}, color={0, - 127,255})); + connect(IntakeAirSource.ports[1], borFie.port_a) + annotation (Line(points={{-58,12},{-22,12}}, color={0,127,255})); + connect(borFie.port_b, massFlow.port_a) + annotation (Line(points={{32,12},{116,12}}, color={0,127,255})); + connect(supplyTemperature.T, add.u1) + annotation (Line(points={{111,48},{111,62},{-180,62}}, color={0,0,127})); + connect(supplyTemperature.port, borFie.port_b) annotation (Line(points={{104, + 38},{90,38},{90,20},{32,20},{32,12}}, color={0,127,255})); + connect(realExpression.y, product1.u2) + annotation (Line(points={{-141,76},{-116,76}}, color={0,0,127})); end Field_new; diff --git a/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/HeatExchangerCommunicationBaseClass2.mo b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/HeatExchangerCommunicationBaseClass2.mo new file mode 100644 index 0000000..aa253cb --- /dev/null +++ b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/HeatExchangerCommunicationBaseClass2.mo @@ -0,0 +1,143 @@ +within ModelicaModels.SubsystemModels.DetailedModels.Geo; +model HeatExchangerCommunicationBaseClass2 + "Base class containing the communication blocks for the heat exchanger models" + + replaceable package MediumWater = AixLib.Media.Water; + + Modelica.Fluid.Sources.MassFlowSource_T IntakeAirSource( + m_flow=0.5, + redeclare package Medium = MediumWater, + T=30 + 273.15, + use_T_in=true, + use_m_flow_in=true, + use_X_in=false) + annotation (Placement(transformation(extent={{-78,2},{-58,22}}))); + Modelica.Fluid.Sources.Boundary_pT IntakeAirSink( + redeclare package Medium = MediumWater, + use_T_in=false, + use_X_in=false, + use_p_in=false, + p(displayUnit="Pa") = 101300, + nPorts=1) + annotation (Placement(transformation(extent={{190,2},{170,22}}))); + + Modelica.Blocks.Sources.CombiTimeTable decisionVariables( + tableOnFile=true, + extrapolation=Modelica.Blocks.Types.Extrapolation.HoldLastPoint, + tableName="tab1", + smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments, + columns={2}, + fileName="decisionVariables.mat") + "Table with decision variables" annotation (Placement( + transformation( + extent={{-10,-10},{10,10}}, + rotation=0, + origin={-110,-110}))); + Modelica.Blocks.Sources.CombiTimeTable MeasuredData( + tableOnFile=true, + tableName="InputTable", + extrapolation=Modelica.Blocks.Types.Extrapolation.HoldLastPoint, + fileName="CompleteInput.mat", + columns=2:3) + annotation (Placement(transformation(extent={{-240,186},{-206,220}}))); + Modelica.Blocks.Sources.CombiTimeTable variation( + tableOnFile=true, + extrapolation=Modelica.Blocks.Types.Extrapolation.HoldLastPoint, + tableName="tab1", + columns=2:3, + fileName="variation.mat") "Table with control input" + annotation ( + Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=0, + origin={-230,140}))); + Modelica.Thermal.HeatTransfer.Celsius.ToKelvin toKelvin3 annotation ( + Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=90, + origin={-132,170}))); + + AixLib.Fluid.Sensors.Temperature supplyTemperature(redeclare package Medium + = MediumWater) "Temperature of supply water" + annotation (Placement(transformation(extent={{94,38},{114,58}}))); + Modelica.Thermal.HeatTransfer.Celsius.FromKelvin fromKelvin annotation ( + Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={186,48}))); + + Modelica.Blocks.Math.Gain convertPercent(k=1/100) "Convert from percent" + annotation (Placement(transformation( + extent={{-6,-6},{6,6}}, + rotation=270, + origin={-100,168}))); + AixLib.Fluid.Sensors.MassFlowRate massFlow(redeclare package Medium = + MediumWater) + annotation (Placement(transformation(extent={{116,6},{128,18}}))); + Modelica.Blocks.Sources.Constant cp_water(k=4180) annotation (Placement( + transformation( + extent={{-10,-10},{10,10}}, + rotation=90, + origin={-222,74}))); + Modelica.Blocks.Math.Division division annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=-90, + origin={-192,80}))); + Modelica.Blocks.Math.Product product annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=-90, + origin={-220,114}))); + Modelica.Blocks.Math.Add add(k2=-1) annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=-90, + origin={-186,50}))); + Modelica.Blocks.Math.Add add1 + annotation (Placement(transformation(extent={{-172,6},{-152,26}}))); + Modelica.Blocks.Sources.Constant Kelvin(k=-273.15) annotation (Placement( + transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={-228,10}))); + Modelica.Thermal.HeatTransfer.Celsius.ToKelvin toKelvin1 annotation ( + Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={-120,16}))); + Modelica.Blocks.Math.Product product1 + annotation (Placement(transformation(extent={{-114,72},{-94,92}}))); +equation + + connect(supplyTemperature.T, fromKelvin.Kelvin) + annotation (Line(points={{111,48},{174,48},{174,48}}, color={0,0,127})); + connect(MeasuredData.y[2], convertPercent.u) annotation (Line(points={{-204.3, + 203},{-100,203},{-100,175.2}}, color={0,0,127})); + connect(massFlow.port_b, IntakeAirSink.ports[1]) + annotation (Line(points={{128,12},{170,12}}, color={0,127,255})); + connect(variation.y[2], division.u1) annotation (Line(points={{-219,140},{ + -204,140},{-204,116},{-186,116},{-186,92}}, color={0,0,127})); + connect(product.u2, cp_water.y) annotation (Line(points={{-226,126},{-236,126}, + {-236,100},{-222,100},{-222,85}}, color={0,0,127})); + connect(product.y, division.u2) annotation (Line(points={{-220,103},{-220,100}, + {-198,100},{-198,92}}, color={0,0,127})); + connect(division.y, add.u2) annotation (Line(points={{-192,69},{-192,62}}, + color={0,0,127})); + connect(MeasuredData.y[2], toKelvin3.Celsius) annotation (Line(points={{ + -204.3,203},{-132,203},{-132,182}}, color={0,0,127})); + connect(add.y, add1.u1) + annotation (Line(points={{-186,39},{-186,22},{-174,22}}, color={0,0,127})); + connect(Kelvin.y, add1.u2) + annotation (Line(points={{-217,10},{-174,10}}, color={0,0,127})); + connect(add1.y, toKelvin1.Celsius) + annotation (Line(points={{-151,16},{-132,16}}, color={0,0,127})); + connect(toKelvin1.Kelvin, IntakeAirSource.T_in) + annotation (Line(points={{-109,16},{-80,16}}, color={0,0,127})); + connect(variation.y[3], product1.u1) annotation (Line(points={{-219,140},{ + -182,140},{-182,100},{-116,100},{-116,88}}, color={0,0,127})); + connect(product1.y, IntakeAirSource.m_flow_in) annotation (Line(points={{-93, + 82},{-84,82},{-84,24},{-78,24},{-78,20}}, color={0,0,127})); + connect(product1.y, product.u1) annotation (Line(points={{-93,82},{-93,138},{ + -214,138},{-214,126}}, color={0,0,127})); + annotation (Icon(coordinateSystem(preserveAspectRatio=false, extent={{-240,-200}, + {200,220}})), Diagram(coordinateSystem(preserveAspectRatio= + false, extent={{-240,-200},{200,220}}))); +end HeatExchangerCommunicationBaseClass2; diff --git a/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/package.order b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/package.order index b1e2437..b3bbe1b 100644 --- a/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/package.order +++ b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/Geo/package.order @@ -1,4 +1,5 @@ HeatExchangerCommunicationBaseClass +HeatExchangerCommunicationBaseClass2 Building Field GeothermalHeatPump diff --git a/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/HRCML.mo b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/HRCML.mo new file mode 100644 index 0000000..fe5e0d2 --- /dev/null +++ b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/HRCML.mo @@ -0,0 +1,160 @@ +within ModelicaModels.SubsystemModels.DetailedModels; +model HRCML + "Detailed model of the heat recovery for machine learning" + + extends ModelicaModels.Subsystems.BaseClasses.HRCBaseClass; + Modelica.Fluid.Sources.MassFlowSource_T IntakeAirSource( + m_flow=0.5, + redeclare package Medium = MediumAir, + X={0.03,0.97}, + T=30 + 273.15, + use_X_in=true, + use_T_in=true, + use_m_flow_in=true, + nPorts=1) + annotation (Placement(transformation(extent={{-60,38},{-40,58}}))); + Modelica.Fluid.Sources.Boundary_pT IntakeAirSink( + redeclare package Medium = MediumAir, + use_T_in=false, + use_X_in=false, + use_p_in=false, + p(displayUnit="Pa") = 101300, + nPorts=1) + annotation (Placement(transformation(extent={{122,22},{102,42}}))); + AixLib.Utilities.Psychrometrics.ToTotalAir toTotAir + annotation (Placement(transformation(extent={{-110,56},{-90,76}}))); + AixLib.Fluid.Sensors.TemperatureTwoPort + supplyAirTemperature(redeclare package + Medium = MediumAir, m_flow_nominal=0.35) + "Temperature of supply air" + annotation (Placement(transformation(extent={{62,20},{82,40}}))); + Modelica.Blocks.Sources.RealExpression realExpression3[4](y=hex.ele[:].mas.T) + annotation (Placement(transformation(extent={{52,-124},{72,-104}}))); + Modelica.Blocks.Interfaces.RealOutput hexele1masT "Value of Real output" + annotation (Placement(transformation(extent={{92,-108},{112,-88}}))); + Modelica.Blocks.Interfaces.RealOutput hexele2masT "Value of Real output" + annotation (Placement(transformation(extent={{92,-118},{112,-98}}))); + Modelica.Blocks.Interfaces.RealOutput hexele3masT "Value of Real output" + annotation (Placement(transformation(extent={{92,-128},{112,-108}}))); + Modelica.Blocks.Interfaces.RealOutput hexele4masT "Value of Real output" + annotation (Placement(transformation(extent={{92,-138},{112,-118}}))); + Modelica.Blocks.Interfaces.RealOutput supplyTemp "Temperature in port medium" + annotation (Placement(transformation(extent={{126,88},{146,108}}))); + Modelica.Blocks.Interfaces.RealInput valveOpening "Input signal connector" + annotation (Placement(transformation(extent={{-160,-70},{-120,-30}}))); + Modelica.Blocks.Sources.Constant x(k=0.007) annotation (Placement( + transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={-130,66}))); + Modelica.Blocks.Sources.Constant mflow(k=0.35) annotation (Placement( + transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={-100,100}))); + Modelica.Blocks.Interfaces.RealInput inflowTemp + "Prescribed fluid temperature" + annotation (Placement(transformation(extent={{-160,0},{-120,40}}))); + Modelica.Thermal.HeatTransfer.Celsius.ToKelvin toKelvin annotation ( + Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={-84,20}))); + Modelica.Thermal.HeatTransfer.Celsius.FromKelvin + fromKelvin + annotation ( + Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={82,98}))); + Modelica.Fluid.Sources.MassFlowSource_T extractAirSource( + m_flow=0.5, + redeclare package Medium = MediumAir, + X={0.03,0.97}, + T=30 + 273.15, + use_X_in=true, + use_T_in=true, + use_m_flow_in=true, + nPorts=1) + annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=180, + origin={138,70}))); + Modelica.Blocks.Sources.Constant extractTemp(k=273.15 + 25) annotation ( + Placement(transformation( + extent={{10,10},{-10,-10}}, + rotation=0, + origin={206,66}))); + Modelica.Blocks.Sources.Constant mflowExtract(k=0.32) annotation (Placement( + transformation( + extent={{10,10},{-10,-10}}, + rotation=0, + origin={206,22}))); + Modelica.Fluid.Sources.Boundary_pT ExhaustAirSink( + redeclare package Medium = MediumAir, + use_T_in=false, + use_X_in=false, + use_p_in=false, + p(displayUnit="Pa") = 101300, + nPorts=1) + annotation (Placement(transformation(extent={{10,-10},{-10,10}}, + rotation=180, + origin={-108,132}))); +equation + connect(toTotAir.XiTotalAir, IntakeAirSource.X_in[1]) + annotation (Line(points={{-89,66},{-76,66},{-76,44},{-62,44}}, + color={0,0,127})); + connect(toTotAir.XNonVapor, IntakeAirSource.X_in[2]) annotation (Line(points={{-89,62}, + {-82,62},{-82,44},{-62,44}}, color={0,0,127})); + connect(realExpression3[1].y, hexele1masT) annotation (Line(points={{73,-114}, + {84,-114},{84,-98},{102,-98}}, color={0,0,127})); + connect(realExpression3[2].y, hexele2masT) annotation (Line(points={{73,-114}, + {84,-114},{84,-108},{102,-108}}, color={0,0,127})); + connect(realExpression3[3].y, hexele3masT) annotation (Line(points={{73,-114}, + {82,-114},{82,-118},{102,-118}}, color={0,0,127})); + connect(realExpression3[4].y, hexele4masT) annotation (Line(points={{73,-114}, + {84,-114},{84,-128},{102,-128}}, color={0,0,127})); + connect(convertCommand.u, valveOpening) + annotation (Line(points={{-65.2,-56},{-102,-56},{-102,-50},{-140,-50}}, + color={0,0,127})); + connect(toTotAir.XiDry, x.y) + annotation (Line(points={{-111,66},{-119,66}}, color={0,0,127})); + connect(mflow.y, IntakeAirSource.m_flow_in) annotation (Line(points={{-89,100}, + {-74,100},{-74,56},{-60,56}}, color={0,0,127})); + connect(inflowTemp, toKelvin.Celsius) + annotation (Line(points={{-140,20},{-96,20}}, color={0,0,127})); + connect(toKelvin.Kelvin, IntakeAirSource.T_in) annotation (Line(points={{-73,20}, + {-70,20},{-70,52},{-62,52}}, color={0,0,127})); + connect(fromKelvin.Celsius, supplyTemp) + annotation (Line(points={{93,98},{136,98}}, color={0,0,127})); + connect(IntakeAirSource.ports[1], exhaustPressureDrop.port_a) annotation ( + Line(points={{-40,48},{-34,48},{-26,48},{-26,28},{-58,28},{-58,10},{-80, + 10},{-80,4},{-70,4}}, color={0,127,255})); + connect(supplyAirTemperature.port_b, IntakeAirSink.ports[1]) + annotation (Line(points={{82,30},{102,30},{102,32}}, color={0,127,255})); + connect(hex.port_b1, supplyAirTemperature.port_a) + annotation (Line(points={{46,52},{62,52},{62,30}}, color={0,127,255})); + connect(dam1.port_b, supplyAirTemperature.port_a) + annotation (Line(points={{54,-10},{62,-10},{62,30}}, color={0,127,255})); + connect(supplyAirTemperature.T, fromKelvin.Kelvin) annotation (Line(points={{ + 72,41},{72,41},{72,64},{58,64},{58,98},{70,98}}, color={0,0,127})); + connect(hex.port_b2, OutgoingAirOutletTemp.port_a) annotation (Line(points={{ + 26,64},{2,64},{2,76},{-24,76}}, color={0,127,255})); + connect(extractAirSource.ports[1], hex.port_a2) annotation (Line(points={{128, + 70},{88,70},{88,64},{46,64}}, color={0,127,255})); + connect(toTotAir.XiTotalAir, extractAirSource.X_in[1]) annotation (Line( + points={{-89,66},{-76,66},{-76,126},{168,126},{168,74},{150,74}}, color + ={0,0,127})); + connect(toTotAir.XNonVapor, extractAirSource.X_in[2]) annotation (Line(points + ={{-89,62},{-82,62},{-82,130},{176,130},{176,74},{150,74}}, color={0,0, + 127})); + connect(mflowExtract.y, extractAirSource.m_flow_in) annotation (Line(points={ + {195,22},{172,22},{172,62},{148,62}}, color={0,0,127})); + connect(extractTemp.y, extractAirSource.T_in) + annotation (Line(points={{195,66},{150,66}}, color={0,0,127})); + connect(ExhaustAirSink.ports[1], OutgoingAirOutletTemp.port_b) annotation ( + Line(points={{-98,132},{-88,132},{-68,132},{-68,76},{-44,76}}, color={0, + 127,255})); + annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false)), + experiment(StopTime=3600, Interval=10)); +end HRCML; diff --git a/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/HeaterML.mo b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/HeaterML.mo new file mode 100644 index 0000000..3951207 --- /dev/null +++ b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/HeaterML.mo @@ -0,0 +1,103 @@ +within ModelicaModels.SubsystemModels.DetailedModels; +model HeaterML "Detailed model of the heater for machine learning" + + extends ModelicaModels.Subsystems.BaseClasses.HeaterBaseClass; + Modelica.Fluid.Sources.MassFlowSource_T IntakeAirSource( + nPorts=1, + m_flow=0.5, + redeclare package Medium = MediumAir, + X={0.03,0.97}, + T=30 + 273.15, + use_X_in=true, + use_T_in=true, + use_m_flow_in=true) + annotation (Placement(transformation(extent={{-60,60},{-40,80}}))); + Modelica.Fluid.Sources.Boundary_pT IntakeAirSink( + nPorts=1, + redeclare package Medium = MediumAir, + use_T_in=false, + use_X_in=false, + use_p_in=false, + p(displayUnit="Pa") = 101300) + annotation (Placement(transformation(extent={{120,60},{100,80}}))); + AixLib.Utilities.Psychrometrics.ToTotalAir toTotAir + annotation (Placement(transformation(extent={{-110,56},{-90,76}}))); + AixLib.Fluid.Sensors.Temperature supplyAirTemperature(redeclare package + Medium = MediumAir) "Temperature of supply air" + annotation (Placement(transformation(extent={{32,88},{52,108}}))); + Modelica.Blocks.Sources.RealExpression realExpression3[4](y=hex.ele[:].mas.T) + annotation (Placement(transformation(extent={{52,-124},{72,-104}}))); + Modelica.Blocks.Interfaces.RealOutput hexele1masT "Value of Real output" + annotation (Placement(transformation(extent={{92,-108},{112,-88}}))); + Modelica.Blocks.Interfaces.RealOutput hexele2masT "Value of Real output" + annotation (Placement(transformation(extent={{92,-118},{112,-98}}))); + Modelica.Blocks.Interfaces.RealOutput hexele3masT "Value of Real output" + annotation (Placement(transformation(extent={{92,-128},{112,-108}}))); + Modelica.Blocks.Interfaces.RealOutput hexele4masT "Value of Real output" + annotation (Placement(transformation(extent={{92,-138},{112,-118}}))); + Modelica.Blocks.Interfaces.RealOutput supplyTemp "Temperature in port medium" + annotation (Placement(transformation(extent={{126,88},{146,108}}))); + Modelica.Blocks.Interfaces.RealInput valveOpening "Input signal connector" + annotation (Placement(transformation(extent={{-160,-70},{-120,-30}}))); + Modelica.Blocks.Sources.Constant x(k=0.007) annotation (Placement( + transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={-130,66}))); + Modelica.Blocks.Sources.Constant mflow(k=0.35) annotation (Placement( + transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={-100,100}))); + Modelica.Blocks.Interfaces.RealInput inflowTemp + "Prescribed fluid temperature" + annotation (Placement(transformation(extent={{-160,0},{-120,40}}))); + Modelica.Thermal.HeatTransfer.Celsius.ToKelvin toKelvin annotation ( + Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={-84,20}))); + Modelica.Thermal.HeatTransfer.Celsius.FromKelvin + fromKelvin + annotation ( + Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={82,98}))); +equation + connect(toTotAir.XiTotalAir, IntakeAirSource.X_in[1]) + annotation (Line(points={{-89,66},{-62,66}}, color={0,0,127})); + connect(toTotAir.XNonVapor, IntakeAirSource.X_in[2]) annotation (Line(points= + {{-89,62},{-82,62},{-82,66},{-62,66}}, color={0,0,127})); + connect(IntakeAirSource.ports[1], hex.port_a2) + annotation (Line(points={{-40,70},{-12,70}}, color={0,127,255})); + connect(hex.port_b2, IntakeAirSink.ports[1]) + annotation (Line(points={{8,70},{100,70}}, color={0,127,255})); + connect(realExpression3[1].y, hexele1masT) annotation (Line(points={{73,-114}, + {84,-114},{84,-98},{102,-98}}, color={0,0,127})); + connect(realExpression3[2].y, hexele2masT) annotation (Line(points={{73,-114}, + {84,-114},{84,-108},{102,-108}}, color={0,0,127})); + connect(realExpression3[3].y, hexele3masT) annotation (Line(points={{73,-114}, + {82,-114},{82,-118},{102,-118}}, color={0,0,127})); + connect(realExpression3[4].y, hexele4masT) annotation (Line(points={{73,-114}, + {84,-114},{84,-128},{102,-128}}, color={0,0,127})); + connect(hex.port_b2, supplyAirTemperature.port) annotation (Line(points={{8, + 70},{26,70},{26,88},{42,88}}, color={0,127,255})); + connect(convertCommand.u, valveOpening) + annotation (Line(points={{-103.2,-50},{-140,-50}}, color={0,0,127})); + connect(toTotAir.XiDry, x.y) + annotation (Line(points={{-111,66},{-119,66}}, color={0,0,127})); + connect(mflow.y, IntakeAirSource.m_flow_in) annotation (Line(points={{-89,100}, + {-74,100},{-74,78},{-60,78}}, color={0,0,127})); + connect(inflowTemp, toKelvin.Celsius) + annotation (Line(points={{-140,20},{-96,20}}, color={0,0,127})); + connect(toKelvin.Kelvin, IntakeAirSource.T_in) annotation (Line(points={{-73, + 20},{-70,20},{-70,74},{-62,74}}, color={0,0,127})); + connect(supplyAirTemperature.T, fromKelvin.Kelvin) + annotation (Line(points={{49,98},{70,98}}, color={0,0,127})); + connect(fromKelvin.Celsius, supplyTemp) + annotation (Line(points={{93,98},{136,98}}, color={0,0,127})); + annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false)), + experiment(StopTime=3600, Interval=10)); +end HeaterML; diff --git a/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/HumidifierML.mo b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/HumidifierML.mo new file mode 100644 index 0000000..4c7906f --- /dev/null +++ b/pyDMPC/ModelicaModels/ModelicaModels/SubsystemModels/DetailedModels/HumidifierML.mo @@ -0,0 +1,164 @@ +within ModelicaModels.SubsystemModels.DetailedModels; +model HumidifierML + "Detailed model of the humidifier for machine learning" + + + replaceable package MediumAir = + AixLib.Media.Air; + replaceable package MediumWater = AixLib.Media.Water; + + Modelica.Fluid.Sources.MassFlowSource_T IntakeAirSource( + m_flow=0.5, + redeclare package Medium = MediumAir, + X={0.03,0.97}, + T=30 + 273.15, + use_X_in=true, + use_T_in=true, + use_m_flow_in=true, + nPorts=1) + annotation (Placement(transformation(extent={{-60,60},{-40,80}}))); + Modelica.Fluid.Sources.Boundary_pT IntakeAirSink( + redeclare package Medium = MediumAir, + use_T_in=false, + use_X_in=false, + use_p_in=false, + p(displayUnit="Pa") = 101300, + nPorts=1) + annotation (Placement(transformation(extent={{120,60},{100,80}}))); + AixLib.Utilities.Psychrometrics.ToTotalAir toTotAir + annotation (Placement(transformation(extent={{-110,56},{-90,76}}))); + AixLib.Fluid.Sensors.Temperature supplyAirTemperature(redeclare package + Medium = MediumAir) "Temperature of supply air" + annotation (Placement(transformation(extent={{32,88},{52,108}}))); + Modelica.Blocks.Interfaces.RealOutput supplyTemp "Temperature in port medium" + annotation (Placement(transformation(extent={{126,88},{146,108}}))); + Modelica.Blocks.Interfaces.RealInput valveOpening "Input signal connector" + annotation (Placement(transformation(extent={{-160,-70},{-120,-30}}))); + Modelica.Blocks.Sources.Constant x(k=0.007) annotation (Placement( + transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={-130,66}))); + Modelica.Blocks.Sources.Constant mflow(k=0.35) annotation (Placement( + transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={-100,100}))); + Modelica.Blocks.Interfaces.RealInput inflowTemp + "Prescribed fluid temperature" + annotation (Placement(transformation(extent={{-160,0},{-120,40}}))); + Modelica.Thermal.HeatTransfer.Celsius.ToKelvin toKelvin annotation ( + Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={-84,20}))); + Modelica.Thermal.HeatTransfer.Celsius.FromKelvin + fromKelvin + annotation ( + Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=180, + origin={82,98}))); + AixLib.Fluid.MixingVolumes.MixingVolume vol( + redeclare package Medium = MediumAir, + m_flow_nominal=0.5, + V=0.1, + nPorts=4) + annotation (Placement(transformation(extent={{-10,74},{10,94}}))); + Modelica.Fluid.Sources.MassFlowSource_T SteamSource( + m_flow=0.5, + redeclare package Medium = MediumAir, + use_m_flow_in=true, + use_X_in=false, + T=100 + 273.15, + X={0.99,0.01}, + use_T_in=true, + nPorts=1) + annotation (Placement(transformation( + extent={{-10,-10},{10,10}}, + rotation=180, + origin={12,-24}))); + Modelica.Blocks.Tables.CombiTable1D HumidifierCharacteristics( + tableOnFile=false, table=[0,0; 1,0.012]) annotation (Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=0, + origin={92,-14}))); + Modelica.Blocks.Sources.Constant SteamFlowNominal(k=0.2) annotation ( + Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=0, + origin={92,-50}))); + Modelica.Blocks.Math.Product product3 + annotation (Placement(transformation(extent={{-10,-10},{10,10}}, + rotation=180, + origin={52,-44}))); + Modelica.Blocks.Sources.Constant steamTemperature(k=100 + 273.15) + annotation (Placement(transformation( + extent={{10,-10},{-10,10}}, + rotation=0, + origin={52,-4}))); + Modelica.Blocks.Sources.RealExpression realExpression3[4](each y=vol.heatPort.T) + annotation (Placement(transformation(extent={{62,-114},{82,-94}}))); + Modelica.Blocks.Interfaces.RealOutput hexele1masT "Value of Real output" + annotation (Placement(transformation(extent={{102,-98},{122,-78}}))); + Modelica.Blocks.Interfaces.RealOutput hexele2masT "Value of Real output" + annotation (Placement(transformation(extent={{102,-108},{122,-88}}))); + Modelica.Blocks.Interfaces.RealOutput hexele3masT "Value of Real output" + annotation (Placement(transformation(extent={{102,-118},{122,-98}}))); + Modelica.Blocks.Interfaces.RealOutput hexele4masT "Value of Real output" + annotation (Placement(transformation(extent={{102,-128},{122,-108}}))); +equation + connect(toTotAir.XiTotalAir, IntakeAirSource.X_in[1]) + annotation (Line(points={{-89,66},{-62,66}}, color={0,0,127})); + connect(toTotAir.XNonVapor, IntakeAirSource.X_in[2]) annotation (Line(points= + {{-89,62},{-82,62},{-82,66},{-62,66}}, color={0,0,127})); + connect(toTotAir.XiDry, x.y) + annotation (Line(points={{-111,66},{-119,66}}, color={0,0,127})); + connect(mflow.y, IntakeAirSource.m_flow_in) annotation (Line(points={{-89,100}, + {-74,100},{-74,78},{-60,78}}, color={0,0,127})); + connect(inflowTemp, toKelvin.Celsius) + annotation (Line(points={{-140,20},{-96,20}}, color={0,0,127})); + connect(toKelvin.Kelvin, IntakeAirSource.T_in) annotation (Line(points={{-73, + 20},{-70,20},{-70,74},{-62,74}}, color={0,0,127})); + connect(supplyAirTemperature.T, fromKelvin.Kelvin) + annotation (Line(points={{49,98},{70,98}}, color={0,0,127})); + connect(fromKelvin.Celsius, supplyTemp) + annotation (Line(points={{93,98},{136,98}}, color={0,0,127})); + connect(HumidifierCharacteristics.y[1],product3. u2) annotation (Line( + points={{81,-14},{72,-14},{72,-38},{64,-38}}, + color={0,0,127}, + smooth=Smooth.None)); + connect(SteamFlowNominal.y,product3. u1) annotation (Line( + points={{81,-50},{64,-50}}, + color={0,0,127}, + smooth=Smooth.None)); + connect(product3.y,SteamSource. m_flow_in) annotation (Line( + points={{41,-44},{32,-44},{32,-32},{22,-32}}, + color={0,0,127}, + smooth=Smooth.None)); + connect(steamTemperature.y,SteamSource. T_in) + annotation (Line(points={{41,-4},{32,-4},{32,-28},{24,-28}}, + color={0,0,127})); + connect(vol.ports[1], IntakeAirSink.ports[1]) annotation (Line(points={{-3,74}, + {-3,74},{60,74},{60,70},{100,70}}, color={0,127,255})); + connect(SteamSource.ports[1], vol.ports[2]) + annotation (Line(points={{2,-24},{2,74},{-1,74}}, color={0,127,255})); + connect(IntakeAirSource.ports[1], vol.ports[3]) annotation (Line(points={{-40, + 70},{-22,70},{-22,74},{1,74}}, color={0,127,255})); + connect(supplyAirTemperature.port, vol.ports[4]) + annotation (Line(points={{42,88},{42,74},{3,74}}, color={0,127,255})); + connect(valveOpening, HumidifierCharacteristics.u[1]) annotation (Line(points= + {{-140,-50},{-86,-50},{24,-50},{24,-74},{118,-74},{118,-14},{104,-14}}, + color={0,0,127})); + connect(realExpression3[1].y,hexele1masT) annotation (Line(points={{83,-104}, + {94,-104},{94,-88},{112,-88}}, color={0,0,127})); + connect(realExpression3[2].y,hexele2masT) annotation (Line(points={{83,-104}, + {94,-104},{94,-98},{112,-98}}, color={0,0,127})); + connect(realExpression3[3].y,hexele3masT) annotation (Line(points={{83,-104}, + {92,-104},{92,-108},{112,-108}}, color={0,0,127})); + connect(realExpression3[4].y,hexele4masT) annotation (Line(points={{83,-104}, + {94,-104},{94,-118},{112,-118}}, color={0,0,127})); + annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram( + coordinateSystem(preserveAspectRatio=false)), + experiment(StopTime=3600, Interval=10)); +end HumidifierML; diff --git a/pyDMPC/Utilities/mlp_train_modelica.py b/pyDMPC/Utilities/mlp_train_modelica.py new file mode 100644 index 0000000..947e1e6 --- /dev/null +++ b/pyDMPC/Utilities/mlp_train_modelica.py @@ -0,0 +1,121 @@ +from sklearn.neural_network import MLPClassifier, MLPRegressor +from sklearn.preprocessing import StandardScaler +import numpy as np +from pyfmi import load_fmu +import random +from joblib import dump, load + +def main(): + + command = [] # The manipulated variable in the model + T_cur = [] # The current inflow temperature + T_prev = [] # The inflow temperature in the previous time step + + """ The metal temperatures in the previous time step""" + T_met_prev_1 = [] + T_met_prev_2 = [] + T_met_prev_3 = [] + T_met_prev_4 = [] + + """ Lists for the training data """ + y_train_1 = [] + y_train_2 = [] + y_train_3 = [] + y_train_4 = [] + y_train_5 = [] + + """ Random inflow temperatures for training """ + T = [2] + + for k in range(49): + T.append(random.uniform(2.0, 45.0)) + + T.append(45) + + """ Simulate the FMU to generate the training data """ + sync_rate = 60 # Synchronisation rate of the FMU + + # Load exisiting FMU + model = load_fmu(r"C:\TEMP\Dymola\ModelicaModels_SubsystemModels_DetailedModels_HumidifierML.fmu") + + """ Initialize the FMU """ + model.set('valveOpening',0) + model.initialize() + model.do_step(0, sync_rate) + time_step = sync_rate + + """ Actual training sequence """ + for k in range(50): + for t in range(100): + """Write random values to the controlled variables""" + if t%120 == 0: + command.append(random.uniform(0.0,100.0)) + else: + command.append(command[-1]) + + model.set('valveOpening',command[-1]) + + """ Write the inflow temperature """ + T_cur.append(T[k]+(T[k+1]-T[k])/1000*t) + if t >= 1: + T_prev.append(T_cur[-2]) + else: + T_prev.append(T_cur[-1]) + + model.set('inflowTemp',T_cur[-1]) + + model.do_step(time_step, sync_rate) + + """ Get the values calculated in the FMU """ + val = model.get("supplyTemp") + y_train_1.append(float(val)) + + val = model.get("hexele1masT") + print(val) + y_train_2.append(float(val)) + val = model.get("hexele2masT") + y_train_3.append(float(val)) + val = model.get("hexele3masT") + y_train_4.append(float(val)) + val = model.get("hexele4masT") + y_train_5.append(float(val)) + + """ Due to the later application, the metal temperature can only + be updated each 60 time steps """ + if t == 0 or t%60 == 0: + T_met_prev_1.append(y_train_2[-1]) + T_met_prev_2.append(y_train_3[-1]) + T_met_prev_3.append(y_train_4[-1]) + T_met_prev_4.append(y_train_5[-1]) + else: + T_met_prev_1.append(T_met_prev_1[-1]) + T_met_prev_2.append(T_met_prev_1[-1]) + T_met_prev_3.append(T_met_prev_1[-1]) + T_met_prev_4.append(T_met_prev_1[-1]) + + time_step += sync_rate + + """ Stack the lists with the relevant training data """ + X_train = np.stack((command,T_cur,T_prev,T_met_prev_1,T_met_prev_2,T_met_prev_3,T_met_prev_4),axis=1) + + """ Scale the training data """ + scaler = StandardScaler() + X_train = scaler.fit_transform(X_train) + print(X_train) + + # Use only the supply temperature as predicted variable + y_train = y_train_1 + + """ Start the regression """ + MLPModel = MLPRegressor(hidden_layer_sizes=(3 ), activation='logistic', solver='lbfgs', alpha=0.0001, batch_size ="auto", + learning_rate= 'constant', learning_rate_init=0.001, power_t=0.5, max_iter=2000, shuffle=True, random_state=None, + tol=0.0001, verbose=True, warm_start=False, momentum=0.9, nesterovs_momentum=True, early_stopping=False, + validation_fraction=0.1, beta_1=0.9, beta_2=0.999, epsilon=1e-08) + + MLPModel.fit(X_train, y_train) + + """ Save the model and the scaler for later use """ + dump(MLPModel, r"C:\TEMP\Dymola\Steam_humidifier.joblib") + dump(scaler, r"C:\TEMP\Dymola\Steam_humidifier_scaler.joblib") + +if __name__=="__main__": main()