Другое

Полное руководство: чтение файлов голов MODFLOW в Python

Узнайте, как читать и анализировать двоичные файлы голов MODFLOW на Fortran с помощью Python с использованием FloPy или прямых методов чтения двоичных файлов. Полное руководство с примерами и советами по устранению неполадок.

Как читать и парсить двоичный файл голов MODFLOW Fortran с помощью Python

Чтение и разбор двоичных файлов голов MODFLOW Fortran в Python

Чтение и разбор двоичных файлов голов MODFLOW Fortran в Python можно осуществить с помощью специализированных библиотек, таких как FloPy, которая предоставляет специализированные классы для обработки двоичных выходных файлов MODFLOW, или через прямые методы чтения двоичных файлов для более индивидуальных подходов.

Содержание

Использование FloPy для двоичных файлов MODFLOW

FloPy является наиболее полным и рекомендуемым подходом для чтения двоичных файлов MODFLOW, включая файлы голов. Библиотека предоставляет специализированные классы, которые понимают формат двоичных файлов MODFLOW.

Класс HeadFile

Класс HeadFile из flopy.utils.binaryfile специально разработан для чтения стандартных двоичных файлов голов MODFLOW:

python
import flopy.utils.binaryfile as bf

# Создание объекта headfile
hdobj = bf.HeadFile('model.hds', precision='single')

# Список доступных временных записей
times = hdobj.get_times()
print(times)

# Получение данных для конкретного времени
head_data = hdobj.get_data(totim=1.0)

Класс HeadUFile

Для моделей MODFLOW-USG используйте класс HeadUFile:

python
headobj = bf.HeadFile(modelname+'.hds', text='headu')
head = headobj.get_data()

Согласно документации flopy, класс BinaryLayerFile “создан… для целых чисел, которые являются указателями на первые байты данных для соответствующего массива данных.”

Основные методы FloPy

  • get_times(): Возвращает список доступных временных шагов
  • get_data(): Извлекает данные голов для указанного времени
  • list_records(): Показывает доступные записи в файле
  • get_kstpkper(): Получает комбинации периодов напряженности/временных шагов

Как показано в учебнике flopy на GitHub, вы можете легко извлекать и строить графики данных голов MODFLOW с помощью этих методов.


Прямые методы чтения двоичных файлов

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

Использование NumPy

Функция numpy.fromfile может читать неформатированные двоичные файлы Fortran:

python
import numpy as np

# Прямое чтение двоичного файла
data = np.fromfile('model.hds', dtype='float32')

# Изменение формы в соответствии с размерами модели
heads = data.reshape((nlay, nrow, ncol))

Использование библиотеки FortranFile

Библиотека fortio предоставляет специализированные инструменты для чтения неформатированных двоичных файлов Fortran:

python
from fortio import FortranFile

# Открытие файла с правильной обработкой заголовка
f = FortranFile('model.hds', header_dtype='uint32')

# Чтение записей
while True:
    try:
        record = f.read_record()
        # Обработка данных записи
    except:
        break

Как описано в репозитории GitHub fortio, эта библиотека обрабатывает “неформатированные двоичные файлы Fortran с записями переменной длины.”

Ручное чтение двоичных файлов

Для полного контроля вы можете реализовать ручное чтение двоичных файлов:

python
import struct

def read_modflow_heads(filename):
    with open(filename, 'rb') as f:
        # Чтение информации заголовка
        header = f.read(4)  # Первые 4 байта
        # Чтение записей данных
        # Реализация зависит от конкретного формата MODFLOW

Понимание структуры двоичных файлов MODFLOW

Двоичные файлы MODFLOW используют специфические структуры неформатированных записей Fortran:

Структура файла

[Запись 1] - Информация заголовка
[Запись 2] - Данные временного шага 1
[Запись 3] - Данные временного шага 2
...

Каждая запись обычно содержит:

  • Заголовок: Информация о записи (время, слой и т.д.)
  • Данные: Фактические значения голов
  • Подвал: Маркеры завершения записи

Размеры данных

Структура данных обычно имеет размеры [output_times, nlay, nrow, ncol], где:

  • output_times: Количество временных шагов с выходными данными
  • nlay: Количество слоев
  • nrow: Количество строк
  • ncol: Количество столбцов

Как отмечено в обсуждении flopy, “данные имеют размеры [output_times, nlay, nrow, ncol], где output_times - это количество раз, когда у вас есть выходные двоичные данные голов.”

Обработка точности

Файлы MODFLOW могут использовать различную точность:

  • Одинарная точность (4 байта на число с плавающей точкой)
  • Двойная точность (8 байт на число с плавающей точкой)

FloPy автоматически определяет точность, но вы можете указать ее вручную:

python
hdobj = bf.HeadFile('model.hds', precision='single')  # или 'double'

Практические примеры

Пример 1: Базовое чтение файла голов

python
import flopy.utils.binaryfile as bf

# Загрузка файла голов MODFLOW
hdobj = bf.HeadFile('model.hds')

# Получение доступных времен
times = hdobj.get_times()
print(f"Доступные временные шаги: {times}")

# Получение данных для последнего временного шага
final_heads = hdobj.get_data(totim=times[-1])

# Сохранение в текстовый файл
np.savetxt('final_heads.txt', final_heads[0])

Пример 2: Извлечение временного ряда

python
import numpy as np
import matplotlib.pyplot as plt

# Чтение файла голов
hdobj = bf.HeadFile('model.hds')

# Получение временного ряда для конкретной ячейки
cell_i, cell_j = 10, 20  # Индексы ячейки
time_series = []

for time in hdobj.get_times():
    heads = hdobj.get_data(totim=time)
    time_series.append(heads[0, cell_i, cell_j])  # Первый слой, конкретная ячейка

# Построение графика временного ряда
plt.plot(hdobj.get_times(), time_series)
plt.xlabel('Время')
plt.ylabel('Голова')
plt.title('Временной ряд голов в ячейке (10, 20)')
plt.show()

Пример 3: Преобразование данных оседания

Как показано в примере Stack Overflow, вы можете читать другие выходные двоичные файлы MODFLOW:

python
import flopy.utils.binaryfile as bf

# Чтение данных оседания
sobj = bf.HeadFile('model.zdisplacement.bin', text='Z DISPLACEMENT')
times = sobj.get_times()
zd = sobj.get_data(totim=times[-1])

# Сохранение смещения первого слоя
np.savetxt('layer0.zdisplacement.txt', zd[0])

Распространенные проблемы и решения

Проблема 1: Ошибки определения точности

Если FloPy не может автоматически определить точность:

python
# Указание точности вручную
hdobj = bf.HeadFile('model.hds', precision='single')

Проблема 2: Значения “HNOFLO” или отсутствующие данные

MODFLOW часто использует специальные значения, такие как -999, для представления неактивных ячеек:

python
import numpy as np

heads = hdobj.get_data(totim=1.0)
heads[heads == -999] = np.nan  # Замена отсутствующих значений на NaN

Проблема 3: Чтение нестандартных файлов

Для нестандартных двоичных файлов используйте прямой подход:

python
# Проверка структуры файла
with open('model.hds', 'rb') as f:
    header = f.read(100)  # Просмотр первых 100 байт

Проблема 4: Обработка больших файлов

Для очень больших моделей MODFLOW обрабатывайте данные порциями:

python
import flopy.utils.binaryfile as bf

hdobj = bf.HeadFile('large_model.hds')

for time in hdobj.get_times():
    # Обработка одного временного шага за раз
    heads = hdobj.get_data(totim=time)
    # Сохранение или обработка данных
    np.save(f'heads_time_{time}.npy', heads)

Заключение

Чтение и разбор двоичных файлов голов MODFLOW Fortran в Python можно эффективно осуществить с помощью нескольких подходов:

  1. Используйте FloPy как основной метод для большинства приложений - он предоставляет надежные, хорошо протестированные классы, специально разработанные для двоичных файлов MODFLOW
  2. Прямое чтение двоичных файлов предлагает гибкость для пользовательских реализаций, когда FloPy не подходит
  3. Понимайте структуру файла, включая заголовки, организацию данных и обработку точности
  4. Правильно обрабатывайте распространенные проблемы, такие как определение точности, специальные значения и управление большими файлами

Для большинства приложений моделирования грунтовых вод FloPy предоставляет наиболее надежное и комплексное решение для чтения двоичных файлов голов MODFLOW, в то время как методы прямого чтения двоичных файлов предлагают ценные альтернативы для специализированных случаев использования.

Источники

  1. flopy.utils.binaryfile module — flopy Documentation 3.3.2
  2. Python Read Fortran Binary File - Stack Overflow
  3. Extract heads from MODFLOW-USG binary output using flopy - Stack Overflow
  4. GitHub - syrte/fortio: A Python IO for Fortran Unformatted Binary File with Variable-Length Records
  5. Reading MODFLOW binary files with flopy – viewing with VisIt
  6. Extracting heads from Modflow binary files using flopy · modflowpy/flopy · Discussion
  7. flopy/.docs/Notebooks/mf_tutorial01.py at develop · modflowpy/flopy
  8. Extract subsidence data from MODFLOW-2000 binary output using FloPy - Stack Overflow
Авторы
Проверено модерацией
Модерация