Mise en solution d'un acide dans l'eau : modèle d'un acide fort ou d'un acide faible

Le script aborde la modélisation de la mise en solution d'un acide dans de l'eau. Selon le cas, la détermination de la composition du système à l'état final se fait en considérant une ou deux réactions :

  • Reaction 1 : $\mathsf{AH(aq) + H_2O(l) = A^-(aq) + H_3O^+(aq)}$
  • Reaction 2 : $\mathsf{2H_2O(l) = HO^-(aq) + H_3O^+(aq)}$

A la fin du script, sont proposés deux programmes automatisant :

  • La détermination de l'état final pour différentes concentrations initiales d'acide. L'utilisateur n'y a qu'à saisir la valeur du $\mathsf{pK_a}$ du couple de l'acide qu'il souhaite étudier.
  • Le tracé de courbes montrant l'évolution du taux de dissociation d'un acide en fonction de la concentration initiale et du $\mathsf{pK_a}$.

Composition du système à l'état final


Principe de recherche de l'état final

Lorsque seule la réaction 1 est envisagée pour modéliser la mise en solution de l'acide dans l'eau, la recherche de l'avancement à l'état final s'effectue par résolution du polynôme issu de la relation de Guldberg-Waage. \begin{equation}\mathsf{ K_a=\frac{[A^-]_{eq} \cdot [H_3O^+]_{eq}}{[AH]_{eq}\cdot C°}=\frac{x^2}{(C-x)\cdot C°}} \end{equation}

En revanche, lorsque les deux réactions sont considérées, deux avancements doivent être introduits (donc deux inconnues) ce qui rend la recherche de l'état final plus difficile. Ce problème est contourné de manière à se ramener à la résolution d'une équation à une seule inconnue.

L'équation à résoudre est obtenue par l'écriture des deux relations de Guldberg-Waage ainsi que par une équation d'électroneutralité. \begin{equation}\mathsf{ K_a=\frac{[A^-]_{eq} \cdot [H_3O^+]_{eq}}{[AH]_{eq}\cdot C°} \\ K_e=\frac{[HO^-]_{eq} \cdot [H_3O^+]_{eq}}{(C°)^2} \\ [A^-]_{eq} + [HO^-]_{eq} = [H_3O^+]_{eq}} \end{equation}

Ainsi, en notant $\mathsf{h}$ la concentration des ions oxonium $\mathsf{[H_3O^+]_{eq}}$, l'équation à résoudre est : \begin{equation}\mathsf{ h^3 + K_a \cdot h^2 - (K_e + K_a \cdot C_0) \cdot h - K_a \cdot K_e = 0 } \end{equation}

Bibliothèques utilisées

La commande linspace de la bibliothèque numpy permet de générer une liste d'abscisses.

La bibliothèque matplolib est utilisée pour tracer des graphiques.

Le module optimize de la bibliothèque scipy offre plusieurs fonctions pour rechercher les racines d'une fonction.

Manipulation du script

L'utilisateur peut modifier la valeur du $\mathsf{pK_a}$ du couple acide-base auquel appartient l'acide, ainsi que la concentration apportée, notée $\mathsf{C_0}$ de cet acide dans la solution.

In [ ]:
#DETERMINATION DE LA COMPOSITION A L'ETAT FINAL

import numpy as np
import scipy.optimize as op

#Saisie des données relatives à l'acide introduit
pKa=5       # pKa du couple de l'acide
C0=1E-2     # concentration en mol/L

#Calcul des constantes d'équilibre
Ka=10**(-pKa)
Ke=10**(-14)


"""Modélisation par une seule réaction"""
#Equation à résoudre
def EFRP(h):
    return h**2 - (C0-h)*Ka

#Recherche de la racine dans l'intervalle [0,CO]
hfRP=op.bisect(EFRP,0,C0)  

#Caractérisation de l'état final : taux d'avancement et pH
tauRP=hfRP/C0             
pHRP=-np.log10(hfRP)      


"""Modélisation par deux réactions"""
#Equation à résoudre
def EF(h):
    return h**3 + Ka * h**2 - (Ke+Ka*C0) * h - Ka*Ke
    
#Recherche de la racine
hf=op.bisect(EF,0,1)   

#Caractérisation de l'état final : taux d'avancement et pH
tau=Ka/(hf+Ka)
pH=-np.log10(hf)


"""Affichage des resultats"""
print("Concentration C0 = ","{:.2e}".format(C0)," mol/L")
print("Avec une réaction : tau = ",round(tauRP,2)," et pH = ",round(pHRP,1))
print("Avec deux réactions : tau = ",round(tau,2)," et pH = ",round(pH,1))
Concentration C0 =  1.00e-02  mol/L
Avec une réaction : tau =  0.03  et pH =  3.5
Avec deux réactions : tau =  0.03  et pH =  3.5

Domaine de validité d'une modélisation par une seule réaction


Le script présenté ci-dessous reprend les fonctions définies dans le script précédent et automatise la recherche de l'état final pour différentes concentrations de l'acide (de $\mathsf{1\cdot10^{-1}}$ à $\mathsf{1\cdot10^{-8} mol\cdot L^{-1}}$).

Le taux d'avancement et le $\mathsf{pH}$ final sont fournis pour les deux modélisations (1 ou 2 réactions) en vue de comparer les résultats obtenus.

D'autre part, un graphique est généré pour faciliter l'identification des limites de validité d'une modélisation de la mise en solution d'un acide dans l'eau par une seule réaction.

Le code inclut des insctructions facultatives de mise en forme du tableau final qui peuvent sembler alourdir son appropriation. Ces instructions peuvent tout à fait être omises si l'utilisateur ne tient pas à avoir des colonnes alignées dans le tableau des résultats.

Manipulation du script

Il est possible de modifier la valeur du $\mathsf{pK_a}$ du couple auquel appartient l'acide mis en solution.

In [ ]:
#DOMAINE DE VALIDITE D'UNE MODELISATION PAR UNE SEULE REACTION

import numpy as np
import scipy.optimize as op
import matplotlib.pyplot as plt

#Saisie du pKa du couple de l'acide étudié 
pKa = 5

#Initialisation de listes de valeurs de pH calculées à l'état final
Liste_pHRP,Liste_pH=[],[]

#Initialisation d'un "tableau" des résultats
Result=[['{:^6}'.format('C'),'{:^6}'.format('tau2R'),'{:^6}'.format('tau1R'),'{:^6}'.format('pH2R'),'{:^6}'.format('pH1R')]]

#Boucle de recherche de l'état final en fonction de la concentration
Liste_pC = [.5*i for i in range(1,17)]
for i in Liste_pC :
    def EF(h):
        return h**3 + 10**-(pKa) * h**2 - (Ke+10**(-pKa)*C)* h - 10**(-pKa)*Ke
    def EFRP(h):
        return h**2 - (C-h)*10**(-pKa)
    C=10**-i
    hfRP=op.bisect(EFRP,0,C)
    hf=op.bisect(EF,0,1)
    Result.append(['{:.0e}'.format(C),'{:^6}'.format(round(10**-pKa/(hf+10**-pKa),2)),'{:^6}'.format(round(hfRP/C,2)),'{:^6}'.format((round(-np.log10(hf),1))),'{:^6}'.format(round(-np.log10(hfRP),1))])
    Liste_pHRP.append(-np.log10(hfRP))
    Liste_pH.append(-np.log10(hf))

#Procédure de tracé
plt.plot(Liste_pC,Liste_pHRP,'b--', label='Mod. 1 réaction')
plt.plot(Liste_pC,Liste_pH,'g--', label='Mod. 2 réactions')
plt.xlabel('pC')
plt.ylabel('pH')
plt.title(f"Mise en solution d'un acide dont le couple a un $pK_a$ = {pKa} \n pH calculé dans le cas d'une modélisation par 1 ou 2 réactions")
plt.legend()
plt.grid()
plt.show()

#Affichage d'un tableau de valeurs
print(f"pKa du couple de l'acide : pKa = {pKa}")
for i in [0,2,4,6,8,10,12,14,16]:
    print(Result[i])
pKa du couple de l'acide : pKa = 5
['  C   ', 'tau2R ', 'tau1R ', ' pH2R ', ' pH1R ']
['1e-01', ' 0.01 ', ' 0.01 ', ' 3.0  ', ' 3.0  ']
['1e-02', ' 0.03 ', ' 0.03 ', ' 3.5  ', ' 3.5  ']
['1e-03', ' 0.1  ', ' 0.1  ', ' 4.0  ', ' 4.0  ']
['1e-04', ' 0.27 ', ' 0.27 ', ' 4.6  ', ' 4.6  ']
['1e-05', ' 0.62 ', ' 0.62 ', ' 5.2  ', ' 5.2  ']
['1e-06', ' 0.92 ', ' 0.92 ', ' 6.0  ', ' 6.0  ']
['1e-07', ' 0.98 ', ' 0.99 ', ' 6.8  ', ' 7.0  ']
['1e-08', ' 0.99 ', ' 1.0  ', ' 7.0  ', ' 8.0  ']

Conclusion

Quelle que soit la valeur du $\mathsf{pK_a}$ du couple auquel appartient l'acide mis en solution dans l'eau, la recherche de l'état final au moyen d'une seule réaction fournit des résultats robustes tant que le $\mathsf{pH}$ de la solution est inférieur à $\mathsf{6,5}$. La prise en compte de l'autoprotolyse de l'eau n'est nécessaire que lorsque le $pH$ calculé est supérieur à $\mathsf{6,5}$.

Modèle d'un acide fort


Le script recherche l'état final pour différentes valeurs de $\mathsf{pK_a}$ et différentes valeurs de concentrations apportées $\mathsf{C_0}$ d'un acide dans l'eau.

L'un des enjeux est de montrer que pour des transformations modélisées par une même réaction (associée par conséquent à une même valeur de constante thermodynamique d'équilibre), le taux d'avancement final est directement liée aux conditions expérimentales (ici, la concentration d'acide apporté).

Manipulation du script

Il est possible de modifier la valeur du $\mathsf{pK_a}$ du couple auquel appartient l'acide mis en solution.

In [ ]:
#INFLUENCE DU pKa DU COUPLE DE L'ACIDE ET DE LA CONCENTRATION APPORTEE SUR LE TAUX DE DISSOCIATION D'UN ACIDE DANS L'EAU

import numpy as np
import scipy.optimize as op
import matplotlib.pyplot as plt

#Liste des valeurs de concentrations et de pKa testées 
Liste_pC=[.25*i for i in range(1,30)]
Liste_pKa=[-2,0,2,4,6,8]

#Initialisation d'une liste des taux d'avancement calculés
Liste_tau=[]

#Boucle de recherche de l'état final
for pKa in Liste_pKa :
    L=[]
    for pC in Liste_pC:
        def EF(h):
            return h**3 + 10**-(pKa) * h**2 - (Ke+10**(-pKa)*10**-pC)* h - 10**(-pKa)*Ke
        hf=op.bisect(EF,0,1)
        L.append(10**-pKa/(hf+10**-pKa))
    Liste_tau.append(L)

#Procédure de tracé
plt.plot(Liste_pC,Liste_tau[0],'b--', label=(f"pKa = {Liste_pKa[0]}"))
plt.plot(Liste_pC,Liste_tau[1],'g--', label=(f"pKa = {Liste_pKa[1]}"))
plt.plot(Liste_pC,Liste_tau[2],'y--', label=(f"pKa = {Liste_pKa[2]}"))
plt.plot(Liste_pC,Liste_tau[3],'k--', label=(f"pKa = {Liste_pKa[3]}"))
plt.plot(Liste_pC,Liste_tau[4],'r--', label=(f"pKa = {Liste_pKa[4]}"))
plt.plot(Liste_pC,Liste_tau[5],'m--', label=(f"pKa = {Liste_pKa[5]}"))   
plt.xlabel('pC')
plt.ylabel("Taux d'avancement")
plt.title("Taux de dissociation en fonction du $pK_a$ et de la concentration $C_0$")
plt.legend()
plt.grid()
plt.show()

Conclusion

Pour les acides appartenant à des couples de $\mathsf{pK_a}$ négatif, le taux de dissociation de l'acide est pratiquement toujours de 100%. Ces acides sont qualifiés d'acides forts.