{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Documentation for the creation and usage of the heatpump library (hplib)\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import hplib as hpl\n",
    "import hplib_database as db\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import warnings\n",
    "warnings.filterwarnings(\"ignore\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Defintions\n",
    "\n",
    "**Abbreviations**\n",
    "\n",
    "| Abbreviation | Meaning |\n",
    "| --- | --- |\n",
    "| P_th | Thermal output power in W |\n",
    "| P_el | Electical input Power in W |\n",
    "| COP | Coefficient of performance |\n",
    "| T_in | Input temperature in °C at primary side of the heat pump |\n",
    "| T_out | Output temperature in °C at secondary side of the heat pump |\n",
    "| T_amb | Ambient temperature in °C |\n",
    "| P_th_ref | Thermal output power in W at T_in = -7 °C and T_out = 52 °C |\n",
    "| P_el_ref | Elecrical output power in W at T_in = -7 °C and T_out = 52 °C |\n",
    "| COP_ref | Coefficient of performance at T_in = -7 °C and T_out = 52 °C |\n",
    "| p1-p4 | Fit-Parameters for Fit-Function |\n",
    "\n",
    "\n",
    "**Group IDs**\n",
    "\n",
    "| Group ID | Type | Subtype |\n",
    "| --- | --- | --- |\n",
    "| 1 | Outdoor Air / Water | Regulated | \n",
    "| 2 | Brine / Water | Regulated | \n",
    "| 3 | Water / Water | Regulated | \n",
    "| 4 | Outdoor Air / Water | On-Off | \n",
    "| 5 | Brine / Water | On-Off | \n",
    "| 6 | Water / Water | On-Off | "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Database Preparation\n",
    "1. we downloaded all manufacturer data from https://keymark.eu/en/products/heatpumps/certified-products\n",
    "2. then we unzipped the files and used the bash-skript to convert pdf into txt\n",
    "3. afterwards we used this following functions to create and extent the heatpump keymark database"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import keymark data and save to csv database\n",
    "db.import_keymark_data()\n",
    "# -> this creates /output/database_keymark.csv)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Reduce to climate measurement series with average climate, delete redundant entries and save to csv sub-database\n",
    "db.reduce_keymark_data('database_keymark.csv','average')\n",
    "# -> this creates /output/database_keymark_average.csv)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Normalize electrical and thermal power from the keymark database to values from setpoint T_in = -7 °C and T_out = 52 °C\n",
    "db.normalize_keymark_data('database_keymark_average.csv')\n",
    "# -> this creates /output/database_keymark_average_normalized.csv)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Identify subtypes like on-off or regulated heat pump and assign group depending on its type and subtype\n",
    "db.identify_subtypes('database_keymark_average_normalized.csv')\n",
    "# -> this creates /output/database_keymark_average_normalized_subtypes.csv)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Calculate parameters p1-p4 for P_th, P_el and COP\n",
    "db.calculate_function_parameters('database_keymark_average_normalized_subtypes.csv')\n",
    "# -> this creates the final hplib_database.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Many heat pump models have several entries because of different controller or storage configurations. Reduce to unique heat pump models.\n",
    "db.reduce_to_unique()\n",
    "# -> this overwrites the hplib_database.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#calculate the relative error for each point of every heat pump\n",
    "db.validation_relative_error()\n",
    "# -> this creates /output/database_keymark_average_normalized_subtypes_validation.csv)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#calculate the mean absolute percentage error (MAPE) for every heat pump\n",
    "db.validation_mape()\n",
    "# -> this overwrites the hplib_database.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Calculate generic heat pump models for each group\n",
    "db.add_generic()\n",
    "# -> this overwrites the hplib_database.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Usage for simulation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Have a look into the hplib database\n",
    "database = hpl.load_database()\n",
    "database"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Manufacturer</th>\n",
       "      <th>Model</th>\n",
       "      <th>MAPE_COP</th>\n",
       "      <th>MAPE_P_el</th>\n",
       "      <th>MAPE_P_th</th>\n",
       "      <th>P_th_ref [W]</th>\n",
       "      <th>P_el_ref [W]</th>\n",
       "      <th>COP_ref</th>\n",
       "      <th>Group</th>\n",
       "      <th>p1_P_th [1/°C]</th>\n",
       "      <th>...</th>\n",
       "      <th>p3_P_th [-]</th>\n",
       "      <th>p4_P_th [1/°C]</th>\n",
       "      <th>p1_P_el [1/°C]</th>\n",
       "      <th>p2_P_el [1/°C]</th>\n",
       "      <th>p3_P_el [-]</th>\n",
       "      <th>p4_P_el [1/°C]</th>\n",
       "      <th>p1_COP [-]</th>\n",
       "      <th>p2_COP [-]</th>\n",
       "      <th>p3_COP [-]</th>\n",
       "      <th>p4_COP [-]</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Advantix</td>\n",
       "      <td>i-SHWAK V4 06</td>\n",
       "      <td>9.244852</td>\n",
       "      <td>22.607658</td>\n",
       "      <td>24.897666</td>\n",
       "      <td>4500.0</td>\n",
       "      <td>2866.0</td>\n",
       "      <td>1.57</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.756924</td>\n",
       "      <td>...</td>\n",
       "      <td>1.284505</td>\n",
       "      <td>-1.780462</td>\n",
       "      <td>255.166152</td>\n",
       "      <td>0.012686</td>\n",
       "      <td>-0.051998</td>\n",
       "      <td>-255.216376</td>\n",
       "      <td>-40.360701</td>\n",
       "      <td>-0.042594</td>\n",
       "      <td>4.862192</td>\n",
       "      <td>40.502338</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>1 rows × 21 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "  Manufacturer          Model  MAPE_COP  MAPE_P_el  MAPE_P_th  P_th_ref [W]  \\\n",
       "0    Advantix   i-SHWAK V4 06  9.244852  22.607658  24.897666        4500.0   \n",
       "\n",
       "   P_el_ref [W]  COP_ref  Group  p1_P_th [1/°C]  ...  p3_P_th [-]  \\\n",
       "0        2866.0     1.57    1.0        1.756924  ...     1.284505   \n",
       "\n",
       "   p4_P_th [1/°C]  p1_P_el [1/°C]  p2_P_el [1/°C]  p3_P_el [-]  \\\n",
       "0       -1.780462      255.166152        0.012686    -0.051998   \n",
       "\n",
       "   p4_P_el [1/°C]  p1_COP [-]  p2_COP [-]  p3_COP [-]  p4_COP [-]  \n",
       "0     -255.216376  -40.360701   -0.042594    4.862192   40.502338  \n",
       "\n",
       "[1 rows x 21 columns]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Define a specific heatpump model and get parameters\n",
    "parameters = hpl.get_parameters('i-SHWAK V4 06')\n",
    "parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Manufacturer</th>\n",
       "      <th>Model</th>\n",
       "      <th>MAPE_COP</th>\n",
       "      <th>MAPE_P_el</th>\n",
       "      <th>MAPE_P_th</th>\n",
       "      <th>P_th_ref [W]</th>\n",
       "      <th>P_el_ref [W]</th>\n",
       "      <th>COP_ref</th>\n",
       "      <th>Group</th>\n",
       "      <th>p1_P_th [1/°C]</th>\n",
       "      <th>...</th>\n",
       "      <th>p3_P_th [-]</th>\n",
       "      <th>p4_P_th [1/°C]</th>\n",
       "      <th>p1_P_el [1/°C]</th>\n",
       "      <th>p2_P_el [1/°C]</th>\n",
       "      <th>p3_P_el [-]</th>\n",
       "      <th>p4_P_el [1/°C]</th>\n",
       "      <th>p1_COP [-]</th>\n",
       "      <th>p2_COP [-]</th>\n",
       "      <th>p3_COP [-]</th>\n",
       "      <th>p4_COP [-]</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Generic</td>\n",
       "      <td>Generic</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>8635.797427</td>\n",
       "      <td>2880.693817</td>\n",
       "      <td>2.997819</td>\n",
       "      <td>2.0</td>\n",
       "      <td>0.002986</td>\n",
       "      <td>...</td>\n",
       "      <td>0.88439</td>\n",
       "      <td>-0.036931</td>\n",
       "      <td>-0.013036</td>\n",
       "      <td>0.013036</td>\n",
       "      <td>0.069821</td>\n",
       "      <td>-0.034154</td>\n",
       "      <td>0.098565</td>\n",
       "      <td>-0.098565</td>\n",
       "      <td>8.122413</td>\n",
       "      <td>-0.000109</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>1 rows × 21 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "  Manufacturer    Model  MAPE_COP  MAPE_P_el  MAPE_P_th  P_th_ref [W]  \\\n",
       "1      Generic  Generic       NaN        NaN        NaN   8635.797427   \n",
       "\n",
       "   P_el_ref [W]   COP_ref  Group  p1_P_th [1/°C]  ...  p3_P_th [-]  \\\n",
       "1   2880.693817  2.997819    2.0        0.002986  ...      0.88439   \n",
       "\n",
       "   p4_P_th [1/°C]  p1_P_el [1/°C]  p2_P_el [1/°C]  p3_P_el [-]  \\\n",
       "1       -0.036931       -0.013036        0.013036     0.069821   \n",
       "\n",
       "   p4_P_el [1/°C]  p1_COP [-]  p2_COP [-]  p3_COP [-]  p4_COP [-]  \n",
       "1       -0.034154    0.098565   -0.098565    8.122413   -0.000109  \n",
       "\n",
       "[1 rows x 21 columns]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Alternatively, define a \"Generic\" heatpump model and get parameters\n",
    "# For every Group ID there is a parameter set which represents an average heat pump of its group\n",
    "# Please define the Type \"Generic\", the Group ID (1-6) and p_th in W at given primary input\n",
    "# (t_in) and secondary output temperature (t_out) in °C.\n",
    "parameters = hpl.get_parameters(model='Generic', group_id=2, t_in=0, t_out=40, p_th=10000)\n",
    "parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "P_th: 10000 W\n",
      "P_el: 2392 W\n",
      "COP: 4.181\n",
      "T_out: 40 °C\n",
      "m_dot: 0.476 kg/s\n"
     ]
    }
   ],
   "source": [
    "# Simulate one time step\n",
    "# Please define primary input temperature (t_in_primary), secondary input temperature (t_in_secondary)\n",
    "# in °C and the parameters from the previous step. The t_in_secondary is supposed to be heated up by\n",
    "# 5 K which then results in output temperature (t_out). For a time series create a loop with the function.\n",
    "P_th, P_el, COP, T_out, m_dot = hpl.simulate(t_in_primary=0, t_in_secondary=35, parameters=parameters, t_amb=-7)\n",
    "print('P_th: '+str(int(P_th))+' W')\n",
    "print('P_el: '+str(int(P_el))+' W')\n",
    "print('COP: '+str(round(COP,3)))\n",
    "print('T_out: '+str(round(T_out,1))+' °C')\n",
    "print('m_dot: '+str(round(m_dot,3))+' kg/s')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Very important:** With the Fit-Parameters p1-p4 for P_th, P_el and COP it is possible to calculate the results with the following methods:\n",
    "\n",
    "1. P_th and P_el with Fit-Functions and `COP = P_th / P_el` or\n",
    "2. P_th and COP with Fit-Functions and `P_el = P_th / COP` or\n",
    "3. P_el and COP with Fut-Functions and `P_th = P_el * COP`\n",
    "\n",
    "While the model by Schwarmberger et. al. uses the 1. method, our validation showed, that the 3. method leads to better results. Therefore we decided to implement this in the `simulate` definition."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Examples"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Schematic plotting** of COP, P_el and P_th for an generic air/water heat pump: subtype = **On-Off** "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<bound method Figure.show of <Figure size 432x288 with 2 Axes>>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 25068 characters]",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 29740 characters]",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 35852 characters]",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Define Temperatures\n",
    "T_in_primary = range(-20, 31) # air temperatur\n",
    "T_in_secondary = range(20,56) # e.g. temperature from hot water storage\n",
    "\n",
    "# Load parameters of Generic Air/Water, On-Off\n",
    "parameters = hpl.get_parameters('Generic', group_id=4, t_in=-7, t_out=52, p_th = 10000)\n",
    "\n",
    "# Simulate \n",
    "names = ['T_in_primary','P_th', 'P_el', 'COP', 'T_out', 'm_dot']\n",
    "data = []\n",
    "\n",
    "for t1 in T_in_primary:\n",
    "    for t2 in T_in_secondary:\n",
    "        P_th, P_el, COP, T_out, m_dot = hpl.simulate(t1, t2, parameters, t1)\n",
    "        data.append([t1, P_th, P_el, COP, T_out, m_dot])\n",
    "\n",
    "results = pd.DataFrame(data, columns=names)\n",
    "\n",
    "# Plot COP\n",
    "fig1, ax1 = plt.subplots()\n",
    "plot = plt.tricontourf(results['T_in_primary'], results['T_out'], results['COP'])\n",
    "ax1.tricontour(results['T_in_primary'], results['T_out'], results['COP'], colors='k')\n",
    "fig1.colorbar(plot)\n",
    "ax1.set_title('COP')\n",
    "ax1.set_xlabel('Primary input temperature [°C]')\n",
    "ax1.set_ylabel('Secondary output temperature [°C]')\n",
    "fig1.show\n",
    "\n",
    "# Plot electrical input power\n",
    "fig1, ax1 = plt.subplots()\n",
    "plot = plt.tricontourf(results['T_in_primary'], results['T_out'], results['P_el'])\n",
    "ax1.tricontour(results['T_in_primary'], results['T_out'], results['P_el'], colors='k')\n",
    "fig1.colorbar(plot)\n",
    "ax1.set_title('Eletrical input power [W]')\n",
    "ax1.set_xlabel('Primary input temperature [°C]')\n",
    "ax1.set_ylabel('Secondary output temperature [°C]')\n",
    "fig1.show\n",
    "\n",
    "# Plot thermal output power\n",
    "fig1, ax1 = plt.subplots()\n",
    "plot = plt.tricontourf(results['T_in_primary'], results['T_out'], results['P_th'])\n",
    "ax1.tricontour(results['T_in_primary'], results['T_out'], results['P_th'], colors='k')\n",
    "fig1.colorbar(plot)\n",
    "ax1.set_title('Thermal output power [W]')\n",
    "ax1.set_xlabel('Primary input temperature [°C]')\n",
    "ax1.set_ylabel('Secondary output temperature [°C]')\n",
    "fig1.show"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Validation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Validation Data as Box-Plots"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.read_csv('../output/database_keymark_average_normalized_subtypes_validation.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "RE_COP     12.076421\n",
       "RE_P_el    19.456381\n",
       "RE_P_th    23.522196\n",
       "dtype: float64"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 14392 characters]",
      "text/plain": [
       "<Figure size 720x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot results for Group 1 (Air/Water, Regulated)\n",
    "Group = 1\n",
    "data = df.loc[(df['Group']==Group)]\n",
    "data = data[['T_amb [°C]','RE_COP', 'RE_P_el', 'RE_P_th']]\n",
    "ax = data.boxplot(by='T_amb [°C]', layout=(1,3), figsize=(10,5), showfliers=False)\n",
    "ax[0].set_ylim(-60,60)\n",
    "ax[0].set_ylabel('relative error in %')\n",
    "data.abs().mean()[1:4] # mean absolute percentage error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "RE_COP      4.228648\n",
       "RE_P_el    17.650300\n",
       "RE_P_th    19.737515\n",
       "dtype: float64"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 13928 characters]",
      "text/plain": [
       "<Figure size 720x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot results for Group 2 (Brine/Water, Regulated)\n",
    "Group = 2\n",
    "data = df.loc[(df['Group']==Group)]\n",
    "data = data[['T_amb [°C]','RE_COP', 'RE_P_el', 'RE_P_th']]\n",
    "ax = data.boxplot(by='T_amb [°C]', layout=(1,3), figsize=(10,5), showfliers=False)\n",
    "ax[0].set_ylim(-60,60)\n",
    "ax[0].set_ylabel('relative error')\n",
    "data.abs().mean()[1:4] # mean relative error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "RE_COP     5.404139\n",
       "RE_P_el    2.525073\n",
       "RE_P_th    5.806641\n",
       "dtype: float64"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 13704 characters]",
      "text/plain": [
       "<Figure size 720x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot results for Group 4 (Air/Water, On-Off)\n",
    "Group = 4\n",
    "data = df.loc[(df['Group']==Group)]\n",
    "data = data[['T_amb [°C]','RE_COP', 'RE_P_el', 'RE_P_th']]\n",
    "ax = data.boxplot(by='T_amb [°C]', layout=(1,3), figsize=(10,5), showfliers=False)\n",
    "ax[0].set_ylim(-60,60)\n",
    "ax[0].set_ylabel('relative error')\n",
    "data.abs().mean()[1:4] # mean relative error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "RE_COP     3.897897\n",
       "RE_P_el    1.678427\n",
       "RE_P_th    2.668440\n",
       "dtype: float64"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 13568 characters]",
      "text/plain": [
       "<Figure size 720x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot results for Group 5 (Brine/Water, On-Off)\n",
    "Group = 5\n",
    "data = df.loc[(df['Group']==Group)]\n",
    "data = data[['T_amb [°C]','RE_COP', 'RE_P_el', 'RE_P_th']]\n",
    "ax = data.boxplot(by='T_amb [°C]', layout=(1,3), figsize=(10,5), showfliers=False)\n",
    "ax[0].set_ylim(-60,60)\n",
    "ax[0].set_ylabel('relative error')\n",
    "data.abs().mean()[1:4] # mean relative error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "RE_COP     1.563460\n",
       "RE_P_el    1.582038\n",
       "RE_P_th    2.415430\n",
       "dtype: float64"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 13464 characters]",
      "text/plain": [
       "<Figure size 720x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot results for Group 6 (Water/Water, On-Off)\n",
    "Group = 6\n",
    "data = df.loc[(df['Group']==Group)]\n",
    "data = data[['T_amb [°C]','RE_COP', 'RE_P_el', 'RE_P_th']]\n",
    "ax = data.boxplot(by='T_amb [°C]', layout=(1,3), figsize=(10,5), showfliers=False)\n",
    "ax[0].set_ylim(-60,60)\n",
    "ax[0].set_ylabel('relative error')\n",
    "data.abs().mean()[1:4] # mean relative error"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Validation-Data as Scatter-Plots"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.0, 50000.0)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 76220 characters]",
      "text/plain": [
       "<Figure size 1080x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot results for Group 1: Air/Water | Regulated\n",
    "Group = 1\n",
    "fig, ax = plt.subplots(1,3)\n",
    "data = df.loc[(df['Group']==Group)]\n",
    "data.plot.scatter(ax=ax[0], x='COP',y='COP_sim', alpha=0.3, figsize=(12,5), grid=True, title='Coefficient of performance')\n",
    "data.plot.scatter(ax=ax[1], x='P_el [W]',y='P_el_sim', alpha=0.1, figsize=(15,5), grid=True, title='Electrical input power [W]')\n",
    "data.plot.scatter(ax=ax[2], x='P_th [W]',y='P_th_sim', alpha=0.1, figsize=(15,5), grid=True, title='Thermal output power [W]')\n",
    "ax[0].set_xlim(0,10)\n",
    "ax[0].set_ylim(0,10)\n",
    "ax[1].set_xlim(0,20000)\n",
    "ax[1].set_ylim(0,20000)\n",
    "ax[2].set_xlim(0,50000)\n",
    "ax[2].set_ylim(0,50000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.0, 50000.0)"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 59748 characters]",
      "text/plain": [
       "<Figure size 1080x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot results for Group 2: Brine/Water | Regulated\n",
    "Group = 2\n",
    "fig, ax = plt.subplots(1,3)\n",
    "data = df.loc[(df['Group']==Group)]\n",
    "data.plot.scatter(ax=ax[0], x='COP',y='COP_sim', alpha=0.3, figsize=(12,5), grid=True, title='Coefficient of performance')\n",
    "data.plot.scatter(ax=ax[1], x='P_el [W]',y='P_el_sim', alpha=0.3, figsize=(15,5), grid=True, title='Electrical input power [W]')\n",
    "data.plot.scatter(ax=ax[2], x='P_th [W]',y='P_th_sim', alpha=0.3, figsize=(15,5), grid=True, title='Thermal output power [W]')\n",
    "ax[0].set_xlim(0,10)\n",
    "ax[0].set_ylim(0,10)\n",
    "ax[1].set_xlim(0,20000)\n",
    "ax[1].set_ylim(0,20000)\n",
    "ax[2].set_xlim(0,50000)\n",
    "ax[2].set_ylim(0,50000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.0, 50000.0)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 45664 characters]",
      "text/plain": [
       "<Figure size 1080x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot results for Group 4: Air/Water | On-Off\n",
    "Group = 4\n",
    "fig, ax = plt.subplots(1,3)\n",
    "data = df.loc[(df['Group']==Group)]\n",
    "data.plot.scatter(ax=ax[0], x='COP',y='COP_sim', alpha=0.3, figsize=(12,5), grid=True, title='Coefficient of performance')\n",
    "data.plot.scatter(ax=ax[1], x='P_el [W]',y='P_el_sim', alpha=0.3, figsize=(15,5), grid=True, title='Electrical input power [W]')\n",
    "data.plot.scatter(ax=ax[2], x='P_th [W]',y='P_th_sim', alpha=0.3, figsize=(15,5), grid=True, title='Thermal output power [W]')\n",
    "ax[0].set_xlim(0,10)\n",
    "ax[0].set_ylim(0,10)\n",
    "ax[1].set_xlim(0,20000)\n",
    "ax[1].set_ylim(0,20000)\n",
    "ax[2].set_xlim(0,50000)\n",
    "ax[2].set_ylim(0,50000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.0, 50000.0)"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 48268 characters]",
      "text/plain": [
       "<Figure size 1080x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot results for Group 5: Brine/Water | On-Off\n",
    "Group = 5\n",
    "fig, ax = plt.subplots(1,3)\n",
    "data = df.loc[(df['Group']==Group)]\n",
    "data.plot.scatter(ax=ax[0], x='COP',y='COP_sim', alpha=0.3, figsize=(12,5), grid=True, title='Coefficient of performance')\n",
    "data.plot.scatter(ax=ax[1], x='P_el [W]',y='P_el_sim', alpha=0.3, figsize=(15,5), grid=True, title='Electrical input power [W]')\n",
    "data.plot.scatter(ax=ax[2], x='P_th [W]',y='P_th_sim', alpha=0.3, figsize=(15,5), grid=True, title='Thermal output power [W]')\n",
    "ax[0].set_xlim(0,10)\n",
    "ax[0].set_ylim(0,10)\n",
    "ax[1].set_xlim(0,20000)\n",
    "ax[1].set_ylim(0,20000)\n",
    "ax[2].set_xlim(0,50000)\n",
    "ax[2].set_ylim(0,50000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.0, 50000.0)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 36568 characters]",
      "text/plain": [
       "<Figure size 1080x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot results for Group 6: Water/Water | On-Off\n",
    "Group = 6\n",
    "fig, ax = plt.subplots(1,3)\n",
    "data = df.loc[(df['Group']==Group)]\n",
    "data.plot.scatter(ax=ax[0], x='COP',y='COP_sim', alpha=0.3, figsize=(15,5), grid=True, title='Coefficient of performance')\n",
    "data.plot.scatter(ax=ax[1], x='P_el [W]',y='P_el_sim', alpha=0.3, figsize=(15,5), grid=True, title='Electrical input power [W]')\n",
    "data.plot.scatter(ax=ax[2], x='P_th [W]',y='P_th_sim', alpha=0.3, figsize=(15,5), grid=True, title='Thermal output power [W]')\n",
    "ax[0].set_xlim(0,10)\n",
    "ax[0].set_ylim(0,10)\n",
    "ax[1].set_xlim(0,20000)\n",
    "ax[1].set_ylim(0,20000)\n",
    "ax[2].set_xlim(0,50000)\n",
    "ax[2].set_ylim(0,50000)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion\n",
    "- On/Off heat pumps can be simulated very well (mean relative error < 6 %)\n",
    "- Regulated heat pumps show relative mean errors about 20 %, because of the non-linearity of electrical input power and COP regarding different primary / secondary temperatures\n",
    "- Despite of that, generic heat pumps should work well, because the median shows only a small relative error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "1c4c526e93e8287540b24b192ade22dda43c6f2790b410e79d9bb5a13eace6d2"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
