Расчет показателей работы скважины BL
В книге «Waterflooding» (1986), в приложении А приведен листинг программы на FORTRAN66, однако мне показалось, что можно переписать проще. В книге также приведен пример расчета, который использовался для контроля правильности написания.
Переписанный код на C# githib
Относительные фазовые проницаемости, описаны функцией Кори
![]()
![]()
public double GetKro(double Swd)
{
return a1 * Math.Pow((1 - Swd), m);
}
public double GetKrw(double Swd)
{
return a2 * Math.Pow(Swd, n);
}
где нормирование насыщенности проводится в интервале от начальной до остаточной нефтенасыщенности,
![]()
public double GetSwd(double Sw)
{
return (Sw - Swi) / (1 - Sor - Swi);
}
Доля воды в потоке (обводненность),
![]()
где,
![]()
public double Getfw(double Swd) // Функция fw в точке Swd
{
double A = (a1 * viscw) / (a2 * visco);
return Math.Pow(Swd, n) / (Math.Pow(Swd, n) + A * Math.Pow((1 - Swd), m));
}
Значение производной от обводненности
![]()
public double GetdfwdSw(double Swd) // Производная fw` в точке Swd
{
double A = (a1 * viscw) / (a2 * visco);
return (1 / (1 - Sor - Swi)) * A * (n * Math.Pow(Swd, (n - 1)) * Math.Pow((1 - Swd), m) + m * Math.Pow(Swd, n) * Math.Pow((1 - Swd), (m - 1))) / (Math.Pow((Math.Pow(Swd, n) + A * Math.Pow((1 - Swd), m)), 2));
}
Определение значения насыщенности на фронте вытеснения происходит простым итеративным методом половинного деления.
Зная, что решение находится в интервале нормированной насыщенности от нуля до единицы, задается начальное приближение Swd = 0.5 и строится уравнение касательной к графику функции fw в этой точке. Если насыщенность подобрана верно, то касательная упадет в точку Swd = 0. В зависимости от того, перелетела ли или не долетела касательная, делается вывод об изменении насыщенности на следующей итерации.
public double GetSwf(double Sw)
{
double L = 0;
double R = 1;
double C = 0;
double Swd; // Нормированная насыщенность
double dfwdSw;
double Y = 1;
double eps = 1e-5;
while (Math.Abs(Y) > eps)
{
C = (L + R) * 0.5;
Swd = GetSwd(C);
dfwdSw = GetdfwdSw(Swd);
// Проводим линию касательной к функции fw, если в точке Swi она не пересекает ноль, значит решение пока не найдено
Y = Getfw(Swd) + dfwdSw * (Sw - C);
if (Y < -eps)
{
L = C;
}
if (Y > +eps)
{
R = C;
}
}
return C;
} // Получить насыщенность на фронте вытеснения
Это всё что касается вспомогательных подпрограмм.
Рассмотрим технологический режим разработки поддержания постоянного перепада давления между нагнетательной и добывающей скважиной. Дебит жидкости в элементарном сечении пласта можно записать как,
![]()
Приведем к привычному уравнению для дебита,
![]()
Запишем в целом для пласта,
![]()
Изменение дебита связано с изменением вязкости жидкости,
![]()
Значение вязкости жидкости в интервале насыщенности от заданной Sw до остаточной нефтенасыщенности, находится интегрированием методом трапеции.
public double GetLaAverage(double Sw) // Определение средней вязкости в интревале насыщенности от Sw до (1 - Sor)
{
// Решение интеграла методом трапеции
int N = 49;
double dSw = (1 - Sor - Sw) / N;
double Swd;
double Kro, Krw;
double La1, La2;
double dfwdSw1, dfwdSw2;
double dfwdSwi;
double LaSum;
double h;
Swd = GetSwd(Sw);
Kro = GetKro(Swd);
Krw = GetKrw(Swd);
La1 = 1 / (Kro / visco + Krw / viscw);
if (dSw == 0) return La1;
dfwdSw1 = GetdfwdSw(Swd);
dfwdSwi = dfwdSw1;
LaSum = 0;
for (int i = 0; i < (N); ++i)
{
Sw = Sw + dSw;
if (Sw > (1 - Sor)) Sw = 1 - Sor;
Swd = GetSwd(Sw);
Kro = GetKro(Swd);
Krw = GetKrw(Swd);
La2 = 1 / (Kro / visco + Krw / viscw);
dfwdSw2 = GetdfwdSw(Swd);
h = dfwdSw1 - dfwdSw2;
LaSum = LaSum + 0.5 * (La1 + La2) * h;
La1 = La2;
dfwdSw1 = dfwdSw2;
}
return LaSum / dfwdSwi;
}
}
На первом этапе расчета, фронт вытеснения нагнетаемой воды не достиг добывающей скважины. Наблюдается период безводной добычи нефти.
Дебит жидкости изменяется обратно пропорционально вязкости системы, по мере прохождения фронта вытеснения,
![]()
Вязкость жидкости в заводненной части остается постоянной и определяется нахождением вязкости от насыщенности на фронте вытеснения Swf до значения остаточной нефтенасыщенности (1-Sor).
В примере используются значения,
![]()
Для заданных параметров Кори, насыщенность на фронте вытеснения,
![]()
И вязкость жидкости,
![]()
Сравнивая полученную вязкость с вязкостью воды, можно отметить, кажущейся вязкость нагнетаемой воды в более чем 3.2 раза выше вязкости воды.
В советской литературе (Борисов Ю.П), использовалось понятие коэффициент увеличения фильтрационных сопротивлений, который показывал, во сколько раз возрастает сопротивление в зоне замещения нефти водой.
![]()
![]()
где
![]()
Определив который, можно рассчитать и среднюю вязкость,
![]()
Подстановка значений в формулу дает такое же значение вязкости 3.2.
Коэффициент безводной нефтеотдачи или же доля отбора нефти из пласта до начала обводнения от порового объема,
![]()
Вязкость системы будет линейно изменятся от вязкости нефти в начальный момент времени, до вязкости жидкости в заводненной части в момент прорыва воды,
![]()
В тексте программы безводный период делится на 10 равных частей, для каждой расчетной точки определяется дебит жидкости, который равен дебиту нефти, накопленная добыча нефти в процентах от порового объема и накопленная добыча нефти.
Последняя неопределенная величина, это время.
В каждой расчетной точке нам известен мгновенный дебит жидкости и накопленные добычи жидкости. Сначала определим средний дебит жидкости за период времени,
![]()
Затем добычу жидкости за рассмотренный период времени,
![]()
где поровый объем обозначен как,
![]()
накопленная закачка воды, выраженная в поровых объемах записана через отношение,
![]()
Время которое проходит при переходе от одной расчетной точки к другой,
![]()
Далее просто накапливаем время,
![]()
Собственно, всё готово для расчета показателей разработки в безводный период.
double Qibt = 1 / BL.GetdfwdSw(BL.GetSwd(Swf));
double dQibt = Qibt / 10;
double Labt = BL.GetLaAverage(Swf);
double time = 0;
double Qi_t_prev = 0;
double qt_t_prev = 0;
double qw = 0;
double qo = 0;
double WCT = 0;
for (int J = 0; J <= 10; ++J) // Десять расчетных шагов до начала обводнения
{
double Qi_t = dQibt * J;
double La_t = BL.visco + (Labt - BL.visco) * J / 10;
double qt_t = BL.GetLiquidRate(La_t);
if (J > 0)
{
time = time + 2 * (Qi_t - Qi_t_prev) * 160285 / (qt_t + qt_t_prev); // PV = 160285
}
qo = qt_t;
if (J == 10) // Прорыв в добывающую скважину
{
var fw = BL.Getfw(BL.GetSwd(Swf));
qw = qt_t * fw;
qo = qt_t - qw;
WCT = fw;
}
Qi_t_prev = Qi_t;
qt_t_prev = qt_t;
}


Прорыв фронта вытеснения происходит при отборе 30.2% от запасов нефти.
Второй этап расчета, это период обводнения, когда в добываемой продукции обводненность постоянно возрастает по мере отбора запасов нефти.
Обводненность продукции зависит от значения насыщенности в прискважинной зоне. В момент прорыва фронта вытеснения в скважину, обводненность определяется насыщенностью на фронте вытеснения. Для условий нашего примера, это значение
![]()
Таким образом, обводненность изменяется мгновенно от 0% до 89.6%. В дальнейшем водонасыщенность продолжит расти, до достижения значения остаточной нефтенасыщенности. Для расчета интервал изменения нефтенасыщенности делится на 50 равных частей.
Накопленная добыча нефти, в поровых объемах определяется для каждой точки насыщенности на фронте вытеснения,
![]()
И вязкость жидкости, определяется в интервале от текущей насыщенности до остаточной нефтенасыщенности.
Это позволяет построить зависимость вязкости системы от накопленной закачки воды, что позволяет определить дебит жидкости. Зная обводненность нетрудно определить и дебит нефти.

До прорыва воды в добывающую скважину, вязкость системы увеличивалась. Однако после прорыва воды, вязкость начинает снижается и после двух поровых объемов снижается ниже вязкости нефти 2 cP. Таким образом в нашем примере, появление воды в продукции скважины увеличивает продуктивность скважины, что сказывается на росте дебита жидкости.
N = 51;
dSw = (1 - BL.Sor - Swf) / (N - 1);
Sw = Swf;
for (int i = 0; i < N - 2; ++i)
{
Qi = 1 / BL.GetdfwdSw(BL.GetSwd(Sw));
var La = BL.GetLaAverage(Sw);
var qt_t = BL.GetLiquidRate(La);
var fw = BL.Getfw(BL.GetSwd(Sw));
var Swav = Sw + (1 - fw) / BL.GetdfwdSw(BL.GetSwd(Sw));
qw = qt_t * fw;
qo = qt_t - qw;
WCT = fw;
if (WCT > 0.999) break;
if (i > 0)
{
time = time + 2 * (Qi - Qi_t_prev) * 160285 / (qt_t + qt_t_prev);
text.WriteLine($"{time:F1}\t{qo:N2}\t{qw:N2}\t{qt_t:N2}\t{WCT:N3}\t{Qi:N3}\t{Qi:N3}\t{160.285 * (Swav - BL.Swi):N3}\t{La:N4}");
}
Qi_t_prev = Qi;
qt_t_prev = qt_t;
Sw = Sw + dSw;
}
Объединяя показатели для безводного периода и периода после прорыва воды, получим показатели работы скважины.

Характеристика вытеснения нефти водой,

Расчет накопленной добычи нефти производится через изменение средней водонасыщенности в пласте,
![]()
![]()