С самого начала численного подхода к моделированию коллектора основная задача остается неизменной - повышение скорости вычислений. С недавнего времени модели машинного обучения привлекают особое внимание как возможное приближение обычных численных моделей. Однако эта исследовательская деятельность ограничена сложностью данных о коллекторе, а также черным ящиком инструментов промышленного моделирования. Редкие, но популярные инструменты с открытым исходным кодом основаны на C или Matlab, что также ограничивает реализацию передовых моделей глубокого обучения. Сегодня мы начинаем серию публикаций, которые знакомят с современным подходом к моделированию коллектора на основе Python. Постепенно мы перейдем от простых вопросов о том, как считывать и сохранять данные, к тому, как обучить модель нейронной сети моделировать динамику коллектора и выполнять адаптацию коллектора (сопоставление истории).

В Части I мы узнаем, из чего состоит модель коллектора и как правильно читать все данные.

Часть II объясняет, как извлекать небольшие порции данных из набора моделей коллектора и преобразовывать данные в тензоры факелов.

Как представить модель коллектора на Python

Чтобы описать модель коллектора, необходимо указать ее геометрию, свойства породы и флюида в каждой точке, расположить добывающие и нагнетательные скважины, а также указать действия, применяемые к пласту, и контролировать его динамику. Позже мы рассмотрим эти компоненты более подробно, теперь нам достаточно нескольких общих стандартов для описания всех этих свойств в текстовых / числовых файлах и для определенности будем придерживаться формата ECLIPSE (работа с композитным форматы аналогичны).

Типичный проект ECLIPSE состоит из основного файла с расширением .DATA и набора дополнительных включенных текстовых / двоичных файлов с различными расширениями. Например, здесь - это образец проекта (папка RESULTS обычно большая, и мы заархивировали ее для экономии места на диске).

Первым шагом в исследовании резервуара является чтение всех файлов, представляющих резервуар, в массивы Python. Для этого воспользуемся фреймворком с открытым исходным кодом DeepField.

Чтобы установить пакет DeepField, запустите pip install git + https: //github.com/Skoltech-CHR/DeepField.git в терминале. В качестве альтернативы можно использовать предоставленный файл сборки docker.

Репозиторий DeepField https://github.com/Skoltech-CHR/DeepField содержит набор общедоступных моделей резервуаров в каталоге open_data. Мы рекомендуем клонировать все репо, чтобы получить данные локально. В частности, мы будем использовать предоставленную модель norne_simplified. После загрузки модели распакуйте архив RESULTS.zip, чтобы все было готово.

Чтобы загрузить модель в Python, мы импортируем класс Field из пакета deepfield, указываем путь к файлу .DATA и вызываем метод загрузки, как показано во фрагменте кода ниже. :

Загрузка данных занимает некоторое время, и вы увидите множество сообщений журнала, рассказывающих, что происходит в данный момент.

Чтобы пропустить сообщения, передайте параметр loglevel = ’ERROR 'в конструктор Field . Ниже мы также покажем, как существенно ускорить загрузку.

В конце сообщений журнала вы увидите сводку того, что было загружено пчелами:

INFO:Field:===== Field summary =====
INFO:Field:GRID attributes: MAPAXES, ZCORN, COORD, ACTNUM, DIMENS
INFO:Field:ROCK attributes: PORO, PERMX, PERMY, PERMZ
INFO:Field:STATES attributes: PRESSURE, RS, SGAS, SOIL, SWAT
INFO:Field:TABLES attributes: PVTO, ROCK, PVTW, DENSITY, SWOF, SGOF, PVDG
INFO:Field:WELLS attributes: WCONINJE, COMPDAT, WELSPECS, WCONPROD, RESULTS
INFO:Field:=========================

Существует набор компонентов с именами GRID, ROCK, STATES, TABLES и WELLS, и каждый компонент содержит набор атрибутов. Например, компонент ROCK содержит атрибуты PORO, PERMX, PERMY и PERMZ (в руководстве ECLIPSE они также называются ключевыми словами). Прежде чем мы начнем подробно рассматривать каждый компонент и атрибут, давайте визуализируем сразу всю модель, используя метод model.show ().

model.show () включает интерактивную 3D-визуализацию. Передайте имя атрибута в метод show, чтобы указать геологическое свойство. Например, model.show (‘PORO’) визуализирует поле пористости. Подробнее о параметрах метода show см. Документацию.

Первоначальное месторождение Норн расположено на норвежском континентальном шельфе и широко используется в качестве эталонной модели. Ниже мы видим упрощенный вариант модели (в частности, без разломов), однако геометрические свойства и стволы сохранены.

Теперь перейдем к компонентам модели.

Сетка

Сетка описывает геометрию (форму) коллектора. Исходя из подхода конечно-разностного моделирования, пространственная форма модели коллектора дискретизируется на более мелкие части, называемые блоками сетки (или ячейками). Если все ячейки имеют правильную форму и одинаковый размер, мы получаем равномерную ортогональную сетку. Чтобы задать такую ​​сетку, необходимо задать количество ячеек в каждом направлении (скажем, nx, ny и nz) и ее размеры (скажем, dx, dy, dz). Это наиболее простой тип сетки, и для ее полного определения требуется всего 6 чисел.

Как узнать пространственные характеристики подземного резервуара? Когда-то давно это было результатом бурения нескольких скважин. В настоящее время сейсморазведка помогает лучше описать коллекторы.

Модель Норна имеет более сложную сеточную структуру, в которой ячейки имеют неправильную форму и разный размер. Для задания такой сетки необходимо задать координаты углов каждой ячейки. Это тип сетки угловых точек, который в соответствии со стандартом ESCLIPSE описывается ключевыми словами DIMENS, ZCORN и COORD. Для доступа к соответствующим числовым массивам используйте model.grid.dimens, model.grid.zcorn и model.grid.coord.

Чтобы получить список доступных атрибутов (ключевых слов) в компоненте модели (в частности, компоненте сетки) введите model.grid.attributes. Обратите внимание, что атрибуты не чувствительны к регистру, поэтому model.grid.zcorn и model.grid.ZCORN одинаковы.

В частности, model.grid.dimens дает [46, 112, 22] - количество ячеек в направлениях x, y и z. Тогда model.grid.coord представляет собой массив формы (47, 113, 6) и содержит (x, y, z) координаты верхней и нижней точек столбов. которые образуют клетки. Наконец, model.grid.zcorn представляет собой массив формы (46, 112, 22, 8) и содержит глубину 8 углов для каждой ячейки. На рисунке ниже показаны эти ключевые слова для одной ячейки:

Есть несколько атрибутов компонента сетки, которые могут быть полезны в различных вычислениях:

  • cell_volumes дает массив объемов ячеек;
  • xyz содержит (x, y, z) координаты углов ячеек;
  • cell_centroids возвращает координаты (x, y, z) центров ячеек.

Дополнительные атрибуты и методы (например, ортогонализация, масштабирование и уменьшение) см. В документации и записной книжке по классу Grid.

Рок и Штаты

Имея сетку, мы можем присвоить каждой ячейке набор статических и временных свойств. Ключевыми статическими свойствами являются тензор пористости и проницаемости породы. Грубо говоря, они описывают, сколько жидкости может содержать ячейка и насколько хорошо жидкость может течь в каждом направлении. Соответствующие атрибуты PORO, PERMX, PERMY. PERMZ содержатся в компоненте model.rock. Каждый атрибут задается массивом формы, равной model.grid.dimens. Ниже поля проницаемости показаны в 3D (с использованием метода model.show (‘PERMX’), например, для поля PERMX).

Исходные свойства породы получены из интерпретации ГИС и образцов керна. Затем информация, передаваемая по скважинам, распространяется на всю модель с использованием сейсмических профилей.

В отличие от компонента Rock, содержащего статические поля горных пород, компонент State содержит динамические поля, которые описывают давление, насыщенность нефтью / водой / газом и содержание газа в каждой ячейке. Соответствующие атрибуты - ДАВЛЕНИЕ, ПОЧВА, SWAT, SGAS и RS - задаются массивом 4D. Первая ось представляет временные шаги, а последние 3 - пространственные размеры модели. На анимации ниже показано, как давление изменяется во времени:

Следует отметить, что любое преобразование сетки (апскейлинг, даунскейлинг) требует нетривиальной повторной интерполяции свойств. Мы оставляем это за рамками Части I и обращаемся к блокнотам этот и этот за подробностями.

Уэллс

Набор колодцев удобно представить в виде древовидной структуры, где корень - это само поле, а группы колодцев, основные и конечные ветви колодцев - узлы. Метод model.wells.render_tree () показывает общую структуру дерева:

FIELD
|-- INJE
|   |-- MANI-C
|   |   |-- C-1H
|   |   |-- C-2H
|   |   |-- C-3H
|   |   |-- C-4AH
|   |   +-- C-4H
|   |-- MANI-F
|   |   |-- F-1H
|   |   |-- F-2H
|   |   |-- F-3H
|   |   +-- F-4H
|   +-- WI-GSEG
+-- PROD
    |-- MANI-B2
    |   |-- B-1AH
    |   |-- B-1BH
    |   |-- B-1H
    |   +-- B-3H
    |-- MANI-B1
    |   |-- MANI-K1
    |   +-- B1-DUMMY
    |       |-- B-2H
    |       |-- B-4AH
    |       |-- B-4BH
    |       |-- B-4DH
    |       +-- B-4H
    |-- MANI-D1
    |   |-- D-1CH
    |   |-- D-1H
    |   |-- D-3AH
    |   |-- D-3BH
    |   +-- D-3H
    |-- MANI-D2
    |   |-- MANI-K2
    |   |   +-- K-3H
    |   +-- D2-DUMMY
    |       |-- D-2H
    |       |-- D-4AH
    |       +-- D-4H
    |-- MANI-E1
    |   |-- E-1H
    |   |-- E-3AH
    |   |-- E-3BH
    |   |-- E-3CH
    |   +-- E-3H
    +-- MANI-E2
        |-- E-2AH
        |-- E-2H
        |-- E-4AH
        +-- E-4H

Мы наблюдаем две основные группы: добывающие скважины (PROD) и нагнетательные скважины (INJE). Листовые узлы, например D-1CH, представляют собой отдельные лунки.

К каждому узлу можно получить доступ по его имени, например model.wells [‘B-4AH’]. Мы можем перечислить атрибуты, назначенные узлу, с помощью model.wells [‘B-4AH’]. Attributes. В результате получается список (WELSPECS, COMPDAT, RESULTS, WELLTRACK), который мы рассмотрим более подробно.

Большинство атрибутов представлены в виде таблиц pandas.DataFrame, что упрощает управление ими. Например, COMPDAT содержит информацию об открытии и закрытии интервалов перфорации:

Аналогично WCONPROD содержит параметры управления скважиной (в частности, забойное давление, BHPT):

Самая важная таблица - РЕЗУЛЬТАТЫ, которая содержит показатели добычи нефти / воды / газа (WOPR, WWPR. WGPR):

Скорость добычи можно визуализировать с помощью метода model.wells.show_rates (). Это включает интерактивную панель, на которой можно исследовать общие ставки:

или каждый узел в отдельности (скважина или группа скважин):

В следующих частях мы обсудим, как рассчитать факторы связности, дебиты, а также другие важные характеристики скважины. См. Также документацию и блокнот для дополнительных действий, например отслеживание блоков.

Таблицы PVT

Физические свойства жидкости (например, объем, вязкость, сжимаемость) зависят от давления и температуры. Отношения приведены в наборе таблиц PVT (давление-объем-температура), а также зависимости относительной проницаемости от насыщения. Таблицы содержатся в компоненте model.tables, а model.tables.attributes показывает его имена. Например, модель Norne содержит свойства PVTO, ROCK, PVTW, DENSITY, SWOF, SGOF и PVDG.

На первый взгляд таблицы выглядят как обычные объекты pandas.DataFrame. Например, ПВДГ:

Таблица PVDG описывает свойства мертвого газа и дает зависимость объемного коэффициента газообразования и вязкости газа от давления.

Как получить вязкость газа, которая соответствует, скажем, давлению = 80 или 100 (обратите внимание, что эти значения отсутствуют в таблице)? Фактически, каждая таблица требует определенной модели интерполяции (не обязательно линейной). По волшебству каждая таблица работает как функция! Вызов таблицы с набором новых значений дает интерполированные результаты:

Наконец, используя метод plot (), можно визуализировать физические зависимости:

Каждое значение в таблицах PVT является результатом физических измерений и экспериментов. Вот почему данные немногочисленны и важна интерполяция.

Больше практических примеров по PVT-таблицам можно найти в этой записной книжке.

Как ускорить ввод-вывод данных

Изменяя данные коллектора, можно сохранить проект в проекте ECLIPSE следующим образом: model.dump (‘path_to_the_directory_where_to_save’). Это обеспечивает совместимость со стандартным программным обеспечением для моделирования. Однако чтение данных из таких форматов происходит очень медленно. Значительно выигрывает работа с файлами .HDF5. Чтобы преобразовать модель в файл .HDF5, используйте model.dump (‘filename.hdf5’). Теперь сравним скорость загрузки данных модели Норна:

Загрузка модели из файла .HDF5 происходит более чем в 10 раз быстрее! Это важно, в частности, для исследований в области машинного обучения, когда у нас будет набор моделей резервуаров и мы будем многократно загружать их для обучения некоторых моделей машинного обучения.

Выводы

Типичное исследование моделей коллектора требует большой работы по предварительной обработке данных. Это ограничивает реализацию современных методов, широко используемых в проектах на основе Python. Фреймворк на основе Python DeepField - это новая инициатива с открытым исходным кодом, направленная на соединение моделей ML / DL и задач моделирования коллектора. В этом посте мы рассмотрели основные этапы загрузки данных и кратко описали основные компоненты и атрибуты моделей пластов. Следуя этой записной книжке, можно воспроизвести результаты. В следующих частях мы рассмотрим более сложные темы.

Что дальше

  • Рассмотрим обучающие программы, представленные в репозитории DeepField. Они дают более практические примеры методов и атрибутов.
  • Проект DeepField продолжает развиваться. Мы приветствуем вопросы и PR на странице проекта GitHub, а также любое сотрудничество!
  • В следующей части мы обсудим, как работать с несколькими моделями пласта и проводить вычисления на GPU.

Автор Егор Илларионов.