import numpy as np
from scipy.optimize import bisect

# Parametres ===================================
# Constante des gaz parfaits en J/(mol.K)
R = 8.314
# Enthalpie standard de réaction en J/mol
deltarH0 = -114.7e3 
# Entropie standard de réaction en J/(mol.K)
deltarS0 = -245.9
# Pression standard en bar
P0 = 1
# Pression totale en bar 
P = 1
# Température en K
T = 373

def ZeroDicho(f,a,b,eps):
    """Recherche un zero de la fonction f entre a et b par dichotomie, et renvoie une valeur approchée à eps près
    La fonction f est supposée continue, et vérifie f(a) * f(b) <= 0"""
    while abs(a-b)>2*eps:
        m=(a+b)/2
        if f(a)*f(m)<0:
            b=m
        else:
            a=m
    return((a+b)/2)

# Fonction à annuler pour déterminer le rendement r
def f(r):
    return(np.log((4*(4-2*r)**2*r**2*P0**2)/(27*(1-r)**4*P**2))+deltarH0/(R*T)-deltarS0/R)

# Résolution par dichotomie puis avec la fonction bisect
r_d=ZeroDicho(f,1e-6,0.999,0.01)
r_b=bisect(f,1e-3,0.999) 

# Affichage des résultats
print("rendement par dichotomie :", r_d)
print("rendement par bisect :", r_b)