{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "f7d9993f",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"QUICK-PDE - Une fonction Qiskit par ColibriTD\"\n",
        "description: \"La fonction QUICK-PDE résout des équations différentielles partielles spécifiques à un domaine à l'aide de l'algorithme H-DES d' ColibriTD's, qui permet de résoudre des problèmes multiphysiques complexes.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore CMAES, Hypoelastic, edgecolor, royalblue, rstride, cstride, colibritd, xlabel, ylabel, zlabel, Jaffali, Pressureless, Colorplot, viridis, fontsize, fontweight */}\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2f87f5f0",
      "metadata": {},
      "source": [
        "<span id=\"quick-pde-a-qiskit-function-by-colibritd\" />\n",
        "\n",
        "# QUICK-PDE : une fonction Qiskit par l' ColibriTD\n",
        "\n",
        "*Consultez la [documentation de l'API](/docs/api/functions/colibritd-pde)*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9cd91354",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "01701579",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\">\n",
        "  Les fonctions Qiskit sont une fonctionnalité expérimentale disponible pour IBM Quantum® Premium Plan, Flex Plan, et On-Prem (via IBM Quantum Platform API). Elles sont en cours de publication et peuvent être modifiées.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dde95705",
      "metadata": {},
      "source": [
        "<span id=\"overview\" />\n",
        "\n",
        "## Aperçu\n",
        "\n",
        "Le solveur d'équations différentielles partielles (PDE) présenté ici fait partie de notre plateforme Quantum Innovative Computing Kit (QUICK) (QUICK-PDE) et est fourni sous forme de fonction Qiskit. La fonction QUICK-PDE vous permet de résoudre des équations aux dérivées partielles spécifiques à un domaine sur les QPU Quantum IBM. Cette fonction est basée sur l'algorithme décrit dans [le document de description H-DES d' ColibriTD's](https://arxiv.org/abs/2410.01130). Cet algorithme permet de résoudre des problèmes multiphysiques complexes, à commencer par la dynamique des fluides computationnelle (CFD) et la déformation des matériaux (MD), et d'autres cas d'utilisation seront bientôt disponibles.\n",
        "\n",
        "Pour résoudre les équations différentielles, les solutions d'essai sont codées sous forme de combinaisons linéaires de fonctions orthogonales (typiquement des polynômes de Chebyshev, et plus précisément $2^n$ où $n$ est le nombre de qubits codant votre fonction), paramétrées par les angles d'un circuit quantique variable (VQC). L'ansatz génère un état codant la fonction, qui est évalué par des observables dont les combinaisons permettent d'évaluer la fonction en tout point. Vous pouvez ensuite évaluer la fonction de perte dans laquelle les équations différentielles sont encodées, et affiner les angles dans une boucle hybride, comme indiqué ci-dessous. Les solutions expérimentales se rapprochent progressivement des solutions réelles jusqu'à ce que vous obteniez un résultat satisfaisant.\n",
        "\n",
        "![Déroulement de la fonction QUICK-PDE](https://quantum.cloud.ibm.com/docs/images/guides/colibritd-equation-solver/diagram.svg)\n",
        "\n",
        "En plus de cette boucle hybride, vous pouvez également enchaîner différents optimiseurs. Ceci est utile lorsque vous souhaitez qu'un optimiseur global trouve un bon ensemble d'angles, puis qu'un optimiseur plus fin suive un gradient jusqu'au meilleur ensemble d'angles voisins. Dans le cas de la dynamique des fluides (CFD), la séquence d'optimisation par défaut produit les meilleurs résultats - mais dans le cas de la déformation des matériaux (MD), bien que la séquence par défaut fournisse de bons résultats, vous pouvez la configurer davantage pour obtenir des avantages spécifiques au problème.\n",
        "\n",
        "Notez que pour chaque variable de la fonction, nous spécifions le nombre de qubits (avec lequel vous pouvez jouer). En empilant 10 circuits identiques et en évaluant les 10 observables identiques sur différents qubits à travers un grand circuit, vous pouvez atténuer le bruit dans le processus d'optimisation CMA, en vous appuyant sur la méthode d'apprentissage du bruit, et réduire de manière significative le nombre de tirs nécessaires.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "be28949c",
      "metadata": {},
      "source": [
        "<span id=\"computational-fluid-dynamics\" />\n",
        "\n",
        "### Dynamique des fluides computationnelle\n",
        "\n",
        "**L'équation de Burgers pour** les fluides non visqueux modélise l'écoulement de ces fluides comme suit :\n",
        "\n",
        "$\\frac{\\partial u}{\\partial t} + u\\frac{\\partial u}{\\partial x} = 0,$\n",
        "\n",
        "$u$ représente le champ de vitesse du fluide. Ce cas d'utilisation comporte une condition aux limites temporelle : vous pouvez choisir la condition initiale, puis laisser le système se stabiliser. Actuellement, les seules conditions initiales admises sont des fonctions linéaires : $ax + b$. La solution analytique est la suivante :\n",
        "\n",
        "$u(t, x) = \\frac{ax + b}{at + 1}.$\n",
        "\n",
        "**Les équations d'Euler sans pression** modélisent l'écoulement d'un fluide compressible et non visqueux avec amortissement comme suit :\n",
        "\n",
        "$\\frac{\\partial g}{\\partial t} + u\\frac{\\partial g}{\\partial x} + g\\frac{\\partial u}{\\partial x} = 0,$\n",
        "\n",
        "$u\\frac{\\partial g}{\\partial t} + g\\frac{\\partial u}{\\partial t} + u^2\\frac{\\partial g}{\\partial x} + 2gu\\frac{\\partial u}{\\partial x} + \\frac{\\mu}{(1+t)^{\\lambda}} g u = 0,$\n",
        "\n",
        "$g$ représente le champ de densité, $u$ le champ de vitesse et $\\mu$ un coefficient d'amortissement. Dans notre formulation, nous posons $\\lambda = 1$; cette variable ne sera donc pas utilisée comme paramètre dans la suite. Ce cas d'utilisation comporte des conditions aux limites temporelles : $g(0, x) = e^{-x}$ et $u(0, x) = x$. La solution analytique est la suivante :\n",
        "\n",
        "$g(t, x) = \\frac{1-\\mu}{(1+t)^{1-\\mu} - \\mu} \\exp\\!\\left(\\frac{(\\mu-1)\\, x}{(1+t)^{1-\\mu} - \\mu}\\right),$\n",
        "\n",
        "$u(t, x) = \\frac{(1-\\mu)\\, x}{\\left((1+t)^{1-\\mu} - \\mu\\right)(1+t)^{\\mu}}.$\n",
        "\n",
        "Les arguments pour les équations différentielles de la CFD sont sur une grille fixe, comme suit :\n",
        "\n",
        "* $t$ est comprise entre 0 et 0.95 et comporte 41 points d'échantillonnage. $x$ est comprise entre 0 et 0.95 et comporte 41 points d'échantillonnage.\n",
        "\n",
        "<span id=\"material-deformation\" />\n",
        "\n",
        "### Déformation du matériau\n",
        "\n",
        "Ce cas d'utilisation porte sur **la déformation hypoélastique dans le cadre d'un essai de traction unidimensionnel**, au cours duquel une barre fixée dans l'espace est soumise à une traction à son autre extrémité. Nous décrivons le problème comme suit :\n",
        "\n",
        "$u' - \\frac{\\sigma}{3K} - \\frac{2}{\\sqrt{3}}\\epsilon_0\\left(\\frac{\\sigma'}{\\sigma_0\\sqrt{3}}\\right)^n = 0,$\n",
        "\n",
        "$\\sigma' - b = 0,$\n",
        "\n",
        "$K$ représente le module de compressibilité du matériau soumis à un étirement, $n$ l'exposant d'une loi de puissance, $b$ la force par unité de masse, $\\epsilon_0$ la limite de contrainte proportionnelle, $\\sigma_0$ la limite de déformation proportionnelle, $u$ la fonction de contrainte, et $\\sigma$ la fonction de déformation. La solution analytique est la suivante :\n",
        "\n",
        "$\\sigma(x) = \\sigma_0 - bx,$\n",
        "\n",
        "$u(x) = -\\frac{3^{-(3+n)/2}}{2bK(1+n)\\,\\sigma_0^{n}}\\Biggl[3^{(1+n)/2}b^2\\sigma_0^n(1+n)x^2 - 2\\cdot 3^{(1+n)/2}b\\sigma_0^n(1+n)\\sigma_0 x - 12\\epsilon_0 K\\sigma_0^{1+n}$\n",
        "$- 12b\\epsilon_0 K\\sigma_0^n x\\left(\\frac{-bx+\\sigma_0}{\\sigma_0}\\right)^n + 12\\epsilon_0 K\\sigma_0^{n+1}\\left(\\frac{-bx+\\sigma_0}{\\sigma_0}\\right)^n - 12\\epsilon_0 K \\sigma_0^{1+n}\\Biggr],$\n",
        "\n",
        "où $\\sigma_0 = g(0)$ correspond à la condition aux limites relative à la déformation au niveau de $x=0$.\n",
        "\n",
        "La barre considérée est de longueur unitaire. Ce cas d'utilisation a une condition limite pour la contrainte de surface $t$, ou la quantité de travail nécessaire pour étirer la barre.\n",
        "\n",
        "Les arguments pour les équations différentielles de MD sont sur une grille fixe, comme suit :\n",
        "\n",
        "* $x$ est comprise entre 0 et 1 et comporte 30 points d'échantillonnage.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b34fe075",
      "metadata": {},
      "source": [
        "<span id=\"benchmarks\" />\n",
        "\n",
        "## Tests de performances\n",
        "\n",
        "Le tableau suivant présente des statistiques sur les différents parcours de notre fonction.\n",
        "\n",
        "| Exemple                            | Nombre de qubits | Initialisation        | Erreur    | Temps total (en minutes) | Durée d'utilisation (min) |\n",
        "| ---------------------------------- | ---------------- | --------------------- | --------- | ------------------------ | ------------------------- |\n",
        "| Équation de Burgers inviscide      | 50               | `PHYSICALLY_INFORMED` | $10^{-2}$ | 66                       | 25                        |\n",
        "| Équations d'Euler sans pression    | 70               | `PHYSICALLY_INFORMED` | $10^{-2}$ | 48                       | 34                        |\n",
        "| Essai de traction hypoélastique 1D | 18               | `RANDOM`              | $10^{-2}$ | 123                      | 100                       |\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "73390a19",
      "metadata": {},
      "source": [
        "<span id=\"get-started\" />\n",
        "\n",
        "## Premiers pas\n",
        "\n",
        "Remplissez le [formulaire pour demander l'accès à la fonction QUICK-PDE](https://forms.cloud.microsoft/e/3Wi9cbjQPK). Ensuite, en partant du principe que vous avez déjà [enregistré votre compte](/docs/guides/functions-get-started#install-qiskit-functions-catalog-client) dans votre environnement local, sélectionnez la fonction comme suit :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "95a715d2",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "\n",
        "catalog = QiskitFunctionsCatalog(\n",
        "    channel=\"ibm_cloud / ibm_quantum_platform\",\n",
        "    instance=\"USER_CRN / HGP\",\n",
        "    token=\"USER_API_KEY / IQP_API_TOKEN\",\n",
        ")\n",
        "\n",
        "catalog = QiskitFunctionsCatalog(channel=\"ibm_quantum_platform\")\n",
        "\n",
        "# Verify that you have access to the function\n",
        "catalog.list()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "4ec04623",
      "metadata": {},
      "outputs": [],
      "source": [
        "quick = catalog.load(\"colibritd/quick-pde\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e8837f5f",
      "metadata": {},
      "source": [
        "<span id=\"examples\" />\n",
        "\n",
        "## Exemples\n",
        "\n",
        "Pour commencer, essayez l'un des exemples suivants :\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "446ac943",
      "metadata": {},
      "source": [
        "<span id=\"inviscid-burgers-equation-cfd\" />\n",
        "\n",
        "### Équation d'Inviscid Burgers (CFD)\n",
        "\n",
        "Pour l'équation de Burgers, lorsque les conditions initiales sont définies comme suit : $u(0,x) = x$, les résultats sont les suivants :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "d56e1440",
      "metadata": {},
      "outputs": [],
      "source": [
        "# launch the simulation with initial conditions u(0,x) = a*x + b\n",
        "job = quick.run(\n",
        "    use_case=\"CFD_BURGER\", physical_parameters={\"a\": 1.0, \"b\": 0.0}\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "03998691",
      "metadata": {},
      "source": [
        "Pour vérifier [l'état](/docs/guides/functions-get-started#check-job-status) de votre charge de travail Qiskit Function ou obtenir [les résultats, procédez](/docs/guides/functions-get-started#retrieve-results) comme suit :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "856fe992",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Print the ID so you can use it later, if necessary\n",
        "print(job.job_id)\n",
        "print(job.status())\n",
        "solution = job.result()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "c42aba9b",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "import matplotlib.pyplot as plt\n",
        "\n",
        "\n",
        "def plot_result_3d(result):\n",
        "    fig = plt.figure()\n",
        "    ax = fig.add_subplot(projection=\"3d\")\n",
        "\n",
        "    t, x = np.meshgrid(result[\"samples\"][\"t\"], result[\"samples\"][\"x\"])\n",
        "\n",
        "    ax.plot_surface(\n",
        "        t,\n",
        "        x,\n",
        "        result[\"functions\"][\"u\"],\n",
        "        edgecolor=\"royalblue\",\n",
        "        lw=0.25,\n",
        "        rstride=26,\n",
        "        cstride=26,\n",
        "        alpha=0.3,\n",
        "    )\n",
        "    ax.scatter(t, x, result[\"functions\"][\"u\"], marker=\".\")\n",
        "    ax.set(xlabel=\"t\", ylabel=\"x\", zlabel=\"u(t,x)\")\n",
        "\n",
        "    plt.show()\n",
        "\n",
        "\n",
        "# Call\n",
        "plot_result_3d(solution)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4408d52e",
      "metadata": {},
      "source": [
        "<span id=\"pressureless-eulers-equation-cfd\" />\n",
        "\n",
        "### Équation d'Euler sans pression (CFD)\n",
        "\n",
        "Pour l'équation d'Euler, lorsque les conditions initiales sont définies comme suit : $g(0, x) = e^{-x}$ et $u(0, x) = x$, pour une valeur donnée de $\\mu$ (ici, $\\mu = 0.1$ ) et $\\lambda = 1$, les résultats sont les suivants :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "e0412513",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Launches the solving for an arbitrary mu\n",
        "job = quick.run(use_case=\"CFD_EULER\", physical_parameters={\"mu\": 0.1})\n",
        "\n",
        "solution = job.result()\n",
        "\n",
        "\n",
        "# Colorplot function\n",
        "def plot_result_2d(result):\n",
        "    fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n",
        "\n",
        "    configs = {\n",
        "        \"g\": {\"cmap\": \"viridis\", \"title\": \"g(t, x)\"},\n",
        "        \"u\": {\"cmap\": \"plasma\", \"title\": \"u(t, x)\"},\n",
        "    }\n",
        "\n",
        "    t = result[\"samples\"][\"t\"]\n",
        "    x = result[\"samples\"][\"x\"]\n",
        "\n",
        "    for ax, (field, cfg) in zip(axes, configs.items()):\n",
        "        v = result[\"functions\"][field]\n",
        "\n",
        "        im = ax.contourf(t, x, v, levels=50, cmap=cfg[\"cmap\"])\n",
        "        fig.colorbar(im, ax=ax, label=cfg[\"title\"])\n",
        "\n",
        "        ax.set_xlabel(\"t\")\n",
        "        ax.set_ylabel(\"x\")\n",
        "        ax.set_title(cfg[\"title\"], fontsize=13, fontweight=\"bold\")\n",
        "\n",
        "    plt.tight_layout()\n",
        "    plt.show()\n",
        "\n",
        "\n",
        "plot_result_2d(solution)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dbbd4509",
      "metadata": {},
      "source": [
        "<span id=\"material-deformation\" />\n",
        "\n",
        "### Déformation du matériau\n",
        "\n",
        "Le cas d'utilisation de la déformation des matériaux nécessite les paramètres physiques de votre matériau et la force appliquée, comme suit :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a568e325",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Select the properties of your material\n",
        "job = quick.run(\n",
        "    use_case=\"MD\",\n",
        "    physical_parameters={\n",
        "        \"t\": 12.0,\n",
        "        \"K\": 100.0,\n",
        "        \"n\": 4.0,\n",
        "        \"b\": 10.0,\n",
        "        \"epsilon_0\": 0.1,\n",
        "        \"sigma_0\": 5.0,\n",
        "    },\n",
        ")\n",
        "\n",
        "# Plot the result\n",
        "solution = job.result()\n",
        "\n",
        "_ = plt.figure()\n",
        "stress_plot = plt.subplot(211)\n",
        "plt.plot(solution[\"samples\"][\"x\"], solution[\"functions\"][\"u\"])\n",
        "strain_plot = plt.subplot(212)\n",
        "plt.plot(solution[\"samples\"][\"x\"], solution[\"functions\"][\"sigma\"])\n",
        "\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f1cfa869",
      "metadata": {},
      "source": [
        "Voici un exemple illustrant comment obtenir la valeur de la fonction pour un ensemble de coordonnées donné :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "c5193114",
      "metadata": {},
      "outputs": [],
      "source": [
        "# u(t=0.2, x=0.7) == 2\n",
        "assert solution[\"samples\"][\"t\"][1] == 0.2\n",
        "assert solution[\"samples\"][\"x\"][2] == 0.7\n",
        "assert solution[\"functions\"][\"u\"][1, 2] == 2"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "04236c83",
      "metadata": {},
      "source": [
        "<span id=\"fetch-error-messages\" />\n",
        "\n",
        "## Récupérer les messages d'erreur\n",
        "\n",
        "Si l'état de votre charge de travail est `ERROR`, utilisez `job.error_message()` pour récupérer le message d'erreur afin de faciliter le débogage, comme suit :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "90c6de7c",
      "metadata": {},
      "outputs": [],
      "source": [
        "job = quick.run(use_case=\"MD\", physical_params={})\n",
        "\n",
        "print(job.error_message())\n",
        "\n",
        "\n",
        "# A wrapper can also be used for a more human readable version\n",
        "def pprint_error(job):\n",
        "    print(\"\".join(eval(job.error_message())[\"error\"]))\n",
        "\n",
        "\n",
        "print(\"___\")\n",
        "pprint_error(job)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e9ec2e67",
      "metadata": {},
      "source": [
        "<span id=\"get-support\" />\n",
        "\n",
        "## Obtenir de l'aide\n",
        "\n",
        "Pour obtenir de l'aide, contactez [qiskit-function-support@colibritd.com](mailto:qiskit-function-support@colibritd.com).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5a6a25c8",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Etapes suivantes\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recommandations\">\n",
        "  * Remplissez le formulaire pour [demander l'accès à la fonction QUICK-PDE](https://forms.cloud.microsoft/e/3Wi9cbjQPK).\n",
        "  * Consultez [la documentation de l'API](/docs/api/functions/colibritd-pde) relative à cette fonction Qiskit.\n",
        "  * Essayez de modéliser un fluide non visqueux en utilisant QUICK-PDE dans le [tutoriel](/docs/tutorials/colibritd-pde).\n",
        "  * Critique [Jaffali, H., et al. (2025).  H-DES : un solveur d'équations différentielles hybride quantique-classique. arXiv prépublication arXiv:2410.01130](https://arxiv.org/abs/2410.01130).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "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"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}