{ "cells": [ { "cell_type": "markdown", "metadata": { "user_expressions": [] }, "source": [ "\n", "\n", "# Simulation models with Python\n", "\n", "*Written by Marc Budinger (INSA Toulouse) and Scott Delbecq (ISAE-SUPAERO), Toulouse, France*" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [], "user_expressions": [] }, "source": [ "### Thermal model of an electric motor\n", "\n", "The thermal model of a motor, **Figure n° 1**, distinguish temperature between\n", "winding and yoke with a 2 bodies model. One can distinguish:\n", "\n", "- heat capacity of the winding: *Cth1*\n", "\n", "- heat capacity of the yoke: *Cth2*\n", "\n", "- the thermal resistance between the winding and the yoke (corresponding to\n", " the electrical insulator): *Rth1*\n", "\n", "- the thermal resistance between the yoke and the ambient air: *Rth2*\n", "\n", "**Figure n° 1 –** *2 bodies thermal model of the motor*\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "user_expressions": [] }, "source": [ "### Modelica or state space model\n", "\n", "A Modelica model such as **Figure 2** could be simulated in Dymola or OpenModelica.\n", "**Figure n° 2** – *Modelica model*\n", "\n", "\n", "To simulate it in Python it is possible to use Functional Mock-up Units ([FMU](https://github.com/modelon-community/PyFMI)) which can be exported by system simulation softwares. \n", "\n", "Here, we propose to use a simple state-space approach using the [scipy](https://scipy.org) package.\n", "\n", "\n", "Recall: the transfert function of the problem can be expressed as \n", "\n", "$Z_{th}=\\frac{\\theta(p)}{P(p)}=R_{th,eq}\\frac{1+T_0p}{1+(T_1+T_2)p+T_1T_2p}$ \n", "with: \n", "- $R_{th,eq}=R_1+R_2$\n", "- $T_0=\\frac{R_1R_2}{R_1+R_2}C_2$\n", "- $T_1+T_2=(R_1+R_2)C_1 + R_2C_2$\n", "- $T_1T_2=R_1C_1R_2C_2$\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from scipy.signal import step\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import pandas as pd\n", "\n", "\n", "def motor_temperature(P, R1, C1, R2, C2, time=np.linspace(0, 200, 100)):\n", " Rtheq = R1 + R2\n", " T0 = R1 * R2 / (R1 + R2) * C2\n", " T1pT2 = (R1 + R2) * C1 + R2 * C2\n", " T1T2 = R1 * C1 * R2 * C2\n", " t, y = step(system=([Rtheq * T0, Rtheq], [T1T2, T1pT2, 1]), T=time)\n", " theta_winding = y * P\n", " d = {\"t\": t, \"theta_winding\": theta_winding}\n", " df = pd.DataFrame(data=d)\n", " return df" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# Parameters\n", "# Losses [W]\n", "P = 100.0\n", "# R1 [K/W]\n", "R1 = 0.3\n", "# C1 [J/K]\n", "C1 = 150.0\n", "# R2 [K/W]\n", "R2 = 0.3\n", "# C2 [J/K]\n", "C2 = 150.0\n", "# Simulation time [s]\n", "t_final = 150.0\n", "\n", "time = np.linspace(0, t_final, 100)\n", "\n", "df = motor_temperature(P, R1, C1, R2, C2, time=time)" ] }, { "cell_type": "markdown", "metadata": { "user_expressions": [] }, "source": [ "We can now access to the simulation results and plot them:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " | t | \n", "theta_winding | \n", "
---|---|---|
0 | \n", "0.000000 | \n", "0.000000 | \n", "
1 | \n", "1.515152 | \n", "0.993470 | \n", "
2 | \n", "3.030303 | \n", "1.955111 | \n", "
3 | \n", "4.545455 | \n", "2.886946 | \n", "
4 | \n", "6.060606 | \n", "3.790832 | \n", "
... | \n", "... | \n", "... | \n", "
95 | \n", "143.939394 | \n", "43.250294 | \n", "
96 | \n", "145.454545 | \n", "43.464381 | \n", "
97 | \n", "146.969697 | \n", "43.675729 | \n", "
98 | \n", "148.484848 | \n", "43.884372 | \n", "
99 | \n", "150.000000 | \n", "44.090345 | \n", "
100 rows × 2 columns
\n", "