{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*ENSAM-Bordeaux, Mathématiques et informatique. Date : le 04/11/19. Auteur : Éric Ducasse. Version : 1.1*"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
*On pourra faire exécuter ce notebook cellule par cellule $\\left(\\mathtt{Maj+Entrée}\\right)$ ou intégralement par $\\mathtt{\\;Kernel\\rightarrow Restart\\;\\&\\;Run\\;All}$.*
**Pour chaque exercice, faire exécuter la partie *exemples* cellule par cellule $\\left(\\mathtt{Maj+Entrée}\\right)$, avant de passer à la partie *Travail à faire*.**
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## *Exercice 12* "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 12.1 Objectifs "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### * Savoir définir et résoudre un système d'équations algébriques, en utilisant la fonction $\\mathtt{sympy.solve}$; savoir utiliser le résultat d’un calcul symbolique pour créer une fonction, en maîtrisant la fonction $\\mathtt{sympy.lambdify}$. *"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Documentation sur les équations et les solveurs : https://docs.sympy.org/latest/tutorial/solvers.html"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Documentation sur $\\mathtt{lambdify}$ : https://docs.sympy.org/latest/tutorial/basic_operations.html#lambdify"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 12.2 Exemples "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Problème à résoudre : déterminer les paramètres $a$ et $b$ d'une fonction paramétrée pour satisfaire des conditions initiales données."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*$a)$ Définition d'une expression représentant une fonction de la variable $t$ avec 4 paramètres $a$, $b$, $\\omega$ et $\\tau$.*"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a,b,t = sb.symbols(\"a,b,t\", real=True)\n",
"w,tau = sb.symbols(\"omega,tau\", positive=True)\n",
"U_de_t = (a*sb.cos(w*t)+b*sb.sin(w*t))*sb.exp(-t/tau)\n",
"U_de_t"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*$b)$ Valeurs initiales de la fonction et de sa dérivée.*"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"valeur_initiale = U_de_t.replace(t,0) ; valeur_initiale"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"derivee_initiale = U_de_t.diff(t).replace(t,0) ; derivee_initiale"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*$c)$ Détermination des paramètres $a$ et $b$ qui permettent à la fonction de satisfaire des conditions initiales données.*"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"u0,v0 = sb.symbols(\"u_0,v_0\")\n",
"equations = [sb.Eq(valeur_initiale,u0), sb.Eq(derivee_initiale,v0)]\n",
"equations"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"regle_ab = sb.solve(equations, [a,b]) ; regle_ab"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* Variante, sans utiliser d'équation :"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"s_annulent = [valeur_initiale-u0, derivee_initiale-v0]\n",
"s_annulent"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sb.solve(s_annulent, [a,b])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*$d)$ Solution du problème.*"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"solu = U_de_t.xreplace(regle_ab).simplify()\n",
"solu"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*$e)$ Définition de fonctions utilisant le dernier résultat.*"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"La fonction $\\mathtt{lambdify}$ est faite pour définir une fonction à valeurs numériques :"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(sb.lambdify.__doc__[:487])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* **Fonction à valeurs symboliques : on utilise $\\mathtt{xreplace}$**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"alpha,f = sb.symbols(\"alpha,f\", positive=True)\n",
"solu.xreplace({tau:1/alpha, w:2*sb.pi*f}).simplify()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def Us(time,initial_value=1,initial_derivative=0,frequency=1,time_constant=1,expression=solu) : \n",
" regle = {u0:initial_value, v0:initial_derivative, w:sb.pi*2*frequency, tau:time_constant}\n",
" return expression.xreplace(regle).simplify()\n",
"# Remarque : on peut aussi définir une fonction lambda, avec des performances identiques\n",
"Us(t)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Us(t,frequency=f,time_constant=1/alpha,initial_value=0,initial_derivative=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* **Fonction vectorisée à valeurs numériques**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Avec $\\mathtt{lambdify}$, on ne peut pas définir de valeurs par défaut.\n",
"Si on veut le faire, il faut procéder en deux temps, comme ci-dessous."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"u_numerique = sb.lambdify( (t,u0,v0,w,tau), solu, \"numpy\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"T = np.arange(0,1.01,0.2)\n",
"print(np.array( [T,u_numerique(T,1,0,2*np.pi,1)] ))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Un = lambda t,u0=1,v0=0,w=2*np.pi,tau=1 : u_numerique(t,u0,v0,w,tau)\n",
"print(np.array( [T,Un(T)] ))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Vt = np.linspace(0,3.2,500)\n",
"plt.plot(Vt,Un(Vt),\"-r\",linewidth=1.6,label=r\"$f$ = 1 Hz ; $\\tau$ = 1 s\")\n",
"for fq,ct in ((1,2),(2,1)) :\n",
" plt.plot(Vt,Un(Vt,w=2*np.pi*fq,tau=ct),\"-\",linewidth=1.6,\\\n",
" label=r\"$f$ = {} Hz ; $\\tau$ = {} s\".format(fq,ct))\n",
"plt.grid() ; plt.legend() ; plt.xlabel(\"Temps $t$ [s]\") ; plt.ylabel(\"$u(t)$\") ;"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 12.3 Travail à faire "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"L'objet de cet exercice est de définir 4 fonctions $p$ polynomiales de degré 3, que l'on considère uniquement sur l'intervalle $[0,1]$ telles que l'une des valeurs parmi $[p(0),p^{\\prime}(0),p(1),p^{\\prime}(1)]$ est 1 et les trois autres sont 0."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$a)$ Soit l'expression $P=p(X)=a+b\\,X+c\\,X^2+d\\,X^3$. Déterminer la liste $[p(0),p^{\\prime}(0),p(1),p^{\\prime}(1)]$ en fonction des paramètres $a$, $b$, $c$ et $d$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a,b,c,d,X = sb.symbols(\"a,b,c,d,X\")\n",
"P = ( a + X*(b + X*(c + X*d))).expand(); P"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"valeurs_limites = [P.replace(X,0), P.diff(X).replace(X,0), P.replace(X,1), P.diff(X).replace(X,1)]\n",
"valeurs_limites"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$b)$ En déduire les expressions correspondants aux 4 fonctions cherchées."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from IPython.display import display\n",
"expr = []\n",
"for p0,q0,p1,q1 in np.eye(4, dtype=np.int) :\n",
" print(f\"+++ p(0)={p0}, p'(0)={q0}, p(1)={p1}, p'(1)={q1} +++\") \n",
" equations = [ sb.Eq(p,v) for p,v in zip((p0,q0,p1,q1),valeurs_limites) ]\n",
" display(equations)\n",
" regle_abcd = sb.solve(equations,(a,b,c,d))\n",
" display(regle_abcd)\n",
" expr.append( P.xreplace(regle_abcd).simplify() )\n",
" display(expr[-1])\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$c)$ Convertir ces expressions en 4 fonctions numériques et faire tracer leurs courbes représentatives sur l'intervalle $[0,1]$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"LF = [ sb.lambdify(X,E,\"numpy\") for E in expr ]\n",
"LF"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Vx = np.linspace(0,1,200)\n",
"for n,f in enumerate(LF,1) :\n",
" plt.plot(Vx,f(Vx),\"-\",linewidth=2.0, label=f\"$p_{n}(x)$\")\n",
"plt.grid() ; plt.legend(loc=\"best\") ; plt.xlabel(\"$x$\") ; plt.ylabel(\"$p(x)$\") ;"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## *Exercice 13* "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 13.1 Travail à faire "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"On s'intéresse à la solution $f$ du système différentiel $(1)$ suivant : $\\displaystyle \\left\\lbrace\\begin{array}{lll} \\forall r\\in]0,2], & \\displaystyle f^{\\prime\\prime}(r)+\\frac{1}{r}\\,f^{\\prime}(r)+25\\,f(r)=0&; \\\\ \\forall r\\in]2,5[ & \n",
"\\displaystyle f^{\\prime\\prime}(r)+\\frac{1}{r}\\,f^{\\prime}(r)+4\\,f(r)=0&.\\end{array}\\right.$ la solution $f$ étant de classe $\\mathcal{C}^{1}$ sur l'intervalle $[0,5]$ et vérifiant les conditions aux limites : $f^{\\prime}(0)=0$ et $f(5)=1$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"On admet que la solution générale de l'équation différentielle $\\displaystyle f^{\\prime\\prime}(r)+\\frac{1}{r}\\,f^{\\prime}(r)+k^2\\,f(r)=0$ est une combinaison linéaire des deux fonctions $r\\mapsto J_0(k\\,r)$ et\n",
"$r\\mapsto Y_0(k\\,r)$, où $J_0$ et $Y_0$ désignent les fonctions de Bessel de première et de seconde espèces :"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"r,k = sb.symbols(\"r,k\", real=True, nonnegative=True)\n",
"S1,S2 = sb.besselj(0,k*r),sb.bessely(0,k*r)\n",
"(S1,S2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"[ (S.diff(r,2) + (1/r)*S.diff(r) + k**2*S ).equals(0) for S in (S1,S2) ]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"L'étude de ces deux fonctions en $r=0$ donne les résultats suivants :"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"S1.replace(r,0), S1.diff(r).replace(r,0), S2.limit(r,0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"On en déduit la solution générale du problème différentiel :"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* Sur l'intervalle $[0,2]$ :"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"a,b,c = sb.symbols(\"a,b,c\", real=True)\n",
"F1 = a*sb.besselj(0,5*r) ; F1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* Sur l'intervalle $[2,5]$ :"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"F2 = b*sb.besselj(0,2*r)+c*sb.bessely(0,2*r) ; F2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$a)$ Vérifier que la solution proposée satisfait bien la condition limite à gauche. Définir ensuite un système de 3 équations à 3 inconnues $a$, $b$ et $c$ à partir des conditions de raccordement en $r=2$ de la fonction et de sa dérivée, et de la condition limite à droite."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sb.Eq(F1.diff(r).replace(r,0),0)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"systeme = [ sb.Eq(F1,F2).replace(r,2), \\\n",
" sb.Eq(F1.diff(r),F2.diff(r)).replace(r,2), \\\n",
" sb.Eq(F2.replace(r,5),1) ]\n",
"systeme"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$b)$ En déduire les coefficients $a$, $b$ et $c$ qui satisfont le problème différentiel $(1)$, puis la solution sur chacun des intervalles $[0,2]$ et $[2,5]$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"regle_abc = sb.solve(systeme, (a,b,c)) ; regle_abc"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"F_sol1 = F1.xreplace(regle_abc).simplify() ; F_sol1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"F_sol2 = F2.xreplace(regle_abc).simplify() ; F_sol2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$c)$ Définir la solution sous forme d'une fonction numérique vectorisée $\\mathtt{f\\underline{\\phantom{m}}num}$ puis faire tracer sa courbe représentative. Les fonctions de Bessel numériques se trouvent dans le module $\\mathtt{scipy.special}$ et se nomment $\\mathtt{jn}$ et $\\mathtt{yn}$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import scipy.special as sf"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mes_modules = [\"numpy\",{\"besselj\":sf.jn, \"bessely\":sf.yn}]\n",
"F_num1 = sb.lambdify( r, F_sol1, modules=mes_modules )\n",
"F_num2 = sb.lambdify( r, F_sol2, modules=mes_modules )"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"F_num_brouillon = lambda r : ((0<=r)&(r<=2))*F_num1(r) + ((2 **Compléments non exigibles** "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## *Exercice 12 : compléments sur $\\mathtt{lambdify}$* "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 12.2 Exemples complémentaires "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*$f)$ Autres exemples avec des fonctions qui ne sont pas dans $\\mathtt{numpy}$ (voir aussi le mémento).*"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* **Fonction $\\mathtt{sympy.erfc}$**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x,t = sb.symbols(\"x,t\", real=True)\n",
"Ix = sb.integrate( sb.exp(-t**2), (t,x,sb.oo) ).rewrite(sb.erfc).simplify()\n",
"Ix"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"try :\n",
" F = sb.lambdify( x, Ix, modules=[\"numpy\"])\n",
" F( np.array([0.2,0.4]) )\n",
"except Exception as e :\n",
" print(\"Erreur :\",e)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(sb.erfc.__doc__[:161])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import scipy.special as sf # Special Functions\n",
"print(sf.erfc.__doc__[:168])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Vérification :\n",
"T = np.linspace(0,2.5,100)\n",
"V1 = sf.erfc(T)\n",
"V2 = np.array( [float(sb.erfc(x)) for x in T] )\n",
"np.allclose(V1,V2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.plot(T,V1-V2,\".m\") ; plt.grid() ;"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"F = sb.lambdify( x, Ix, modules=[{\"erfc\":sf.erfc}, \"numpy\"])\n",
"F( np.array([0.2,0.4]) )"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"plt.plot(T,F(T),\"-g\") ; plt.grid() ; plt.xlabel(\"$t$\") ; plt.ylabel(\"$F(t)$\") ; "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* **Fonction $\\mathtt{sympy.lowergamma}$**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x,t = sb.symbols(\"x,t\", positive=True)\n",
"Jx = sb.integrate( sb.sqrt(t)*sb.exp(-t**2), (t,0,x) ).simplify()\n",
"Jx"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"try :\n",
" G = sb.lambdify( x, Jx, modules=[\"numpy\"])\n",
" G( np.array([0.2,0.4]) )\n",
"except Exception as e :\n",
" print(\"Erreur :\",e)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(sb.lowergamma.__doc__[:202])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(sf.gammainc.__doc__[:259])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def my_lowergamma(s,x) :\n",
" return sf.gamma(s)*sf.gammainc(s,x)\n",
"T = np.linspace(0,2.5,100)\n",
"W1 = my_lowergamma(0.75,T) ; W1[:5]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"W2 = np.array([ float(sb.lowergamma(0.75,x)) for x in T ]) ; W2[:5]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"np.allclose(W1,W2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"G = sb.lambdify( x, Jx, modules=[{\"lowergamma\":my_lowergamma},\"numpy\"])\n",
"G( np.array([0.2,0.4]) )"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.plot(T,G(T),\"-r\") ; plt.grid() ; plt.xlabel(\"$t$\") ; plt.ylabel(\"$G(t)$\") ; "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#Variante :\n",
"G_bis = sb.lambdify( x, Jx, modules=[{\"lowergamma\": lambda s,x : sf.gamma(s)*sf.gammainc(s,x)},\"numpy\"])\n",
"G_bis( np.array([0.2,0.4]) )"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"np.allclose(G(T),G_bis(T))"
]
}
],
"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.6.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}