이번엔 7월에 했던 과제로 중화적정 곡선을 코딩을 통해 그려보도록 하겠습니다.
코딩을 통해 구현하려는 것은 "중화적정 그래프 그리기" 입니다.
화학을 공부하면서 중화적정 과정에서 pH를 구하는 것을 배우게 되는데 익히는데 시간이 좀 걸렸었습니다. 그래서 알고리즘으로 편하게 구할 수 있도록 해보겠습니다.
1. 배경이론
간단히 이론을 설명하고 코드를 설명해보겠습니다.
1) 산, 염기
산, 염기는 다음과 같이 정의할 수 있습니다.
종류 \ 정의 | 아레니우스 | 브뢴스퇴드 · 로리 | 루이스 |
산 | H+ 를 내놓음 | H+ 주개 | 전자쌍 받개 |
염기 | OH- 를 내놓음 | H+ 받개 | 전자쌍 주개 |
2) 산, 염기의 세기
* 이온화도($\alpha$)
전해질을 물에 녹였을 때, 이온화 평형을 이루는 수용액에서 용해된 전해질의 전체 양(mol)에 대한 이온화된 전해질 양의 비
$$ \alpha = \frac{이온화된 전해질의 양(mol)}{용해된 전해질의 전체 양(mol)} (0≤\alpha ≤1) $$
- 이온화도가 클수록 세기가 강합니다.
* 이온화 상수
- 산의 이온화 상수($K_a$)
$$ HA_{(aq)} + H_2O_{(l)} → H_3O^+_{(aq)} + A^-_{(aq)} $$
$$ K = \frac{[H_3O^+][A^-]}{[HA][H_2O]} $$
$$ K × [H_2O] = K_a $$
$$ K_a = \frac{[H_3O^+][A^-]}{[HA]} $$
- 염기의 이온화 상수($K_b$)
$$ B{(aq)} + H_2O_{(l)} → BH^+_{(aq)} + OH^-_{(aq)} $$
$$ K = \frac{[BH^+][OH^-]}{[B][H_2O]} $$
$$ K × [H_2O] = K_b $$
$$ K_b = \frac{[BH^+][OH^-]}{[B]} $$
3) 중화적정
* 중화적정
: 이미 농도를 알고 있는 산 또는 염기의 수용액으로 농도를 모르는 염기 또는 산 수용액의 농도를 구하는 실험적 방법
중화반응과 양적관계를 이용하여 농도를 구하는 것입니다.
- 표준용액 : 농도를 알고 있는 용액
- 중화점 : 산과 염기가 완전히 중화되는 지점
= 당량점 : 산의 H+ 양 = 염기의 OH- 양
≠ 종말점 : 실험자가 중화점이라고 판단한 시점
* 중화반응
: 산의 H+와 염기의 OH-가 H2O를 생성하고 산의 음이온과 염기의 양이온이 염을 생성합니다.
반응식은 이렇게 됩니다.
$$ H^+ + OH^- → H_2O $$
* 양적관계
$$ nMV = n'M'V' $$
(n/n' : H+ 나 OH-의 가수, M/M' : 몰 농도, V/V' : 용액의 부피)
* 실험방법
https://www.youtube.com/watch?v=MEOS4SwpcCg (참고)
* 실험결과
ex) 인산(H3PO4)적정곡선
녹색 – pH / 보라색 – 전도도 / 청록색 - 온도
실험결과 pH 곡선은 저렇게 나옵니다.
산과 염기의 세기에 따라 그래프 형태도 달라지고 중화적정 시 사용할 수 있는 지시약도 달라집니다.
적정하면서 생기는 현상은 다음에 더 자세히 알아보기로 하고 pH를 구할 수 있는 식을 보도록 하겠습니다.
4) pH 구하기
그래프에서 구간을 4개로 나눌 수 있습니다.
구간에 다른 pH 구하는 식을 정리해보겠습니다.
[1] v = 0 : $ pH = -log(\sqrt{K_a}) $
[2] 0 < v < t : 헨더슨-하셀바흐식- $pH = pK_a + log(\frac{[A-]}{[HA]})$
[3] v = t (당량점) : 염의 몰농도를 구하여 pH 계산 - 양적관계
[4]v > t : 남아있는 H+ 또는 OH- 몰농도를 구하여 pH 계산
이제 이것을 토대로 짠 코드는 다음과 같습니다.
2. 코드
import matplotlib.pyplot as plt
import math
import numpy as np
# 입력
acid, Ma, Va = input('1가 산, 몰농도, 부피를 단위를 제외하고 공백으로 분리하여 입력. 단위: M, ml ').split()
base, Mb, Vb = input('1가 염기, 몰농도, 부피를 단위를 제외하고 공백으로 분리하여 입력. 단위: M, ml ').split()
p, l = input('()을 ()으로 적정: acid or base 를 공백으로 분리하여 순서대로 입력 ').split()
n, m = input('원래 있던 용액의 해리상수 입력: ()*10^()').split()
#몰농도, 부피 설정
Ma = float(Ma)
Va = int(Va)
Mb = float(Mb)
Vb = int(Vb)
# 염기를 산으로 적정할 때
if p == 'base':
Ma, Mb = Mb, Ma
Va, Vb = Vb, Va
# pH를 구하는 함수
def graph(Ma, Va, Mb, Vb): #Ma: 원래 용액 몰농도, Va: 원래 용액 부피, Mb: 첨가하는 용액 몰농도, Vb: 첨가하는 용액 부피
v = [] # 부피 변화 리스트
pH = [] # pH 변화 리스트
Ka = float(n) * 10**int(m) #이온화 상수
t= (Ma*Va)/Mb # 당량점 부피
for i in range(Vb+1): #i: 첨가한 부피
if i == 0 :
v.append(i)
h = math.sqrt(Ka*Ma)
a = -(math.log10(h))
pH.append(a)
print(a, i)
if i > 0 and i < t:
v.append(i)
HA = Ma*Va - Mb*i
A = Mb*i
a = -(math.log10(Ka)) + (math.log10(A/HA))
pH.append(a)
print(a, i)
if i == t:
v.append(i)
C = (Mb*i)/(Va+i)
oh = math.sqrt(Ka*C)
a = -(math.log10(oh))
pH.append(14-a)
print('당량점:', 14-a, i)
if i > t :
Kb = 10**(-14)/Ka
v.append(i)
oh = (Mb*i-Ma*Va)/(i+Va)
a = -(math.log10(oh))
pH.append(14-a)
print(14-a, i)
return v, pH
#구한 pH의 array
res_v, res_ph = graph(Ma, Va, Mb, Vb)
res_v = np.array(res_v)
res_ph = np.array(res_ph)
# 염기를 산으로 적정할 때
if p == 'base':
res_ph = 14 - res_ph
#그래프 출력
plt.ylim([0, 14])
plt.xlabel('V(ml)')
plt.ylabel('pH')
plt.plot(res_v, res_ph, color='red')
plt.show()
# 입력
적정하려는 용액과 그 몰농도, 부피를 입력받고 어떤 용액으로 적정할지와 원래있던 용액의 해리상수를 입력받습니다.
# 출력
중화적정 그래프
* 결과
- 산 0.1M 40ml 를 염기 0.1M 60ml로 적정했을 때:
$K_a=1.8 × 10^{-5}$
- 염기 0.1M 40ml를 산 0.1M 60ml로 적정했을 때:
$K_b = 1.8 × 10^{-5}$
* 보완할 점
첨가하는 용액의 부피를 반복문의 i 로 두어서 당량점의 부피를 정수로 놓아야 했습니다.
이 때문에 그래프에서 삐쭉 튀어나오는 오차가 생겼는데 오차를 줄이기 위해서 자료형을 float로 바꿔야 할 것입니다.
그리고 그래프에서 당량점과 그때의 부피, pH를 표시하는 것도 좋을 것 같습니다.
직접 pH를 계산할 때는 몇가지 경우만 구해보았었는데 코드를 짜서 1ml 가할 때마다 그 변화를 확인해 볼 수 있었습니다.
가한 부피에 따른 경우를 조건으로 나누어 식에 대입해 구해보면서 각 경우의 이론적인 값을 볼 수 있었습니다.
여러 산과 염기의 경우를 입력해보면서 그 때의 중화적정 그래프의 모양과 pH를 확인해 볼 수 있다는 점이 좋았습니다.
배운 내용을 활용해보고 다른 과목과 연결해서 코드를 짜보는 과정이 재밌었던 것 같습니다.
'프로그래밍 > 융합' 카테고리의 다른 글
[화학] 분자 구조 그리기 (0) | 2023.07.24 |
---|