.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/ex22_solid_body_thermal.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_ex22_solid_body_thermal.py: Thermal Analysis ---------------- .. topic:: Thermal analysis of a simple construction. * use :class:`~felupe.thermal.SolidBodyThermal` and :class:`~felupe.thermal.SolidBodySurfaceHeatTransfer` * evaluate the surface heat flux at internal and external boundaries with a job :class:`~felupe.Plugin` * view the temperature field This example describes a simple two-dimensional light-weight construction system set up with three :class:`solids `. The temperature boundary conditions have a :math:`\pm 1` K sinusoidal variation around their average value with a period of 24 h. .. GENERATED FROM PYTHON SOURCE LINES 21-28 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np import felupe as fem .. GENERATED FROM PYTHON SOURCE LINES 30-32 Define material properties as lists for plasterboard, insulation and wood. This includes mass density, specific heat capacity and thermal conductivity. .. GENERATED FROM PYTHON SOURCE LINES 32-36 .. code-block:: Python density = [1000, 20, 500] # kg/m^3 specific_heat = [1125, 1450, 1600] # J/(kg K) thermal_conductivity = [0.4, 0.035, 0.16] # W/(m K) .. GENERATED FROM PYTHON SOURCE LINES 37-41 Set up one mesh per material. If a material consists of multiple areas, the separate rectangles are collected in a :class:`mesh container ` and are merged into one mesh per material. These meshes per material are then added to a mesh container for the construction. .. GENERATED FROM PYTHON SOURCE LINES 41-73 .. code-block:: Python plasterboard_1 = fem.Rectangle(b=(0.018, 0.47), n=(6, 18)) # bottom left plasterboard_2 = fem.Rectangle(a=(0.0, 0.47), b=(0.018, 0.53), n=(11, 7)) # center left plasterboards = fem.MeshContainer( [ plasterboard_1, # bottom left plasterboard_1.translate(0.268, axis=0), # bottom right plasterboard_1.translate(0.53, axis=1), # top left plasterboard_1.translate(0.268, axis=0).translate(0.53, axis=1), # top right plasterboard_2, # center left plasterboard_2.translate(0.268, axis=0), # center right ], merge=True, ).stack() insulation = fem.Rectangle(a=(0.018, 0), b=(0.268, 0.47), n=(12, 18)) # bottom insulations = fem.MeshContainer( [ insulation, insulation.translate(0.53, axis=1), ], merge=True, ).stack() wood = fem.Rectangle(a=(0.018, 0.47), b=(0.268, 0.53), n=(12, 8)) container = fem.MeshContainer([plasterboards, insulations, wood], merge=True) container.plot( colors=["lightgrey", "khaki", "sepia"], labels=["Plasterboard", "Insulation", "Wood"], show_edges=False, ).show() .. tab-set:: .. tab-item:: Static Scene .. image-sg:: /examples/images/sphx_glr_ex22_solid_body_thermal_001.png :alt: ex22 solid body thermal :srcset: /examples/images/sphx_glr_ex22_solid_body_thermal_001.png :class: sphx-glr-single-img .. tab-item:: Interactive Scene .. offlineviewer:: /home/docs/checkouts/readthedocs.org/user_builds/felupe-ja/checkouts/latest/felupe/docs/examples/images/sphx_glr_ex22_solid_body_thermal_001.vtksz .. GENERATED FROM PYTHON SOURCE LINES 74-78 A top-level temperature field is defined on the whole construction with an initial temperature value of 10 °C, and separate fields are defined for each material. The surface heat transfer coefficients and ambient temperatures are defined for the internal and external boundaries. Thermal solid bodies are created for each material. .. GENERATED FROM PYTHON SOURCE LINES 78-118 .. code-block:: Python regions = [fem.RegionQuad(m) for m in container] fields = [fem.Field(r, dim=1).as_container() for r in regions] # top level temperature field mesh = container.stack() region = fem.RegionQuad(mesh) temperature = fem.Field(region, dim=1, values=10.0) # initial temperature 10 °C field = fem.FieldContainer([temperature]) external_region = fem.RegionQuadBoundary(mesh, mask=mesh.x == mesh.x.min()) external_temperature = fem.Field(external_region, dim=1) external_field = fem.FieldContainer([external_temperature]) internal_region = fem.RegionQuadBoundary(mesh, mask=mesh.x == mesh.x.max()) internal_temperature = fem.Field(internal_region, dim=1) internal_field = fem.FieldContainer([internal_temperature]) external_heat_transfer = fem.thermal.SolidBodySurfaceHeatTransfer( field=external_field, coefficient=25.0, # W/(m^2 K) temperature=0.0, # °C ) internal_heat_transfer = fem.thermal.SolidBodySurfaceHeatTransfer( field=internal_field, coefficient=7.69, # W/(m^2 K) temperature=20.0, # °C ) materials = [] for mfield, rho, cp, k in zip(fields, density, specific_heat, thermal_conductivity): materials.append( fem.thermal.SolidBodyThermal( field=mfield, mass_density=rho, specific_heat_capacity=cp, thermal_conductivity=k, ) ) .. GENERATED FROM PYTHON SOURCE LINES 119-125 A callback-function records the mean surface heat flux at the internal and external boundaries after each completed time step. The mean surface heat flux is calculated by the :meth:`~felupe.thermal.SolidBodyThermal.heat_flux_boundary` method of the thermal solid body, which returns the integrated surface heat flux for a given boundary region and time step. The mean surface heat flux is stored in the ``flux_data`` dictionary, which is passed to the callback function as an argument. .. GENERATED FROM PYTHON SOURCE LINES 125-139 .. code-block:: Python def callback(stepnumber, substepnumber, substep, flux_data): """Save mean surface heat flux at internal and external boundaries.""" heat_flux = materials[0].heat_flux_boundary flux_data["external"].append(heat_flux(region=external_region)) flux_data["internal"].append(heat_flux(region=internal_region)) time_steps = fem.math.linsteps([0, 24 * 3600], num=int(24 * 3600 / 720))[1:] t_ext = 0 + 1 * np.sin(2 * np.pi * time_steps / 86400) t_int = 20 + 1 * np.sin(2 * np.pi * time_steps / 86400) .. GENERATED FROM PYTHON SOURCE LINES 140-147 The time step item is created with the thermal solid bodies. It must be located as the first item in the step to properly update the time step in the materials. The internal and external heat transfer item values are defined in the ramp, which specifies how their values change over time. Finally, a job is created with the step and the callback function, and evaluated with the top-level temperature field. A result file is created for visualization in Paraview, and the temperature field is saved as point- data in the result file. .. GENERATED FROM PYTHON SOURCE LINES 147-170 .. code-block:: Python time = fem.thermal.TimeStep( [*materials, external_heat_transfer, internal_heat_transfer] ) ramp = { time: time_steps, internal_heat_transfer: t_int, external_heat_transfer: t_ext, } step = fem.Step( items=[time, *materials, internal_heat_transfer, external_heat_transfer], ramp=ramp, ) flux_data = {"external": [], "internal": []} job = fem.Job(steps=[step], callback=callback, flux_data=flux_data).evaluate( x0=field, filename="result.xdmf", # create a result file for Paraview point_data={"Temperature": lambda field, substep: temperature.values}, point_data_default=False, cell_data_default=False, ) .. GENERATED FROM PYTHON SOURCE LINES 171-179 Internal and external surface heat flux values are plotted over time. .. note:: The heat flux is **positive** when **heat leaves the construction** (here, on the external surface), and **negative** when **heat enters the construction** (here, on the internal surface). .. GENERATED FROM PYTHON SOURCE LINES 179-194 .. code-block:: Python fig, ax = plt.subplots() ax.plot(time_steps / 3600, flux_data["external"], color="C3", label="external") ax.plot(time_steps / 3600, flux_data["internal"], color="C0", label="internal") tmin, tmax = ax.get_xlim() ax.plot([tmin, tmax], np.zeros(2), "black", lw=0.5) text_kwargs = dict(transform=ax.transAxes, ha="center", va="center") ax.text(0.5, 0.97, "heat leaves construction", **text_kwargs) ax.text(0.5, 0.03, "heat enters construction", **text_kwargs) ax.legend() ax.set(xlim=(tmin, tmax), xlabel="time in h", ylabel=r"surface heat flux in W/m$^2$") .. image-sg:: /examples/images/sphx_glr_ex22_solid_body_thermal_002.png :alt: ex22 solid body thermal :srcset: /examples/images/sphx_glr_ex22_solid_body_thermal_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 195-197 A view on the temperature field at the end of the simulation period visualizes the temperature distribution. .. GENERATED FROM PYTHON SOURCE LINES 197-198 .. code-block:: Python field.plot("Field", scalar_bar_vertical=True).show() .. tab-set:: .. tab-item:: Static Scene .. image-sg:: /examples/images/sphx_glr_ex22_solid_body_thermal_003.png :alt: ex22 solid body thermal :srcset: /examples/images/sphx_glr_ex22_solid_body_thermal_003.png :class: sphx-glr-single-img .. tab-item:: Interactive Scene .. offlineviewer:: /home/docs/checkouts/readthedocs.org/user_builds/felupe-ja/checkouts/latest/felupe/docs/examples/images/sphx_glr_ex22_solid_body_thermal_003.vtksz .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 2.072 seconds) .. _sphx_glr_download_examples_ex22_solid_body_thermal.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: ex22_solid_body_thermal.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: ex22_solid_body_thermal.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: ex22_solid_body_thermal.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_