{ "cells": [ { "cell_type": "markdown", "id": "3e7fcdb2", "metadata": {}, "source": [ "# Plates and Channels, an MTR Love Story\n", "\n", "In the following example, we will construct a channel and a fuel plate based on IRR-1 (MAMAG) reactor specifications." ] }, { "cell_type": "code", "execution_count": null, "id": "ea8328dd", "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "from matplotlib import rc\n", "\n", "rc(\"font\", family=\"serif\", size=15)\n", "rc(\"savefig\", dpi=600)\n", "rc(\"figure\", figsize=(8, 6))\n", "rc(\"mathtext\", fontset=\"dejavuserif\")\n", "rc(\"lines\", linewidth=3)\n", "\n", "from functools import partial\n", "\n", "from stream.calculations import ChannelAndContacts, Fuel\n", "from stream.calculations.heat_diffusion import Solid\n", "from stream.composition import symmetric_plate_steady_state\n", "from stream.composition.mtr_geometry import symmetric_plate, x_boundaries\n", "from stream.physical_models.heat_transfer_coefficient import (\n", " regime_dependent_q_scb,\n", " spl_htc,\n", " wall_heat_transfer_coeff,\n", ")\n", "from stream.physical_models.pressure_drop import (\n", " friction_factor,\n", " pressure_diff,\n", " rectangular_laminar_correction,\n", ")\n", "from stream.pipe_geometry import EffectivePipe\n", "from stream.substances import light_water\n", "from stream.units import cm, mm\n", "from stream.utilities import cosine_shape" ] }, { "cell_type": "markdown", "id": "c8218451", "metadata": {}, "source": [ "## Entering data for fuel plate modeling\n", "We need to specify the discretization, dimensions and properties of the plate - both fuel and cladding:" ] }, { "cell_type": "code", "execution_count": null, "id": "7ae8baa7", "metadata": {}, "outputs": [], "source": [ "z_N, fuel_N, clad_N = 25, 8, 3\n", "meat_height = 60.4 * cm\n", "meat_width = 63 * mm\n", "meat_depth = 0.51 * mm\n", "clad_depth = 0.38 * mm\n", "clad = Solid(density=2700, specific_heat=900, conductivity=250) # numbers are approximate\n", "fuel = Solid(density=3500, specific_heat=750, conductivity=100) # numbers are approximate" ] }, { "cell_type": "markdown", "id": "6d60625b", "metadata": {}, "source": [ "## Creating a model of the fuel plate\n", "We set the power distribution along the plate to be cosine-shaped in the xz plane, and fixed throughout the depth of the plate and its width (along the x-axis and y-axis):" ] }, { "cell_type": "code", "execution_count": null, "id": "d468ce7f", "metadata": {}, "outputs": [], "source": [ "shape = np.array((z_N, fuel_N + 2 * clad_N))\n", "meat = np.zeros(shape, dtype=bool)\n", "meat[:, clad_N:-clad_N] = True\n", "\n", "materials = np.empty(shape, dtype=object)\n", "materials[meat] = fuel\n", "materials[~meat] = clad\n", "material = Solid.from_array(materials)\n", "\n", "power_shape_in_rod = cosine_shape(np.linspace(0, meat_height, z_N + 1))\n", "dx_meat = np.diff(x_boundaries(clad_N, fuel_N, clad_depth, meat_depth))[clad_N:-clad_N]\n", "area_fraction = dx_meat / meat_depth\n", "plate_power_shape = np.outer(power_shape_in_rod, area_fraction)" ] }, { "cell_type": "markdown", "id": "41cd753d", "metadata": {}, "source": [ "## Defining the fuel plate using the defined values and inputs" ] }, { "cell_type": "code", "execution_count": null, "id": "750fa566", "metadata": {}, "outputs": [], "source": [ "F = Fuel(\n", " z_boundaries=np.linspace(0, meat_height, z_N + 1),\n", " x_boundaries=x_boundaries(clad_N=clad_N, fuel_N=fuel_N, clad_w=clad_depth, meat_w=meat_depth),\n", " material=material,\n", " y_length=meat_width,\n", " meat_indices=meat,\n", " power_shape=plate_power_shape,\n", " name=\"Fuel\",\n", ")" ] }, { "cell_type": "markdown", "id": "5a0579de", "metadata": {}, "source": [ "## Creating a model of the channel\n", "we enter inputs defining the dimensions of the channel (between two already-defined plates, coupled with periodic boundary conditions), and properties of the flow in the channel:" ] }, { "cell_type": "code", "execution_count": null, "id": "11529e24", "metadata": {}, "outputs": [], "source": [ "channel_width = 66.6 * mm\n", "channel_depth = 2.1 * mm\n", "\n", "re_bounds = laminar_re_max, turbulent_re_min = 2500, 4000\n", "a_dp = channel_depth / channel_width\n", "k_R = rectangular_laminar_correction(a_dp)\n", "\n", "comp_friction = friction_factor(\"regime_dependent\", re_bounds=re_bounds, k_R=k_R)\n", "\n", "pressure_diff_func = partial(pressure_diff, f=comp_friction)\n", "\n", "comp_h_spl = spl_htc(\"regime_dependent\", re_bounds=re_bounds, a_dp=a_dp, Lh=meat_height)\n", "comp_scb = partial(regime_dependent_q_scb, re_bounds=re_bounds)\n", "htc = partial(wall_heat_transfer_coeff, h_spl=comp_h_spl, q_scb=comp_scb)" ] }, { "cell_type": "markdown", "id": "6aafbe28", "metadata": {}, "source": [ "## Defining the channel using the defined values and inputs\n", "Notice that for our coupled construction (which we will create in a moment), the `z_N` discretization of both fuel and channel must be the same." ] }, { "cell_type": "code", "execution_count": null, "id": "8d8b98fc", "metadata": {}, "outputs": [], "source": [ "C = ChannelAndContacts(\n", " z_boundaries=np.linspace(0, meat_height, z_N + 1),\n", " fluid=light_water,\n", " pipe=EffectivePipe.rectangular(\n", " length=meat_height,\n", " edge1=channel_depth,\n", " edge2=channel_width,\n", " heated_edge=meat_width,\n", " ),\n", " h_wall_func=htc,\n", " pressure_func=pressure_diff_func,\n", " name=\"Channel\",\n", ")" ] }, { "cell_type": "markdown", "id": "11482912", "metadata": {}, "source": [ "## Coupling Fuel and Channel\n", "\n", "Assuming symmetry, we will construct the fuel and channel as if they envelope each other simultaneously from both sides:" ] }, { "cell_type": "code", "execution_count": null, "id": "a87ed1e6", "metadata": {}, "outputs": [], "source": [ "sys = symmetric_plate(C, F)\n", "from stream.analysis.report import report\n", "\n", "report(sys.to_aggregator())" ] }, { "cell_type": "markdown", "id": "1281edb8-c704-42ff-b3f4-3f48a4724bd7", "metadata": {}, "source": [ "The missing parameters must be provided, as shown below." ] }, { "cell_type": "markdown", "id": "36ff1d06", "metadata": {}, "source": [ "## Let us define some approximate parameters of IRR-1:" ] }, { "cell_type": "code", "execution_count": null, "id": "88901d8d", "metadata": {}, "outputs": [], "source": [ "total_power = 5e6\n", "FA_flow = 17.5 # in m3/h, in one fuel assembly\n", "core_rods = 24 # a typical number\n", "plates_per_rod = 23\n", "plates_in_core = plates_per_rod * core_rods" ] }, { "cell_type": "markdown", "id": "a9b941ce", "metadata": {}, "source": [ "Now, we can run any simulation we want with this coupled system, or compose it into a larger system. Let's say we only wish to know the steady state of this system given some obvious parameters. Easily enough, there's already a function for that in STREAM, which employs `symmetric_plate` internally: " ] }, { "cell_type": "code", "execution_count": null, "id": "1831faa5", "metadata": {}, "outputs": [], "source": [ "state = symmetric_plate_steady_state(\n", " C,\n", " F,\n", " mdot=FA_flow\n", " * (1000 / 3600)\n", " / plates_per_rod, # Coolant mass flow. A positive value indicates downward flow [KgPerS]\n", " p_abs=1.67e5, # Absolute pressure at the top of the channel [Pascal]\n", " power=total_power / plates_in_core, # Total power generated by the fuel plate, averaged for the entire core [Watt]\n", " Tin=35.0, # Inlet coolant temperature [Celsius]\n", ")" ] }, { "cell_type": "markdown", "id": "dc335703", "metadata": {}, "source": [ "Here we will draw the temperature distribution along the channel (z-axis) of the coolant, the cladding and the fuel:" ] }, { "cell_type": "code", "execution_count": null, "id": "74fb20aa", "metadata": { "tags": [] }, "outputs": [], "source": [ "plt.figure()\n", "plt.plot(C.centers, state[C.name][\"T_cool\"], label=\"Coolant\")\n", "plt.plot(C.centers, state[F.name][\"T_wall_right\"])\n", "plt.plot(C.centers, state[F.name][\"T_wall_left\"], label=\"Wall\")\n", "plt.plot(\n", " C.centers,\n", " state[F.name][\"T\"].reshape(F.shape)[:, clad_N + int((fuel_N - 1) / 2)],\n", " label=\"Fuel Center\",\n", ")\n", "plt.xlabel(\"Distance from top [m]\")\n", "plt.ylabel(r\"Temperature [$\\degree$C]\")\n", "plt.legend()\n", "plt.grid()\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "315ff21a", "metadata": {}, "source": [ "And here we will draw a color map of the temperature distribution of the fuel along the channel:" ] }, { "cell_type": "code", "execution_count": null, "id": "5246ee20", "metadata": {}, "outputs": [], "source": [ "plt.figure(figsize=(8, 6))\n", "ax = plt.imshow(state[F.name][\"T\"].reshape(F.shape), cmap=\"jet\")\n", "plt.colorbar(ax, label=\"Fuel Temp. [C]\")\n", "plt.xticks([])\n", "plt.yticks([])\n", "plt.show()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.10.6" } }, "nbformat": 4, "nbformat_minor": 5 }