动机
优化油气田工作效率最关键的环节之一是对历史生产数据的分析。稳健的生产数据分析方法,如递减曲线分析 (DCA),可帮助生产工程师评估油井产能相关度量,如递减率、平均油气生产率和累积产量。更重要的是,这些方法使得预测油气产量能够准确评估资产的当前财务绩效和长期可行性。
生产数据分析方法依赖基于油气井性能参数的数学模型,通过回归分析来拟合历史油气生产数据。例如,DCA 使用了表现出类似指数样递减的数学函数。Arps 方程可以说是油气行业中最流行、最广泛采用的 DCA 方法。与大多数 DCA 模型一样,Arps 与更复杂的方法(如速率瞬变分析)相比有几个重要的优势。首先,DCA 计算量小,易于实现。其次,DCA 的特点是参数数目少,因此回归结果更容易解释。再就是,DCA 可以处理大型数据集,如单井或多井的密集历史产量记录。然而,与任何其他模型一样,输入数据的质量对于获得用于数据分析、产量预测和石油经济学的物理有效 DCA 模型至关重要。
在本文中,我们将介绍如何使用 MATLAB® 开发和部署基于 DCA 的油气生产数据分析工作流。我们将讨论如何格式化和预处理历史生产数据集,创建自定义回归模型,生成产量预测,并执行石油经济学分析。我们的主要目标是展示 MATLAB 如何通过遵循简单而稳健的软件开发实践来帮助封装和处理工作流中涉及的复杂性。出于演示目的,我们将使用德克萨斯铁路委员会 (TRRC) 网站上公开的历史油气生产报告。
生产数据分析 Web App
我们将描述在 MATLAB 中执行油气生产数据分析的工作流中的主要步骤,以及软件开发和实现方面的一些最佳实践。这些实践有助于为油气生产设计和自定义更加可靠和可维护的软件应用程序。
在导入数据后,用户可以执行 DCA 回归分析。图 2 显示 App 中的 Regression 选项卡。该选项卡用于调整回归设置并选择是否使用特定流体相(石油或天然气)的平均生产速率或累积产量数据进行模型拟合。请注意,该 App 还支持用户选择回归窗口的起点和终点,从而使分析更加灵活,可以为感兴趣的特定时间范围(例如修井作业前后)创建 DCA 回归以评估生产行为。在定义所有参数后,用户可以点击拟合数据选项,让底层优化算法估计一组与数据集最优拟合的 DCA 参数。然后,App 会显示所用参数的汇总,以及每个流体相的决定系数 (R2)。我们会在递减曲线分析一节提供 DCA 流程的更多详细信息。
要基于 DCA 模型创建油气产出预测,用户只需提前定义预测的年数,该 App 将分别计算两种流体相的平均生产速率和总产量。如图 3 所示,该 App 支持用户使用滑块或数字文本字段以年为单位指定预测时间。当修改首选预测时间选项时,平均产量速率和累积生产图会自动更新。
基于产量预测数据执行石油经济学分析是此生产数据分析工作流的最后阶段。从油田规模分析到单井分析,资产管理者使用石油经济学在每个阶段作出明智的决策。为了在 App 中创建新预测,数据会立即传输到 Economics 选项卡,用户可以在此处修改税收、资本支出 (CAPEX)、运营支出 (OPEX) 以及油气价格等参数。接下来,App 通过内部计算净现值 (NPV)、盈亏平衡点、衰退点(如果适用)、内部收益率和投资回报来自动更新图上的净现值 (NPV) 曲线。图 4 显示 NPV 曲线示例,该曲线从负值变为正值(盈亏平衡点),达到最大值(最大 NPV),然后开始衰减,表明油井从该点开始运行成本将过高。该 App 还显示最高的预测 NPV 以及预计的实现日期。我们将在经济学分析一节讨论这些实现细节。
我们回顾一下 MATLAB 中的一些软件开发功能,开发执行油气生产数据分析工作流的 Web App 中我们用到了这些功能。
软件架构
您可能在上一节中注意到,App 的组件呈现出线性关系,其中一个组件的输入依赖于另一个组件的输出。例如,注意 DCA 选项卡如何依赖 Import 选项卡提供的数据,而 Import 选项卡同时又依赖用户提供的数据集。Economics 选项卡依赖 Forecast 选项卡提供的产量预测,正如 Forecast 选项卡依赖 DCA 选项卡提供的 DCA 模型一样。这是管道和过滤器软件架构模式的经典示例。鉴于这种众所周知的软件架构,我们使应用程序逻辑基于其设计模式概念。表 1 描述各组件或过滤器以及其职责、输入和输出。
组件 | 职责 | 输入 | 输出 |
数据导入 |
|
|
|
数据预处理 |
|
|
|
递减曲线分析 |
|
|
|
产量预测 |
|
|
|
经济学分析 |
|
|
|
除了这些组件,我们还建立了两个主要模块:Analysis 和 Results。这些组装元素共同涵盖流程给定部分的主要职责。图 5 描述了讨论中的软件架构。
管道和过滤器架构具有几个优势,例如能将复杂的工作流分解为独立的协作组件,从而使软件易于调试和维护。此外,您还可以通过添加新组件来扩展程序的功能,唯一要求是新组件应具有与您的管道或连接器兼容的应用程序编程接口 (API)。例如,扩展 Results 子系统的一种方法是包含 Report 组件。该组件使用 MATLAB Report Generator™ 来生成专门为生产工程师或资产管理者设计的报告。
样本生产数据
我们使用 TRRC 的 Public GIS Viewer 工具在德克萨斯州南部伊格尔福特页岩的黑色石油窗口区域内随机选取了 200 个油井,创建了一个井口样本。然后,我们使用 Mapping Toolbox™ 生成累积产油量的气泡图。
使用 TRRC 的 Public GIS Viewer 工具,我们生成了一个包含 200 口油井的样本。这些油井是在德克萨斯州南部伊格尔福特页岩的黑色石油窗口区域中随机选取的。接下来,我们使用 Mapping Toolbox 创建了累积产油量的气泡图,如图 6 所示。
图 7 显示这些卡恩斯县油井的平均日产油量,这些油井的石油产自下伊格尔福特地层。请注意每日石油生产的下降,这非常类似于幂律衰减 - Arps DCA 恰好可用于描述幂律衰减。
我们从上述油井样本中随机选择了一口油井,用于本文涉及的生产数据分析方法。为了保持其匿名性,在本文中我们将此油井称为“样本油井”。运营商、位置等油井元数据不会透露。
生产数据分析工作流
上一节为我们的 Web App 中采用的生产数据分析工作流奠定了基础。本节集中讨论软件架构一节中提到的组件的软件实现,强调如何使用 MATLAB 构造每个组件所需的功能。假设用户具备计算机编程的基础知识,我们在本文中包含指向其他资源的链接,这些资源具有关于这些步骤的更多详细信息。
数据导入
MATLAB 强大的数据导入功能支持 Excel® 电子表格、逗号分隔值 (CSV) 文件、图像文件、音频和视频文件等典型数据类型。虽然我们的重点是本地存储的数据,但必须指出,MATLAB 附带的内置接口支持云服务,如 Amazon® Web Services、Microsoft® Azure® 和 Google Cloud Platform™(请参阅在云中使用 MATLAB 和 Simulink),以及通过 Database Toolbox™ 支持的关系数据库和 NoSQL 数据库。
准备样本油井数据集
我们样本油井的油气生产记录保存在本地遵循 TRRC 模板格式的 CSV 文件中。虽然 CSV 文件中的表可以直接读取并导入 MATLAB 中,但此特定模板带来了一些困难。首先,数值数据(如净油气产量)和元数据(包括运营商名称、位置等)混杂在一起。其次,某些数据点缺失,并标注为 NO RPT
。最后,日期时间格式有点不寻常,因为它不指示记录特定报告的确切日期。图 8 显示样本油井数据集的截图。
尽管存在这些困难,MATLAB 仍能够通过导入工具处理此数据集。这是一个图形应用程序,支持您通过指示对应于每列的数据类型、定义感兴趣的数据范围以及选择是否包含缺失数据条目的行来进一步自定义导入参数。
在此处,我们首先选择 Number
作为适当的数据类型,并突出显示表中的油气生产数据。接下来,我们为第 1 列中的值定义一个自定义日期时间类型,方便 MATLAB 正确读取和处理报告日期。完成此操作后,我们将第 1、2 和 4 列分别重命名为 reportDates
、netOil
和 netGas
。
创建自定义导入函数
在完成准备和正确导入样本油井数据集的必要步骤后,我们使用 MATLAB 中的代码生成功能创建函数 wellDataParser
,该函数可自动实现前面描述的数据准备步骤。使用 wellDataParser
函数可从 MATLAB 命令行直接导入 CSV 文件中的 TRRC 数据集。此函数返回一个包含原始数据的表。这些数据可用于随后的分析,如软件架构一节中所述。
由于 wellDataParser
是作为白盒函数创建的,您可以对其进行修改以支持更多功能。例如,我们计算给定报告日期的最后一天,并重构 reportDates
中的所有报告日期,如图 9 所示。
专业提示:您可以将数据存储与 Parallel Computing Toolbox™ 结点使用,以同时导入数百甚至成千上万个 TRRC 数据集。
数据预处理
如上一节中所示,数据集偶尔会包含无效或缺失元素,例如 Inf
或 NaN
值。通过对数据集应用内置的 MATLAB 函数 rmmissing
可以轻松消除这些问题。但数据也可能包含难以用肉眼识别的异常。
清洗生产数据集
幸运的是,不一致的数据可以使用数据清洗器清洗掉。此 App 探索和可视化数据,并定义离群值检测规则。图 10 显示了数据清洗器的快照,其中包含对样本油井中 netOil
和 netGas
的可视化分析。在定义清除数据集合所需的操作后,我们使用数据清洗器创建自定义函数 wellDataCleaner
,其中包含了我们在该 App 中执行的预处理操作。
数据增强
此时数据集已干净。下一步是定义执行 DCA 回归分析的变量,即作业时间(也称为流动时间)、平均每日油气速率和累积油气产量。由于 wellDataCleaner
是白盒函数,我们添加了必要的代码来计算缺失特征 flowTime
、oilRate
、gasRate
、cumOil
和 cumGas
,并将它们插入到输出表中以符合软件架构计划的要求。图 11 显示样本油井经过预处理的表。
软件架构进度
生产数据分析管道的开发如图 12 所示,其中自定义 MATLAB 函数 wellDataParser
和 wellDataCleaner
表示用于数据导入和数据预处理的软件组件。此示意图中的蓝色箭头表示原始表,它是前一个函数的结果,并被后一个函数用作输入。在 MATLAB 中,这两部分之间的关系能够以如下方式实现:
>> well = wellDataParser("sampleWellData.csv"); >> well = wellDataCleaner(well);
上面的代码清楚地说明了连接数据导入组件和数据预处理组件的管道。请注意,wellDataCleaner
通过原位修改 well 对象而不是返回新 well 对象来有效利用内存。
专业提示:MATLAB 提供了许多使用数据清洗器的示例。有关详细信息,请参考 MATLAB 文档。
递减曲线分析
许多业内人士将 Arps 方程视为油气生产数据分析中 DCA 的标准模型。其最受欢迎的方程是基于速率的双曲递减方程,该方程将平均日产量随时间的衰减描述为一个包含三个回归参数 - 初始速率 \( q_{i} \)(体积/天)、递减速率 \( D \)(1/天)和 \( b \) 因子 - 以及关于参考时间 \( t_{i} \)(天)的函数。此方程定义如下:
\( q(t; t_{i}) = \frac{q_{i}}{[1 \ + \ bD(t \ - \ t_{i})]^{\frac{1}{b}}} \)
方程 1。
其中 \( q(t; t_{i}) \) 表示在 \( t > t_{i} \) 处的生产速率。随时间推移,从参考时间 \( t_{i} \) 到时间 \(t\) > \( t_{i} \) ,对方程 1 进行积分后,获得与累积生产相关的第二个方程。因此,基于生产的 Arps 方程定义如下:
\( Q(t; t_{i}) = Q_{i} + \frac{q_{i}^{b}}{D(b \ - \ 1)}(q^{1-b}(t; t_{i}) - q_{i}^{1-b}) \)
方程 2。
其中 \( Q(t;t_{i}) \) 表示在 \( t>t_{i} \) 处的累积产量。注意,方程 2 纳入起始累积产量 \( Q(t_{i}) ≡ Q_{i} \) 作为参数。此参数可从油井的生产记录中获得,或定义为额外的回归参数。表 2 总结了我们用于 DCA 分析的单位。
流体 | 生产速率 | 累积产量 |
石油 | 每天桶数 (bbl/day) |
桶数 (bbl) |
天然气 | 百万标准立方英尺/天 (MMscf/day) |
百万标准立方英尺 (MMscf) |
创建 DCA 回归模型
我们使用 Curve Fitting Toolbox™ 中的曲线拟合器,根据方程 1 和 2 为每个流体相独立创建了自定义 DCA 回归模型。此处,假设 well
表在您的工作区中,我们将向您介绍开发平均日产油量基于速率的 DCA 回归的四个阶段:
- 步骤 1:导入
well
并将 x 和 y 数据分别赋给well.flowTime
和well.oilRate
。请注意,油速率峰值在大约 120 天处开始下降,因此您不应包含任何此点之前的数据。 - 步骤 2:使用 Custom Equation 选项创建基于速率的 DCA 模型。MATLAB 将尝试以正确的方式执行回归,这很可能会失败,因为一个或多个回归参数过于接近于零或变为负值或非常大都会导致收敛问题。通过为每个参数定义有物理意义的边界来解决此问题。每个参数的良好初始估计值也将有助于算法更快地收敛。
- 步骤 3:检查运营的汇总统计量,并确保生成的回归参数合理且在指定的范围内。MATLAB 将显示其值和 95% 置信边界。得到的误差平方和 R2 和均方根误差 (RMSE) 可让您更好地了解回归的优度。MATLAB 将这种汇总统计量称为拟合优度 (
gof
)。 - 步骤 4:使用 Export 选项生成一个包含生成的回归模型以及
gof
统计量的函数。
要创建其余 DCA 回归,我们再次执行相同的步骤。因此,我们能够创建和修改函数 getDCAParamRate
和 getDCAParamProd
,以便根据方程 1 和 2 分别对油相和气相运行 DCA 回归。图 13 显示曲线拟合器的截图,指示从哪里开始特定步骤。
表 3 列出了样本油井中每个 DCA 回归和流体相的回归参数和 \( R^{2} \)。由于累积产量数据通常比平均日速率更平滑,因此基于生产的 DCA 产生最高的 \( R^{2} \) 分数也就不足为奇。
基于速率的 DCA | 基于生产的 DCA | |||
石油 | 天然气 | 石油 | 天然气 | |
\( Q_{i} \) | 192095 | 84475.5 | 192095 | 84475.5 |
\( q_{i} \) | 1530.6 | 984.06 | 1098.68 | 698.46 |
\( b \) | 1.1398 | 1.279 | 0.9388 | 0.7806 |
\( D \) | 0.0089 | 0.004 | 0.0045 | 0.0015 |
\( R^{2} \) 分数 | 0.945 | 0.784 | 0.999 | 0.997 |
我们设计了 getDCAParamRate
和 getDCAParamProd
,专门负责计算方程 1 和 2 的 DCA 参数。然而,它们无法预测累积生产能力或平均日产量。因此,有必要通过开发能够接受 DCA 回归参数作为输入并输出所需结果(如流量或体积)的 MATLAB 函数来运营 DCA 模型。
为此,我们在架构中添加了两个函数 flowRate(t,dcaParam)
和 cumulProd(t,dcaParam)
,其中 t
或者是正标量,或者是正标量的向量,而 dcaParam
是保存 \( q_{i} \)、\(Q_{i} \)、\( b \)、\(D \) 和 \( t_{i} \) 的 MATLAB 结构体。这两个函数是工具函数,这意味着它们不一定依赖特定数据集,而是依赖 DCA 回归参数。此后,flowRate
和 cumulProd
都可以打包为独立的实用工具包。
我们使用这两个函数来比较数据集的 DCA 回归,基于生产的回归和基于速率的回归。图 14a 和 14b 对基于生产和基于速率的 DCA 方法进行比较,以检查平均日油气产量。这两种回归模型在估计产率方面都表现良好,产生的结果高度相似。
图 15a 和 15b 分别比较预测的累积油气产量和报告的历史产量。与平均日产率一样,两种 DCA 模型在预测累积生产方面都很出色,同时展现出非常相似的结果。
软件架构进度
图 16 展示工作流的当前状态。进展到此处的一个关键点是添加一个实用工具软件组件,DCA 组件使用该组件来计算预期平均产率和累积生产数字。
我们可以选择将此实用工具包包含在该组件内。然而,考虑到可维护性和职责驱动的设计,我们选择将它们分离。这种方式可极大地提高可维护性,因为只要组件的函数签名不变,就可以独立地构建和维护组件。同样,我们还通过这种方式提高了灵活性,以便将来添加其他 DCA 模型时不会中断工作流。
此外,将工具函数分离通常会使代码更具可读性,因此如果其他人想研究工具函数,他们能够确切地知道每个部分执行的具体功能,从而减少编码时间。
这种模块化软件设计尽管看起来前期成本更高,但其可维护性和可开发性远远优于“上帝”函数,后者对数百甚至成千上万行代码一起进行测试和管理,具有极高的挑战性。
产量预测
对于此软件组件,我们利用了从 DCA 组件中派生的回归参数,以使用上一节中讨论的工具函数 flowRate
和 cumulProd
来估计将来的油气生产。由于生成产量预测所需的所有函数现在都已可用,我们接下来要编写调用它们的代码了。
为此,我们创建了函数 generateForecast
。该函数接受每种流体的 well
DCA 回归参数并请求预测时间作为输入参量,通过执行以下内部任务来生成完整的产量预测:
- 生成将来流动时间的向量
- 生成将来日期的向量
- 计算油气递减率
- 计算累积油气产量
因此,generateForecast
会返回与原始输入表格式相同的新表,只是生产度量是使用 DCA 模型生成的前瞻性值。
以下各小节描述 generateForecast
的工作原理。我们假设产量预测从上次报告日期后的一个日历月开始,并将每月报告一次,直到达到预期的展望时间。
生成产量预测
图 17 显示样本井从 2024 年 1 月 31 日开始将来 50 年的油气预测结果。与基于产率的 DCA 等效模型相比,基于生产的 DCA 模型预测,随着时间的推移,石油产量的下降幅度略大,如图 17a 所示。然而,图 17b 显示,平均日气产量预测的差异似乎更明显。
累积油气产量预测模型之间的差异变得更加显著,如图 18a 和 18b 所示。需要注意的是,累积产量预测的差异超出 50,000 桶石油和 3 亿标准立方英尺天然气,这可能会给勘探区的经济学评估带来不确定性。
鉴于不同模型可能会产生不同生产估计值,试验不同 DCA 模型并选择最接近所研究油田生产行为的模型是至关重要的。可帮助您做出此决定的一种方法是利用现有油井的生产数据以便于模型的比较。为此,您可以考虑向 DCA 组件添加更多 DCA 模型,但这样做会增大函数的复杂度。为了避免这种情况,您可以改为求助于面向对象的设计,其中每个对象对应于一个 DCA 模型。这样,您可以提高系统的可维护性和可靠性,因为这些对象可以单独管理,就像管道和过滤器软件架构本身一样。
软件架构进度
图 19 展示到目前为止软件架构的进度。如上所述,产量预测组件利用上一节中创建的 DCA 实用工具包来生成油气产量预测。
经济学分析
我们工作流的最后一步是将产量预测转换为财务度量。资产管理者依靠这种分析(通常称为石油经济学)决定是保留还是废弃油井。投资者使用这种分析来计算收购现有油井的可行性。然而,任何石油经济学分析的可信度均强烈依赖于产量预测和相关联的财务度量的准确度。
示例评估案例
假设某投资者有兴趣收购我们的样本油井。资产所有者同意以 180 万美元的价格出售。您的目标是确定这项投资在财务上是否合理。为了帮助您作出更好的决策,所有者向您提供了一些附加信息:
- 油井运营成本 (OPEX):2000 美元/月
- 石油生产税:36%
- 天然气生产税:16%
此外,您的财务部门建议在分析中考虑 10% 的贴现率,油气的平均价格分别为 80 美元/桶和 2.78 美元/千立方英尺。您还要引入油气价格的变化,以更好地了解您的投资在面临严峻的市场波动时的韧性。
我们创建了 MATLAB 函数 econAnalysis
来执行整个经济学分析,并在其中包含了价格变化功能。此函数接受一个预测表和一个 MATLAB 结构体,其中包含必需的财务参数(如折扣率、CAPEX、OPEX、税率等)并计算净现金流和累积现金流、盈亏平衡点和衰退点以及内部收益率 (IRR)。我们依靠 Financial Toolbox™ 中的 xirr
来计算 IRR。
石油经济学结果
图 21 显示为此项目生成的 NPV,从中可以得出几个结论。首先,如果您决定继续收购,可以在 2026 年 2 月 11 日前后达到收支平衡。IRR 是项目健康的另一个重要指标。另一个有趣的观测是,如果您坚持运营此项目大约 30 年,也就是说到 2053 年 12 月,您会赚到将近 500 万美元。请注意,此分析不考虑任何与维护、运营成本增加等相关的将来费用,因此乐观的回报可能会形成误导。然而,NPV 曲线显示,到 2031 年 12 月 31 日,也就是说在您的项目开始 8 年后,可以赚大约 300 万美元,即表示您的投资回报率为 166.7%。
软件架构进度
经济学分析组件的完成标志着生产数据分析工作流的完成。如图 22 所示,在此阶段,架构保持不变,因为石油经济学分析函数不需要开发或集成任何外部实用工具组件。尽管如此,它仍支持灵活地添加补充模块和实用工具包。
小结
在本文中,我们开发了一个管道和过滤器软件架构,用来自动化油气生产数据分析。我们剖析并彻底详述了工作流的每个步骤,展示了 MATLAB 如何让我们执行复杂的任务。这些任务原本可能需要用单独的编程语言进行数小时的编码。
我们还演示了如何自动创建 MATLAB 函数以便能够通过一次函数调用完成复杂的任务。我们还讨论了模块化软件设计在可维护性和可靠性方面的好处,同时也注意到将来可能需要额外的数据格式、清洗方法、DCA 模型和其他用于创建绘图和图窗的实用工具包。
最后,值得注意的是,我们特意避免了讨论高级软件设计实践,例如面向对象的设计,因为本文的目的是帮助读者入门。尽管如此,由于 MATLAB 是一种面向对象的编程语言,您完全可以自由地使用本文中的知识来创建为特定用例(例如云部署和 C/C++ 代码生成)定制的软件架构。
选择网站
选择网站以获取翻译的可用内容,以及查看当地活动和优惠。根据您的位置,我们建议您选择:。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)