{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Step 1 : generate $Q$-coefficients\n", "\n", "📜 _We denote by_ $Q$**-coefficients** (or **Butcher table**) _what fully describes a multi-stage time stepping scheme (or Runge-Kutta method):_\n", "\n", "$$\n", "Q\\text{-coefficients : }\n", "\\begin{array}\n", " {c|c}\n", " \\tau & Q \\\\\n", " \\hline\n", " & w^\\top\n", "\\end{array}\n", "\\quad \\Leftrightarrow \\quad\n", "\\begin{array}\n", " {c|c}\n", " c & A \\\\\n", " \\hline\n", " & b^\\top\n", "\\end{array}\n", "\\quad\\text{(Butcher table)}\n", "$$\n", "\n", "_where_ $\\tau$ _are the_ **nodes**, $w$ _the_ **weights** _and_ $Q$ _... well, the_ $Q$ **matrix**.\n", "\n", "There is **two approaches** in `qmat` to generate those coefficients for many time-stepping schemes, from which you can choose depending on your needs and preferences." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Use a generic function\n", "\n", "First, you can simply import the following :" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from qmat import genQCoeffs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then generate $Q$-coefficients like this :" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "node : [0.08858796 0.40946686 0.78765946 1. ]\n", "weights : [0.22046221 0.38819347 0.32884432 0.0625 ]\n", "Q : \n", "[[ 0.11299948 -0.04030922 0.02580238 -0.00990468]\n", " [ 0.234384 0.20689257 -0.04785713 0.01604742]\n", " [ 0.21668178 0.40612326 0.18903652 -0.0241821 ]\n", " [ 0.22046221 0.38819347 0.32884432 0.0625 ]]\n" ] } ], "source": [ "# Coefficients or a collocation method\n", "nodes, weights, Q = genQCoeffs(\"Collocation\", nNodes=4, nodeType=\"LEGENDRE\", quadType=\"RADAU-RIGHT\")\n", "\n", "print(\"node : \", nodes)\n", "print(\"weights : \", weights)\n", "print(\"Q : \")\n", "print(Q)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "c : [0. 0.5 0.5 1. ]\n", "b : [0.16666667 0.33333333 0.33333333 0.16666667]\n", "A : \n", "[[0. 0. 0. 0. ]\n", " [0.5 0. 0. 0. ]\n", " [0. 0.5 0. 0. ]\n", " [0. 0. 1. 0. ]]\n" ] } ], "source": [ "# Coefficients of a Runge-Kutta method (Butcher table)\n", "c, b, A = genQCoeffs(\"RK4\")\n", "\n", "print(\"c : \", c)\n", "print(\"b : \", b)\n", "print(\"A : \")\n", "print(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Depending on its first given argument, `genQCoeffs` uses the associated $Q$-generator,\n", "potentially passing keyword arguments to instantiate.\n", "\n", "> 📜 Checkout the [tutorial on nodes generation](./22_nodes.ipynb) for details about `nodeType` and `quadType`.\n", "\n", "If some generator arguments are missing or wrongly given, then a descriptive error is raised, for instance :" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TypeError: Collocation.__init__() got an unexpected keyword argument 'node_type'. Did you mean 'nodeType'?\n" ] } ], "source": [ "try:\n", " nodes, weights, Q = genQCoeffs(\"Collocation\", nNodes=4, node_type=\"LEGENDRE\", quadType=\"RADAU-RIGHT\")\n", "except Exception as e:\n", " print(f\"{e.__class__.__name__}: {e}\")" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TypeError: Collocation.__init__() missing 1 required positional argument: 'quadType'\n" ] } ], "source": [ "try:\n", " nodes, weights, Q = genQCoeffs(\"Collocation\", nNodes=4, nodeType=\"LEGENDRE\")\n", "except Exception as e:\n", " print(f\"{e.__class__.__name__}: {e}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> 🔔 Note that different aliases exists for each generators. For instance :" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# alias for Collocation\n", "nodes, weights, Q = genQCoeffs(\"coll\", nNodes=4, nodeType=\"LEGENDRE\", quadType=\"RADAU-RIGHT\")\n", "\n", "# alias for RK4\n", "c, b, A = genQCoeffs(\"ERK4\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All those aliases are uniques among $Q$-generators, and if the requested alias does not correspond to any generator, \n", "an appropriate error is raised :" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ValueError: qType='collocation' is not available\n" ] } ], "source": [ "try:\n", " genQCoeffs(\"collocation\")\n", "except Exception as e:\n", " print(f\"{e.__class__.__name__}: {e}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Don't hesitate to look at the [API documentation](../api/qmat/qcoeff/index.html) for a full list of available generators ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Use generator objects\n", "\n", "You can also directly use the generator classes, either by\n", "\n", "- importing the generator directly from its submodule" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "from qmat.qcoeff.collocation import Collocation\n", "coll = Collocation(nNodes=4, nodeType=\"LEGENDRE\", quadType=\"RADAU-RIGHT\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- retrieving it with one of its aliases from the `Q_GENERATORS` dictionary" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "from qmat import Q_GENERATORS\n", "Generator = Q_GENERATORS[\"coll\"]\n", "coll = Generator(nNodes=4, nodeType=\"LEGENDRE\", quadType=\"RADAU-RIGHT\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In both case, you'll instantiate an object that provides properties to access each of the given coefficients :" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "nodes : [0.08858796 0.40946686 0.78765946 1. ]\n", "weights : [0.22046221 0.38819347 0.32884432 0.0625 ]\n", "Q :\n", "[[ 0.11299948 -0.04030922 0.02580238 -0.00990468]\n", " [ 0.234384 0.20689257 -0.04785713 0.01604742]\n", " [ 0.21668178 0.40612326 0.18903652 -0.0241821 ]\n", " [ 0.22046221 0.38819347 0.32884432 0.0625 ]]\n" ] } ], "source": [ "print(\"nodes :\", coll.nodes)\n", "print(\"weights :\", coll.weights)\n", "print(\"Q :\")\n", "print(coll.Q)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "... or a `genCoeffs` **method** providing all coefficients, used similarly as the `genQCoeffs` function :" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "nodes, weights, Q = coll.genCoeffs()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, you can use those coefficients to [build a Runge-Kutta type time-stepper...](./02_rk.ipynb)" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 }