Smart water flooding analytical solution

This document is mostly based on the SPE-7660 paper by Gary Pope. I first implement the simple water flooding analytical solution and then expand it to low salinity water flooding with and without ionic adsorption.

Mathematical model

The two phase flow equation in a 1D porous medium reads $$\frac{\partial S_w}{\partial t}+\frac{u}{\varphi}\frac{df_w}{dS_w}\frac{\partial S_w}{\partial x} = 0 $$ The dimensionless time and space are defined as $$t_D = \frac{ut}{\varphi L}$$ and $$x_D = \frac{x}{L}$$ The velocity of a constant saturation front is calculated by $$V_{S_w} = (\frac{dx}{dt})_{S_w}=\frac{u}{\varphi}\frac{df_w}{dS_w}$$ The shock front is specified by $$\frac{f_w(S_{w,shock})-f_w(S_{w,init})}{S_{w,shock}-S_{w,init}}=\left(\frac{df_w}{dS_w}\right)_{S_{w,shock}}$$ The injected water front velocity (i.e., a tracer in the injected water, or the low salinity of the injected brine) is calculated by $$V_{c} = (\frac{dx}{dt})_{c}=\frac{u}{\varphi}\frac{f_w}{S_w}$$ an the water saturation that corresponds to the position of the salinity front is given by $$\frac{f_w(S_{w,s})-f_w(0)}{S_{w}-0.0}=\left(\frac{df_w}{dS_w}\right)_{S_{w,shock}}$$ which is the tangent line fron the point (0,0) to the $f_w-S_w$ (fractional flow) curve. The breakthrough time (in number of pore volume) is calculated by $$t_{D, bt} = \left(\frac{df_w}{dS_w}\right)^{-1}_{S_{w,shock}}$$ The other useful relation is the average saturation after breakthrough, which reads $$S_{w,av} = S_{or}+\left[(1-f_w)\left(\frac{df_w}{dS_w}\right)\right]_{x=L}, \;t_D>t_{D,bt}$$ The recovery factor then can be calculated based on the fact that the recovery curve is linear until the breakthrough, and after breakthrough it gradually reaches a plateau. The oil recovery factor before the breakthrough is calculated by $$R = \frac{(1-f_w(S_{w,init}))t_D}{1-S_{w,init}}, \;t_D<t_{D,bt}$$ and after breakthrough by $$R = \frac{S_{w,init}-S_{w,av}}{1-S_{w,init}}, \; t_D>t_{D,bt}$$ Let's try the above formulation in Julia.

Testing the codes

The FractionalFlow.jl package is built to solve and visualize the analytical solutions to several injection problem in the petroleum engineering, including water flooding, low salinity water flooding with and without ionic adsorption, and solvent flooding (carbonated water, DME, etc). There are several functions that are documented in the code. Here, I show by example how to define a problem, solve it, and visualize the results.


In [71]:
include("../FractionalFlow/FractionalFlow.jl")
using PyPlot
FF = FractionalFlow


WARNING: replacing module FractionalFlow.
Out[71]:
Main.FractionalFlow

Water flooding


In [72]:
# define the problem
# relative permeabilities
rel_perms = FF.oil_water_rel_perms(krw0=0.4, kro0=0.9, 
    swc=0.15, sor=0.2, nw=2.0, no = 2.0)
FF.visualize(rel_perms)


Out[72]:
PyObject <matplotlib.legend.Legend object at 0x7f315f431160>

In [73]:
FF.print_relperm(rel_perms, title="Corey rel-perm parameters")


Out[73]:

Corey rel-perm parameters

krw0kro0nwnoSwcSor
0.40.92.02.00.150.2

In [74]:
# define the fluids
fluids = FF.oil_water_fluids(mu_water=1e-3, mu_oil=2e-3)

# define the fractional flow functions
fw, dfw = FF.fractional_flow_function(rel_perms, fluids)
# visualize the fractional flow
FF.visualize(rel_perms, fluids, label="lowsal")
tight_layout()



In [75]:
fluids.oil_viscosity


Out[75]:
0.002

In [76]:
core_flood = FF.core_flooding(u_inj=1.15e-5, pv_inject=5.0, 
    p_back=1e5, sw_init=0.2, sw_inj=1.0, rel_perms=rel_perms)
core_props = FF.core_properties()
wf_res = FF.water_flood(core_props, fluids, rel_perms, core_flood)
fw, dfw = FF.fractional_flow_function(rel_perms, fluids)
sw_tmp = range(0, 1, length=100)
# plot(sw_tmp, fw.(sw_tmp), xlabel = "Sw", ylabel="fw", label="")
# plot!(sw_tmp, dfw.(sw_tmp))
# figure(1)
# plot(pv, R) 
# xlabel("PV injected")
# ylabel("Recovery factor") 
# title("Water flooding")
# figure(2)
# plot(xt, sw)
# xlabel("x/t [-]")
# ylabel("Water saturation [-]")
FF.visualize(wf_res)


┌ Info: difficulty finding the shock front saturation range!
└ @ Main.FractionalFlow /home/ali/projects/peteng/analytical/FractionalFlow/FractionalFlow.jl:395
┌ Info: difficulty finding the shock front saturation range!
└ @ Main.FractionalFlow /home/ali/projects/peteng/analytical/FractionalFlow/FractionalFlow.jl:395
[0.0, 3.98548e-7, 8.04231e-7, 1.21713e-6, 1.63731e-6, 2.06486e-6, 2.49986e-6, 2.94237e-6, 3.39248e-6, 3.85026e-6, 4.31579e-6, 4.78913e-6, 5.27036e-6, 5.75955e-6, 6.25678e-6, 6.76209e-6, 7.27558e-6, 7.7973e-6, 8.32731e-6, 8.86568e-6, 9.41247e-6, 9.96774e-6, 1.05315e-5, 1.11039e-5, 1.1685e-5, 1.22747e-5, 1.28732e-5, 1.34805e-5, 1.40966e-5, 1.47216e-5, 1.53555e-5, 1.59983e-5, 1.66501e-5, 1.7311e-5, 1.79809e-5, 1.86598e-5, 1.93478e-5, 2.00449e-5, 2.07512e-5, 2.14665e-5, 2.21909e-5, 2.29245e-5, 2.36672e-5, 2.44189e-5, 2.51798e-5, 2.59497e-5, 2.67287e-5, 2.75166e-5, 2.83136e-5, 2.91194e-5, 2.99342e-5, 3.07578e-5, 3.15902e-5, 3.24313e-5, 3.3281e-5, 3.41393e-5, 3.50061e-5, 3.58813e-5, 3.67647e-5, 3.76564e-5, 3.85561e-5, 3.94639e-5, 4.03794e-5, 4.13027e-5, 4.22335e-5, 4.31717e-5, 4.41172e-5, 4.50698e-5, 4.60293e-5, 4.69955e-5, 4.79683e-5, 4.89475e-5, 4.99328e-5, 5.0924e-5, 5.1921e-5, 5.29234e-5, 5.39311e-5, 5.49438e-5, 5.59612e-5, 5.6983e-5, 5.80091e-5, 5.9039e-5, 6.00726e-5, 6.11094e-5, 6.21493e-5, 6.31918e-5, 6.42367e-5, 6.52836e-5, 6.63322e-5, 6.73821e-5, 6.84329e-5, 6.94843e-5, 7.05358e-5, 7.15872e-5, 7.2638e-5, 7.36878e-5, 7.47362e-5, 7.57828e-5, 7.68271e-5, 7.78688e-5, 7.78688e-5, 0.000155738]
[0.8, 0.798065, 0.79613, 0.794195, 0.79226, 0.790325, 0.78839, 0.786455, 0.78452, 0.782585, 0.78065, 0.778715, 0.77678, 0.774845, 0.77291, 0.770976, 0.769041, 0.767106, 0.765171, 0.763236, 0.761301, 0.759366, 0.757431, 0.755496, 0.753561, 0.751626, 0.749691, 0.747756, 0.745821, 0.743886, 0.741951, 0.740016, 0.738081, 0.736146, 0.734211, 0.732276, 0.730341, 0.728406, 0.726471, 0.724536, 0.722601, 0.720666, 0.718731, 0.716797, 0.714862, 0.712927, 0.710992, 0.709057, 0.707122, 0.705187, 0.703252, 0.701317, 0.699382, 0.697447, 0.695512, 0.693577, 0.691642, 0.689707, 0.687772, 0.685837, 0.683902, 0.681967, 0.680032, 0.678097, 0.676162, 0.674227, 0.672292, 0.670357, 0.668422, 0.666487, 0.664552, 0.662617, 0.660683, 0.658748, 0.656813, 0.654878, 0.652943, 0.651008, 0.649073, 0.647138, 0.645203, 0.643268, 0.641333, 0.639398, 0.637463, 0.635528, 0.633593, 0.631658, 0.629723, 0.627788, 0.625853, 0.623918, 0.621983, 0.620048, 0.618113, 0.616178, 0.614243, 0.612308, 0.610373, 0.608438, 0.2, 0.2]
[0.0, 7.66667e-6, 1.53333e-5, 2.3e-5, 3.06667e-5, 3.83333e-5, 4.6e-5, 5.36667e-5, 6.13333e-5, 6.9e-5, 7.66667e-5, 8.43333e-5, 9.2e-5, 9.96667e-5, 0.000107333, 0.000115, 0.000122667, 0.000130333, 0.000138, 0.000145667, 0.000153333, 0.000161, 0.000168667, 0.000176333, 0.000184, 0.000191667, 0.000199333, 0.000207, 0.000214667, 0.000222333, 0.00023, 0.000237667, 0.000245333, 0.000253, 0.000260667, 0.000268333, 0.000276, 0.000283667, 0.000291333, 0.000299, 0.000306667, 0.000314333, 0.000322, 0.000329667, 0.000337333, 0.000345, 0.000352667, 0.000360333, 0.000368, 0.000375667, 0.000383333, 0.000391, 0.000398667, 0.000406333, 0.000414, 0.000421667, 0.000429333, 0.000437, 0.000444667, 0.000452333, 0.00046, 0.000467667, 0.000475333, 0.000483, 0.000490667, 0.000498333, 0.000506, 0.000513667, 0.000521333, 0.000529, 0.000536667, 0.000544333, 0.000552, 0.000559667, 0.000567333, 0.000575, 0.000582667, 0.000590333, 0.000598, 0.000605667, 0.000613333, 0.000621, 0.000628667, 0.000636333, 0.000644, 0.000651667, 0.000659333, 0.000667, 0.000674667, 0.000682333, 0.00069, 0.000697667, 0.000705333, 0.000713, 0.000720667, 0.000728333, 0.000736, 0.000743667, 0.000751333, 0.000759, 0.000766667, 0.000774333, 0.000782, 0.000789667, 0.000797333, 0.000805, 0.000812667, 0.000820333, 0.000828, 0.000835667, 0.000843333, 0.000851, 0.000858667, 0.000866333, 0.000874, 0.000881667, 0.000889333, 0.000897, 0.000904667, 0.000912333, 0.00092, 0.000927667, 0.000935333, 0.000943, 0.000950667, 0.000958333, 0.000966, 0.000973667, 0.000981333, 0.000989, 0.000996667, 0.00100433, 0.001012, 0.00101967, 0.00102733, 0.001035, 0.00104267, 0.00105033, 0.001058, 0.00106567, 0.00107333, 0.001081, 0.00108867, 0.00109633, 0.001104, 0.00111167, 0.00111933, 0.001127, 0.00113467, 0.00114233, 0.00115, 0.00115767, 0.00116533, 0.001173, 0.00118067, 0.00118833, 0.001196, 0.00120367, 0.00121133, 0.001219, 0.00122667, 0.00123433, 0.001242, 0.00124967, 0.00125733, 0.001265, 0.00127267, 0.00128033, 0.001288, 0.00129567, 0.00130333, 0.001311, 0.00131867, 0.00132633, 0.001334, 0.00134167, 0.00134933, 0.001357, 0.00136467, 0.00137233, 0.00138, 0.00138767, 0.00139533, 0.001403, 0.00141067, 0.00141833, 0.001426, 0.00143367, 0.00144133, 0.001449, 0.00145667, 0.00146433, 0.001472, 0.00147967, 0.00148733, 0.001495, 0.00150267, 0.00151033, 0.001518, 0.00152567]
[0.8, 0.76759, 0.742019, 0.72047, 0.701531, 0.684381, 0.668481, 0.65345, 0.638981, 0.624809, 0.610671, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2]
Out[76]:
PyObject <matplotlib.legend.Legend object at 0x7f315fb87be0>

Low salinity water flooding - with/without adsorption


In [77]:
fluids_hs = FF.oil_water_fluids(mu_water=1.5e-3, mu_oil=3e-3)
fluids_ls = FF.oil_water_fluids(mu_water=1e-3, mu_oil=3e-3)
rel_perms_hs = FF.oil_water_rel_perms(krw0=0.4, kro0=0.9, 
        swc=0.15, sor=0.2, nw=2.0, no = 2.0)
rel_perms_ls = FF.oil_water_rel_perms(krw0=0.3, kro0=0.95, 
        swc=0.15, sor=0.15, nw=2.0, no = 2.0)
core_flood = FF.core_flooding(u_inj=1.15e-5, pv_inject=5.0, p_back=1e5, sw_init=0.2, sw_inj=1.0, rel_perms=rel_perms_hs)
core_props = FF.core_properties()
ls_res = FF.low_sal_water_flood(core_props, fluids_ls, fluids_hs, rel_perms_hs, 
        rel_perms_ls, core_flood)
FF.visualize(ls_res)


┌ Info: difficulty finding the shock front saturation range!
└ @ Main.FractionalFlow /home/ali/projects/peteng/analytical/FractionalFlow/FractionalFlow.jl:395
┌ Info: difficulty finding the shock front saturation range!
└ @ Main.FractionalFlow /home/ali/projects/peteng/analytical/FractionalFlow/FractionalFlow.jl:395
Out[77]:
PyObject <matplotlib.legend.Legend object at 0x7f315f7ced30>

compare with numeric


In [78]:
t_sec, pv_num, rec_fact, xt_num, sw_num, c_old, c_out_sal = 
    FF.forced_imb_implicit_upwind(core_props, fluids_ls, fluids_hs, rel_perms_hs, 
        rel_perms_ls, core_flood)
# plot(ls_res)


Progress:  92%|█████████████████████████████████████▊   |  ETA: 0:00:01
Out[78]:
([0.0, 1.30435, 2.6087, 3.91304, 5.21739, 6.52174, 7.82609, 9.13043, 10.4348, 11.7391  …  1162.17, 1163.48, 1164.78, 1166.09, 1167.39, 1168.7, 1170.0, 1171.3, 1172.61, 1173.91], [0.0, 0.000333333, 0.000666667, 0.001, 0.00133333, 0.00166667, 0.002, 0.00233333, 0.00266667, 0.003  …  0.297, 0.297333, 0.297667, 0.298, 0.298333, 0.298667, 0.299, 0.299333, 0.299667, 0.3], [0.0, 0.000412844, 0.000825688, 0.00123853, 0.00165138, 0.00206422, 0.00247706, 0.00288991, 0.00330275, 0.0037156  …  0.367844, 0.368257, 0.36867, 0.369083, 0.369495, 0.369908, 0.370321, 0.370734, 0.371147, 0.37156], [0.0, 0.0003, 0.0006, 0.0009, 0.0012, 0.0015, 0.0018, 0.0021, 0.0024, 0.0027  …  0.1473, 0.1476, 0.1479, 0.1482, 0.1485, 0.1488, 0.1491, 0.1494, 0.1497, 0.15], [1.0, 0.846108, 0.844368, 0.842739, 0.841174, 0.839654, 0.838169, 0.836714, 0.835284, 0.833877  …  0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2], [0.0, 1.16822e-83, 1.29599e-81, 7.25119e-80, 2.72532e-78, 7.73532e-77, 1.76771e-75, 3.38681e-74, 5.59411e-73, 8.12996e-72  …  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0  …  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0])

In [79]:
figure(2)
plot(xt_num/(core_props.length)/pv_num[end], sw_num)
plot(xt_num/(core_props.length)/pv_num[end], 1.-c_old)
plot(ls_res.saturation_profile_xt[:,1], ls_res.saturation_profile_xt[:,2])
plot(ls_res.tracer_profile_xt[:,1], ls_res.tracer_profile_xt[:,2])
xlabel("x/t [-]")
ylabel("Water saturation [-]")


MethodError: no method matching -(::Int64, ::Array{Float64,1})
Closest candidates are:
  -(!Matched::PyCall.PyObject, ::Any) at /home/ali/.julia/packages/PyCall/0jMpb/src/pyoperators.jl:14
  -(::Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}) at int.jl:51
  -(::T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}, !Matched::T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} at int.jl:52
  ...

Stacktrace:
 [1] top-level scope at In[79]:3

Low salinity flooding, an exceptional case


In [29]:
sor_hs = 0.25
sw_init = 1-sor_hs
fluids_hs = FF.oil_water_fluids(mu_water=1e-3, mu_oil=2e-3)
fluids_ls = FF.oil_water_fluids(mu_water=1e-3, mu_oil=2e-3)
rel_perms_hs = FF.oil_water_rel_perms(krw0=0.4, kro0=0.9, 
        swc=0.15, sor=sor_hs, nw=2.0, no = 2.0)
rel_perms_ls = FF.oil_water_rel_perms(krw0=0.3, kro0=0.95, 
        swc=0.15, sor=0.15, nw=2.0, no = 2.0)
core_flood = FF.core_flooding(u_inj=1.15e-5, pv_inject=30.0, p_back=1e5, sw_init=sw_init, 
    sw_inj=1.0, rel_perms=rel_perms_hs)
core_props = FF.core_properties()
ls_res = FF.low_sal_water_flood(core_props, fluids_ls, fluids_hs, rel_perms_hs, 
        rel_perms_ls, core_flood)
FF.visualize(ls_res)


┌ Info: difficulty finding the shock front saturation range!
└ @ Main.FractionalFlow /home/ali/projects/peteng/analytical/FractionalFlow/FractionalFlow.jl:395
┌ Info: difficulty finding the shock front saturation range!
└ @ Main.FractionalFlow /home/ali/projects/peteng/analytical/FractionalFlow/FractionalFlow.jl:395
Out[29]:
PyObject <matplotlib.legend.Legend object at 0x7f31606b3828>

In [30]:
t_sec, pv_num, rec_fact, xt_num, sw_num, c_old, c_out_sal = 
    FF.forced_imb_implicit_upwind(core_props, fluids_ls, fluids_hs, rel_perms_hs, 
        rel_perms_ls, core_flood)


UndefVarError: update! not defined

Stacktrace:
 [1] #forced_imb_implicit_upwind#11(::Float64, ::Function, ::Main.FractionalFlow.CoreProperties, ::Main.FractionalFlow.Fluids, ::Main.FractionalFlow.Fluids, ::Main.FractionalFlow.CoreyRelativePermeability, ::Main.FractionalFlow.CoreyRelativePermeability, ::Main.FractionalFlow.CoreFlooding) at /home/ali/projects/peteng/analytical/FractionalFlow/water_flood_fvm_upwind.jl:173
 [2] forced_imb_implicit_upwind(::Main.FractionalFlow.CoreProperties, ::Main.FractionalFlow.Fluids, ::Main.FractionalFlow.Fluids, ::Main.FractionalFlow.CoreyRelativePermeability, ::Main.FractionalFlow.CoreyRelativePermeability, ::Main.FractionalFlow.CoreFlooding) at /home/ali/projects/peteng/analytical/FractionalFlow/water_flood_fvm_upwind.jl:14
 [3] top-level scope at In[30]:1

In [15]:
figure(2)
plot(xt_num/(core_props.length)/pv_num[end], sw_num)
plot(xt_num/(core_props.length)/pv_num[end], 1-c_old)
plot(ls_res.saturation_profile_xt[:,1], ls_res.saturation_profile_xt[:,2])
plot(ls_res.tracer_profile_xt[:,1], ls_res.tracer_profile_xt[:,2])
xlabel("x/t [-]")
ylabel("Water saturation [-]")
title("tertiary low-sal water flood")


Out[15]:
PyObject Text(0.5,1,'tertiary low-sal water flood')

In [15]:
sor_hs = 0.20
sw_init = 1-sor_hs
fluids_hs = FF.oil_water_fluids(mu_water=1e-3, mu_oil=2e-3)
fluids_ls = FF.oil_water_fluids(mu_water=1e-3, mu_oil=2e-3)
rel_perms_hs = FF.oil_water_rel_perms(krw0=0.4, kro0=0.9, 
        swc=0.15, sor=sor_hs, nw=2.0, no = 2.0)
rel_perms_ls = FF.oil_water_rel_perms(krw0=0.3, kro0=0.95, 
        swc=0.15, sor=0.15, nw=2.0, no = 2.0)
core_flood = FF.core_flooding(u_inj=1.15e-5, pv_inject=30.0, p_back=1e5, sw_init=sw_init, 
    sw_inj=1.0, rel_perms=rel_perms_hs)
core_props = FF.core_properties()
ls_res = FF.single_ion_adsorption_water_flood_single_shock(core_props, fluids_ls, fluids_hs, rel_perms_hs, 
        rel_perms_ls, core_flood, 0.0)
FF.visualize(ls_res)


Out[15]:
PyObject <matplotlib.legend.Legend object at 0x7f596b5c0bd0>

In [17]:
t_sec, pv_num, rec_fact, xt_num, sw_num, c_old, c_out_sal = 
    FF.forced_imb_implicit_upwind(core_props, fluids_ls, fluids_hs, rel_perms_hs, 
        rel_perms_ls, core_flood)


Progress:  98%|████████████████████████████████████████ |  ETA: 0:00:00
Out[17]:
([0.0, 1.30435, 2.6087, 3.91304, 5.21739, 6.52174, 7.82609, 9.13043, 10.4348, 11.7391  …  1162.17, 1163.48, 1164.78, 1166.09, 1167.39, 1168.7, 1170.0, 1171.3, 1172.61, 1173.91], [0.0, 0.000333333, 0.000666667, 0.001, 0.00133333, 0.00166667, 0.002, 0.00233333, 0.00266667, 0.003  …  0.297, 0.297333, 0.297667, 0.298, 0.298333, 0.298667, 0.299, 0.299333, 0.299667, 0.3], [0.0, 1.05956e-13, 1.06617e-13, 9.78054e-14, 9.75851e-14, 1.96712e-13, 1.70939e-13, -5.72734e-15, 4.20739e-14, 4.11928e-14  …  -1.78649e-12, -1.79839e-12, -1.82724e-12, -1.86645e-12, -1.81182e-12, -1.86161e-12, -1.93826e-12, -1.87262e-12, -1.96316e-12, -1.9039e-12], [0.0, 0.0003, 0.0006, 0.0009, 0.0012, 0.0015, 0.0018, 0.0021, 0.0024, 0.0027  …  0.1473, 0.1476, 0.1479, 0.1482, 0.1485, 0.1488, 0.1491, 0.1494, 0.1497, 0.15], [1.0, 0.847414, 0.846251, 0.845158, 0.844104, 0.843076, 0.842068, 0.841076, 0.840099, 0.839135  …  0.79, 0.79, 0.79, 0.79, 0.79, 0.79, 0.79, 0.79, 0.79, 0.79], [0.0, 5.0858e-83, 5.94677e-81, 3.49838e-79, 1.37953e-77, 4.10032e-76, 9.79528e-75, 1.95863e-73, 3.37116e-72, 5.09786e-71  …  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0  …  1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0])

In [18]:
figure(2)
plot(xt_num/(core_props.length)/pv_num[end], sw_num)
plot(xt_num/(core_props.length)/pv_num[end], c_old)
plot(ls_res.saturation_profile_xt[:,1], ls_res.saturation_profile_xt[:,2])
plot(ls_res.tracer_profile_xt[:,1], ls_res.tracer_profile_xt[:,2])
xlabel("x/t [-]")
ylabel("Water saturation [-]")


Out[18]:
PyObject Text(24,0.5,'Water saturation [-]')

In [19]:
plot(xt_num/(core_props.length)/pv_num[end], sw_num)
# plot(xt_num/(core_props.length)/pv_num[end], c_old)
plot(ls_res.saturation_profile_xt[:,1], ls_res.saturation_profile_xt[:,2])
# plot(ls_res.tracer_profile_xt[:,1], ls_res.tracer_profile_xt[:,2])
xlabel("x/t [-]")
ylabel("Water saturation [-]")


Out[19]:
PyObject Text(24,0.5,'Water saturation [-]')

Solvent injection: DME example

One necessary detail is the volumetric partition coefficient that is needed for finding the analytical solution. It can be done by doing some thermodynamic magic for finding the partial molar volumes of DME in the aqueous and in the oleic phase.
I've done it in another file, because it is boring for everybody else (not me, I love thermodynamics). The result is here. I have also shown the molar and mass partition coefficients


In [26]:
fluids_oil_water = FF.oil_water_fluids(mu_water=1e-3, mu_oil=2e-3)
fluids_solvent = FF.oil_water_fluids(mu_water=1.1e-3, mu_oil=1e-3)
rel_perms_oil_water = FF.oil_water_rel_perms(krw0=0.4, kro0=0.9, 
    swc=0.15, sor=0.2, nw=2.0, no = 2.0)
rel_perms_solvent = FF.oil_water_rel_perms(krw0=0.4, kro0=0.9, 
swc=0.15, sor=0.05, nw=2.0, no = 2.0)
core_flood = FF.core_flooding(sw_init = 1-0.2)
core_props = FF.core_properties()
K_eq = 2.0
sol_res = FF.water_soluble_solvent_flood(core_props, fluids_solvent, fluids_oil_water, 
    rel_perms_oil_water, rel_perms_solvent, core_flood, K_eq)
FF.visualize(sol_res)


low sal sw_shock = 0.8608359516499842
low sal breakthrough time = 1.0980083098209574
high sal sw_shock = 0.5418926584207182
high sal breakthrough time = 0.7870168506036143
Out[26]:
PyObject <matplotlib.legend.Legend object at 0x7f0873cf9ad0>

In [17]:
typeof(sol_res)


UndefVarError: sol_res not defined