>>> python · niveau 4 · terminale spé PC

Ouverture vers le supérieur

loi normale · régression · Monte-Carlo · scipy · tests · documentation

Ce que les classes préparatoires, les BUT et les BTS attendent dès la première année, appris sur des situations de votre cours de terminale. Chaque notion indique la formation qui l'attend.

← Le parcours Python

Mode d'emploi

Statut de ce niveau

Ce niveau est en cours d'audit par M. Van Hoorde. Il est utilisable, mais pas encore garanti à 100 %.

Ce niveau suppose acquis les niveaux 1 à 3 : tableaux numpy, tracés, if et for, tirages aléatoires, fonctions def, np.polyfit, méthode d'Euler et dichotomie. Il ne prépare pas l'ECE : il vous montre ce qui vous attend après le bac.

  • Chaque étape porte une étiquette : la formation dont le programme officiel demande la notion (« attendu de PCSI », « BUT Mesures physiques »…). Les phrases entre guillemets sont recopiées de ces programmes.
  • Les étapes 5 et 6 utilisent la bibliothèque scipy. Elle se télécharge à la première exécution qui contient import scipy ou from scipy… : 14 Mo, comptez une dizaine de secondes, puis elle reste chargée tant que la page est ouverte.
  • Les tirages aléatoires changent à chaque exécution : vos nombres ne seront jamais exactement ceux des solutions, seulement très proches.
  • Comme aux niveaux précédents : 💡 Aide donne un indice à la fois, la solution s'ouvre après un premier essai, ⓘ Rappel de cours rappelle la notion de physique-chimie.

La loi normale et l'intervalle de confiance

attendu de PCSI · et de toutes les CPGE de 1re année

En terminale, l'incertitude-type u indique un intervalle « dans lequel on peut raisonnablement penser » que se trouve la valeur. En classe préparatoire, on dit avec quelle probabilité. Le programme de PCSI demande d'« associer un intervalle de confiance à l'écart-type dans l'hypothèse d'une distribution suivant la loi normale », et, dans ses outils numériques, d'« utiliser la fonction random.normal de la bibliothèque numpy ».

À retenir

  • np.random.normal(m, s, N) tire au hasard N valeurs qui suivent une loi normale (ou loi gaussienne) de moyenne m et d'écart-type s. C'est le modèle des mesures répétées soumises à de petites causes de dispersion indépendantes.
  • Pour une loi normale, environ 68 % des valeurs tombent entre m − s et m + s, et environ 95 % entre m − 2s et m + 2s : c'est l'intervalle de confiance à 95 %.
  • Une comparaison appliquée à un tableau numpy donne un tableau de True et de False. np.mean de ce tableau donne la proportion de True, car True compte pour 1 et False pour 0.
  • np.exp(x) calcule l'exponentielle ex, sur un nombre ou sur tout un tableau.
x = np.array([55.47, 55.43, 55.45])
print(x > 55.44)             # [ True False  True]
print(np.mean(x > 55.44))    # 0.6666666666666666 : deux valeurs sur trois

1.1 Dix mille pesées simulées

Rappel de cours — Moyenne, écart-type, incertitude-type

La moyenne x̄ est la meilleure estimation de la grandeur mesurée. L'écart-type expérimental s(x) caractérise la dispersion des mesures autour de la moyenne.

u(x̄) = s(x)√n

Un résultat s'écrit par exemple T = (22,3 ± 0,5) °C, soit 21,8 °C ≤ T ≤ 22,8 °C.

Les 15 pesées du cylindre d'aluminium (niveau 1) ont une moyenne de 55,449 g et un écart-type s = 0,018 g. On simule 10 000 pesées qui suivent une loi normale de mêmes moyenne et écart-type.

  1. Compléter la ligne p1 = …… : la proportion des tirages x situés à moins de s de la moyenne.
  2. Compléter la ligne p2 = …… : la proportion des tirages situés à moins de 2s de la moyenne. Comparer à l'encadré.
  1. « À moins de s de la moyenne » : l'écart entre la valeur et m, pris en valeur absolue, est inférieur à s.
  2. La valeur absolue s'écrit abs(...), et elle s'applique à tout un tableau : abs(x - m).
  3. abs(x - m) < s est un tableau de True et de False : il reste à en prendre la moyenne avec np.mean.
Voir une solution
p1 = np.mean(abs(x - m) < s)
p2 = np.mean(abs(x - m) < 2 * s)

On obtient p1 ≈ 0,68 et p2 ≈ 0,95, à quelques millièmes près selon le tirage. Si les mesures suivent une loi normale, une nouvelle pesée a donc 95 chances sur 100 de tomber entre m − 2s et m + 2s. Le même raisonnement, appliqué à la moyenne et à son incertitude-type u, donne l'intervalle de confiance à 95 % d'un résultat : [x̄ − 2u ; x̄ + 2u].

1.2 La courbe de Gauss sur l'histogramme

Rappel — La courbe de Gauss

La loi normale de moyenne m et d'écart-type s a pour densité de probabilité :

f(x) = 1s √(2π) × exp(− (x − m)²2 s²)

L'aire totale sous la courbe vaut 1 : c'est une densité, pas un effectif.

On veut superposer à l'histogramme des 10 000 tirages la courbe de Gauss qui leur correspond. Le programme ci-dessous calcule la courbe, mais la figure obtenue n'est pas exploitable.

  1. Exécuter. Pourquoi la courbe rouge paraît-elle écrasée au bas du graphique ?
  2. La fonction plt.hist possède un paramètre qui transforme les effectifs en densité, pour que l'aire totale des barres vaille 1. Le trouver dans sa documentation, l'ajouter, et vérifier que la courbe épouse l'histogramme.
  1. Ouvrez la page matplotlib.pyplot.hist et lisez la liste Parameters, de haut en bas.
  2. Le mot anglais recherché est le même qu'en français, à une lettre près : « densité ».
  3. Les paramètres se notent comme bins=40 : un nom, le signe =, une valeur. Celui-ci attend True ou False.
Voir une solution
plt.hist(x, bins=40, density=True, edgecolor='black')

Sans ce paramètre, les barres montent à plusieurs centaines (des effectifs), alors que la courbe de Gauss culmine vers 22 g⁻¹ (une densité) : elle paraît plate. Avec density=True, la hauteur de chaque barre est divisée par l'effectif total et par la largeur de la classe : les deux se comparent enfin. L'histogramme des tirages a bien la forme d'une cloche.

1.3 Prédire

Répondre, puis vérifier dans la console si besoin (commencer par import numpy as np).

Loi normale et proportions

Des mesures de la célérité du son suivent une loi normale de moyenne 340 m·s⁻¹ et d'écart-type 2 m·s⁻¹. Quelle proportion des mesures attend-on entre 336 et 344 m·s⁻¹ ?

np.mean(np.array([1.2, 3.5, 0.4]) > 1)

Un résultat s'écrit m = 55,449 g avec u = 0,005 g. Quel est son intervalle de confiance à 95 % ?

Comparer deux mesures : l'écart normalisé

attendu de PCSI · MPSI · MP2I · BCPST · TSI

Le z-score compare une mesure à une valeur de référence, supposée exacte. Mais comment comparer deux mesures, qui ont chacune leur incertitude ? Le bloc « Mesures et incertitudes », commun à toutes les classes préparatoires scientifiques, demande de « comparer deux valeurs dont les incertitudes-types sont connues à l'aide de leur écart normalisé ».

Rappel de cours — Le z-score

z = |xexp − xréf|u(x)

z < 1 : valeurs très compatibles ; 1 ≤ z ≤ 2 : valeurs compatibles ; z ≥ 2 : valeurs non compatibles (seuil retenu en terminale).

À retenir

Deux valeurs x1 et x2 d'une même grandeur, d'incertitudes-types u1 et u2, se comparent par leur écart normalisé :

EN = |x1 − x2|√(u1² + u2²)

On l'interprète avec les mêmes seuils que le z-score. Si la seconde valeur est une référence sans incertitude (u2 = 0), on retrouve exactement le z-score.

2.1 Une longueur d'onde, deux méthodes

Rappel de cours — Diffraction et interférences

Diffraction par une fente de largeur a : L = 2 λ Da. Interférences par deux fentes distantes de b : i = λ Db.

D'après ECE PC, banque 2026, sujet n° 78. On mesure la longueur d'onde d'un laser rouge par diffraction, puis par interférences. Résultats : λdiff = 641 nm avec u = 9 nm ; λinter = 628 nm avec u = 7 nm. Le fabricant annonce 633 nm (valeurs construites pour l'exercice).

  1. Compléter la fonction ecart_normalise, puis exécuter. Les deux méthodes donnent-elles des résultats compatibles ?
  2. Avec la même fonction, comparer chacune des deux mesures à la valeur du fabricant, considérée comme exacte. Afficher les deux résultats.
  1. La racine carrée s'écrit np.sqrt, la valeur absolue abs.
  2. Attention aux parenthèses : tout le dénominateur est sous la racine, np.sqrt(u1**2 + u2**2).
  3. Pour la question 2, la valeur du fabricant a une incertitude nulle : ecart_normalise(lam_diff, u_diff, lam_ref, 0).
Voir une solution
def ecart_normalise(x1, u1, x2, u2):
    return abs(x1 - x2) / np.sqrt(u1**2 + u2**2)

print('diffraction / fabricant :', round(ecart_normalise(lam_diff, u_diff, lam_ref, 0), 2))
print('interférences / fabricant :', round(ecart_normalise(lam_inter, u_inter, lam_ref, 0), 2))

EN ≈ 1,14 : les deux méthodes sont compatibles. Face au fabricant : 0,89 et 0,71, très compatibles. Les 13 nm d'écart entre les deux méthodes semblent grands, mais chacune a sa propre incertitude : le dénominateur les compose, comme pour une différence (√(9² + 7²) ≈ 11,4 nm).

2.2 Même écart, conclusion différente

Deux groupes mesurent l'intensité de la pesanteur. Groupe A : 9,72 m·s⁻² ; groupe B : 9,86 m·s⁻². Calculer dans la console, puis répondre.

Écarts normalisés

Chaque groupe annonce une incertitude-type de 0,05 m·s⁻². Que vaut l'écart normalisé ?

Les deux groupes refont leurs mesures avec plus de soin : mêmes valeurs, mais une incertitude-type de 0,02 m·s⁻² chacun. L'écart normalisé vaut alors…

Une régression linéaire raisonnée

attendu de PCSI · MPSI · MP2I · BCPST · TSI

Au lycée, une droite qui « passe près des points » suffit souvent. Les programmes de CPGE précisent que l'analyse d'une régression linéaire « ne saurait s'appuyer sur l'exploitation non raisonnée du coefficient de corrélation (R2) ». Il faut « analyser les résultats obtenus à l'aide d'une procédure de validation : analyse graphique intégrant les barres d'incertitude ou analyse des écarts normalisés ».

À retenir

  • a, b = np.polyfit(x, y, 1) donne la pente a et l'ordonnée à l'origine b de la droite la plus proche des points (niveau 3).
  • plt.errorbar(x, y, yerr=u_y, fmt='o') trace les points avec leurs barres d'incertitude verticales. u_y est l'incertitude-type sur y : un seul nombre, ou un tableau d'une valeur par point. fmt choisit le marqueur, comme 'b+' dans plt.plot.
  • L'écart normalisé d'un point au modèle vaut Ei = (yi − (a xi + b)) / u(yi). Le modèle est validé si tous les |Ei| restent inférieurs à 2 et si leurs signes se répartissent au hasard.
  • Un R² proche de 1 dit seulement que les points sont presque alignés. Il ne dit pas si les écarts sont compatibles avec les incertitudes.

3.1 La droite d'étalonnage du TP4, validée

Rappel de cours — Loi de Kohlrausch

Pour une solution diluée ne contenant qu'un seul soluté ionique, la conductivité σ est proportionnelle à la concentration c : σ = k × c.

On reprend la gamme étalon de chlorure de sodium du TP4 (niveau 1). On estime l'incertitude-type sur chaque conductivité à 0,015 mS·cm⁻¹ (valeur construite pour l'exercice).

  1. Remplacer la ligne …… du bloc 1 par le tracé des mesures avec leurs barres d'incertitude.
  2. Compléter E = …… : le tableau des écarts normalisés des cinq points au modèle affine. Le modèle est-il validé ?
Voir une solution
plt.errorbar(c, sigma, yerr=u_sigma, fmt='o', label='mesures')
E = (sigma - (a * c + b)) / u_sigma

Les écarts normalisés valent environ −0,07 ; 0,13 ; 0,13 ; −0,53 ; 0,33 : tous inférieurs à 2 en valeur absolue, de signes mêlés. La droite passe dans toutes les barres d'incertitude : le modèle affine est validé sur cette gamme de concentrations.

3.2 Quand R² ne suffit pas

On prolonge la gamme étalon jusqu'à 100 mmol·L⁻¹. L'incertitude-type sur σ vaut maintenant 1 % de la mesure plus 0,002 mS·cm⁻¹ (valeurs construites pour l'exercice, d'ordre de grandeur réaliste).

  1. Exécuter : que vaut R² ? Que conclurait-on en ne regardant que lui ?
  2. Compléter E = ……, exécuter, et répondre au quiz.

Que conclure ?

R² vaut 0,9995. Les écarts normalisés valent environ −12 ; −3,2 ; 1,0 ; 2,1 ; 1,4 ; 0,7 ; −1,0.

Voir une solution
E = (sigma - (a * c + b)) / u_sigma

R² ≈ 0,9995 : un tableur afficherait une droite « parfaite ». Pourtant le graphique des écarts normalisés dessine une arche, avec un point à −12. Le modèle affine est rejeté sur cette gamme : il faut se limiter aux solutions diluées, ou changer de modèle.

Monte-Carlo sur une régression

attendu de PCSI · MPSI · BCPST · TSI

np.polyfit donne une pente, mais avec quelle incertitude ? Les classes préparatoires demandent de « simuler, à l'aide d'un langage de programmation ou d'un tableur, un processus aléatoire de variation des valeurs expérimentales de l'une des grandeurs – simulation Monte-Carlo – pour évaluer l'incertitude sur les paramètres du modèle ».

À retenir

  • La méthode : on fait varier au hasard chaque mesure selon son incertitude-type, on refait la régression, et on recommence un grand nombre de fois. L'écart-type des pentes obtenues est l'incertitude-type sur la pente.
  • y + np.random.normal(0, u_y, len(y)) décale chaque valeur de y d'une quantité tirée au hasard, différente pour chaque point.
  • pentes = [] crée une liste vide ; pentes.append(a) ajoute a à la fin de la liste.

4.1 L'incertitude sur la pente

Mêmes mesures qu'à l'exercice 3.1 : cinq conductivités, chacune avec une incertitude-type de 0,015 mS·cm⁻¹.

  1. Compléter la ligne sigma_sim = ……, dans la boucle, puis exécuter.
  2. Écrire la pente avec son incertitude-type, avec le bon nombre de chiffres significatifs.
  1. À chaque tour, sigma_sim est une nouvelle version des cinq mesures, légèrement modifiées au hasard.
  2. Le décalage de chaque point se tire avec np.random.normal(0, u_sigma, 5) : moyenne nulle, écart-type u_sigma, cinq valeurs.
  3. Il reste à ajouter ce décalage aux mesures sigma.
Voir une solution
    sigma_sim = sigma + np.random.normal(0, u_sigma, 5)

On obtient u(a) ≈ 0,0019, arrondi à l'excès : 0,002. La pente s'écrit a = (0,110 ± 0,002) mS·cm⁻¹ par mmol·L⁻¹. L'histogramme des 1 000 pentes a la forme d'une cloche. Le même calcul sur les ordonnées donne b = (0,05 ± 0,02) mS·cm⁻¹ : une ordonnée à l'origine non compatible avec 0, alors que la loi de Kohlrausch prévoit une droite passant par l'origine. Le modèle affine en tient compte.

4.2 La concentration du sérum, avec son incertitude

Le sérum physiologique dilué du TP4 a une conductivité σ = 0,869 mS·cm⁻¹. Sa concentration vaut c = σ − ba. Chaque couple (a, b) simulé donne une valeur de c.

  1. Compléter la ligne c_sim = …… : les 1 000 concentrations calculées avec les 1 000 couples (a, b).
  2. Afficher la concentration et son incertitude-type ; tracer l'histogramme de c_sim.
  1. pentes et ordonnees sont deux tableaux de 1 000 valeurs : un seul calcul les traite toutes d'un coup.
  2. c_sim = (sigma_serum - ordonnees) / pentes.
  3. La moyenne et l'écart-type de c_sim se calculent comme à l'exercice 4.1.
Voir une solution
c_sim = (sigma_serum - ordonnees) / pentes
print('c =', np.mean(c_sim), 'mmol/L')
print('u(c) =', np.std(c_sim, ddof=1), 'mmol/L')
plt.hist(c_sim, bins=30, edgecolor='black')
plt.xlabel('c (mmol/L)')
plt.ylabel('effectif')
plt.show()

u(c) ≈ 0,072 mmol·L⁻¹, arrondi à l'excès : 0,08. Résultat : c = (7,42 ± 0,08) mmol·L⁻¹. Au niveau 1, on lisait 7,41 sur la droite sans aucune incertitude. On pourrait aussi faire varier σsérum, mesurée elle aussi avec une incertitude : il suffit d'un tirage de plus par tour.

Résoudre une équation : bisect et Newton

attendu de PCSI · méthode de Newton : PCSI chimie

Au niveau 3, vous avez écrit une dichotomie. En classe préparatoire, on utilise aussi celle de la bibliothèque scipy. Le programme de PCSI demande de « déterminer, en s'appuyant sur une représentation graphique, un intervalle adapté à la recherche numérique d'une racine » et d'« utiliser la fonction bisect de la bibliothèque scipy.optimize (sa spécification étant fournie) ». Celui de chimie ajoute la « méthode de Newton ».

Bon à savoir

Le premier programme de cette étape qui importe scipy la télécharge : 14 Mo, une dizaine de secondes. Ensuite, elle reste chargée.

À retenir

  • from scipy.optimize import bisect charge la fonction bisect.
  • Spécification : bisect(f, a, b) renvoie une valeur approchée d'une racine de la fonction f située entre a et b. Condition : f(a) et f(b) doivent être de signes contraires, sinon bisect s'arrête sur une ValueError.
  • On passe la fonction elle-même, sans parenthèses : bisect(f, 0, 1), et non bisect(f(x), 0, 1).

5.1 L'acide éthanoïque dans l'eau

Rappel de cours — Acide faible et taux d'avancement

Un acide faible AH réagit avec l'eau selon une transformation limitée : AH(aq) + H2O(l) ⇌ A−(aq) + H3O+(aq). Sa constante d'acidité vaut :

Ka = [A−]éq × [H3O+]éq[AH]éq × c0 τ = xfxmax

Pour une concentration apportée C, en notant x = [H3O+]éq = [A−]éq, on a [AH]éq = C − x, d'où l'équation à résoudre : x²C − x = Ka. Le taux d'avancement final vaut τ = xC.

On dissout de l'acide éthanoïque (pKa = 4,8) dans l'eau, à la concentration C = 1,0 × 10⁻² mol·L⁻¹. On cherche la racine de f(x) = x²C − x − Ka.

  1. Exécuter : le graphique montre f. Lire un intervalle [a ; b] dans lequel f change de signe, et compléter la ligne x_f = bisect(f, ……, ……).
  2. Calculer le taux d'avancement final τ.
  3. Calculer le pH de la solution.
  1. La courbe coupe l'axe horizontal un peu avant 0,0005 : l'intervalle [0 ; 0,001] convient, par exemple.
  2. Choisir b = C serait une erreur : C − x s'annule, et Python refuse de diviser par zéro.
  3. τ = x_f / C, et pH = −log [H3O+], soit -np.log10(x_f).
Voir une solution
x_f = bisect(f, 0, 0.001)
tau = x_f / C
pH = -np.log10(x_f)
print('tau =', tau, ' pH =', pH)

[H3O+] ≈ 3,9 × 10⁻⁴ mol·L⁻¹, τ ≈ 0,039 et pH ≈ 3,4. En terminale, on obtient le même résultat en résolvant l'équation du second degré x² + Ka x − Ka C = 0. La méthode numérique, elle, s'applique aussi aux équations qu'on ne sait pas résoudre à la main.

5.2 La méthode de Newton

À retenir

Pour résoudre g(x) = 0, la méthode de Newton part d'une valeur x0, remplace la courbe par sa tangente en ce point, et prend pour nouvelle valeur l'abscisse où cette tangente coupe l'axe :

xn+1 = xn − g(xn)g′(xn)

scipy.optimize.newton(g, x0, fprime=g_prime) fait ce calcul jusqu'à ce que la valeur ne bouge plus.

Même solution d'acide éthanoïque. On résout cette fois g(x) = x² + Ka x − Ka C = 0, de dérivée g′(x) = 2x + Ka, en partant de x0 = C.

  1. Compléter la ligne x = …… pour qu'elle effectue une itération de Newton. Exécuter.
  2. À partir de quelle itération les quatre premiers chiffres significatifs ne changent-ils plus ? Comparer avec le résultat de scipy.
Voir une solution
    x = x - g(x) / g_prime(x)

Les valeurs successives : 5,00 × 10⁻³ ; 2,51 × 10⁻³ ; 1,28 × 10⁻³ ; 7,0 × 10⁻⁴ ; 4,58 × 10⁻⁴ ; 3,952 × 10⁻⁴ ; 3,9029 × 10⁻⁴ ; 3,902616 × 10⁻⁴. Les quatre premiers chiffres sont fixés à la 7ᵉ itération. Ensuite, le nombre de chiffres exacts double à chaque tour : c'est ce qui rend la méthode de Newton si rapide près de la racine. La dichotomie, elle, ne gagne qu'un chiffre tous les trois ou quatre tours.

5.3 L'état final d'une estérification

attendu de PCSI chimie · MPSI · TSI1

Le programme de chimie de PCSI demande de « déterminer, à l'aide d'un langage de programmation, l'état final d'un système, siège d'une transformation, modélisée par une ou deux réactions à partir des conditions initiales et valeur(s) de la(es) constante(s) thermodynamique(s) d'équilibre ».

Rappel de cours — Quotient de réaction et équilibre

Acide carboxylique + alcool ⇌ ester + eau. À l'équilibre, le quotient de réaction est égal à la constante d'équilibre K. Pour cette réaction en solvant organique, le volume se simplifie :

K = nester × neaunacide × nalcool = xf²(nA − xf)(nB − xf)

Mettre un réactif en excès déplace l'équilibre et augmente le rendement.

On fait réagir nA mol d'acide éthanoïque avec nB mol d'éthanol, sans eau ni ester au départ. Constante d'équilibre : K = 4. L'équation se réécrit h(x) = x² − K(nA − x)(nB − x) = 0, avec x entre 0 et xmax.

  1. Compléter la ligne x_max = …… de la fonction etat_final.
  2. Afficher le rendement xfxmax pour 1 mol d'acide et 1, 2 puis 5 mol d'éthanol.
  1. xmax est fixé par le réactif limitant : la plus petite des deux quantités.
  2. La fonction intégrée min(a, b) renvoie la plus petite de deux valeurs.
  3. Pour la question 2, une boucle for n_B in [1, 2, 5]: évite de recopier trois fois la même ligne.
Voir une solution
    x_max = min(n_A, n_B)

for n_B in [1, 2, 5]:
    print(n_B, 'mol d\'éthanol : rendement', etat_final(1, n_B, 4) / 1)

Rendements : 0,67 ; 0,85 ; 0,94. Avec des quantités égales, on retrouve le rendement classique de deux tiers. Un excès d'alcool améliore le rendement, de moins en moins à mesure qu'on en ajoute. Remarquez la ligne entre triples guillemets sous def : c'est la spécification de la fonction, dont l'étape 7 fait une habitude.

Équations différentielles avec odeint

attendu de PCSI · MPSI · MP2I · BCPST1

La méthode d'Euler du niveau 3 avance pas à pas. scipy fournit un solveur bien plus précis. Le programme de PCSI demande de « transformer une équation différentielle d'ordre n en un système différentiel de n équations d'ordre 1 » et d'« utiliser la fonction odeint de la bibliothèque scipy.integrate (sa spécification étant fournie) ».

À retenir

  • from scipy.integrate import odeint charge le solveur.
  • Spécification : sol = odeint(derivee, y0, t) résout dy/dt = derivee(y, t) à partir de la valeur initiale y0, aux instants du tableau t. La fonction derivee reçoit y puis t, dans cet ordre.
  • sol est un tableau à deux dimensions : une ligne par instant, une colonne par grandeur. sol[:, 0] est la première colonne, toutes lignes comprises ; sol[:, 1] la deuxième.
  • Une équation d'ordre 2 en θ devient un système d'ordre 1 en posant ω = dθ/dt : y est alors la liste [theta, omega], et derivee renvoie [dθ/dt, dω/dt].

6.1 La charge d'un condensateur

Rappel de cours — Circuit RC

Lors de la charge d'un condensateur de capacité C à travers une résistance R, sous une tension constante E, la tension uC vérifie :

duCdt = E − uCτ avec τ = R × C

Pour un condensateur initialement déchargé : uC(t) = E(1 − e−t/τ).

E = 5,0 V, R = 10 kΩ, C = 100 µF : τ = 1,0 s.

  1. Compléter la fonction derivee, puis exécuter.
  2. Ajouter au graphique la solution exacte, en pointillés, pour vérifier le résultat de odeint.
Voir une solution
def derivee(u, t):
    return (E - u) / tau

plt.plot(t, E * (1 - np.exp(-t / tau)), 'r--', label='solution exacte')

Les deux courbes sont confondues : l'écart maximal est de l'ordre de 10⁻⁷ V. Avec la méthode d'Euler et un pas de 0,025 s, l'écart serait de quelques centièmes de volt.

6.2 Le pendule simple n'est pas isochrone

Rappel — Le pendule simple

Une masse ponctuelle suspendue à un fil de longueur L oscille dans le champ de pesanteur. En PCSI, on établit l'équation de son mouvement, ici fournie, où θ est l'angle du fil avec la verticale :

d²θdt² = − gL × sin θ

Pour de petites oscillations, la période vaut T0 = 2π √(L/g), indépendante de l'amplitude : on dit que les oscillations sont isochrones.

Le programme de PCSI demande de « mettre en évidence le non isochronisme des oscillations ». Pendule de longueur L = 1,0 m, lâché sans vitesse initiale.

  1. Compléter la fonction derivee : elle renvoie [dθ/dt, dω/dt]. Exécuter.
  2. Ajouter la courbe d'un lâcher à 90°. Lire les deux périodes sur le graphique et répondre au quiz.
  1. dθ/dt vaut ω, par définition de ω.
  2. dω/dt = d²θ/dt² : c'est le second membre de l'équation, avec np.sin.
  3. Pour la seconde courbe, recopiez les trois lignes theta0 = …, sol = …, plt.plot(…) avec 90 au lieu de 10, et un autre label.

Lire les périodes

Quelle période lit-on pour le lâcher à 90° ?

Que montre la comparaison des deux courbes ?

Voir une solution
def derivee(Y, t):
    theta, omega = Y
    return [omega, -g / L * np.sin(theta)]

theta0 = 90 * np.pi / 180
sol = odeint(derivee, [theta0, 0], t)
plt.plot(t, sol[:, 0] * 180 / np.pi, label='lâcher à 90°')

À 10°, la période vaut 2,01 s, comme T0. À 90°, elle vaut 2,37 s. Essayez 150° : environ 3,5 s.

Programmer comme en CPGE : spécifier, tester

informatique commune de CPGE · BUT Mesures physiques

Toutes les classes préparatoires scientifiques ont un cours d'informatique commune. Son premier semestre veut « mettre en place une discipline de programmation : spécification précise des fonctions et programmes, annotations et commentaires, jeux de tests ». En BUT Mesures physiques, la ressource R1.07 prévoit elle aussi le « test d'un programme ».

À retenir

  • La spécification d'une fonction s'écrit entre triples guillemets, juste sous la ligne def : ce que la fonction reçoit (avec les unités et les conditions), ce qu'elle renvoie.
  • assert condition ne fait rien si la condition est vraie, et arrête le programme sur une AssertionError si elle est fausse.
  • Un jeu de tests est une suite d'assert sur des cas dont on connaît la réponse, placés juste après la fonction.
  • On ne compare jamais deux nombres à virgule avec == : on teste que leur écart est minuscule, abs(a - b) < 1e-9.
def periode(f):
    """Renvoie la période (en s) d'un signal de fréquence f (en Hz, f > 0)."""
    return 1 / f

assert abs(periode(500) - 0.002) < 1e-9
assert abs(periode(1) - 1) < 1e-9

7.1 Tester le z-score

Rappel de cours — Le z-score

z = |xexp − xréf|u(x)

Exemple du cours, titrage des ions chlorure : Cexp = 2,05 × 10⁻² mol·L⁻¹, u(C) = 0,10 × 10⁻² mol·L⁻¹, Créf = 2,10 × 10⁻² mol·L⁻¹ : z = 0,5.

  1. Compléter la ligne return ……, puis exécuter. Le test échoue : pourtant la fonction est juste. Afficher z_score(2.05, 2.10, 0.10) pour comprendre.
  2. Réécrire ce test correctement, ajouter un test qui vérifie que l'ordre des deux valeurs ne change rien, et terminer le programme par print('Tous les tests passent').
Voir une solution
    return abs(x_exp - x_ref) / u

assert abs(z_score(2.05, 2.10, 0.10) - 0.5) < 1e-9
assert abs(z_score(2.10, 2.05, 0.10) - 0.5) < 1e-9
print('Tous les tests passent')

Python calcule 0.5000000000000027 : 2,05 et 2,10 ne s'écrivent pas exactement en binaire, et la soustraction garde une trace de cette approximation. Le test avec == échoue alors que la fonction est juste. Le programme d'informatique de CPGE insiste sur ce point : « les limites de précision dans le calcul avec des flottants, en particulier pour les comparaisons ».

7.2 Les tests trouvent l'erreur

Cette fonction traduit un z-score en conclusion, avec les seuils du cours. Elle contient une erreur de logique : Python ne signale rien tant qu'on ne la teste pas.

  1. Exécuter : quel test échoue ?
  2. Corriger la fonction, sans toucher aux tests.
  1. Le test qui échoue est celui de la ligne signalée par Python.
  2. Pour z = 0,5, suivez le programme ligne à ligne : quel return est atteint en premier ?
  3. Les conditions sont examinées dans l'ordre : il faut tester le seuil le plus petit d'abord.
Voir une solution
    if z < 1:
        return 'très compatibles'
    elif z < 2:
        return 'compatibles'
    else:
        return 'non compatibles'

Le troisième test échoue : pour z = 0,5, la condition z < 2 est vraie, la fonction renvoie « compatibles » et ne regarde jamais la suite. La branche « très compatibles » n'était jamais atteinte. Sans test, l'erreur serait passée inaperçue.

À retenir

  • Un dictionnaire associe des valeurs à des clés : pKa = {'acide méthanoïque': 3.7, 'ion ammonium': 9.2}.
  • pKa['ion ammonium'] donne la valeur associée à la clé, 9.2. Une clé absente provoque une KeyError.
  • pKa['acide éthanoïque'] = 4.8 ajoute une clé, ou change sa valeur si elle existe déjà.
  • 'ion ammonium' in pKa vaut True si la clé existe ; len(pKa) donne le nombre de clés.
  • for nom in pKa: parcourt les clés ; for nom, valeur in pKa.items(): parcourt les couples clé-valeur.

7.3 Une table de pKa

Rappel de cours — pKa et force d'un acide

pKa = −log Ka Ka = 10−pKa

Plus la constante d'acidité Ka d'un couple est grande, donc plus son pKa est petit, plus l'acide est fort.

Valeurs des tables, arrondies au dixième.

  1. Ajouter au dictionnaire l'acide benzoïque, de pKa 4,2.
  2. Compléter la première boucle pour qu'elle affiche, pour chaque acide, son nom et son Ka.
  3. Compléter la condition de la seconde boucle pour trouver l'acide le plus fort de la table.
Voir une solution
pKa['acide benzoïque'] = 4.2

for nom, valeur in pKa.items():
    print(nom, 'Ka =', 10 ** (-valeur))

plus_fort = 'acide éthanoïque'
for nom in pKa:
    if pKa[nom] < pKa[plus_fort]:
        plus_fort = nom

On compare le pKa de chaque acide à celui du meilleur candidat trouvé jusque-là. L'acide méthanoïque, de pKa 3,7, est le plus fort ; l'ion ammonium, de pKa 9,2, le plus faible. Le dictionnaire évite de tenir deux listes parallèles, une de noms et une de valeurs, qu'il faudrait garder dans le même ordre.

Personnaliser un graphique : chercher dans la documentation

attendu de PCSI chimie · BUT Mesures physiques

À l'ECE, tout le code de tracé est fourni. Après le bac, personne ne vous dira quel paramètre écrire : on cherche dans la documentation. Le programme de chimie de PCSI demande de « rendre le graphe exploitable (présence d'une légende, choix des échelles…) », et celui du BUT Mesures physiques d'« utiliser différentes représentations graphiques pour le traitement de données de mesures ». Dans cette étape, la réponse n'est jamais dans l'énoncé : elle est dans la documentation de matplotlib.

Lire une page de documentation

  • La documentation est en anglais. Chaque fonction a sa page, toujours construite de la même façon : la signature en haut (le nom et ses paramètres), puis Parameters (chaque paramètre, ce qu'il attend), Returns, et des Examples en bas.
  • Les paramètres listés après **kwargs se donnent sous la forme nom=valeur, dans n'importe quel ordre.
  • Quelques mots utiles : width largeur, style style, dashed en tirets, dotted en pointillés, scale échelle, arrow flèche, vertical vertical, row ligne, column colonne.
  • La page d'accueil des fonctions de pyplot : matplotlib.org — pyplot. Votre navigateur sait aussi traduire une page.

8.1 Le diagramme de distribution, lisible

Rappel de cours — Diagramme de distribution

Le diagramme de distribution d'un couple acide/base donne les pourcentages de l'acide et de la base en fonction du pH. À l'intersection des deux courbes, les deux espèces sont à 50 % : pH = pKa.

%AH = 1001 + 10pH − pKa

Couple acide méthanoïque / ion méthanoate, pKa = 3,7. Pages utiles : pyplot.plot, les couleurs nommées, et la page d'accueil de pyplot.

  1. Tracer la courbe de l'acide avec une épaisseur de trait de 3.
  2. Tracer la courbe de la base en tirets.
  3. Ajouter une droite verticale en pH = pKa. Indice : au niveau 4, vous avez déjà rencontré plt.axhline.
  4. Sans correction automatique : choisir pour chaque courbe une couleur dans la liste des couleurs nommées.
Voir une solution
plt.plot(pH, acide, color='darkorange', linewidth=3, label='HCOOH')
plt.plot(pH, base, color='teal', linestyle='--', label='HCOO⁻')
plt.axvline(pKa, color='gray', linestyle=':')

linewidth a un nom court, lw ; linestyle accepte '--' ou 'dashed'. axvline se trouve dans la page d'accueil de pyplot, juste à côté d'axhline : v pour vertical, h pour horizontal.

8.2 Une échelle logarithmique

Rappel de cours — Loi de vitesse d'ordre 1

Si la vitesse volumique de disparition d'un réactif A est proportionnelle à sa concentration, v = k × [A], alors [A] décroît exponentiellement : [A](t) = [A]0 × e−kt.

On suit la concentration d'un réactif A pendant 20 minutes (valeurs construites pour l'exercice). Sur le graphique ordinaire, les dernières mesures sont écrasées contre l'axe : on ne voit pas si la loi d'ordre 1 est vérifiée. Page utile : pyplot.yscale.

  1. Trouver dans la documentation comment mettre l'axe vertical en échelle logarithmique, et l'ajouter.
  2. Les points sont-ils alignés ? Que peut-on en conclure sur l'ordre de la réaction ?
Voir une solution
plt.yscale('log')

Sur une échelle logarithmique, des valeurs qui se divisent par le même nombre à intervalles de temps égaux sont régulièrement espacées : une exponentielle décroissante devient une droite. Les points sont alignés : la loi de vitesse d'ordre 1 est compatible avec les mesures. plt.semilogy(t, A, 'o'), trouvée dans la même documentation, fait le même travail en une ligne.

8.3 Deux graphiques l'un sous l'autre

Rappel de cours — Interférences de deux ondes

Deux ondes de même fréquence qui se superposent s'additionnent. En phase, l'amplitude de la somme est maximale : interférences constructives. En opposition de phase (déphasage de π), elles s'annulent : interférences destructives.

Le programme de terminale demande de « représenter, à l'aide d'un langage de programmation, la somme de deux signaux sinusoïdaux périodiques synchrones en faisant varier la phase à l'origine de l'un des deux ». On veut les deux signaux en haut, leur somme en bas. Page utile : pyplot.subplot.

  1. Trouver dans la documentation comment découper la figure en deux graphiques l'un sous l'autre, et placer chaque tracé dans le bon.
  2. Donner à phi la valeur π. Qu'observe-t-on ?
  1. Dans la page de subplot, les trois nombres décrivent le nombre de lignes, le nombre de colonnes, puis le numéro du graphique.
  2. Ici, 2 lignes et 1 colonne : plt.subplot(2, 1, 1) pour le graphique du haut.
  3. Chaque appel à subplot se place juste avant les tracés et les légendes du graphique qu'il désigne.
Voir une solution
phi = np.pi

plt.subplot(2, 1, 1)
plt.plot(t, s1, label='s1')
plt.plot(t, s2, '--', label='s2')
plt.ylabel('tension (V)')
plt.legend()

plt.subplot(2, 1, 2)
plt.plot(t, s, 'k', label='s1 + s2')
plt.xlabel('t (s)')
plt.ylabel('tension (V)')
plt.legend()
plt.show()

Avec φ = 0, la somme a une amplitude de 4 V : constructives. Avec φ = π, les deux signaux sont en opposition de phase et la somme est nulle à chaque instant : destructives.

8.4 Une flèche sur le graphique

On reprend la droite d'étalonnage du TP4 et le point du sérum dilué. On veut un texte « sérum dilué » placé à côté du point, relié à lui par une flèche. Page utile : pyplot.annotate — lisez d'abord les exemples en bas de page.

  1. Ajouter l'annotation avec sa flèche, le texte étant placé vers c = 3 mmol·L⁻¹, σ = 1,0 mS·cm⁻¹.
  1. plt.annotate attend d'abord le texte, puis xy : les coordonnées du point visé.
  2. xytext donne la position du texte. Sans lui, le texte se pose sur le point.
  3. La flèche demande le paramètre arrowprops, qui reçoit un dictionnaire, par exemple arrowprops={'arrowstyle': '->'}.
Voir une solution
plt.annotate('sérum dilué', xy=(c_serum, sigma_serum), xytext=(3, 1.0),
             arrowprops={'arrowstyle': '->'})

arrowprops reçoit un dictionnaire, comme ceux de l'étape 7 : la documentation de matplotlib en utilise partout pour regrouper des réglages.

Bilan du niveau 4

Ce que je sais faire

  • Simuler des mesures avec np.random.normal et associer un intervalle de confiance à un écart-type.
  • Superposer une courbe de Gauss à un histogramme normalisé.
  • Comparer deux mesures par leur écart normalisé.
  • Valider une régression linéaire avec des barres d'incertitude et des écarts normalisés, sans me fier au seul R².
  • Évaluer par Monte-Carlo l'incertitude sur la pente d'une droite, et sur une grandeur qui s'en déduit.
  • Résoudre une équation avec bisect ou la méthode de Newton, et trouver l'état final d'un équilibre.
  • Résoudre une équation différentielle d'ordre 1 ou 2 avec odeint.
  • Spécifier une fonction, la tester avec assert, utiliser un dictionnaire.
  • Trouver dans la documentation de matplotlib le paramètre qui me manque.

Ces outils sont ceux de la première année de classe préparatoire. Le niveau 5 regarde plus loin : spectre d'un son, échantillonnage, filtrage, ce qu'attendent la deuxième année et les spécialités.