{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "f7d9993f",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"QUICK-PDE - Una funzione Qiskit di ColibriTD\"\n",
        "description: \"La funzione QUICK-PDE risolve equazioni differenziali parziali specifiche del dominio utilizzando un algoritmo H-DES ( ColibriTD's ), in grado di risolvere complessi problemi multifisici.\"\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: una funzione Qiskit di ColibriTD\n",
        "\n",
        "*Consulta la [documentazione dell'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",
        "  Le funzioni Qiskit sono una funzione sperimentale disponibile per gli utenti di IBM Quantum® Premium Plan, Flex Plan e On-Prem (tramite IBM Quantum Platform API) Plan. Sono in stato di anteprima e sono soggetti a modifiche.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dde95705",
      "metadata": {},
      "source": [
        "<span id=\"overview\" />\n",
        "\n",
        "## Panoramica\n",
        "\n",
        "Il risolutore di equazioni differenziali parziali (PDE) qui presentato fa parte della nostra piattaforma Quantum Innovative Computing Kit (QUICK) (QUICK-PDE) ed è confezionato come funzione Qiskit. Con la funzione QUICK-PDE, è possibile risolvere equazioni differenziali parziali specifiche del dominio sulle QPU IBM Quantum. Questa funzione si basa sull'algoritmo descritto nel [documento descrittivo H-DES](https://arxiv.org/abs/2410.01130) disponibile all'indirizzo ColibriTD's. Questo algoritmo è in grado di risolvere complessi problemi multifisici, a partire dalla fluidodinamica computazionale (CFD) e dalla deformazione dei materiali (MD), con altri casi d'uso in arrivo.\n",
        "\n",
        "Per affrontare le equazioni differenziali, le soluzioni di prova sono codificate come combinazioni lineari di funzioni ortogonali (tipicamente polinomi di Chebyshev, e più precisamente $2^n$ di essi, dove $n$ è il numero di qubit che codificano la funzione), parametrizzate dagli angoli di un Circuito Quantico Variabile (VQC). L'ansatz genera uno stato che codifica la funzione, valutato da osservabili le cui combinazioni permettono di valutare la funzione in tutti i punti. È quindi possibile valutare la funzione di perdita in cui sono codificate le equazioni differenziali e regolare con precisione gli angoli in un ciclo ibrido, come mostrato di seguito. Le soluzioni di prova si avvicinano gradualmente alle soluzioni reali fino a raggiungere un risultato soddisfacente.\n",
        "\n",
        "![Flusso di lavoro della funzione QUICK-PDE](https://quantum.cloud.ibm.com/docs/images/guides/colibritd-equation-solver/diagram.svg)\n",
        "\n",
        "Oltre a questo ciclo ibrido, è possibile concatenare diversi ottimizzatori. Ciò è utile quando si desidera che un ottimizzatore globale trovi un buon insieme di angoli e che un ottimizzatore più preciso segua un gradiente verso il miglior insieme di angoli vicini. Nel caso della fluidodinamica computazionale (CFD), la sequenza di ottimizzazione predefinita produce i risultati migliori; nel caso della deformazione dei materiali (MD), invece, pur fornendo buoni risultati, è possibile configurarla ulteriormente per ottenere vantaggi specifici per il problema.\n",
        "\n",
        "Si noti che per ogni variabile della funzione viene specificato il numero di qubit (con cui si può giocare). Impilando 10 circuiti identici e valutando le 10 osservabili identiche su qubit diversi in un unico grande circuito, è possibile attenuare il rumore all'interno del processo di ottimizzazione CMA, affidandosi al metodo noise learner, e ridurre significativamente il numero di scatti necessari.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "be28949c",
      "metadata": {},
      "source": [
        "<span id=\"computational-fluid-dynamics\" />\n",
        "\n",
        "### Dinamica dei fluidi computazionale\n",
        "\n",
        "**L'equazione di Burgers per** i fluidi non viscosi descrive il flusso di tali fluidi come segue:\n",
        "\n",
        "$\\frac{\\partial u}{\\partial t} + u\\frac{\\partial u}{\\partial x} = 0,$\n",
        "\n",
        "$u$ rappresenta il campo di velocità del fluido. Questo caso d'uso presenta una condizione al contorno temporale: è possibile selezionare la condizione iniziale e poi lasciare che il sistema si stabilizzi. Attualmente, le uniche condizioni iniziali ammesse sono le funzioni lineari: $ax + b$. La soluzione analitica è:\n",
        "\n",
        "$u(t, x) = \\frac{ax + b}{at + 1}.$\n",
        "\n",
        "**Le equazioni di Eulero senza pressione** modellano il flusso di un fluido compressibile e non viscoso con smorzamento come segue:\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$ rappresenta il campo di densità, $u$ il campo di velocità e $\\mu$ un coefficiente di smorzamento. Nella nostra formulazione, definiamo l' $\\lambda = 1$; pertanto, non verrà utilizzata come parametro nel prosieguo. Questo caso d'uso presenta condizioni al contorno temporali: $g(0, x) = e^{-x}$ e $u(0, x) = x$. La soluzione analitica è:\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",
        "Le argomentazioni per le equazioni differenziali della CFD sono su una griglia fissa, come segue:\n",
        "\n",
        "* $t$ è compreso tra 0 e 0.95 con 41 punti di campionamento. $x$ è compreso tra 0 e 0.95 con 41 punti di campionamento.\n",
        "\n",
        "<span id=\"material-deformation\" />\n",
        "\n",
        "### Deformazione del materiale\n",
        "\n",
        "Questo caso d'uso si concentra sulla **deformazione ipoelastica nell'ambito della prova di trazione unidimensionale**, in cui una barra fissata nello spazio viene sottoposta a trazione all'altra estremità. Descriviamo il problema come segue:\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$ rappresenta il modulo di compressibilità del materiale sottoposto a deformazione, $n$ l'esponente di una legge di potenza, $b$ la forza per unità di massa, $\\epsilon_0$ il limite di sollecitazione proporzionale, $\\sigma_0$ il limite di deformazione proporzionale, $u$ la funzione di sollecitazione e $\\sigma$ la funzione di deformazione. La soluzione analitica è:\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",
        "dove $\\sigma_0 = g(0)$ è la condizione al contorno relativa alla deformazione in $x=0$.\n",
        "\n",
        "La barra considerata è di lunghezza unitaria. Questo caso d'uso prevede una condizione al contorno per la sollecitazione superficiale $t$, ovvero la quantità di lavoro necessaria per allungare la barra.\n",
        "\n",
        "Le argomentazioni per le equazioni differenziali di MD sono su una griglia fissa, come segue:\n",
        "\n",
        "* $x$ è compreso tra 0 e 1 con 30 punti di campionamento.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b34fe075",
      "metadata": {},
      "source": [
        "<span id=\"benchmarks\" />\n",
        "\n",
        "## Benchmark\n",
        "\n",
        "La tabella seguente presenta i dati statistici relativi a diverse esecuzioni della nostra funzione.\n",
        "\n",
        "| Esempio                             | Numero di qubit | Inizializzazione      | Errore    | Tempo totale (min) | Utilizzo del tempo di esecuzione (min) |\n",
        "| ----------------------------------- | --------------- | --------------------- | --------- | ------------------ | -------------------------------------- |\n",
        "| Equazione di Burgers inviscida      | 50              | `PHYSICALLY_INFORMED` | $10^{-2}$ | 66                 | 25                                     |\n",
        "| Equazioni di Eulero senza pressione | 70              | `PHYSICALLY_INFORMED` | $10^{-2}$ | 48                 | 34                                     |\n",
        "| Test di trazione ipoelastico 1D     | 18              | `RANDOM`              | $10^{-2}$ | 123                | 100                                    |\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "73390a19",
      "metadata": {},
      "source": [
        "<span id=\"get-started\" />\n",
        "\n",
        "## Introduzione\n",
        "\n",
        "Compila il [modulo per richiedere l'accesso alla funzione QUICK-PDE](https://forms.cloud.microsoft/e/3Wi9cbjQPK). A questo punto, supponendo che tu abbia già [salvato il tuo account](/docs/guides/functions-get-started#install-qiskit-functions-catalog-client) nell'ambiente locale, seleziona la funzione come segue:\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",
        "## Esempi\n",
        "\n",
        "Per iniziare, provate uno dei seguenti esempi:\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "446ac943",
      "metadata": {},
      "source": [
        "<span id=\"inviscid-burgers-equation-cfd\" />\n",
        "\n",
        "### Equazione di Inviscid Burgers (CFD)\n",
        "\n",
        "Per l'equazione di Burgers, quando le condizioni iniziali sono impostate su $u(0,x) = x$, i risultati sono i seguenti:\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": [
        "Per verificare [lo stato](/docs/guides/functions-get-started#check-job-status) del carico di lavoro della funzione Qiskit o per ottenere [i risultati, procedere](/docs/guides/functions-get-started#retrieve-results) come segue:\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",
        "### Equazione di Eulero senza pressione (CFD)\n",
        "\n",
        "Per l'equazione di Eulero, quando le condizioni iniziali sono impostate su $g(0, x) = e^{-x}$ e $u(0, x) = x$, per un dato $\\mu$ (in questo caso, $\\mu = 0.1$ ) e $\\lambda = 1$, i risultati sono i seguenti:\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",
        "### Deformazione del materiale\n",
        "\n",
        "Il caso d'uso della deformazione del materiale richiede i parametri fisici del materiale e la forza applicata, come segue:\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": [
        "Di seguito è riportato un esempio di come ottenere il valore della funzione per un determinato insieme di coordinate:\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",
        "## Recupera i messaggi di errore\n",
        "\n",
        "Se lo stato del carico di lavoro è `ERROR`, usare `job.error_message()` per recuperare il messaggio di errore per aiutare il debug, come segue:\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",
        "## Ottenere supporto\n",
        "\n",
        "Per assistenza, contattare [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",
        "## Passi successivi\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Suggerimenti\">\n",
        "  * Compila il modulo per [richiedere l'accesso alla funzione QUICK-PDE](https://forms.cloud.microsoft/e/3Wi9cbjQPK).\n",
        "  * Consulta la documentazione [di riferimento dell'API](/docs/api/functions/colibritd-pde) relativa a questa funzione di Qiskit.\n",
        "  * Provate a modellare un fluido non viscoso che scorre utilizzando QUICK-PDE nel [tutorial](/docs/tutorials/colibritd-pde).\n",
        "  * Recensione [Jaffali, H., et al. (2025).  H-DES: un risolutore di equazioni differenziali ibrido quantistico-classico. arXiv preprint 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
}