{ "cells": [ { "cell_type": "markdown", "id": "0136f8ef", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-9546f1bdb893cdcd", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "source": [ "## Examen de rattrapage\n", "\n", "- Ce notebook est à soumettre sur Educnet avant 16h15.\n", "\n", "- L’examen comporte trois exercices indépendants. Dans chaque exercice les\n", " cellules peuvent éventuellement dependre des cellules précèdentes.\n", "\n", "- Afin de faciliter l'évaluation de votre code,\n", " ne pas changer les signatures des fonctions à implémenter.\n", "\n", "- La cellulle ci-dessous importe les bibliothèques utilisées dans ce notebook. Si une ou plusieurs d'entre elles manquent sur votre machine, vous êtes invités à les installer au préalable." ] }, { "cell_type": "code", "execution_count": null, "id": "a57b1a8f", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-4d638a879ba6f86e", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "using ForwardDiff\n", "using LaTeXStrings\n", "using LinearAlgebra\n", "using Plots\n", "using Polynomials" ] }, { "cell_type": "markdown", "id": "fe25b04b", "metadata": {}, "source": [ "## [Exercice 1] Interpolation pour l'équation des poutres" ] }, { "cell_type": "markdown", "id": "a9d93a90", "metadata": { "lines_to_next_cell": 2 }, "source": [ "Le but de cet exercice est d'explorer une application de l'interpolation polynomiale à la résolution d'une équation différentielle.\n", "Plus précisément, nous allons mettre en œuvre une méthode numérique pour résoudre approximativement l'équation des poutres d'Euler-Bernoulli avec des conditions aux limites de Dirichlet homogènes :\n", "\n", "$$\n", "u \\in C^4([0,1]), \\qquad \\left\\{ \\begin{aligned} u''''(x) &= \\varphi(x) \\qquad \\forall\\, x \\in (0,1),\\\\\n", "u(0) &= u'(0) = u'(1) = u(1) = 0, \\end{aligned} \\right.\n", "$$\n", "\n", "où $\\varphi(x) = (2\\pi)^4\\cos(2\\pi x)$ est une charge transverse appliquée à la poutre.\n", "Afin de résoudre l'équation numériquement,\n", "nous allons approximer le terme de droite $\\varphi$ par un polynôme interpolant $\\widehat \\varphi$,\n", "puis résoudre l'équation exactement avec $\\widehat \\varphi$ au lieu de $\\varphi$.\n", "\n", "0. Commençons par écrire une fonction `fit_values_and_slopes(u₀, up₀, u₁, up₁)` qui retourne l'unique polynôme de degré 3 tel que\n", " $$\n", " p(0) = u_0, \\qquad p'(0) = up_0, \\qquad p(1) = u_1, \\qquad p'(1) = up_1.\n", " $$" ] }, { "cell_type": "code", "execution_count": null, "id": "94188e2a", "metadata": {}, "outputs": [], "source": [ "function fit_values_and_slopes(u₀, up₀, u₁, up₁)\n", " # We look for polynomials p(x) = a₀ + a₁ x + a₂ x² + a₃ x³\n", " A = [1 0 0 0; 0 1 0 0; 1 1 1 1; 0 1 2 3]\n", " α = A\\[u₀; up₀; u₁; up₁]\n", " return Polynomial(α)\n", "end\n", "\n", "# Test code\n", "p = fit_values_and_slopes(-1, -1, 1, 1)\n", "plot(p, xlims=(0, 1))" ] }, { "cell_type": "markdown", "id": "79ee3492", "metadata": {}, "source": [ "1. Écrire une fonction `approx(n)` implémentant l'approche décrite ci-dessus pour résoudre l'EDP.\n", " La fonction devra retourner une approximation polynomiale de la solution basée sur une interpolation de **degré** $n$ du membre de droite à des points équidistants entre 0 et 1 compris.\n", "\n", "
\n", " \n", " Indication (cliquer pour afficher)\n", " \n", "\n", " - Utiliser la fonction `fit` de la bibliothèque `Polynomials.jl` pour obtenir le polynôme interpolateur :\n", "\n", " ```julia\n", " p = fit(x, y)\n", " ```\n", "\n", " où `x` sont les nœuds d'interpolation et `y` sont les valeurs correspondantes de la fonction à interpoler.\n", "\n", " - Pour calculer la solution analytique lorsque le membre de droite est un polynôme,\n", " on pourra remarquer que toutes les solutions sont des polynômes,\n", " et que sans les conditions aux bords, la solution est unique modulo un polynôme cubique.\n", "\n", " - La fonction `integrate` de la bibliothèque `Polynomials.jl` permet de calculer une primitive d'un polynôme :\n", " ```julia\n", " P = integrate(p)\n", " ```\n", "\n", " - Utiliser le format `BigFloat` pour limiter les erreurs d'arrondi.\n", " En particulier, la fonction `LinRange{BigFloat}(a, b, N)` permet de créer un vecteur de `N` nombres au format `BigFloat` également distribués entre `a` et `b` inclus.\n", " ```julia\n", " X = LinRange{BigFloat}(0, 1, n + 1)\n", " ```\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "8b28140c", "metadata": { "nbgrader": { "grade": false, "grade_id": "interp_pde", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Right-hand side\n", "φ(x) = (2*big(π))^4 * cospi(2*x)\n", "\n", "# Exact solution (for comparison purposes)\n", "uₑ(x) = cospi(2*x) - 1\n", "\n", "function approx(n)\n", " X = LinRange{BigFloat}(0, 1, n + 1)\n", " ### BEGIN SOLUTION\n", " Y = φ.(X)\n", " p = fit(X, Y)\n", " uh = integrate(integrate(integrate(integrate(p))))\n", " ∂uh = derivative(uh)\n", " uh -= fit_values_and_slopes(uh(0), ∂uh(0), uh(1), ∂uh(1))\n", " return uh\n", " ### END SOLUTION\n", "end;" ] }, { "cell_type": "code", "execution_count": null, "id": "2b7c09fe", "metadata": { "nbgrader": { "grade": true, "grade_id": "cell-e79ffe6285cd8198", "locked": true, "points": 2, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "@assert typeof(approx(3)) == Polynomial{BigFloat, :x}\n", "@assert degree(approx(3)) == 7\n", "@assert approx(3)(0) ≈ 0\n", "@assert approx(3)(1) ≈ 0\n", "@assert derivative(approx(3))(0) ≈ 0\n", "@assert derivative(approx(3))(1) ≈ 0" ] }, { "cell_type": "markdown", "id": "ec8cdd87", "metadata": {}, "source": [ "2. Écrire une fonction `estimate_error(n)` qui approxime l'erreur,\n", " en norme $L^\\infty$,\n", " entre la solution approchée par l'approche ci-dessus et la solution exacte.\n", " La solution exacte est donnée par\n", " $$\n", " u_e(x) = \\cos(2\\pi x) - 1.\n", " $$" ] }, { "cell_type": "code", "execution_count": null, "id": "b9087f01", "metadata": { "nbgrader": { "grade": false, "grade_id": "interp_error", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Exact solution (for comparison purposes)\n", "uₑ(x) = cospi(2*x) - 1\n", "\n", "function estimate_error(n)\n", " ### BEGIN SOLUTION\n", " un = approx(n)\n", " x_fine = LinRange{BigFloat}(0, 1, 1000)\n", " un_fine, u_fine = un.(x_fine), uₑ.(x_fine)\n", " return maximum(abs.(u_fine - un_fine))\n", " ### END SOLUTION\n", "end;" ] }, { "cell_type": "code", "execution_count": null, "id": "515eedfa", "metadata": { "nbgrader": { "grade": true, "grade_id": "cell-9764a7b6ad0837c3", "locked": true, "points": 2, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "@assert estimate_error(2) > 0\n", "@assert estimate_error(20) < 1e-3\n", "@assert estimate_error(20) > 1e-20\n", "@assert estimate_error(40) < 1e-12" ] }, { "cell_type": "markdown", "id": "d0540971", "metadata": {}, "source": [ "3. Tracer un graphique de l'erreur en fonction de $n$ pour $n$ allant de 5 à 30.\n", " Utiliser l'échelle par défaut pour l'axe des abcisses et une échelle logarithmique pour l'axe des ordonnées." ] }, { "cell_type": "code", "execution_count": null, "id": "40c5b77b", "metadata": { "nbgrader": { "grade": true, "grade_id": "interp_plot", "locked": false, "points": 1, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# ### BEGIN SOLUTION\n", "ns = 5:50\n", "errors = estimate_error.(ns)\n", "plot(ns, errors, marker = :circle, label=L\"$L^{\\infty}$ Error\")\n", "plot!(yaxis=:log, lw=2)\n", "# ### END SOLUTION" ] }, { "cell_type": "markdown", "id": "7d1589d9", "metadata": {}, "source": [ "### [Exercice 2] Différence finies pour Poisson non-linéaire\n", "On s'intéresse dans cet exercice à la résolution de l'équation de Poisson non-linéaire suivante :\n", "$$\n", "\\tag{Poisson}\n", "- \\frac{\\mathrm d} {\\mathrm d x} \\left( \\kappa(u, \\alpha) \\frac{\\mathrm d u} {\\mathrm d x} \\right) = 1,\n", "\\qquad u(0) = u(1) = 0, \\qquad \\kappa(u, α) := 1 + α u^2,\n", "$$\n", "où $\\alpha \\in \\mathbb R_{\\geq 0}$ un paramètre positif.\n", "Cette équation modélise la température à l'équilibre dans une barre unidimensionnelle dont les extrémités sont maintenues à température nulle,\n", "en présence d'une source de chaleur uniforme.\n", "La non-linéarité de cette équation provient du fait que la conductivité thermique $\\kappa$ dépend explicitement de la solution $u$.\n", "Pour résoudre numériquement cette équation,\n", "on utilisera la méthode des différences finies.\n", "Soit une grille d'abcisses équidistantes\n", "$$\n", "0 = x_0 < x_1 < \\dots < x_{N-1} < x_N = 1, \\qquad x_i = \\frac{i}{N},\n", "$$\n", "et soit $(u_i)_{i \\in \\{0, \\dots N\\}}$ les valeurs de la solution à ces points.\n", "La condition aux limites implique que $u_0 = u_N = 0$,\n", "et il ne sera donc pas nécessaire d'inclure ces valeurs dans les inconnues.\n", "Aux points intérieurs, on utilise l'approximation\n", "$$\n", "- \\frac{\\mathrm d} {\\mathrm d x} \\left( \\kappa(u, α) \\frac{\\mathrm d u} {\\mathrm d x} \\right) (x_i)\n", "\\approx \\frac{F_{i+\\frac{1}{2}} - F_{i-\\frac{1}{2}}}{\\Delta x},\n", "\\qquad\n", "i \\in \\{1, \\dotsc, N-1\\},\n", "\\tag{Approx}\n", "$$\n", "où $\\Delta x = 1/N$ et, pour $k \\in \\{0, \\dotsc, N-1\\}$,\n", "$$\n", "F_{k + \\frac{1}{2}} := - \\kappa_{k+\\frac{1}{2}} \\frac{u_{k+1} - u_{k}}{\\Delta x}, \\qquad\n", "\\kappa_{k + \\frac{1}{2}} := \\frac{\\kappa(u_{i}, α) + \\kappa(u_{i+1}, α)}{2}.\n", "$$\n", "Le terme $F_{k+ 1/2}$ est une approximation du flux de chaleur vers la droite,\n", "c'est à dire de la fonction qui à $x \\in [0, 1]$ associe $- \\kappa\\bigl(u(x), α\\bigr) u'(x)$,\n", "au point $x_k + \\frac{\\Delta x}{2}$.\n", "En substituant l'approximation (Approx) dans (PDE) et en réarrangant les termes,\n", "on obtient le système suivant :\n", "$$\n", "\\forall i \\in \\{1, \\dotsc, N-1\\}, \\qquad\n", "\\frac{1}{\\Delta x^2} \\left( - \\kappa_{i-\\frac{1}{2}} u_{i-1} + \\Bigl(\\kappa_{i-\\frac{1}{2}} + \\kappa_{i+\\frac{1}{2}}\\Bigr) u_{i} - \\kappa_{i+\\frac{1}{2}} u_{i+1} \\right) = 1,\n", "$$\n", "qui constitue un système non-linéaire de $N-1$ équations en les inconnues $\\mathbf u = (u_1, \\dotsc, u_{N-1})^\\top$.\n", "Notons que les coefficients $(\\kappa_{k+1/2})_{k \\in \\{0, \\dots, N-1\\}}$ dépendent de manière non-linéaire de $\\mathbf u$ et $α$,\n", "mais cette dépendance est omise dans la notation par souci de concision.\n", "Ce système peut être réécrit sous forme matricielle comme suit :\n", "$$\n", "\\tag{NonLin}\n", "\\frac{\\mathsf A_N(\\mathbf u, α)}{Δx^2}\n", "\\begin{pmatrix}\n", " u_1 \\\\\n", " u_2 \\\\\n", " u_3 \\\\\n", " \\vdots \\\\\n", " u_{N-2} \\\\\n", " u_{N-1}\n", "\\end{pmatrix}\n", "=\n", "\\begin{pmatrix}\n", " 1 \\\\\n", " 1 \\\\\n", " 1 \\\\\n", " \\vdots \\\\\n", " 1 \\\\\n", " 1\n", "\\end{pmatrix}\n", "=: \\mathbf b\n", "$$\n", "où $\\mathsf A_N(\\mathbf u, α) \\in \\mathbb R^{(N-1)\\times (N-1)}$ est la matrice suivante (dimension N-1 x N-1):\n", "$$\n", "A_N(\\mathbf u, α) =\n", "\\begin{pmatrix}\n", " \\kappa_{1/2} + \\kappa_{3/2} & - \\kappa_{3/2} \\\\\n", " -\\kappa_{3/2} & \\kappa_{3/2} + \\kappa_{5/2} & - \\kappa_{5/2} \\\\\n", " & -\\kappa_{5/2} & \\kappa_{5/2} + \\kappa_{7/2} & - \\kappa_{7/2} \\\\\n", " & & \\ddots & \\ddots & \\ddots & \\\\\n", " & & & -\\kappa_{N-5/2} & \\kappa_{N-5/2} + \\kappa_{N-3/2} & -\\kappa_{N-3/2} \\\\\n", " & & & & -\\kappa_{N-3/2} & \\kappa_{N-3/2} + \\kappa_{N-1/2} \\\\\n", "\\end{pmatrix}.\n", "$$\n", "\n", "0. On fournit ci-dessous une fonction `build_A(N, u, α)` permettant de construire la matrice $\\mathsf A_N(\\mathbf u, \\alpha)$.\n", "
\n", " \n", " Indication (cliquer pour afficher)\n", " \n", "\n", " En vue de pouvoir dans la suite dériver la matrice $\\mathsf A_N$ par rapport à $α$ en utilisant la différentiation automatique,\n", " il est crucial que la matrice $\\mathbf A$ puisse contenir des nombres duaux.\n", " C'est pourquoi on utilise la commande\n", " ```julia\n", " A = zeros(typeof(α), N+1, N+1)\n", " ```\n", " pour initialiser la matrice `A`.\n", " De cette manière, les élément de la matrice sont du même type que le paramètre $α$.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "124a4c21-3a99-4b2c-a400-84f7de3730d9", "metadata": { "nbgrader": { "grade": false, "grade_id": "cell-7cc040866d32d6b0", "locked": true, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "κ(u, α) = 1 + α^2 * u^2\n", "\n", "function build_A(N, u, α)\n", " @assert length(u) == N-1\n", " A = zeros(typeof(α), N+1, N+1)\n", " v = [0.; u; 0.]\n", " for i in 2:N\n", " A[i, i-1] = - (κ(v[i-1], α) + κ(v[i], α)) / 2\n", " A[i, i] = (κ(v[i-1], α) + 2κ(v[i], α) + κ(v[i+1], α)) / 2\n", " A[i, i+1] = - (κ(v[i], α) + κ(v[i+1], α)) / 2\n", " end\n", " return A[2:end-1, 2:end-1]\n", "end\n", "\n", "@assert begin N = 20; size(build_A(N, zeros(N-1), 0.)) == (N - 1, N - 1) end\n", "@assert begin N = 20; build_A(N, zeros(N-1), 0.) == SymTridiagonal(fill(2, N-1), fill(-1, N-2)) end" ] }, { "cell_type": "markdown", "id": "4d1d4efb", "metadata": {}, "source": [ "1. Pour résoudre le système non-linéaire (NonLin),\n", " on se propose d'utiliser une méthode de point fixe basée sur l'itération\n", " $$\n", " \\frac{\\mathsf A_{N}(\\mathbf u^{n}, α)}{Δ x^2} \\mathbf u^{n+1} = \\mathbf b.\n", " $$\n", " Cette itération permet de générer,\n", " à partir d'une approximation courante de la solution $\\mathbf u^n$,\n", " une nouvelle approximation $\\mathbf u^{n+1}$.\n", " Écrire une fonction `solve_nonlin(N, α; maxiter=500, ε=1e-12)` permettant de calculer une solution approximative de (NonLin) par cette approche,\n", " en utilisant comme critère d'arrêt que.\n", " $$\n", " \\left\\| \\frac{\\mathsf A_N(\\mathbf u, α)}{Δx^2} \\mathbf u - \\mathbf b \\right\\| \\leq ε\n", " $$\n", " La fonction devra renvoyer uniquement le résultat final $\\mathbf u = (u_1, \\dotsc, u_{N-1})^\\top$ de l'itération,\n", " ou `nothing` si une solution n'a pas été trouvée après `maxiter` itérations.\n", "
\n", " \n", " Indication (cliquer pour afficher)\n", " \n", "\n", " Afin de pouvoir dans la suite dériver la solution par rapport au paramètre $α$ en utilisant la différentiation automaiique,\n", " il est important que les éléments `u` puissent contenir des nombres duaux.\n", " Il est donc recommandé d'initialiser `u` comme suit :\n", " ```julia\n", " u = zeros(typeof(α), N-1)\n", " ```\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "b6499aa1", "metadata": { "nbgrader": { "grade": false, "grade_id": "solve_nonlin", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "function solve_nonlin(N, α; maxiter=1000, ε=1e-10)\n", " b = ones(N-1)\n", " u = zeros(typeof(α), N-1)\n", " A = N^2 * build_A(N, u, α)\n", " ### BEGIN SOLUTION\n", " for i in 1:maxiter\n", " u = A\\b\n", " A = N^2*build_A(N, u, α)\n", " norm(A*u - b) ≤ ε && return u\n", " end\n", " return nothing\n", " ### END SOLUTION\n", "end;" ] }, { "cell_type": "code", "execution_count": null, "id": "4e7d5b3e", "metadata": { "nbgrader": { "grade": true, "grade_id": "cell-68fd71f3ebf99d3e", "locked": true, "points": 2, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "@assert size(solve_nonlin(10, 1.)) == (9,)\n", "@assert solve_nonlin(10, 0; ε = 1e-100) == nothing\n", "@assert begin N, α = 20, 1.; u = solve_nonlin(N, α); A_ = build_A(N, u, α); norm(N^2*A_*u - ones(N-1)) ≤ 1e-5 end" ] }, { "cell_type": "markdown", "id": "780f44f1", "metadata": {}, "source": [ "2. Écrire une fonction `solve_poisson(N, α)` permettant de résoudre approximativement (Poisson),\n", " en faisant appel à la fonction `solve_nonlin` définie au point précédent.\n", " Plus précisément, la fonction devra renvoyer les vecteurs $(x_0, x_1, \\dotsc, x_N)^\\top$ et $(u_0, u_1, \\dotsc, u_N)^\\top$,\n", " où les **points aux limites sont inclus**.\n", "
\n", " \n", " Hint (click to display)\n", " \n", "\n", " Pour ajouter des éléments au début et à la fin d'un vecteur,\n", " on pourra utiliser la concaténation verticale grâce à `;`\n", "\n", " ```julia\n", " v1 = [1., 2., 3.]\n", " v2 = [0.; v1; 0.] # v2 = [0., 1., 2., 3., 0.]\n", " ```\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "0e642215", "metadata": { "nbgrader": { "grade": false, "grade_id": "solve_poisson", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "function solve_poisson(N, α)\n", " ### BEGIN SOLUTION\n", " Δx = 1/N\n", " x = (0:N)*Δx\n", " u = [0.; solve_nonlin(N, α); 0.]\n", " return x, u\n", " ### END SOLUTION\n", "end" ] }, { "cell_type": "code", "execution_count": null, "id": "ad1d6e71", "metadata": { "nbgrader": { "grade": true, "grade_id": "cell-0daaf7cc0874d73d", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "@assert solve_poisson(20, 1.) isa Tuple\n", "@assert length(solve_poisson(20, 1.)) == 2\n", "@assert solve_poisson(20, 1.)[1] == (0:20)/20" ] }, { "cell_type": "markdown", "id": "fe3fae17", "metadata": {}, "source": [ "3. Fixer $α = 30.0$ et illustrer dans ce cas la convergence de la méthode numérique quand $N \\to \\infty$,\n", " en traçant sur un même graphe les solutions numériques obtenues pour les valeurs de $N$ données ci-dessous." ] }, { "cell_type": "code", "execution_count": null, "id": "caa0f074", "metadata": { "nbgrader": { "grade": true, "grade_id": "plot_poisson_1", "locked": false, "points": 1, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "α = 30.\n", "p = plot(title=L\"Convergence as $N \\to \\infty$\", xlims=(0, 1),\n", " legend=:outertopright)\n", "for N in (5, 10, 20, 30, 40)\n", " # Plot numerical solution for current value of `N`\n", " ### BEGIN SOLUTION\n", " x, u = solve_poisson(N, α)\n", " plot!(x, u, label=\"N = $N\")\n", " ### END SOLUTION\n", "end\n", "p" ] }, { "cell_type": "markdown", "id": "03d1fc13", "metadata": {}, "source": [ "4. Fixer $N = 50$, et illustrer sur un même graphe\n", " - La solution exacte de l'équation de Poisson quand $\\alpha = 0$,\n", " qui est donnée par\n", " $$\n", " u(x) = \\frac{1}{8} - \\frac{1}{2} \\left(x - \\frac{1}{2} \\right)^2.\n", " $$\n", " - Les solutions numériques obtenues pour $α \\in \\{0, 10, 20, 50, 100\\}$." ] }, { "cell_type": "code", "execution_count": null, "id": "9f6d7c94", "metadata": { "nbgrader": { "grade": true, "grade_id": "plot_poisson_2", "locked": false, "points": 1, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "N = 50\n", "u_exact(x) = 1/8 - (x - .5)^2/2\n", "p = plot(title=\"Solution to the nonlinear Poisson equation\", xlims=(0, 1),\n", " legend=:outertopright)\n", "\n", "### BEGIN SOLUTION\n", "plot!(u_exact, label=\"Exact\")\n", "for α in (0., 10., 20., 50., 100.)\n", " x, u = solve_poisson(N, α)\n", " plot!(x, u, label=\"α = $α\")\n", "end\n", "### END SOLUTION\n", "p" ] }, { "cell_type": "markdown", "id": "0cfe0e47", "metadata": {}, "source": [ "5. On suppose maintenant que le paramètre $\\alpha$ est inconnu,\n", " mais que la température moyenne de la barre a été mesurée:\n", " $$\n", " \\tag{Constraint}\n", " \\int_{0}^{1} u(x) \\, \\mathrm dx = \\overline u.\n", " $$\n", " On s'intéresse au problème inverse visant à calculer le paramètre $α$ correspondant à la température moyenne mesurée.\n", " Pour ce faire, commencer par écrire une fonction `mean_temperature(N, α)`,\n", " donnant la température moyenne dans la barre pour la valeur de $α$ donnée,\n", " sur base d'une approximation numérique de la solution de l'équation de Poisson par `solve_poisson`.\n", " On pourra supposer que le nombre $N$ est pair,\n", " de manière à ce que la méthode de Simpson puisse étre utilisée." ] }, { "cell_type": "code", "execution_count": null, "id": "e2971944", "metadata": { "nbgrader": { "grade": false, "grade_id": "mean_temperature", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "function mean_temperature(N, α)\n", " @assert N % 2 == 0\n", " ### BEGIN SOLUTION\n", " x, u = solve_poisson(N, α)\n", " result = u[1] + u[end]\n", " result += 4sum(u[2:2:end-1])\n", " result += 2sum(u[3:2:end-2])\n", " return result/N/3\n", " ### END SOLUTION\n", "end" ] }, { "cell_type": "code", "execution_count": null, "id": "715287f6", "metadata": { "nbgrader": { "grade": true, "grade_id": "2", "locked": true, "points": 0, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "@assert mean_temperature(10, 10.) isa Float64\n", "@assert mean_temperature(100, 0.) ≈ 1/12\n", "@assert mean_temperature(100, 10.) < 1/12" ] }, { "cell_type": "markdown", "id": "7f2cb2bc", "metadata": {}, "source": [ "6. Écrire ensuite une fonction `newton_raphson(x, f; maxiter=100, ε = 1e-12)`\n", " implémentant la méthode de Newton-Raphson pour résoudre l'équation scalaire $f(x) = 0$,\n", " avec comme critère d'arrêt que $| f(x) | \\leq \\varepsilon$.\n", " La fonction devra renvoyer uniquement le résultat final de l'itération,\n", " ou `nothing` si une solution n'a pas été trouvée après `maxiter` itérations.\n", " On considérera uniquement le cas où `x` est un scalaire et `f` est une fonction de $\\mathbb R$ dans $\\mathbb R$.\n", "\n", "
\n", " \n", " Indication (cliquer pour afficher)\n", " \n", "\n", " Pour calculer numériquement la dérivée de $f$,\n", " la bibliothèque `ForwardDiff` peut être utilisée.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "60e45859", "metadata": { "nbgrader": { "grade": false, "grade_id": "newton_raphson", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "const dx = ForwardDiff.Dual(0., 1.)\n", "function newton_raphson(f, x; maxiter=100, ε = 1e-12)\n", " ### BEGIN SOLUTION\n", " for i in 1:maxiter\n", " y = f(x + dx)\n", " x -= y.partials[1]\\y.value\n", " norm(f(x)) < ε && return x\n", " end\n", " error(\"Failed to converge!\")\n", " ### END SOLUTION\n", "end;" ] }, { "cell_type": "code", "execution_count": null, "id": "bc762d5f", "metadata": { "nbgrader": { "grade": true, "grade_id": "cell-d2e7364ddc277254", "locked": true, "points": 2, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "@assert newton_raphson(x -> x^2 - 2, 1) ≈ √2\n", "@assert newton_raphson(x -> x^2 - 2, -1) ≈ -√2\n", "@assert newton_raphson(x -> x^3 - 2, 1) ≈ cbrt(2)\n", "@assert newton_raphson(x -> cos(x) - .5, 2) ≈ acos(.5)" ] }, { "cell_type": "markdown", "id": "ab521ae8", "metadata": {}, "source": [ "7. Écrire une fonction `get_alpha(N)` permettant de calculer $α$ de manière à ce que l'équation (Constraint) soit satisfaite avec $\\overline u = .07$.\n", " Pour ce faire, appliquer la méthode de Newton-Raphson à une fonction appropriée,\n", " faisant intervenir un appel à `mean_temperature` avec la valeur de $N$ passée en argument.\n", "
\n", " \n", " Indications (cliquer pour afficher)\n", " \n", "\n", " Il vaut mieux ne pas initialiser l'itération de Newton-Raphson à $α = 0$.\n", " En effet, la dérivée partielle par rapport à $α$ de la conductivité thermique $\\kappa$ est égale à 0 en $α = 0$.\n", " On pourra par exemple initialiser l'itération à $α = 10$\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "d76a2cbc", "metadata": { "nbgrader": { "grade": true, "grade_id": "get_alpha", "locked": false, "points": 1, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "function get_alpha(N)\n", " ### BEGIN SOLUTION\n", " u_bar = .07\n", " α = newton_raphson(a -> mean_temperature(N, a) - u_bar, 10.)\n", " ### END SOLUTION\n", " return α\n", "end;" ] }, { "cell_type": "markdown", "id": "f119b659", "metadata": {}, "source": [ "8. Illustrer sur un graphe la variation de la valeur trouvée pour $α$ en fonction de $N$,\n", " par exemple pour $N \\in \\{10, \\dotsc, 100\\}$." ] }, { "cell_type": "code", "execution_count": null, "id": "d077124b-d74f-47fa-a936-2da2f758a557", "metadata": { "nbgrader": { "grade": true, "grade_id": "plot_alpha", "locked": false, "points": 1, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "### BEGIN SOLUTION\n", "plot(title=\"Solution of inverse problem\", xlabel=L\"N\", ylabel=L\"α\")\n", "Ns = 10:2:100\n", "plot!(Ns, get_alpha.(Ns))\n", "### END SOLUTION" ] }, { "cell_type": "markdown", "id": "1b8b808c", "metadata": {}, "source": [ "### [Exercice 3] Une équation différentielle à la rescousse" ] }, { "cell_type": "markdown", "id": "e559b563", "metadata": {}, "source": [ "Les plongeurs amateurs disposent parfois d'une bouée de secours autogonflable,\n", "qu'ils peuvent utiliser pour remonter rapidement à la surface en cas de problème.\n", "Cet exercice vise à étudier la remontée d'un plongeur à l'aide d'une telle bouée à laquelle il est attaché,\n", "et à délimiter les conditions d'utilisation de la bouée afin de garantir une ascension suffisamment rapide.\n", "On fera plusieurs hypothèses simplificatrices :\n", "\n", "- La bouée contient du CO₂, modélisé par un gaz idéal.\n", "\n", "- La température du CO₂ dans la bouée est constante, égale à 25°C\n", "\n", "- Bien que son volume soit variable en fonction de la pression,\n", " la bouée reste toujours de forme sphérique.\n", "\n", "- Le volume du plongeur est indépendant de sa profondeur.\n", "\n", "- Le coefficient du traînée $C_d$ du système \"plongeur + bouée\" est constant, égal à 0.47.\n", "\n", "- On néglige la masse à vide de la bouée; toute sa masse provient du CO₂ qu'elle contient." ] }, { "cell_type": "markdown", "id": "ada6bc7f", "metadata": {}, "source": [ "Les paramètres physiques du problème sont donnés ci-dessous:" ] }, { "cell_type": "code", "execution_count": null, "id": "acd3fe20", "metadata": {}, "outputs": [], "source": [ "# Temperature [K]\n", "const T = 298.15 # = 25°C\n", "\n", "# Density of water [kg/m³]\n", "const ρ_w = 1000\n", "\n", "# Gravitational acceleration [m/s²]\n", "const g = 9.81\n", "\n", "# Mass of the diver [kg]\n", "const m_diver = 80\n", "\n", "# Volume of the diver [m³]\n", "const V_diver = .07\n", "\n", "# Cross section of diver [m²]\n", "const A_diver = .25\n", "\n", "# Drag coefficient\n", "const C_d = 0.47\n", "\n", "# Universal gas constant [J/mol·K]\n", "const R = 8.314\n", "\n", "# Molar mass of CO₂ [kg/mol]\n", "const M_CO₂ = 0.04401\n", "\n", "# Sea level pressure [Pa]\n", "const P₀ = 101325" ] }, { "cell_type": "markdown", "id": "b3bea51c", "metadata": {}, "source": [ "**Remarques**:\n", "- La densité du plongeur est supérieure à la densité de l'eau. Il s'ensuit que, sans bouée, un plongeur inconscient coulerait.\n", "\n", "- La masse de la bouée n'a pas encore été définie,\n", " car elle a vocation à varier dans cet exercice.\n", " On la notera `m_buoy`." ] }, { "cell_type": "markdown", "id": "00f7a41e", "metadata": {}, "source": [ "Notons $z(t)$ la coordonnée verticale du plongeur.\n", "On supposera, par convention,\n", "que $z = 0$ correspond au niveau de la surface de l'eau,\n", "et que $z ≤ 0$ correspond au dessous de la surface.\n", "Notons aussi $v(t) = \\dot z(t)$,\n", "la vitesse verticale du plongeur vers le haut.\n", "\n", "1. Écrire une fonction `V_buoy(z, m_buoy)`,\n", " retournant le volume de la bouée à une profondeur $z ≤ 0$,\n", " lorsque celle-ci contient une masse `m_buoy` de CO₂.\n", " Pour ce faire, utiliser la loi des gaz parfaits :\n", " $$\n", " V = \\frac{n R T}{P},\n", " \\qquad n := \\frac{m_{\\rm buoy}}{M_{\\rm CO_2}}.\n", " $$\n", " Ici $n$ est le nombre de moles de CO₂ contenues dans la bouée.\n", " On rappelle que la pression hydrostatique à une profondeur $z ≤ 0$ est donnée par\n", " $$\n", " P(z) = P_0 - g \\rho_w z.\n", " $$" ] }, { "cell_type": "code", "execution_count": null, "id": "0b3bd6e0", "metadata": { "nbgrader": { "grade": false, "grade_id": "V_buoy", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Volume of the buoy at depth `z` (z ≤ 0)\n", "function V_buoy(z, m_buoy)\n", " ### BEGIN SOLUTION\n", " P = P₀ - ρ_w * g * z\n", " return (m_buoy * R * T) / (P * M_CO₂)\n", " ### END SOLUTION\n", "end;" ] }, { "cell_type": "code", "execution_count": null, "id": "f5187d3e", "metadata": { "nbgrader": { "grade": true, "grade_id": "cell-0eef22c644cfc99f", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "@assert V_buoy(0, 1.) ≈ (R * T) / (P₀ * M_CO₂)\n", "@assert V_buoy(0, 1.)*P₀ ≈ V_buoy(-1, 1.)*(P₀ + ρ_w * g)" ] }, { "cell_type": "markdown", "id": "e3bc2de1", "metadata": {}, "source": [ "On modélise les forces sur le système,\n", "toutes dans la direction $z$, comme suit :\n", "\n", "- La **force de gravité** est donnée par\n", "\n", " $$\n", " F_g = - m \\cdot g, \\qquad m := m_{\\rm diver} + m_{\\rm buoy}.\n", " $$\n", "\n", "- La **poussée d'Archimède** est donnée par\n", "\n", " $$\n", " F_a(z) = \\rho_w \\cdot V(z) \\cdot g, \\qquad V(z) := V_{\\rm diver} + V_{\\rm buoy}(z).\n", " $$\n", "\n", "- La **force de traînée** est donnée par\n", " $$\n", " F_d(v) = - \\frac{1}{2} \\rho_w \\cdot A_{\\rm total} \\cdot C_d \\cdot v^2 \\cdot {\\rm sign}(v).\n", " $$\n", " Pour la surface de référence $A_{\\rm total}$,\n", " on prendra pour simplifier le maximum entre celle de la bouée et celle du plongeur.\n", " Comme la bouée est supposée sphérique,\n", " sa surface de référence peut être calculée explicitement,\n", " et on a donc\n", " $$\n", " A_{\\rm total} = \\max\\left\\{ A_{\\rm diver}, π\\left(\\frac{3V_{\\rm buoy}}{4π}\\right)^{\\frac{2}{3}} \\right\\}.\n", " $$\n", "\n", "En appliquant la seconde loi de Newton, on obtient\n", "une équation différentielle décrivant le mouvement du plongeur :\n", "$$\n", "\\tag{EDO}\n", "\\left\\{\n", "\\begin{aligned}\n", "\\dot z &= v, \\\\\n", "\\dot v &= \\frac{F_g + F_a(z) + F_d(v)}{m_{\\rm diver} + m_{\\rm buoy}}.\n", "\\end{aligned}\n", "\\right.\n", "$$\n", "\n", "2. Soit $X = (z, v)^\\top$.\n", " L'équation (EDO) peut-être réécrite sous la forme\n", " $$\n", " \\tag{EDOv}\n", " \\dot X(t) = f\\bigl(X; m_{\\rm buoy})\n", " $$\n", " Écrire la fonction $f$ sous forme d'une fonction Julia `f(X, m_buoy)`,\n", " où `m_buoy` est vu comme un paramètre." ] }, { "cell_type": "code", "execution_count": null, "id": "b8fcb790", "metadata": { "nbgrader": { "grade": false, "grade_id": "f_ode", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# Parameter `A` in the drag force (depends on volume `Vb` of the buoy)\n", "A_total(Vb) = max(A_diver, π*(3Vb/4π)^(2/3))\n", "\n", "function f(X, m_buoy)\n", " ### BEGIN SOLUTION\n", " z, v = X\n", " Vb = V_buoy(z, m_buoy)\n", " m = m_diver + m_buoy\n", " F_a = ρ_w * (V_diver + Vb) * g\n", " F_g = - m * g\n", " F_d = - 0.5 * C_d * ρ_w * A_total(Vb) * v^2 * sign(v)\n", " return [v, (F_g + F_a + F_d) / m]\n", " ### END SOLUTION\n", "end" ] }, { "cell_type": "code", "execution_count": null, "id": "75e24f37", "metadata": { "nbgrader": { "grade": true, "grade_id": "cell-e119b00105e73c51", "locked": true, "points": 2, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "@assert f([0., 0.], 0.) |> length == 2\n", "@assert f([0., 0.], 0.)[1] == 0.\n", "@assert f([0., 5.], 0.)[1] == 5.\n", "@assert f([-1., 0.], 0.)[2] ≈ f([0., 0.], 0.)[2]\n", "@assert f([-1., 0.], .1)[2] ≥ f([0., 0.], 0.)[2]\n", "@assert f([0., 0.], 0.)[2] ≈ -1.22625\n", "@assert f([0., 0.], .1)[2] ≈ 5.5709364718165455" ] }, { "cell_type": "markdown", "id": "bf139448", "metadata": {}, "source": [ "3. Écrire une fonction `rkx(Xₙ, h, Δ)` implémentant un pas de temps de taille $\\Delta$ de la méthode de Runge-Kutta suivante pour une équation différentielle générique de la forme $X' = h(X)$:\n", " $$\n", " X_{n+1} = X_n + \\frac{\\Delta}{9}\\left(2k_1 + 3k_2 + 4k_3 \\right),\n", " $$\n", " où\n", " \\begin{align*}\n", " k_1 &= \\ h(X_n), \\\\\n", " k_2 &= \\ h\\!\\left(X_n + \\frac{\\Delta}{2} k_1\\right), \\\\\n", " k_3 &= \\ h\\!\\left(X_n + \\frac{3\\Delta}{4} k_2\\right).\n", " \\end{align*}\n", " La fonction devra renvoyer $X_{n+1}$." ] }, { "cell_type": "code", "execution_count": null, "id": "79a6cfbd", "metadata": { "nbgrader": { "grade": false, "grade_id": "rkx", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "function rkx(Xₙ, h, Δ)\n", " k₁ = h(Xₙ)\n", " k₂ = h(Xₙ + Δ/2 * k₁)\n", " k₃ = h(Xₙ + 3Δ/4 * k₂)\n", " return Xₙ + Δ/9 * (2k₁ + 3k₂ + 4k₃)\n", "end" ] }, { "cell_type": "code", "execution_count": null, "id": "a63e1c5a", "metadata": { "nbgrader": { "grade": true, "grade_id": "cell-35dffc49bd8d021b", "locked": true, "points": 1, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "@assert rkx([0.], X -> [1.], 1.) ≈ [1]\n", "@assert rkx([1.], X -> X, 1.) ≈ [2 + 1/2 + 1/6]" ] }, { "cell_type": "markdown", "id": "1fce2f3e", "metadata": {}, "source": [ "4. Écrire une fonction `solve_ode(Δ, z₀, m_buoy; tmax=20)` pour résoudre (EDOv)\n", " avec une condition initiale $X(0) = (z₀, 0)^\\top$,\n", " en utilisant la méthode de Runge-Kutta de point précédent avec pas de temps fixe `Δ`.\n", " On supposera que `z₀ < 0`.\n", " Votre fonction devra renvoyer un vecteur de temps `ts` et un vecteur de vecteurs `Xs` contenant la solution à ces temps.\n", "\n", " On calculera le mouvement du plongeur jusqu'à ce qu'il ait atteint la surface,\n", " ou jusqu'à `tmax` s'il n'a pas atteint la surface après ce temps.\n", " Il faudra donc que soit `Xs[end][1] ≥ 0`, soit `ts[end] ≥ tmax`." ] }, { "cell_type": "code", "execution_count": null, "id": "3a95fc9a", "metadata": { "nbgrader": { "grade": false, "grade_id": "solve_ode", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "function solve_ode(Δ, z₀, m_buoy; tmax=20)\n", " X₀ = [z₀; 0.]\n", " ts = [0.]\n", " Xs = [X₀]\n", " ### BEGIN SOLUTION\n", " h(X) = f(X, m_buoy)\n", " while Xs[end][1] ≤ 0 && ts[end] < tmax\n", " push!(Xs, rkx(Xs[end], h, Δ))\n", " push!(ts, ts[end] + Δ)\n", " end\n", " ### END SOLUTION\n", " return ts, Xs\n", "end" ] }, { "cell_type": "code", "execution_count": null, "id": "dd865014", "metadata": { "nbgrader": { "grade": true, "grade_id": "cell-362b4d008e1484af", "locked": true, "points": 2, "schema_version": 3, "solution": false, "task": false } }, "outputs": [], "source": [ "@assert solve_ode(.01, -1., 0.) |> length == 2\n", "@assert solve_ode(.01, -1., 0.)[1][end] ≈ 20\n", "@assert solve_ode(.01, -1., .1)[2][1] |> length == 2\n", "@assert solve_ode(.01, -1., .1)[2][end][1] ≥ 0\n", "@assert solve_ode(.01, -1., .1)[2][end-1][1] ≤ 0\n", "@assert solve_ode(.01, -10., .1)[1][end] > 5\n", "@assert solve_ode(.01, -10., .1)[1][end] < 6" ] }, { "cell_type": "markdown", "id": "11d21d0c", "metadata": {}, "source": [ "5. Écrire une fonction `plot_z(Δ, z₀, ms)` permettant d'illustrer sur un même graphe la coordonnée $z$ du plongeur en fonction du temps,\n", "pour **une** valeur de $z_0$ donnée et **plusieurs** valeurs de `m_buoy` dans le vecteur `ms`." ] }, { "cell_type": "code", "execution_count": null, "id": "2e1c9dc7", "metadata": { "nbgrader": { "grade": true, "grade_id": "plot_z", "locked": false, "points": 1, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "function plot_z(Δ, z₀, ms)\n", " p = plot(title=\"Depth of the diver\")\n", " ### BEGIN SOLUTION\n", " for m ∈ ms\n", " ts, Xs = solve_ode(Δ, z₀, m)\n", " plot!(ts, [x[1] for x in Xs], label=\"m = $m\")\n", " xlabel!(\"t [s]\")\n", " ylabel!(\"z [m]\")\n", " end\n", " ### END SOLUTION\n", " return p\n", "end\n", "\n", "Δ, z₀, ms = .01, -20., [.1, .2, .3]\n", "plot_z(Δ, z₀, ms)" ] }, { "cell_type": "markdown", "id": "24159795", "metadata": {}, "source": [ "6. Écrire une fonction `plot_v(Δ, z₀, ms)` permettant d'illustrer sur un même graphe la vitesse du plongeur en fonction du temps,\n", "pour **une** valeur de $z₀$ donnée et **plusieurs** valeurs de `m_buoy` dans le vecteur `ms`." ] }, { "cell_type": "code", "execution_count": null, "id": "911a4324", "metadata": { "nbgrader": { "grade": true, "grade_id": "plot_v", "locked": false, "points": 1, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "function plot_v(Δ, z₀, ms)\n", " p = plot(title=\"Velocity of the diver\")\n", " ### BEGIN SOLUTION\n", " for m ∈ ms\n", " ts, Xs = solve_ode(Δ, z₀, m)\n", " plot!(ts, [x[2] for x in Xs], label=\"m = $m\")\n", " xlabel!(\"t [s]\")\n", " ylabel!(\"v [m/s]\")\n", " end\n", " ### END SOLUTION\n", " return p\n", "end\n", "\n", "Δ, z₀, ms = .01, -20., [.1, .2, .3]\n", "plot_v(Δ, z₀, ms)" ] }, { "cell_type": "markdown", "id": "35241c91", "metadata": {}, "source": [ "7. On fixe à partir de maintenant la masse de la bouée à `m_buoy = .1`.\n", " Écrire une fonction `rescue_time(z₀)`,\n", " qui retourne une approximation du temps mis par le plongeur pour rejoindre la surface\n", " à partir d'une profondeur initiale $z_0$.\n", " Pour ce faire, résoudre l'équation différentielle avec un pas de temps fixe $Δ = 0.01$,\n", " et estimer le temps de sauvetage par interpolation linéaire sur le dernier pas de temps,\n", " durant lequel la coordonnée $z$ passe au dessus de 0." ] }, { "cell_type": "code", "execution_count": null, "id": "870b3fb7", "metadata": { "nbgrader": { "grade": true, "grade_id": "rescue_time", "locked": false, "points": 1, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "function rescue_time(z₀)\n", " Δ, m_buoy = .01, .1\n", " ### BEGIN SOLUTION\n", " Ts, Xs = solve_ode(Δ, z₀, m_buoy)\n", " t₁, t₂, δx₁, δx₂ = Ts[end-1], Ts[end], Xs[end-1][1]-1, Xs[end][1]-1\n", " return (t₁*δx₂ - t₂*δx₁)/(δx₂-δx₁)\n", " ### END SOLUTION\n", "end" ] }, { "cell_type": "markdown", "id": "6b0bf075", "metadata": {}, "source": [ "8. Faire un plot du temps de remontée en fonction de `z₀`,\n", " pour des valeurs de ce paramètre dans l'intervalle $[-30, -5]$.\n", " Estimer graphiquement, par exemple à l'aide de la fonction `vline`,\n", " la profondeur maximale telle que le plongeur peut rejoindre la surface en moins de 10 secondes grâce à la bouée." ] }, { "cell_type": "code", "execution_count": null, "id": "928d87cf", "metadata": { "nbgrader": { "grade": true, "grade_id": "plot_rescue_time", "locked": false, "points": 1, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "### BEGIN SOLUTION\n", "plot(-30:.1:-5, rescue_time)\n", "vline!([-16.2])\n", "hline!([10])\n", "xlabel!(\"z₀ [m]\")\n", "ylabel!(\"Rescue time [s]\")\n", "### END SOLUTION" ] }, { "cell_type": "markdown", "id": "bd9862f2", "metadata": {}, "source": [ "9. **Question ouverte**. Afin de déterminer les normes d'utilisation de la bouée,\n", " calculer avec précision,\n", " par la méthode de votre choix,\n", " la valeur de `z₀` permettant au plongeur de rejoindre la surface en exactement 10 secondes.\n", " Vous pouvez pour ce faire utiliser la bibliothèque `ForwardDiff`." ] }, { "cell_type": "code", "execution_count": null, "id": "60161eff", "metadata": { "nbgrader": { "grade": true, "grade_id": "bonus", "locked": false, "points": 1, "schema_version": 3, "solution": true, "task": false } }, "outputs": [], "source": [ "# BEGIN SOLUTION\n", "z = -10\n", "for i in 1:10\n", " r = rescue_time(z + dx)\n", " z -= (r.value - 10) / r.partials[1]\n", "end\n", "z\n", "### END SOLUTION" ] } ], "metadata": { "citation-manager": { "items": {} }, "jupytext": { "encoding": "# -*- coding: utf-8 -*-" }, "kernelspec": { "display_name": "Julia release", "language": "julia", "name": "julia-1.11" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "1.10.4" } }, "nbformat": 4, "nbformat_minor": 5 }