# -*- coding: utf-8 -*-
"""TP_1_2024_2025_titrage_vinaigre_complété_Monte_Carlo_fonctionnel.ipynb

Automatically generated by Colab.

Original file is located at
    https://colab.research.google.com/drive/1x7HoAtXs15hphWpiyEk8TVW1jvARZRjC

# **1. Résultats expérimentaux**
"""

#Importation des bibliothèques essentielles

import numpy as np
import matplotlib.pyplot as plt
import numpy.random as rd

#Données du problème (A compléter)

M = 60                      #g/mol  (masse molaire de l'acide éthanoïque)
rho = 1020                  #g/L    (masse volumique du vinaigre)
t_Vbur = 0.03               #mL     (tolérance de la burette)
t_Va = 0.05                 #mL     (tolérance de la pipette jaugée)
Cb = 0.100                  #mol/L
u_Cb = 0.00058              #mol/L
Va = 10                     #mL
u_Va = 0.029                #mL
u_Ve = 0.05                 #mL (à adapter en fonction du déroulement réel du titrage)

#Résultats expérimentaux

V = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11.25, 11.5, 11.75, 12, 12.25, 12.4, 12.65, 12.9, 13.2, 13.4, 13.7, 13.9, 14.2, 14.9, 15.4, 16.4, 17.4, 18.4, 19.4, 20.4, 21.4])
pH = np.array([2.83, 3.72, 4.05, 4.27, 4.45, 4.60, 4.74, 4.88, 5.03, 5.20, 5.41, 5.70, 5.80, 5.94, 6.12, 6.42, 7.66, 10.86, 11.27, 11.47, 11.61, 11.71, 11.79, 11.85, 11.91, 12.04, 12.11, 12.21, 12.29, 12.35, 12.40, 12.44, 12.48])

"""#**2. Tracé de la courbe du pH en fonction du volume de solution titrante versé**"""

#Tracé de la courbe pH = f(V)

plt.plot(V, pH, 'b+')
plt.xlabel('Volume de solution titrante versée / mL')
plt.ylabel('pH')
plt.title('Evolution du pH en fonction de V')
plt.grid()
plt.show()

"""# **3. Évaluation du volume équivalent**

On estime numériquement les valeurs de $\frac{\mathrm{d}pH}{\mathrm{d}V}$ pour divers volumes $V$ de solution titrante versée. Les valeurs de $\frac{\mathrm{d}pH}{\mathrm{d}V}$ sont déterminées à l'aide de la dérivée centrée sur un point d'abscisse $V_i$, c'est à dire :

$$ \left( \dfrac{dpH}{dV} \right)_i =  \dfrac {pH_{i+1}-pH_{i-1}}{V_{i+1}-V_{i-1}}. $$

Il faut noter qu'on ne peut évaluer ainsi la dérivée sur les points extrèmes — on n'en a de toute façon pas besoin. On crée une fonction `VolEq` qui prend en argument les array `V` et `pH`, et qui retourne :
* un array contenant les dérivées numériques ;
* un array contenant les volumes, privés des deux points extrèmes.

Pour évaluer le volume équivalent, on repère le volume qui maximise la dérivée précédemment calculée.
"""

def VolEq(V, pH):
  dpHdV = (pH[2:]-pH[0:-2])/(V[2:]-V[0:-2]) # [2:] de 2 jusqu'à la fin ; [0:-2] de 0 jusqu'à l'avant avant dernier (on retire à partir de l'avant dernier élément d'où le -2)
  V2 = V[1:-1]                              # [1:-1] de 1 jusqu'à l'avant dernier élément (on retire le dernier élèment d'où le -1)
  return V2[np.argmax(dpHdV)]  # np.argmax renvoie l'indice pour lequel l'élément de l'array argument est le plus grand

plt.plot(V[1:-1], (pH[2:]-pH[0:-2])/(V[2:]-V[0:-2]), 'b.')
plt.xlabel('Volume de solution titrante versée / mL')
plt.ylabel('$\dfrac{pH}{dV}$')
plt.title('Courbe dérivée du pH en fonction du volume')
plt.grid()
plt.show()

print('Veq =', VolEq(V, pH), 'mL')

#Calcul et affichage de la concentration du vinaigre dilué
Cdilué = Cb*VolEq(V,pH)/Va
print('Cdilué =', Cdilué, 'mol/L')

"""# **4- Principe de la méthode Monte-Carlo**

---


**Le résultat d'une mesure correspond à l'ensemble des valeurs raisonnablement attribuables à la grandeur mesurée.**

L'écart-type de cet ensemble de valeurs est appelée l'incertitude-type.

**Evaluation de type A :** Lorsque la mesure est répétée plusieurs fois, l'expérimentateur obtient plusieurs valeurs de la grandeur mesurée.  L'incertitude-type est l'écart-type de cet ensemble de valeurs.

**Evaluation de type B :** Lorsque l'expérience n'est pas répétée plusieurs fois, il faut mettre en oeuvre une autre méthode pour évaluer l'incertitude-type. Dans ce contexte, la méthode de Monte-Carlo consiste à simuler numériquement la répétition de l'expérience. L'écart-type de l'ensemble des valeurs obtenues lors de ces répétitions *in silico* fournit l'incertitude-type recherchée.

La méthode de Monte-Carlo est très utile à mettre en oeuvre dans le cas d'une **propagation d'incertitudes**, c'est-à-dire lorsque l'on souhaite déterminer l'incertitude-type sur une grandeur calculée à partir de grandeurs expérimentales, mesurées ou fournies.

## Sources d'incertitudes

L'incertitude sur la concentration en acide est liée aux incertitudes sur les grandeurs $\mathsf{ [CH_3COOH]_{titrée} \text{ , } [HO^-]_{titrante} \text{ et } V_{eq}}$. Celles-ci doivent être évaluées.

Proposition à adapter en fonction de la situation :

* **volume de solution titrée :** l'expérimentateur a utilisé une pipette jaugée de $\mathsf{10 mL}$ pour prélever le volume $\mathsf{V_{sol}}$. Selon l'habileté du manipulateur et la classe de la pipette, le volume effectivement prélevé a de grandes chances d'appartenir à l'intervalle $\mathsf{[9,9 \text{ , } 10,1] \text{ mL}}$ *(valeurs à adapter selon le contexte et l'expérimentateur)*,

* **concentration de la solution titrante :** selon la qualité des réactifs utilisés, la nature de la verrerie utilisée et l'habileté du préparateur, la solution titrante de concentration affichée $\mathsf{[HO^-]_{titrante} = 0,100 \text{ mol} \cdot L^{-1}}$ a de grandes chances d'appartenir à l'intervalle $\mathsf{[0.099 \text{ , } 0.101] \text{ mol} \cdot L^{-1}}$ *(valeurs à adapter selon le contexte et l'expérimentateur)*,

* **volume équivalent :** selon l'espacement entre les points de mesure sur la courbe de titrage, selon la méthode retenue pour évaluer le volume équivalent, selon la précision de la burette graduée utilisée et la capacité de l'expérimentateur à lire les volumes sur les graduations et à régler le zéro, on peut penser que si le volume équivalent $\mathsf{V_{eq} = 9.7 \text{ mL}}$ alors il a de grandes chances d'appartenir à l'intervalle $\mathsf{[9.6 \text{ , } 9.8] \text{ mL}}$ *(valeurs à adapter selon le contexte et l'expérimentateur)*.

# **5- Etapes de la méthode**

---

1. Lister les grandeurs expérimentales utiles pour le calcul de $\mathsf{ [CH_3COOH]_{titrée}}$ et associer à chacune, un intervalle au sein duquel on peut raisonnablement penser que celle-ci appartient,

2. Faire procéder à un tirage au sort aléatoire d'un jeu de valeurs pour chaque grandeur expérimentale $\mathsf{[HO^-]_{titrante} \text{ et } V_{sol} \text{ et } V_{eq}}$ et faire calculer la valeur de concentration $\mathsf{ [CH_3COOH]_{titrée}}$ obtenue avec ce jeu de valeurs.

3. Stocker la valeur dans une liste de résultats,

4. Calculer la moyenne des valeurs de concentration $\mathsf{ [CH_3COOH]_{titrée}}$ obtenues, meilleur estimateur de la concentration recherchée,

5. Calculer l'écart-type de l'ensemble des valeurs de concentration, incertitude-type associée à $\mathsf{ [CH_3COOH]_{titrée}}$.

# **6- Fonctions pour réaliser le tirage au sort**

---

La bibliothèque `numpy` est ici utilisée pour simuler un processus aléatoire (`numpy.random`).

Pour réaliser le tirage au sort :

* Si l'on suppose que la *valeur centrale* de l'intervalle **n'est pas plus probable** que les valeurs latérales de l'intervalle, on peut utiliser la commande `numpy.random.uniform(borne_inf , borne_sup)`.

* Si l'on suppose que la *valeur centrale* de l'intervalle **est plus probable** que les valeurs latérales de l'intervalle, on peut utiliser la commande `numpy.random.triangular(borne_inf , centre ,  borne_sup)`.

* Si **l'incertitude-type sur la grandeur est fournie/connue**, on peut utiliser la commande `numpy.random.normal(valeur centrale ,  incertitude-type)`.

# **7- Exemple de code**
"""

# Simulation de N = 10000 titrages par la méthode de Monte Carlo
N = 10000                    # nombre de tirages à réaliser

Va_sim =  Va + rd.normal(0,u_Va, N)           # simulation des valeurs de Va
Cb_sim =  Cb + rd.normal(0,u_Cb, N)           # simulation des valeurs de Cb
Ve_sim =  12.25 + rd.normal(0,u_Ve, N)             # simulation des valeurs de Ve

Ca_sim =  Cb_sim*Ve_sim/Va_sim           # simulation des valeurs de Ca

# Représentation de l'histogramme
plt.hist(Ca_sim, bins='rice')
plt.show()

# Analyse statistique des résultats de la simulation de Monte Carlo
Ca_moy = np.average(Ca_sim)                             #Calcul de la valeur moyenne de Ca_sim
uCa = np.std(Ca_sim,ddof=1)                             #Calcul de l'écart-type

print(f'Concentration Ca : {Ca_moy} mol/L')             #Affichage des résultats
print(f'Incertitude-type u(Ca) : {uCa} mol/L')

"""# **8- Conclusion**

---


Calculer le degré d'acidité du vinaigre et comparer à l'étiquette.

"""