1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
#!/usr/bin/env python
#-*- coding: utf-8 -*-
import numpy as np #Importation d'une extention de la librairie matplotlib : numpy.
#NumPy est une extension du language de programmation Python, destinée à manipuler des matrices ou tableaux multidimensionnels ainsi que des fonctions mathématiques opérant sur ces tableaux.
import math
from matplotlib.pyplot import * #Importation d'une librairie supplémentaire : matplotlib.
#Matplotlib est une librairie permettant de tracer des graphiques pour le langage de programmation Python. Il utilise une extension de mathématiques numérique : NumPy.
from Tkinter import * #Tkinter est la bibliothèque graphique libre d'origine pour le language Python, permettant la création d'interfaces graphiques.
def volume(pK,ca,va,cb,ph): #On définit la fonction "volume" dépendant du pka de l'acide (pK), de la concentration initiale de ce dernier (ca), son volume initial(va), la concentration initiale en titrant (cb) et le pH.
#Cette fonction fait le calcul des concentrations et des volumes à une valeur de pH donnée.
#Le but de cette première partie de code est de traduire en language python les équations d'échanges protoniques et de conservation de masse de notre problème.
n = len(pK) #pK est une liste contenant 3 éléments ( qui sont les pka de notre polyacide). la fonction "len" appliquée à pK nous renvoie le nombre d'éléments n compris dans cette liste.
#Ainsi, n correspond au nombre maximal de protons que le polyacide peut libérer.
Ke = 1.0e-14 #On pose que Ke correspond au produit ionique de l'eau.
h = 10**(-ph) #On pose que h correspond à la concentration en ion H+ présent dans le milieu.
c = np.ones(n+1) #On définit c comme étant une matrice constituée de n + 1 colonnes, 1 ligne et uniquement remplies de 1.
Da = 1 #On pose que Da correspond au coefficient de distribution de la base conjuguée (phosphate) provenant du titré. Sa forme actuelle ne correspond pas encore à celle dans nos calculs.
kk = 1
for p in range(1,n+1): #Nous devons définir Da comme étant égale à la somme de 4 termes (d'où cette largeur de "range"). Pour tout élément p dans une liste allant de 1 à n+1.
kk *= 10**(-pK[p-1])#kk est ici redéfini comme étant un produit de constantes de dissociation, et cela en multipliant kk = 1 par des Ka.
x = h**p/kk
c[p] = x #????
Da += x #On incrémente à la variable Da = 1, la variable x = c[p]
Na = n #Tout comme Da, Na est introduit afin d'alléger l'écriture de nos calculs. Sa forme actuelle ne correspond pas encore à celle de nos calculs.
kk = 1
for p in range(1,n): #Nous devons définir Na comme étant égale à la somme de 3 termes (d'où cette largeur de "range").
kk *= 10**(-pK[p-1])#idem que précédemment.
Na += (n-p)*h**p/kk #On incrémente à la variable Na = n la variable (n-p)*h**p/kk.
y = Ke/h-h #Comme Ke/h correspond à la concentration en ion hydroxyde, y correspond à [H3O+] - [OH-].
vb = va*(y+Na*ca/Da)/(cb-y) #Au final, par ce raisonnement, nous réussissons à exprimer vb uniquement au départ de constantes et de h.
for p in range(n+1):
c[p] *= ca*va/(va+vb)/Da
return [vb,c]
def plot_pH(pK,ca,va,cb,vb_max): # On définit une fonction "graphique" qui va nous permettre de créer le graphique de titrage. Les paramètres de cette fonction sont les pK, ca, va, cb et vb_max.
npts = 1000 # On définit le nombre de points que va contenir notre graphique afin de le tracer avec une assez bonne précision.
pH = np.zeros(npts) # On définit pH comme étant une matrice constituée de 1000 colonnes (npts), 1 ligne et uniquement remplies de 0.
vb = np.zeros(npts) # On définit vb comme étant une matrice constituée de 1000 colonnes (npts), 1 ligne et uniquement remplies de 0.
ph_max = 14+math.log10((vb_max*cb-ca*va)/(vb_max+va)) # On définit le pH maximum (ph_max) de notre titrage par la formule d'une base forte (ici, le titrant) qui sera en excès en solution une fois l'acide complètement neutralisé.
# Le volume maximum (vb_max) de la base (titré) est choisi arbitrairement plus tard.
dph = ph_max/(npts-1) #
for i in range(npts):
ph = dph*i
[vb[i],c] = volume(pK,ca,va,cb,ph)
pH[i] = ph
plot(vb,pH)
axis([0,vb_max,0,14])
xlabel("Volume de NaOH (mL)")
ylabel("pH")
ax = gca()
ax.barh(3.1, vb_max, height=1.3, color='orange', label=u"hélianthine")
ax.barh(8.2, vb_max, height=1.8, color='red', label=u"phénolphtaléine")
legend(loc=2)
ax.annotate(u'1ère équivalence', xy=(10., 4.65), xycoords='data',
xytext=(15.,5.), textcoords='data',
bbox=dict(boxstyle="round", fc="#0FE3E3"),
arrowprops=dict(arrowstyle="->",
connectionstyle="arc3"),)
ax.annotate(u'2ème équivalence', xy=(20., 9.2), xycoords='data',
xytext=(5.,9.), textcoords='data',
bbox=dict(boxstyle="round", fc="#0FE3E3"),
arrowprops=dict(arrowstyle="->",
connectionstyle="arc3"),)
ax.annotate('[$H_3PO_4$] = [$H_2PO_4^-$]', xy=(5., 2.7), xycoords='data',
xytext=(5.,1.), textcoords='data',
bbox=dict(boxstyle="roundtooth", fc="#2EF075"),
arrowprops=dict(arrowstyle="->",
connectionstyle="arc3"),)
ax.annotate('[$H_2PO_4^-$] = [$HPO_4^{2-}$]', xy=(15., 7.2), xycoords='data',
xytext=(20.,6.7), textcoords='data',
bbox=dict(boxstyle="roundtooth", fc="#2EF075"),
arrowprops=dict(arrowstyle="->",
connectionstyle="arc3"),)
ax.annotate('[$HPO_4^{2-}$] = [$PO_4^{3-}$]', xy=(25., 11.1), xycoords='data',
xytext=(22.,12.7), textcoords='data',
bbox=dict(boxstyle="roundtooth",fc='#2EF075'),
arrowprops=dict(arrowstyle="->",
connectionstyle="arc3"),)
pK = [12.1,7.2,2.15]
ca=np.arange(0.,1.,10) #intervalle de valeur des volumes (m3)
cb=np.arange(0.,1.,10)#intervalle de valeur des pressions voulues (Pa)
vb_max = 40.0
va=np.arange(0.,40.,40)
(vb_max*cb>ca*va)
figure(figsize=(8,5))
vb_max = 40.0
plot_pH(pK,ca,va,cb,vb_max)
grid()
title("Titrage de l'acide phosphorique ($H_3PO_4$) par la soude (NaOH)")
def plot_dis(pK,ca,va,cb,vb_max):
npts = 1000
n = len(pK)
vb = np.zeros(npts)
dis = np.zeros((n+1,npts))
ph_max = 14+math.log10((vb_max*cb-ca*va)/(vb_max+va))
dph = ph_max/(npts-1)
for i in range(npts):
ph = dph*i
[vb[i],c] = volume(pK,ca,va,cb,ph)
for p in range(n+1):
dis[p][i] = c[p]*(vb[i]+va)/(ca*va)*100
for p in range(0,n+1):
s1 = "H_{"+str(p)+"}"
if p==0:
s1 = ""
elif p==1:
s1 = "H"
s2 = "A^{"+str(n-p)+"-}"
if n-p==0:
s2 = "A"
elif n-p==1:
s2 = "A^-"
plot(vb,dis[p],label="$"+s1+s2+"$")
axis([0,vb_max,0,100])
xlabel("Volume de NaOH (mL)")
ylabel(u"Pourcentage de chaque espèce phosphorée (%)")
figure(figsize=(8,5))
plot_dis(pK,ca,va,cb,vb_max)
legend(loc=7)
grid()
title(u"Diagramme de distribution des espèces")
fen = Tk() #création de l'interface graphique où l'on va mettre les données
fen.title('Valeur de ca, cb et va') # donne un titre à la fenêtre
fen.geometry('470x160') #permet de régler les dimensions de la fenêtre de données
CA = Label(fen, text= "Valeur de ca:") #La commande Label permet de mettre du texte et ainsi nommer les cellules qui serviront à insérer les données
CB = Label(fen, text= "Valeur de cb:")
VA = Label(fen, text= "Valeur de va:")
CA.grid(row=1, sticky=W) # la commande grid permet de donner la position voulue dans l'interface
CB.grid(row=2, sticky=W)
VA.grid(row=3, sticky=W)
ca= Entry(fen) #crée une cellule d'écriture
cb= Entry(fen)
va= Entry(fen)
ca.grid(row=2, column=1)
cb.grid(row=3, column=1)
va.grid(row=4, column=1)
b=Button(fen,text="Graphe",command=plot_pH)
b.grid(row=7, column=0)
show()
mainloop() # permet le démarrage du programme |
Partager