Simple Building Model

This notebooks shows an example of Modelica model that represents a building with only one room. The following image is a schematic diagram of the building model


In [1]:
from pymodelica import compile_fmu
from pyfmi import load_fmu
from pylab import rcParams
rcParams['figure.figsize'] = 14, 8
from matplotlib import pyplot as plt
import numpy as np

Load and compile the model


In [2]:
# Specify Modelica model and model file (.mo or .mop)
model_name = 'SimpleBuilding.Room'
mo_file = '/home/docker/modelica/SimpleBuilding/SimpleBuilding.mo'

# Compile the model and save the return argument, which is the file name of the FMU
my_fmu = compile_fmu(model_name, mo_file)

Load the input file with weather data

The model takes as input weather data such as the outside air temperature and the solar radiation. There are two files

  • San Francisco prototypical weather data for January
  • San Francisco prototypical weather data for June

The data is in CSV format and is loaded in a numpy array with named columns. Please note that the column names of the CSV file match the names of the input of the model.


In [3]:
fname = "/home/docker/modelica/SimpleBuilding/SFO_weather_data_summer.csv"
#fname = "/home/docker/modelica/SimpleBuilding/SFO_weather_data_winter.csv"

with open(fname, "r") as f:
    col_names = f.readlines()[0].rstrip().split(",")
print "Read from file {} the following columns".format(fname)
for c in col_names:
    print " - {}".format(c)

wd = np.loadtxt(fname, skiprows=1, delimiter=",", dtype=[(n, np.float) for n in col_names])


Read from file /home/docker/modelica/SimpleBuilding/SFO_weather_data_summer.csv the following columns
 - time
 - timeOfYear
 - T_dry_bulb
 - T_dew
 - rel_hum
 - ext_hor_rad
 - ext_dir_rad
 - hor_IR_rad
 - hor_rad
 - dir_rad
 - diff_hor_rad
 - wind_dir
 - wind_speed

Load the model and assign the inputs

The model takes the following inputs

  • timeOfYear time of the year, useful for computing the solar incidence angle),
  • T_dry_bulb outside air dry bulb temperature,
  • dir_rad direct solar radiation,
  • diff_hor_rad diffuse horizontal solar radiation

In [4]:
model = load_fmu(my_fmu)

u_traj = np.transpose(np.vstack((wd["time"], wd["timeOfYear"], wd["T_dry_bulb"], wd["dir_rad"], wd["diff_hor_rad"])))
input_object = (['timeOfYear', 'T_dry_bulb','dir_rad', 'diff_hor_rad'], u_traj)

Simulate the model

We can now use JModelica to set the simulation options and run a simulation.


In [5]:
ONE_HOUR = 3600
ONE_DAY = 24*ONE_HOUR
ONE_WEEK = 7*ONE_DAY

# Get/set options
opts = model.simulate_options()
opts["ncp"] = ONE_WEEK / ONE_HOUR
opts["CVode_options"]["atol"] = 1e-6
opts["CVode_options"]["rtol"] = 1e-4
opts["filter"] = ["Tair*", "Troom*", "Twall*", "T_*", "SolRad*", "Q*"]

# Simulate
model.reset()
res = model.simulate(final_time=ONE_WEEK, input=input_object, options=opts)


Final Run Statistics: SimpleBuilding.Room 

 Number of steps                                 : 656
 Number of function evaluations                  : 986
 Number of Jacobian evaluations                  : 15
 Number of function eval. due to Jacobian eval.  : 75
 Number of error test failures                   : 78
 Number of nonlinear iterations                  : 958
 Number of nonlinear convergence failures        : 0
 Number of state function evaluations            : 663
 Number of time events                           : 7

Solver options:

 Solver                   : CVode
 Linear multistep method  : BDF
 Nonlinear solver         : Newton
 Linear solver type       : DENSE
 Maximal order            : 5
 Tolerances (absolute)    : 1e-06
 Tolerances (relative)    : 0.0001

Simulation interval    : 0.0 - 604800.0 seconds.
Elapsed simulation time: 0.132383 seconds.

In [6]:
plt.plot(res["time"]/ONE_DAY, res["Troom"], 'r', label="$T_{room}$")
plt.plot(res["time"]/ONE_DAY, res['T_dry_bulb'], 'b', label="$T_{air}(t)$")
for i in range(4):
    plt.plot(res["time"]/ONE_DAY, res['Twall[{}]'.format(i+1)], 'k', alpha=0.5, label="$T_w^{}(t)$".format(i+1))
plt.xlabel("Time [days]")
plt.ylabel("Temperature [C]")
plt.legend()


Out[6]:
<matplotlib.legend.Legend at 0x7fee290128d0>

In [7]:
plt.plot(res["time"]/ONE_DAY, res["Qcool"], 'b', label="$Q_{cool}$")
plt.plot(res["time"]/ONE_DAY, res["Qheat"], 'r', label="$Q_{heat}$")
plt.xlabel("Time [days]")
plt.ylabel("Heating / Cooling power [W]")
plt.legend()


Out[7]:
<matplotlib.legend.Legend at 0x7fee25e3c1d0>

In [8]:
plt.plot(res["time"]/ONE_DAY, res["SolRadWall"], label="$\dot{Q}_{sun}^{wall}$")
plt.plot(res["time"]/ONE_DAY, res["SolRadWindow"], label="$\dot{Q}_{sun}^{window}$")
plt.xlabel("Time [days]")
plt.ylabel("Solar gains [W]")
plt.legend()


Out[8]:
<matplotlib.legend.Legend at 0x7fee2031abd0>