In [36]:
import numpy as np
import pandas as pd
import math
import cmath
from scipy.optimize import root
from scipy.integrate import odeint
from __future__ import division
from scipy import *
from scipy.optimize import curve_fit
from pylab import *
import matplotlib.pyplot as plt
%matplotlib inline

import pylab as pp
from scipy import integrate, interpolate
from scipy import optimize

Evaluation des modèles pour l'extraction supercritique

L'extraction supercritique est de plus en plus utilisée afin de retirer des matières organiques de différents liquides ou matrices solides. Cela est dû au fait que les fluides supercritiques ont des avantages non négligeables par rapport aux autres solvants, ils ont des caractèreistiques comprises entre celles des gaz et celles des solides. En changeant la température et la pression ils peuvent capter des composés différents, ils sont donc très efficaces. Le méchanisme de l'extraction supercritique est le suivant :

  • Transport du fluide vers la particule, en premier lieu sur sa surface et en deuxième lieu a l'intérieur de la particule par diffusion
  • Dissolution du soluté avec le fluide supercritique
  • Transport du solvant de l'intérieur vers la surface de la particule
  • Transport du solvant et des solutés de la surface de la particule vers la masse du solvant

A - Le modèle de Reverchon :

Afin d'utiliser ce modèle, définissons les variables qui vont y être admises, ci-dessous la nomenclature du modèle :

Le modèle : Il est basé sur l'intégration des bilans de masses différentielles tout le long de l'extraction, avec les hypothèses suivants :

  • L'écoulement piston existe à l'intérieur du lit, comme le montre le schéma ci-contre :
  • La dispersion axiale du lit est négligeable
  • Le débit, la température et la pression sont constants

Cela nous permet d'obtenir les équations suivantes :

  • $uV.\frac{\partial c_{c}}{\partial t}+eV.\frac{\partial c_{c}}{\partial t}+ AK(q-q*) = 0$
  • $(1-e).V.uV*\frac{\partial c_{q}}{\partial t}= -AK(q-q*)$

  • Les conditions initiales sont les suivantes : C = 0, q=q0 à t = 0 et c(0,t) à h=0

La phase d'équilibre est : $c = k.q*$

Sachant que le fluide et la phase sont uniformes à chaque stage, nous pouvons définir le modèle en utilisant les équations différentielles ordinaires (2n). Les équations sont les suivantes :

  • $(\frac{W}{p}).(Cn- Cn-1) + e (\frac{v}{n}).(\frac{dcn}{dt})+(1-e).(\frac{v}{n}).(\frac{dcn}{dt}) = 0$
  • $(\frac{dqn}{dt} = - (\frac{1}{ti})(qn-qn*)$
  • Les conditions initiales sont : cn = 0, qn = q0 à t = 0

Ejemplo ODE


In [13]:
import numpy as np
from scipy import integrate
from matplotlib.pylab import *

Ejemplo 2 funciona


In [14]:
import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt

def vdp1(t, y):
    return np.array([y[1], (1 - y[0]**2)*y[1] - y[0]])

t0, t1 = 0, 20                # start and end
t = np.linspace(t0, t1, 100)  # the points of evaluation of solution
y0 = [2, 0]                   # initial value
y = np.zeros((len(t), len(y0)))   # array for solution
y[0, :] = y0

r = integrate.ode(vdp1).set_integrator("dopri5")  # choice of method
r.set_initial_value(y0, t0)   # initial values

for i in range(1, t.size):
   y[i, :] = r.integrate(t[i]) # get one more value, add it to the array
   if not r.successful():
       raise RuntimeError("Could not integrate")

plt.plot(t, y)
plt.show()


Fonction

Modelo Reverchon

Mathematical Modeling of Supercritical Extraction of Sage Oil


In [15]:
P = 9 #MPa
T = 323 # K
Q = 8.83 #g/min
e = 0.4
rho = 285 #kg/m3
miu = 2.31e-5 # Pa*s
dp = 0.75e-3 # m
Dl = 0.24e-5 #m2/s
De = 8.48e-12 # m2/s
Di = 6e-13
u = 0.455e-3 #m/s
kf = 1.91e-5 #m/s
de = 0.06 # m
W = 0.160 # kg
kp = 0.2

r = 0.31 #m

n = 10
V = 12

#C = kp * qE
C = 0.1
qE = C / kp

Cn = 0.05
Cm = 0.02


t = np.linspace(0,10, 1)

ti = (r ** 2) / (15 * Di)

In [16]:
def reverchon(x,t):
    
    #Ecuaciones diferenciales del modelo Reverchon    
    #dCdt = - (n/(e * V)) * (W * (Cn - Cm) / rho + (1 - e) * V * dqdt)
    #dqdt = - (1 / ti) * (q - qE)
    
    q = x[0]
    C = x[1]
    qE = C / kp
    dqdt = - (1 / ti) * (q - qE)
    dCdt = - (n/(e * V)) * (W * (C - Cm) / rho + (1 - e) * V * dqdt)
    
    return [dqdt, dCdt]

In [17]:
reverchon([1, 2], 0)


Out[17]:
[8.428720083246617e-10, -0.0023158021167643352]

In [18]:
x0 = [0, 0]
t = np.linspace(0, 3000, 500)

resultado = odeint(reverchon, x0, t)

qR = resultado[:, 0]
CR = resultado[:, 1]
plt.plot(t, CR)
plt.title("Modelo Reverchon")
plt.xlabel("t [=] min")
plt.ylabel("C [=] $kg/m^3$")


Out[18]:
Text(0,0.5,'C [=] $kg/m^3$')

In [19]:
x0 = [0, 0]
t = np.linspace(0, 3000, 500)

resultado = odeint(reverchon, x0, t)

qR = resultado[:, 0]
CR = resultado[:, 1]
plt.plot(t, qR)
plt.title("Modelo Reverchon")
plt.xlabel("t [=] min")
plt.ylabel("C solid–fluid interface [=] $kg/m^3$")


Out[19]:
Text(0,0.5,'C solid–fluid interface [=] $kg/m^3$')

In [20]:
print(CR)


[0.         0.00014014 0.0002793  0.00041748 0.00055469 0.00069094
 0.00082624 0.00096058 0.00109399 0.00122646 0.001358   0.00148862
 0.00161833 0.00174713 0.00187503 0.00200203 0.00212814 0.00225336
 0.00237771 0.00250119 0.0026238  0.00274556 0.00286646 0.00298651
 0.00310572 0.0032241  0.00334165 0.00345837 0.00357427 0.00368937
 0.00380365 0.00391714 0.00402983 0.00414173 0.00425285 0.00436319
 0.00447276 0.00458156 0.00468959 0.00479687 0.0049034  0.00500918
 0.00511422 0.00521853 0.0053221  0.00542495 0.00552707 0.00562848
 0.00572919 0.00582918 0.00592848 0.00602708 0.00612498 0.00622221
 0.00631875 0.00641461 0.0065098  0.00660433 0.00669819 0.0067914
 0.00688395 0.00697585 0.00706711 0.00715773 0.00724771 0.00733707
 0.0074258  0.0075139  0.00760139 0.00768827 0.00777454 0.0078602
 0.00794526 0.00802973 0.0081136  0.00819689 0.00827959 0.00836172
 0.00844327 0.00852424 0.00860465 0.0086845  0.00876379 0.00884252
 0.0089207  0.00899833 0.00907542 0.00915196 0.00922798 0.00930345
 0.0093784  0.00945283 0.00952673 0.00960012 0.00967299 0.00974535
 0.0098172  0.00988855 0.0099594  0.01002976 0.01009962 0.01016899
 0.01023788 0.01030628 0.0103742  0.01044165 0.01050863 0.01057513
 0.01064117 0.01070675 0.01077187 0.01083653 0.01090074 0.0109645
 0.01102781 0.01109068 0.01115311 0.0112151  0.01127665 0.01133778
 0.01139847 0.01145874 0.01151859 0.01157802 0.01163703 0.01169563
 0.01175381 0.01181159 0.01186897 0.01192594 0.01198251 0.01203869
 0.01209447 0.01214986 0.01220486 0.01225948 0.01231371 0.01236757
 0.01242104 0.01247415 0.01252688 0.01257924 0.01263123 0.01268286
 0.01273413 0.01278504 0.01283559 0.01288579 0.01293564 0.01298514
 0.01303429 0.0130831  0.01313156 0.01317969 0.01322748 0.01327493
 0.01332206 0.01336885 0.01341531 0.01346145 0.01350727 0.01355276
 0.01359794 0.0136428  0.01368734 0.01373158 0.0137755  0.01381911
 0.01386242 0.01390543 0.01394813 0.01399054 0.01403264 0.01407446
 0.01411597 0.0141572  0.01419814 0.01423879 0.01427916 0.01431925
 0.01435905 0.01439857 0.01443782 0.0144768  0.01451549 0.01455392
 0.01459208 0.01462997 0.0146676  0.01470496 0.01474207 0.01477891
 0.01481549 0.01485182 0.01488789 0.01492371 0.01495928 0.0149946
 0.01502967 0.0150645  0.01509908 0.01513342 0.01516752 0.01520138
 0.015235   0.01526839 0.01530154 0.01533446 0.01536715 0.01539961
 0.01543185 0.01546386 0.01549564 0.0155272  0.01555854 0.01558966
 0.01562056 0.01565125 0.01568172 0.01571198 0.01574202 0.01577186
 0.01580148 0.0158309  0.01586011 0.01588912 0.01591792 0.01594653
 0.01597493 0.01600313 0.01603114 0.01605895 0.01608656 0.01611398
 0.01614121 0.01616825 0.01619509 0.01622175 0.01624823 0.01627452
 0.01630062 0.01632654 0.01635228 0.01637784 0.01640322 0.01642842
 0.01645344 0.01647829 0.01650297 0.01652747 0.0165518  0.01657596
 0.01659995 0.01662378 0.01664743 0.01667092 0.01669425 0.01671741
 0.01674041 0.01676325 0.01678593 0.01680845 0.01683081 0.01685302
 0.01687507 0.01689696 0.01691871 0.0169403  0.01696173 0.01698302
 0.01700416 0.01702515 0.017046   0.01706669 0.01708725 0.01710766
 0.01712792 0.01714805 0.01716803 0.01718787 0.01720757 0.01722714
 0.01724657 0.01726586 0.01728502 0.01730404 0.01732293 0.01734169
 0.01736031 0.01737881 0.01739717 0.01741541 0.01743352 0.0174515
 0.01746936 0.01748709 0.0175047  0.01752218 0.01753954 0.01755678
 0.0175739  0.0175909  0.01760778 0.01762454 0.01764118 0.01765771
 0.01767412 0.01769042 0.0177066  0.01772267 0.01773863 0.01775447
 0.0177702  0.01778583 0.01780134 0.01781675 0.01783204 0.01784723
 0.01786232 0.01787729 0.01789217 0.01790694 0.0179216  0.01793616
 0.01795062 0.01796498 0.01797924 0.0179934  0.01800746 0.01802142
 0.01803528 0.01804905 0.01806272 0.01807629 0.01808977 0.01810315
 0.01811645 0.01812964 0.01814275 0.01815576 0.01816868 0.01818151
 0.01819425 0.01820691 0.01821947 0.01823194 0.01824433 0.01825663
 0.01826885 0.01828098 0.01829302 0.01830498 0.01831686 0.01832865
 0.01834036 0.01835199 0.01836354 0.018375   0.01838639 0.01839769
 0.01840892 0.01842007 0.01843114 0.01844213 0.01845304 0.01846388
 0.01847464 0.01848533 0.01849594 0.01850648 0.01851695 0.01852734
 0.01853766 0.0185479  0.01855807 0.01856818 0.01857821 0.01858817
 0.01859806 0.01860789 0.01861764 0.01862732 0.01863694 0.01864649
 0.01865598 0.01866539 0.01867474 0.01868403 0.01869325 0.0187024
 0.01871149 0.01872052 0.01872949 0.01873839 0.01874723 0.018756
 0.01876472 0.01877338 0.01878197 0.0187905  0.01879898 0.01880739
 0.01881575 0.01882404 0.01883228 0.01884047 0.01884859 0.01885666
 0.01886467 0.01887262 0.01888052 0.01888836 0.01889615 0.01890389
 0.01891156 0.01891919 0.01892676 0.01893428 0.01894175 0.01894916
 0.01895653 0.01896384 0.0189711  0.0189783  0.01898546 0.01899257
 0.01899963 0.01900664 0.0190136  0.01902051 0.01902737 0.01903418
 0.01904095 0.01904767 0.01905434 0.01906097 0.01906755 0.01907408
 0.01908057 0.01908701 0.0190934  0.01909976 0.01910606 0.01911233
 0.01911855 0.01912472 0.01913085 0.01913694 0.01914299 0.01914899
 0.01915495 0.01916088 0.01916675 0.01917259 0.01917839 0.01918414
 0.01918986 0.01919554 0.01920117 0.01920677 0.01921233 0.01921784
 0.01922332 0.01922876 0.01923417 0.01923953 0.01924486 0.01925015
 0.01925541 0.01926062 0.0192658  0.01927095 0.01927605 0.01928113
 0.01928616 0.01929116 0.01929613 0.01930106 0.01930596 0.01931082
 0.01931565 0.01932044 0.0193252  0.01932993 0.01933463 0.01933929
 0.01934392 0.01934851 0.01935308 0.01935761 0.01936211 0.01936658
 0.01937102 0.01937542 0.0193798  0.01938414 0.01938846 0.01939274
 0.019397   0.01940122]

In [21]:
r = 0.31 #m
x0 = [0, 0]
t = np.linspace(0, 3000, 500)

resultado = odeint(reverchon, x0, t)

qR = resultado[:, 0]
CR = resultado[:, 1]
plt.plot(t, CR)
plt.title("Modelo Reverchon")
plt.xlabel("t [=] min")
plt.ylabel("C [=] $kg/m^3$")


Out[21]:
Text(0,0.5,'C [=] $kg/m^3$')

In [22]:
r = 0.231 #m
x0 = [0, 0]
t = np.linspace(0, 3000, 500)

resultado = odeint(reverchon, x0, t)

qR = resultado[:, 0]
CR = resultado[:, 1]
plt.plot(t, CR)
plt.title("Modelo Reverchon")
plt.xlabel("t [=] min")
plt.ylabel("C [=] $kg/m^3$")


Out[22]:
Text(0,0.5,'C [=] $kg/m^3$')

In [23]:
fig,axes=plt.subplots(2,2)
axes[0,0].plot(t,CR)
axes[1,0].plot(t,qR)


Out[23]:
[<matplotlib.lines.Line2D at 0x27f6b0c1320>]

Trabajo futuro

  • Realizar modificaciones de los parametros para observar cómo afectan al comportamiento del modelo.
  • Realizar un ejemplo de optimización de parámetros utilizando el modelo de Reverchon.

Referencias

[1] E. Reverchon, Mathematical modelling of supercritical extraction of sage oil, AIChE J. 42 (1996) 1765–1771. https://onlinelibrary.wiley.com/doi/pdf/10.1002/aic.690420627

[2] Amit Rai, Kumargaurao D.Punase, Bikash Mohanty, Ravindra Bhargava, Evaluation of models for supercritical fluid extraction, International Journal of Heat and Mass Transfer Volume 72, May 2014, Pages 274-287. https://www.sciencedirect.com/science/article/pii/S0017931014000398

Ajuste de parámetros con ODEs: modelo Reverchon

Explicaciones :

  • Poner los datos experimentales
  • Definir las ecuaciones diferenciales ordinarias del systema con los diferentes parametros
  • Calcular el valor de la ecuacion diferencial en cada punto, se necesita una otra funcion para integrar la ecuacion
  • Despues tenemos que definir una funcion de minimos cuadrados para cada valor de y : minimos cuadrados es una tecnica de analisis numerico enmarcada dentro de la optimizacion matematica y se intenta encontrar la funcion continua entre los variables independentes y dependentes
  • Para resolverlo se necesita las varoles iniciales para los parametros y los ecuacions ordinarias, para obtener los paramètros de la funcion. Despues se necesita hacer una interpolacion para los valores de las ODEs y para hacerlo se usa splines (spline es una funcion definida per partes por los polynomios), en Python splines es un método que se usa cuando hay problemas de interpolacion.

In [24]:
#Datos experimentales
x_data = np.linspace(0,9,10)
y_data = np.array([0.000,0.416,0.489,0.595,0.506,0.493,0.458,0.394,0.335,0.309])

def f(y, t, k): 
    """ sistema de ecuaciones diferenciales ordinarias """
    return (-k[0]*y[0], k[0]*y[0]-k[1]*y[1], k[1]*y[1])

def my_ls_func(x,teta):
    f2 = lambda y, t: f(y, t, teta)
    # calcular el valor de la ecuación diferencial en cada punto
    r = integrate.odeint(f2, y0, x)
    return r[:,1]

def f_resid(p):
    # definir la función de minimos cuadrados para cada valor de y"""
    
    return y_data - my_ls_func(x_data,p)

#resolver el problema de optimización
guess = [0.2, 0.3] #valores inicales para los parámetros
y0 = [1,0,0] #valores inciales para el sistema de ODEs
(c, kvg) = optimize.leastsq(f_resid, guess) #get params

print("parameter values are ",c)

# interpolar los valores de las ODEs usando splines
xeval = np.linspace(min(x_data), max(x_data),30) 
gls = interpolate.UnivariateSpline(xeval, my_ls_func(xeval,c), k=3, s=0)


xeval = np.linspace(min(x_data), max(x_data), 200)
#Gráficar los resultados
pp.plot(x_data, y_data,'.r',xeval,gls(xeval),'-b')
pp.xlabel('t [=] min',{"fontsize":16})
pp.ylabel("C",{"fontsize":16})
pp.legend(('Datos','Modelo'),loc=0)
pp.show()


parameter values are  [0.5221712 0.181713 ]

In [25]:
f_resid(guess)


Out[25]:
array([0.        , 0.26017495, 0.24598319, 0.31051605, 0.2097305 ,
       0.20350144, 0.18620935, 0.14571892, 0.11264286, 0.11281323])

In [26]:
#Datos experimentales
x_data = np.linspace(0,9,10)
y_data = np.array([0.000,0.416,0.489,0.595,0.506,0.493,0.458,0.394,0.335,0.309])
print(y_data)

# def f(y, t, k): 
#     """ sistema de ecuaciones diferenciales ordinarias """
    
#     return (-k[0]*y[0], k[0]*y[0]-k[1]*y[1], k[1]*y[1])
def reverchon(x,t,Di):
    
    #Ecuaciones diferenciales del modelo Reverchon    
    #dCdt = - (n/(e * V)) * (W * (Cn - Cm) / rho + (1 - e) * V * dqdt)
    #dqdt = - (1 / ti) * (q - qE)
    
    q = x[0]
    C = x[1]
    qE = C / kp
    ti = (r**2) / (15 * Di)
    dqdt = - (1 / ti) * (q - qE)
    dCdt = - (n/(e * V)) * (W * (C - Cm) / rho + (1 - e) * V * dqdt)
    
    return [dqdt, dCdt]  

def my_ls_func(x,teta):
    f2 = lambda y, t: reverchon(y, t, teta)
    # calcular el valor de la ecuación diferencial en cada punto
    rr = integrate.odeint(f2, y0, x)
    print(f2)
    return rr[:,1]

def f_resid(p):
    # definir la función de minimos cuadrados para cada valor de y"""
    
    return y_data - my_ls_func(p,x_data)

#resolver el problema de optimización
guess = np.array([0.2]) #valores inicales para los parámetros
y0 = [0,0] #valores inciales para el sistema de ODEs
(c, kvg) = optimize.leastsq(f_resid, guess) #get params

print("parameter values are ",c)

# interpolar los valores de las ODEs usando splines
xeval = np.linspace(min(x_data), max(x_data),30) 
gls = interpolate.UnivariateSpline(xeval, my_ls_func(xeval,c), k=3, s=0)


xeval = np.linspace(min(x_data), max(x_data), 200)
#Gráficar los resultados
pp.plot(x_data, y_data,'.r',xeval,gls(xeval),'-b')
pp.xlabel('t [=] min',{"fontsize":16})
pp.ylabel("C",{"fontsize":16})
pp.legend(('Datos','Modelo'),loc=0)
pp.show()


[0.    0.416 0.489 0.595 0.506 0.493 0.458 0.394 0.335 0.309]
<function my_ls_func.<locals>.<lambda> at 0x0000027F6A63B0D0>
<function my_ls_func.<locals>.<lambda> at 0x0000027F6A63B0D0>
<function my_ls_func.<locals>.<lambda> at 0x0000027F6A63B0D0>
<function my_ls_func.<locals>.<lambda> at 0x0000027F6A63B0D0>
parameter values are  [0.2]
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-26-e984341f071e> in <module>()
     44 # interpolar los valores de las ODEs usando splines
     45 xeval = np.linspace(min(x_data), max(x_data),30)
---> 46 gls = interpolate.UnivariateSpline(xeval, my_ls_func(xeval,c), k=3, s=0)
     47 
     48 

<ipython-input-26-e984341f071e> in my_ls_func(x, teta)
     26     f2 = lambda y, t: reverchon(y, t, teta)
     27     # calcular el valor de la ecuación diferencial en cada punto
---> 28     rr = integrate.odeint(f2, y0, x)
     29     print(f2)
     30     return rr[:,1]

~\Anaconda3\lib\site-packages\scipy\integrate\odepack.py in odeint(func, y0, t, args, Dfun, col_deriv, full_output, ml, mu, rtol, atol, tcrit, h0, hmax, hmin, ixpr, mxstep, mxhnil, mxordn, mxords, printmessg)
    213     output = _odepack.odeint(func, y0, t, args, Dfun, col_deriv, ml, mu,
    214                              full_output, rtol, atol, tcrit, h0, hmax, hmin,
--> 215                              ixpr, mxstep, mxhnil, mxordn, mxords)
    216     if output[-1] < 0:
    217         warning_msg = _msgs[output[-1]] + " Run with full_output = 1 to get quantitative information."

RuntimeError: The array return by func must be one-dimensional, but got ndim=2.

In [ ]:
def my_ls_func(x,teta):
    f2 = lambda y, t: reverchon(y, t, teta)
    # calcular el valor de la ecuación diferencial en cada punto
    r = integrate.odeint(f2, y0, x)
    print(f2)
    return r[:,1]

In [27]:
my_ls_func(y0,guess)


<function my_ls_func.<locals>.<lambda> at 0x0000027F6C459AE8>
Out[27]:
array([0., 0.])

In [28]:
f_resid(guess)


<function my_ls_func.<locals>.<lambda> at 0x0000027F6C459BF8>
Out[28]:
array([0.   , 0.416, 0.489, 0.595, 0.506, 0.493, 0.458, 0.394, 0.335,
       0.309])

Méthode des moindres carrés


In [ ]:


In [ ]: