{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "f7d9993f",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"QUICK-PDE - Uma função Qiskit por ColibriTD\"\n",
        "description: \"A função QUICK-PDE resolve equações diferenciais parciais específicas do domínio usando um algoritmo H-DES ( ColibriTD's ), que pode resolver problemas multifísicos complexos.\"\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: Uma função Qiskit por ColibriTD\n",
        "\n",
        "*Consulte a [referência da 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",
        "  As funções Qiskit são um recurso experimental disponível para os usuários dos planos IBM Quantum® Premium Plan, Flex Plan e On-Prem (via IBM Quantum Platform API). Eles estão no status de versão prévia e estão sujeitos a alterações.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dde95705",
      "metadata": {},
      "source": [
        "<span id=\"overview\" />\n",
        "\n",
        "## Visão geral\n",
        "\n",
        "O solucionador de equações diferenciais parciais (PDE) apresentado aqui faz parte da nossa plataforma Quantum Innovative Computing Kit (QUICK) (QUICK-PDE) e está empacotado como uma função Qiskit. Com a função QUICK-PDE, é possível resolver equações diferenciais parciais específicas de domínios em QPUs do IBM Quantum. Esta função baseia-se no algoritmo descrito no [documento de descrição H-DES](https://arxiv.org/abs/2410.01130) da ColibriTD's. Este algoritmo pode resolver problemas multifísicos complexos, começando com Dinâmica de Fluidos Computacional (CFD) e Deformação de Materiais (MD), e outros casos de uso em breve.\n",
        "\n",
        "Para lidar com as equações diferenciais, as soluções experimentais são codificadas como combinações lineares de funções ortogonais (normalmente polinômios de Chebyshev e, mais especificamente, $2^n$ deles, em que $n$ é o número de qubits que codificam sua função), parametrizadas pelos ângulos de um circuito quântico variável (VQC). O ansatz gera um estado que codifica a função, que é avaliada por observáveis cujas combinações permitem a avaliação da função em todos os pontos. Em seguida, é possível avaliar a função de perda na qual as equações diferenciais são codificadas e ajustar os ângulos em um loop híbrido, conforme mostrado a seguir. As soluções de teste se aproximam gradualmente das soluções reais até que você chegue a um resultado satisfatório.\n",
        "\n",
        "![Fluxo de trabalho da função QUICK-PDE](https://quantum.cloud.ibm.com/docs/images/guides/colibritd-equation-solver/diagram.svg)\n",
        "\n",
        "Além desse loop híbrido, você também pode encadear diferentes otimizadores. Isso é útil quando você deseja que um otimizador global encontre um bom conjunto de ângulos e, em seguida, um otimizador mais refinado siga um gradiente até o melhor conjunto de ângulos vizinhos. No caso da dinâmica de fluidos computacional (CFD), a sequência de otimização padrão produz os melhores resultados, mas no caso da deformação de materiais (MD), embora o padrão forneça bons resultados, você pode configurá-lo ainda mais para obter benefícios específicos do problema.\n",
        "\n",
        "Observe que, para cada variável da função, especificamos o número de qubits (com o qual você pode brincar). Ao empilhar 10 circuitos idênticos e avaliar os 10 observáveis idênticos em qubits diferentes em um circuito grande, é possível mitigar o ruído no processo de otimização do CMA, contando com o método de aprendizagem de ruído, e reduzir significativamente o número de disparos necessários.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "be28949c",
      "metadata": {},
      "source": [
        "<span id=\"computational-fluid-dynamics\" />\n",
        "\n",
        "### Dinâmica de fluidos computacional\n",
        "\n",
        "**A equação de Burgers para** fluidos não viscosos modela o fluxo desses fluidos da seguinte forma:\n",
        "\n",
        "$\\frac{\\partial u}{\\partial t} + u\\frac{\\partial u}{\\partial x} = 0,$\n",
        "\n",
        "$u$ representa o campo de velocidade do fluido. Este caso de uso possui uma condição de contorno temporal: é possível selecionar a condição inicial e, em seguida, permitir que o sistema se estabilize. Atualmente, as únicas condições iniciais aceitas são funções lineares: $ax + b$. A solução analítica é:\n",
        "\n",
        "$u(t, x) = \\frac{ax + b}{at + 1}.$\n",
        "\n",
        "**As equações de Euler sem pressão** modelam o fluxo de um fluido compressível e não viscoso com amortecimento da seguinte forma:\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$ representa o campo de densidade, $u$ o campo de velocidade e $\\mu$ um coeficiente de amortecimento. Em nossa formulação, definimos $\\lambda = 1$; portanto, ele não será utilizado como parâmetro a seguir. Este caso de uso possui condições de contorno temporais: $g(0, x) = e^{-x}$ e $u(0, x) = x$. A solução analítica é:\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",
        "Os argumentos para as equações diferenciais da CFD estão em uma grade fixa, como segue:\n",
        "\n",
        "* $t$ está entre 0 e 0.95, com 41 pontos de amostragem. $x$ está entre 0 e 0.95, com 41 pontos de amostragem.\n",
        "\n",
        "<span id=\"material-deformation\" />\n",
        "\n",
        "### Deformação do material\n",
        "\n",
        "Este caso de uso se concentra na **deformação hipoelástica por meio do ensaio de tração unidimensional**, no qual uma barra fixada no espaço é submetida a tração em sua outra extremidade. Descrevemos o problema da seguinte forma:\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$ representa o módulo de volume do material que está sendo distendido, $n$ o expoente de uma lei de potência, $b$ a força por unidade de massa, $\\epsilon_0$ o limite de tensão proporcional, $\\sigma_0$ o limite de deformação proporcional, $u$ a função de tensão e $\\sigma$ a função de deformação. A solução analítica é:\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",
        "onde $\\sigma_0 = g(0)$ é a condição de contorno para a deformação em $x=0$.\n",
        "\n",
        "A barra considerada é de comprimento unitário. Esse caso de uso tem uma condição de limite para a tensão superficial $t$, ou a quantidade de trabalho necessária para esticar a barra.\n",
        "\n",
        "Os argumentos para as equações diferenciais do MD estão em uma grade fixa, como segue:\n",
        "\n",
        "* $x$ está entre 0 e 1, com 30 pontos de amostragem.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b34fe075",
      "metadata": {},
      "source": [
        "<span id=\"benchmarks\" />\n",
        "\n",
        "## Referências\n",
        "\n",
        "A tabela a seguir apresenta estatísticas sobre várias execuções de nossa função.\n",
        "\n",
        "| Exemplo                         | Número de qubits | Inicialização         | Erro      | Tempo total (min) | Uso do tempo de execução (min) |\n",
        "| ------------------------------- | ---------------- | --------------------- | --------- | ----------------- | ------------------------------ |\n",
        "| Equação de Burgers invíscida    | 50               | `PHYSICALLY_INFORMED` | $10^{-2}$ | 65                | 25                             |\n",
        "| Equações de Euler sem pressão   | 65               | `PHYSICALLY_INFORMED` | $10^{-2}$ | 48                | 34                             |\n",
        "| Hipoelástico 1D teste de tração | 18               | `RANDOM`              | $10^{-2}$ | 123               | 100                            |\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "73390a19",
      "metadata": {},
      "source": [
        "<span id=\"get-started\" />\n",
        "\n",
        "## Introdução\n",
        "\n",
        "Preencha o [formulário para solicitar acesso à função QUICK-PDE](https://forms.cloud.microsoft/e/3Wi9cbjQPK). Então, supondo que você já tenha [salvo sua conta](/docs/guides/functions-get-started#install-qiskit-functions-catalog-client) no seu ambiente local, selecione a função da seguinte maneira:\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",
        "## Exemplos\n",
        "\n",
        "Para começar, experimente um dos exemplos a seguir:\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "446ac943",
      "metadata": {},
      "source": [
        "<span id=\"inviscid-burgers-equation-cfd\" />\n",
        "\n",
        "### Equação de Burgers para fluidos não viscosos (CFD)\n",
        "\n",
        "Para a equação de Burgers, quando as condições iniciais são definidas como $u(0,x) = x$, os resultados são os seguintes:\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": [
        "Verifique [o status](/docs/guides/functions-get-started#check-job-status) da sua carga de trabalho do Qiskit Function ou obtenha [os resultados](/docs/guides/functions-get-started#retrieve-results) da seguinte maneira:\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",
        "### Equação de Euler sem pressão (CFD)\n",
        "\n",
        "Para a equação de Euler, quando as condições iniciais são definidas como $g(0, x) = e^{-x}$ e $u(0, x) = x$, para um determinado $\\mu$ (aqui, $\\mu = 0.1$ ) e $\\lambda = 1$, os resultados são os seguintes:\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",
        "### Deformação do material\n",
        "\n",
        "O caso de uso de deformação de material requer os parâmetros físicos de seu material e a força aplicada, como 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": [
        "A seguir, apresentamos um exemplo de como obter o valor da função para um conjunto específico de coordenadas:\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",
        "## Buscar mensagens de erro\n",
        "\n",
        "Se o status de sua carga de trabalho for `ERROR`, use `job.error_message()` para obter a mensagem de erro para ajudar na depuração, como 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",
        "## Obtenha suporte\n",
        "\n",
        "Para obter suporte, entre em contato com [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",
        "## Próximas etapas\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendações\">\n",
        "  * Preencha o formulário para [solicitar acesso à função QUICK-PDE](https://forms.cloud.microsoft/e/3Wi9cbjQPK).\n",
        "  * Consulte a [referência da API](/docs/api/functions/colibritd-pde) para esta função do Qiskit.\n",
        "  * Tente modelar um fluido não viscoso em movimento usando o QUICK-PDE no [tutorial](/docs/tutorials/colibritd-pde).\n",
        "  * Revisão [Jaffali, H., et al. (2025).  H-DES: um solucionador híbrido quântico-clássico de equações diferenciais. arXiv pré-impressão 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
}