{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Conjugate Heat Transfer\n",
    "\n",
    "In this example we go over how to set up and perform a Conjugate Heat Transfer (CHT) simulation using Flow360 Python API. CHT is used to predict thermal interaction between a solid body and a fluid domain. We will go through creating a project, defining simulation settings, as well as post-processing results using the report functionality.\n",
    "\n",
    "![CHT mesh](figures/CHT_mesh.png)\n",
    "\n",
    "**Note:** The settings in this example are by no means a validation setup; they are crafted to showcase the capabilities of Flow360 and we have intentionally reduced node count and example FC cost. For rigorous validation, modify the settings as needed."
   ],
   "id": "f1c2a005"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Setup and Imports\n",
    "\n",
    "First, we import the required modules from `flow360` library."
   ],
   "id": "6ab5fdda"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "import flow360 as fl\n",
    "from flow360 import u\n",
    "from flow360.examples import TutorialCHTSolver\n",
    "from flow360.plugins.report.report import ReportTemplate\n",
    "from flow360.plugins.report.report_items import (\n",
    "    Camera,\n",
    "    Chart3D,\n",
    "    FrontCamera,\n",
    "    Inputs,\n",
    "    LeftCamera,\n",
    "    Settings,\n",
    "    Summary,\n",
    ")"
   ],
   "execution_count": 1,
   "outputs": [],
   "id": "2cc68150"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Project Initialization\n",
    "\n",
    "A `Project` in Flow360 acts as a container for simulations and their related data. In this instance, the project is initialized directly from a pre-existing volume mesh file."
   ],
   "id": "f8ee27b5"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "TutorialCHTSolver.get_files()\n",
    "\n",
    "project = fl.Project.from_volume_mesh(\n",
    "    TutorialCHTSolver.mesh_filename, name=\"CHT results from Python\"\n",
    ")\n",
    "\n",
    "volume_mesh = project.volume_mesh"
   ],
   "execution_count": 2,
   "outputs": [
    {
     "output_type": "display_data",
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">[11:11:19] </span><span style=\"color: #008080; text-decoration-color: #008080\">INFO</span>: VolumeMesh successfully submitted:                                                                \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">           </span>        type   = Volume Mesh                                                                            \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">           </span>        name   = CHT results from Python                                                                \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">           </span>        id     = vm-<span style=\"color: #ffff00; text-decoration-color: #ffff00\">8d68a03b-3db8-4913-abe5-e457188fa9ea</span>                                                \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">           </span>        status = uploaded                                                                               \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">           </span>                                                                                                        \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m[11:11:19]\u001b[0m\u001b[2;36m \u001b[0m\u001b[36mINFO\u001b[0m: VolumeMesh successfully submitted:                                                                \n",
       "\u001b[2;36m           \u001b[0m        type   = Volume Mesh                                                                            \n",
       "\u001b[2;36m           \u001b[0m        name   = CHT results from Python                                                                \n",
       "\u001b[2;36m           \u001b[0m        id     = vm-\u001b[93m8d68a03b-3db8-4913-abe5-e457188fa9ea\u001b[0m                                                \n",
       "\u001b[2;36m           \u001b[0m        status = uploaded                                                                               \n",
       "\u001b[2;36m           \u001b[0m                                                                                                        \n"
      ]
     },
     "metadata": {}
    }
   ],
   "id": "575744d8"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Simulation Parameters Definition\n",
    "\n",
    "All parameters for the simulation exist within the `SimulationParams` object. In order to better focus on `Solid` model definition, we will define it a bit further down below.\n",
    "\n",
    "Before that, we need to specify our `Fluid` domain solver settings and boundary conditions, operating condition of our simulation, as well as post-processing information such as reference geometry dimensions and outputs we want to get from the solver."
   ],
   "id": "eead6719"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "with fl.SI_unit_system:\n",
    "    params = fl.SimulationParams(\n",
    "        reference_geometry=fl.ReferenceGeometry(\n",
    "            moment_center=[0, 0, 0] * fl.u.m,\n",
    "            moment_length=[1, 1, 1] * fl.u.m,\n",
    "            area=1 * fl.u.m**2,\n",
    "        ),\n",
    "        operating_condition=fl.AerospaceCondition.from_mach(mach=0.1),\n",
    "        time_stepping=fl.Steady(\n",
    "            max_steps=10000, CFL=fl.RampCFL(initial=1, final=100, ramp_steps=1000)\n",
    "        ),\n",
    "        models=[\n",
    "            fl.Fluid(\n",
    "                navier_stokes_solver=fl.NavierStokesSolver(\n",
    "                    absolute_tolerance=1e-9,\n",
    "                    linear_solver=fl.LinearSolver(max_iterations=35),\n",
    "                    order_of_accuracy=2,\n",
    "                    kappa_MUSCL=-1,\n",
    "                ),\n",
    "                turbulence_model_solver=fl.SpalartAllmaras(\n",
    "                    absolute_tolerance=1e-8,\n",
    "                    linear_solver=fl.LinearSolver(max_iterations=25),\n",
    "                    equation_evaluation_frequency=4,\n",
    "                    order_of_accuracy=2,\n",
    "                ),\n",
    "            ),\n",
    "            fl.Wall(\n",
    "                surfaces=volume_mesh[\"fluid/centerbody\"],\n",
    "            ),\n",
    "            fl.Freestream(\n",
    "                surfaces=volume_mesh[\"fluid/farfield\"],\n",
    "            ),\n",
    "        ],\n",
    "        outputs=[\n",
    "            fl.VolumeOutput(\n",
    "                output_format=[\"paraview\", \"tecplot\"],\n",
    "                output_fields=[\n",
    "                    \"primitiveVars\",\n",
    "                    \"T\",\n",
    "                    \"Cp\",\n",
    "                    \"Mach\",\n",
    "                ],\n",
    "            ),\n",
    "            fl.SurfaceOutput(\n",
    "                surfaces=volume_mesh[\"*\"],\n",
    "                output_format=[\"paraview\", \"tecplot\"],\n",
    "                output_fields=[\"primitiveVars\", \"T\", \"Cp\", \"Cf\", \"CfVec\"],\n",
    "            ),\n",
    "            fl.SliceOutput(\n",
    "                entities=[\n",
    "                    fl.Slice(\n",
    "                        name=\"slice_x\",\n",
    "                        normal=(1, 0, 0),\n",
    "                        origin=(0.35, 0, 0),\n",
    "                    ),\n",
    "                    fl.Slice(\n",
    "                        name=\"slice_y\",\n",
    "                        normal=(0, 1, 0),\n",
    "                        origin=(0, 0, 0),\n",
    "                    ),\n",
    "                ],\n",
    "                output_fields=[\"T\", \"Mach\"],\n",
    "            ),\n",
    "        ],\n",
    "    )"
   ],
   "execution_count": 3,
   "outputs": [
    {
     "output_type": "display_data",
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">[11:11:50] </span><span style=\"color: #008080; text-decoration-color: #008080\">INFO</span>: using: SI unit system for unit inference.                                                         \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m[11:11:50]\u001b[0m\u001b[2;36m \u001b[0m\u001b[36mINFO\u001b[0m: using: SI unit system for unit inference.                                                         \n"
      ]
     },
     "metadata": {}
    }
   ],
   "id": "65c97ba5"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Solid Model\n",
    "\n",
    "The `Solid` model is used in CHT analysis. Its parameters define the thermal behavior of the solid body:\n",
    "- `entities`: Specifies which mesh regions are to be treated as solid. Here, the \"solid\" entity from the volume mesh is selected.\n",
    "- `heat_equation_solver`: Configures the numerical solver for the heat equation within the solid. Parameters such as tolerance and linear solver iterations can be adjusted to control convergence.\n",
    "- `material`: Defines the thermal properties of the solid material. `SolidMaterial` class requires a name and `thermal_conductivity`.\n",
    "- `volumetric_heat_source`: Allows for the specification of an internal heat generation rate within the solid's volume, specified in Watts per cubic meter.\n",
    "\n",
    "For solid surfaces not coupled with the fluid, an adiabatic condition is applied using a `Wall` boundary with a specified zero `HeatFlux`."
   ],
   "id": "c4decba1"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "with fl.SI_unit_system:\n",
    "    models = [\n",
    "        fl.Solid(\n",
    "            entities=volume_mesh[\"solid\"],\n",
    "            heat_equation_solver=fl.HeatEquationSolver(\n",
    "                absolute_tolerance=1e-11,\n",
    "                linear_solver=fl.LinearSolver(\n",
    "                    max_iterations=25,\n",
    "                    absolute_tolerance=1e-12,\n",
    "                ),\n",
    "                equation_evaluation_frequency=10,\n",
    "            ),\n",
    "            material=fl.SolidMaterial(\n",
    "                name=\"copper\",\n",
    "                thermal_conductivity=398 * fl.u.W / (fl.u.m * fl.u.K),\n",
    "            ),\n",
    "            volumetric_heat_source=5e3 * fl.u.W / (0.01257 * fl.u.m**3),\n",
    "        ),\n",
    "        fl.Wall(\n",
    "            surfaces=volume_mesh[\"solid/adiabatic\"],\n",
    "            heat_spec=fl.HeatFlux(0 * fl.u.W / fl.u.m**2),\n",
    "        ),\n",
    "    ]\n",
    "\n",
    "params.models.extend(models)"
   ],
   "execution_count": 4,
   "outputs": [
    {
     "output_type": "display_data",
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">           </span><span style=\"color: #008080; text-decoration-color: #008080\">INFO</span>: using: SI unit system for unit inference.                                                         \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m          \u001b[0m\u001b[2;36m \u001b[0m\u001b[36mINFO\u001b[0m: using: SI unit system for unit inference.                                                         \n"
      ]
     },
     "metadata": {}
    }
   ],
   "id": "479871ae"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. Case Execution\n",
    "\n",
    "We run the simulation by using `project.run_case()`. The script then calls `case.wait()` to wait until the simulation is finished on the Flow360 platform."
   ],
   "id": "5ab12091"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "case = project.run_case(params=params, name=\"CHT case from Python\")\n",
    "\n",
    "case.wait()"
   ],
   "execution_count": 5,
   "outputs": [
    {
     "output_type": "display_data",
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">           </span><span style=\"color: #008080; text-decoration-color: #008080\">INFO</span>: using: SI unit system for unit inference.                                                         \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m          \u001b[0m\u001b[2;36m \u001b[0m\u001b[36mINFO\u001b[0m: using: SI unit system for unit inference.                                                         \n"
      ]
     },
     "metadata": {}
    },
    {
     "output_type": "display_data",
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">[11:11:52] </span><span style=\"color: #008080; text-decoration-color: #008080\">INFO</span>: Successfully submitted:                                                                           \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">           </span>        type   = Case                                                                                   \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">           </span>        name   = CHT case from Python                                                                   \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">           </span>        id     = case-<span style=\"color: #ffff00; text-decoration-color: #ffff00\">a12053be-2867-4159-8e28-1ba088a05062</span>                                              \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">           </span>        status = pending                                                                                \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">           </span>                                                                                                        \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m[11:11:52]\u001b[0m\u001b[2;36m \u001b[0m\u001b[36mINFO\u001b[0m: Successfully submitted:                                                                           \n",
       "\u001b[2;36m           \u001b[0m        type   = Case                                                                                   \n",
       "\u001b[2;36m           \u001b[0m        name   = CHT case from Python                                                                   \n",
       "\u001b[2;36m           \u001b[0m        id     = case-\u001b[93ma12053be-2867-4159-8e28-1ba088a05062\u001b[0m                                              \n",
       "\u001b[2;36m           \u001b[0m        status = pending                                                                                \n",
       "\u001b[2;36m           \u001b[0m                                                                                                        \n"
      ]
     },
     "metadata": {}
    }
   ],
   "id": "9a8b20d0"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. Results Post-Processing\n",
    "\n",
    "Upon completion, results can be accessed via the `case.results` attribute. Various data, such as surface heat transfer, can be retrieved."
   ],
   "id": "41e40b72"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "results = case.results\n",
    "\n",
    "surface_heat_transfer = results.surface_heat_transfer.as_dataframe()\n",
    "print(surface_heat_transfer)"
   ],
   "execution_count": 6,
   "outputs": [
    {
     "output_type": "display_data",
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">[11:20:04] </span><span style=\"color: #008080; text-decoration-color: #008080\">INFO</span>: Saved to                                                                                          \n",
       "<span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">           </span><span style=\"color: #800080; text-decoration-color: #800080\">/var/folders/qk/mywsrvps5gl_f3yjx2k1v1xm0000gn/T/tmprcsk4uyf/</span><span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">c2da6cbc-1e41-4e8e-bdea-ce5549440fcc.csv</span>   \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m[11:20:04]\u001b[0m\u001b[2;36m \u001b[0m\u001b[36mINFO\u001b[0m: Saved to                                                                                          \n",
       "\u001b[2;36m           \u001b[0m\u001b[35m/var/folders/qk/mywsrvps5gl_f3yjx2k1v1xm0000gn/T/tmprcsk4uyf/\u001b[0m\u001b[95mc2da6cbc-1e41-4e8e-bdea-ce5549440fcc.csv\u001b[0m   \n"
      ]
     },
     "metadata": {}
    },
    {
     "output_type": "stream",
     "text": [
      "      physical_step  pseudo_step  fluid/Interface_solid_HeatTransferRate  \\\n",
      "0                 0            0                               -0.000111   \n",
      "1                 0           10                               -0.000144   \n",
      "2                 0           20                               -0.000109   \n",
      "3                 0           30                               -0.000118   \n",
      "4                 0           40                               -0.000105   \n",
      "...             ...          ...                                     ...   \n",
      "996               0         9960                               -0.000074   \n",
      "997               0         9970                               -0.000074   \n",
      "998               0         9980                               -0.000074   \n",
      "999               0         9990                               -0.000074   \n",
      "1000              0         9999                               -0.000074   \n",
      "\n",
      "      fluid/centerbody_HeatTransferRate  totalHeatFlux  \n",
      "0                             -0.000296            0.0  \n",
      "1                             -0.000140            0.0  \n",
      "2                             -0.000096            0.0  \n",
      "3                             -0.000068            0.0  \n",
      "4                             -0.000051            0.0  \n",
      "...                                 ...            ...  \n",
      "996                           -0.000001            0.0  \n",
      "997                           -0.000001            0.0  \n",
      "998                           -0.000001            0.0  \n",
      "999                           -0.000001            0.0  \n",
      "1000                          -0.000001            0.0  \n",
      "\n",
      "[1001 rows x 5 columns]\n"
     ],
     "name": "stdout"
    }
   ],
   "id": "589add76"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Report Preparation\n",
    "\n",
    "Flow360 includes a feature for automated report generation to visualize simulation outcomes. This involves defining cameras for different views and specifying chart objects that determine the content of the report."
   ],
   "id": "0c4ff428"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "cases = [case]\n",
    "\n",
    "exclude = [\"fluid/farfield\", \"solid/interface_fluid\", \"solid/adiabatic\"]\n",
    "\n",
    "front_camera_slice = FrontCamera(dimension=1, dimension_dir=\"width\")\n",
    "side_camera_slice = LeftCamera(pan_target=(0.35, 0, 0), dimension=2, dimension_dir=\"width\")\n",
    "front_right_top_camera = Camera(\n",
    "    position=(-1, -1, 1), look_at=(0.35, 0, 0), dimension=1, dimension_dir=\"width\"\n",
    ")"
   ],
   "execution_count": 7,
   "outputs": [],
   "id": "b1f7aa74"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Report Item Configuration\n",
    "\n",
    "`Chart3D` objects are used to create three-dimensional visualizations of the results. Each chart can be configured to display specific data fields (e.g., temperature `T`) on selected surfaces or slices, with defined contour limits and camera views."
   ],
   "id": "ab4dec40"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "x_slice_screenshot = Chart3D(\n",
    "    section_title=\"Slice temperature at x=0.35\",\n",
    "    items_in_row=2,\n",
    "    force_new_page=True,\n",
    "    show=\"slices\",\n",
    "    include=[\"slice_x\"],\n",
    "    field=\"T\",\n",
    "    limits=(285 * u.K, 395 * u.K),\n",
    "    camera=front_camera_slice,\n",
    "    fig_name=\"slice_x\",\n",
    ")\n",
    "\n",
    "y_slice_screenshot = Chart3D(\n",
    "    section_title=\"Slice temperature at y=0\",\n",
    "    items_in_row=2,\n",
    "    force_new_page=True,\n",
    "    show=\"slices\",\n",
    "    include=[\"slice_y\"],\n",
    "    field=\"T\",\n",
    "    limits=(285 * u.K, 395 * u.K),\n",
    "    camera=side_camera_slice,\n",
    "    fig_name=\"slice_y\",\n",
    ")\n",
    "\n",
    "surface_screenshot = Chart3D(\n",
    "    section_title=\"Surface temperature\",\n",
    "    items_in_row=2,\n",
    "    force_new_page=True,\n",
    "    show=\"boundaries\",\n",
    "    field=\"T\",\n",
    "    limits=(285 * u.K, 395 * u.K),\n",
    "    exclude=exclude,\n",
    "    camera=front_right_top_camera,\n",
    ")"
   ],
   "execution_count": 8,
   "outputs": [],
   "id": "080f7fab"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Report Creation and Download\n",
    "\n",
    "`ReportTemplate` class is where we assemble all the defined charts and summary items into a complete report structure. Then, `create_in_cloud` method initiates the generation process. Once everything is done, a report PDF file will be automatically downloaded"
   ],
   "id": "5066a1dd"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "report = ReportTemplate(\n",
    "    title=\"CHT results screenshots\",\n",
    "    items=[\n",
    "        Summary(),\n",
    "        Inputs(),\n",
    "        x_slice_screenshot,\n",
    "        y_slice_screenshot,\n",
    "        surface_screenshot,\n",
    "    ],\n",
    "    settings=Settings(dpi=150),\n",
    ")\n",
    "report = report.create_in_cloud(\n",
    "    \"CHT, dpi=default\",\n",
    "    cases,\n",
    ")\n",
    "\n",
    "report.wait()\n",
    "report.download(\"report.pdf\")"
   ],
   "execution_count": 9,
   "outputs": [
    {
     "output_type": "display_data",
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7fbfbf; text-decoration-color: #7fbfbf\">[11:21:33] </span><span style=\"color: #008080; text-decoration-color: #008080\">INFO</span>: Saved to report.pdf                                                                               \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2;36m[11:21:33]\u001b[0m\u001b[2;36m \u001b[0m\u001b[36mINFO\u001b[0m: Saved to report.pdf                                                                               \n"
      ]
     },
     "metadata": {}
    },
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": [
       "'report.pdf'"
      ]
     },
     "metadata": {},
     "execution_count": null
    }
   ],
   "id": "feb20529"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "flow360",
   "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.11.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
