首页 / 专利库 / 人工智能 / 对话系统 / 面向对象的烃储集层系统模拟

面向对象的储集层系统模拟

阅读:563发布:2024-01-11

专利汇可以提供面向对象的储集层系统模拟专利检索,专利查询,专利分析的服务。并且本 发明 公开一种用于模拟复杂系统中输运现象的 计算机系统 。该系统包括内存装置,存储装置,和面向对象 软件 。该 软件包 括面向对象的可扩展类层次结构,该类层次结构包括表示多种对象类型的通用类的第一集合和表示对象类型的成员变量的通用类的第二集合。可扩展的类层次结构允许增加另外的对象类型或另外的成员变量,而不 修改 类层次结构本身。在另一种实施方案中,计算机系统也包含使计算机系统的用户能够动态地构造逻辑来自定义物理系统的模拟的逻辑界面,用于将构造的逻辑转换成相应的面向对象代码的装置,用于将面向对象代码与主模拟系统集成在一起的装置,以及用于执行集成模拟系统的装置。,下面是面向对象的储集层系统模拟专利的具体信息内容。

1.一种计算机系统,包括内存装置,存储装置和面向对象的软 件产品,该软件产品包含用于存储输运现象模拟数据的面向对象的可 扩展类层次结构,该类层次结构包括表示多种对象类型的通用类的第 一集合和表示对象类型的成员变量的通用类的第二集合,该可扩展的 类层次结构允许增加另外的对象类型和另外的成员变量,而不修改类 层次结构本身。
2.权利要求1的计算机系统,其中输运现象包括下列一种或多 种:地下含储集层中以及地下含烃储集层和地面上的一个或多个输 送位置之间的动量、能量、和质量输运。
3.权利要求2的计算机系统,其中地下含烃储集层和一个或多 个输送位置之间的输运包括一种或多种输运路径,输运路径包括至少 一种生产和注入井类型和一种或多种设施类型,它们被链接在一起来 形成一种设施网络,通过该设施网络烃流体在地下储集层和输送位置 之间输运。
4.权利要求3的计算机系统,其中包含于输运路径中的设施类 型包括选自地面流线歧管,分离器,压缩机中的至少一种 设施。
5.权利要求4的计算机系统,其中文本文件(数据定义文件) 包含可以包含于模拟模型中的可能设施类型的定义和每种设施类型的 可能成员变量类型的定义。
6.权利要求1的计算机系统,其中面向对象的软件产品包括图 形用户界面,由此计算机系统的用户定义包含井和设施对象的专网 络的模拟模型来模拟进出专门含烃储集层的输运现象。
7.权利要求1的计算机系统,其中另外的数据成员类型由权利 要求1的面向对象软件产品计算机系统的用户来定义,其中计算机系 统的用户通过图形用户界面来定义另外的设施数据成员,所述另外的 数据成员以用户自定义的方式扩展计算机系统的功能性。
8.权利要求1的面向对象的软件产品,其中面向对象软件用 C++来编写。
9.权利要求1的计算机系统,其中存储装置包括面向对象的数 据库。
10.一种通过使用具有内存装置,存储装置和面向对象软件的计 算机来模拟设施网络中的输运现象的方法,该方法包括步骤:
(a)构建包括设施网络的模型;
(b)为每种设施指定成员变量的值;
(c)在设施网络中的输运现象的数学模拟中使用成员变量的指定 值作为时间的函数。
11.权利要求10的方法,其中设施网络是更大的模拟模型的一 部分,所述设施网络能够与该模拟模型的至少一个其他部分交换流 体。
12.权利要求11的方法,其中模拟模型包括设施网络和含烃地 层。
13.一种模拟物理系统中输运现象的方法,其中物理系统包括被 多个井穿过的含烃储集层以及连接到井的地面设施,该方法包括:
a.将物理系统离散化为许多体积单元,其中每个体积单元被模 拟为一个节点,并且相邻的节点能够通过节点之间的连接来交换流 体;
b.使用权利要求1的类层次结构的设施对象和成员变量对象来 模拟离散化模型的表示井和表面设施的部分中的节点和连接;
c.指定每个节点和连接的几何和输运性质;
d.指定每个节点和连接的初始条件;
e.以时间的函数来模拟离散化系统中的输运现象。
14.一种具有多个类的面向对象软件系统结构,其将成员变量和 成员变量逻辑上从属的类分开,所述软件系统结构包括:
a.设施类的层次结构,其中设施类的层次结构中最专门化的派 生类(Node,Connection,Compound,Well)被设计来一般地表示 可以被模拟的设施的类型;
b.成员变量类的层次结构,其中成员变量类的层次结构中最专 门化的派生类(SystemAttributeValue,UserAttributeValue, RateConstraint,PressureConstraint)被设计来一般地表示设施可以 具有的成员变量的类型,所述成员变量是下列类型的一种:浮点标量 或数组,整型标量或数组,字符串,布尔,枚举类型,流动速率限 制,和压限制;
c.ValueUse类(206,图2),其具有与数据成员类的层次结 构中的基类(Value,207,图2)的多对一的关联以及与设施类的层 次结构中的基类(FacBase,200,图2)的多对一的关联,使得每个 Value对象具有到ValueUse对象一个或多个引用,ValueUse对象将 Value对象的使用关联到逻辑上拥有它并控制到它的访问的FacBase 对象。
15.权利要求14的面向对象软件系统结构,其中类的完整层次 结构包括除前述设施类和成员变量类之外的类,所述另外的类提供可 变通性来在多种模拟实现中重用设施对象,每种不同的实现能够重用 使用设施对象的一种或多种其他实现中的成员变量对象的全部、一些 或没有,所述另外的类包括:
a.WmSystem控制器类(217,图2),其具有与设施类的层 次结构中的基类(FacBase,200,图2)的直接一对多的关联,使得 模拟实现的集合中的WmSystem类的对象具有到用于那些模拟实现 中的所有设施对象的超集的直接引用;
b.Case类(215,图2),其具有与WmSystem类的多对一的 关联,使得WmSystem类的对象可以被Case类的许多对象使用, Case对象包括用于模拟实现的数据的完整集;
c.ValueUse类(206,图2),其具有与数据层次结构中的基 类(Value,207,图2)的多对一的关联以及与Case类的多对一的 关联,使得在给定模拟Case中,Value类的每个对象直接引用 ValueUse类的一个或多个对象,ValueUse类的每个被引用的对象将 Value对象的使用关联到使用它的Cases或模拟实现,包括该给定的 Case。
16.一种用于模拟物理系统的计算机系统,包括内存装置,存储 装置和在主模拟系统中的面向对象软件,所述计算机系统还包括:
a)使计算机系统的用户能够动态地构造逻辑来自定义物理系统 的模拟的逻辑界面;
b)用于将构造的逻辑转换成相应的面向对象代码的装置;
c)用于将面向对象代码与包括模拟数据模型和模拟算法的主模 拟系统集成在一起的,导致集成模拟系统的装置;
d)用于执行集成模拟系统的装置。
17.权利要求16的计算机系统,其中构造的逻辑包括设施管理 逻辑,设施管理逻辑表示用于监测和控制与物理系统相关联的机械设 施的步骤。
18.权利要求16的计算机系统,其中逻辑界面包括逻辑流程图 界面。
19.权利要求18的计算机系统,其中逻辑流程图界面包括图 标,箭头,菜单,对话框,工具条按钮以及文本中的一个或多个,来 使计算机系统的用户能够构建、编辑和显示流程图的形式的设施管理 逻辑。
20.权利要求18的计算机系统,其中逻辑流程图界面包括表示 用于循环,判断,语句执行,以及逻辑进入和退出的基本逻辑控制结 构的图标。
21.权利要求20的计算机系统,其中表示逻辑控制机制的图标 使计算机系统的用户能够构造自定义的逻辑流程图。
22.权利要求16的计算机系统,其中逻辑界面包括基于文本的 逻辑代码界面。
23.权利要求22的计算机系统,其中基于文本的逻辑代码界面 包括用于执行输入,修改和删除字母数字文本行的一种或多种操作的 图形文本编辑器
24.权利要求22的计算机系统,其中基于文本的逻辑代码,其 是设施管理控制语言,能够从逻辑流程图自动地创建。
25.权利要求24的计算机系统,其中设施管理控制语言能够自 动地转换成C++形式的面向对象的设施管理代码。
26.权利要求24的方法,其中设施管理控制语言是具有适合于 具体化设施管理逻辑的特征和范围的面向对象语言。
27.权利要求16的计算机系统,其中面向对象代码是C++形式 的设施管理面向对象代码。
28.权利要求16的计算机系统,其中逻辑界面使计算机系统的 用户能够使用逻辑流程图界面或者基于文本的逻辑代码界面来开发逻 辑。
29.权利要求16的计算机系统,其中面向对象代码具有通过创 建从模拟数据模型继承的新的类来扩展模拟数据模型,从而使面向对 象代码能够调用模拟数据模型的函数和使用模拟数据模型的成员数据 的能力。
30.权利要求16的计算机系统还包括用于将面向对象代码编译 成面向对象设施管理目标代码的装置,以及用于链接设施管理目标代 码来产生共享程序库,从而能够将共享程序库装载到主模拟系统中的 装置。
31.权利要求16的计算机系统还包括用于将面向对象代码编译 成面向对象设施管理目标代码的装置,以及用于链接设施管理目标代 码来产生动态连接库,从而能够将动态连接库装载到主模拟系统中的 装置。
32.权利要求16的计算机系统能够通过在模拟期间的多个时间 步调用面向对象设施管理代码来执行集成模拟系统。
33.权利要求32的计算机系统,其中面向对象设施管理代码能 够在设施管理代码已经完成当前时间步的执行之后,将控制返回给主 模拟系统。
34.权利要求16的计算机系统包括多个连接的处理器来执行模 拟。
35.一种在计算机系统中模拟物理系统的方法,其中计算机系统 包括内存装置,存储装置,以及主模拟系统中的面向对象软件,该方 法包括步骤:
a)动态地构造逻辑来自定义物理系统的模拟;
b)通过启动下面的步骤,来开始物理系统的模拟:
i)自动地将逻辑转换成相应的面向对象代码;
ii)将面向对象代码与包括模拟数据模型和模拟算法的主模拟系 统集成在一起,导致用于模拟物理系统的集成模拟系统;
iii)执行集成模拟系统来模拟物理系统。
36.权利要求35的方法,其中物理系统包括含烃地层
37.权利要求36的方法,其中物理系统包括与烃从含烃地层的 生产相关的包含流体的设施。
38.权利要求35的方法,其中逻辑的构造包括使用图形用户界 面来执行选自下面的至少一步:
a)选择并使用现有逻辑;
b)选择并修改现有逻辑;
c)开发新的逻辑。
39.权利要求38的方法,其中逻辑的构造产生逻辑流程图。
40.权利要求35的方法,其中逻辑的构造产生基于文本的逻辑 代码。
41.权利要求39的方法,其中逻辑流程图的构造包括使用图 标,箭头,菜单,对话框,工具条按钮和文本的一种或多种,来使计 算机系统的用户能够构建、编辑和显示流程图形式的设施管理逻辑。
42.权利要求39的方法,其中逻辑流程图的构造包括使用基于 文本的逻辑代码界面,该界面包括用于执行输入,修改和删除字母数 字文本行的图形文本编辑器。
43.权利要求35的方法,其中逻辑的转换是转换成C++代码。
44.权利要求35的方法,其中转换的面向对象代码具有通过创 建从模拟数据模型继承的新的类来扩展模拟数据模型,从而使面向对 象代码能够调用模拟数据模型的函数和使用模拟数据模型的成员数据 的能力。
45.权利要求35的方法,其中被启动的模拟系统的执行产生预 测物理系统整体行为的结果。
46.权利要求35的方法,其中被启动的模拟系统的执行使用多 个相连的处理器来实施。

说明书全文

发明领域

本发明涉及数值模拟,尤其涉及模拟系统的一种改进方法, 烃系统包括下面的一个或多个:地下含烃地层,穿过该地层的注入 井,穿透该地层的生产井,地面流送管,相关含层,以及地面流体 处理设施。

发明背景

数值模拟作为一种使用计算机来模拟物理系统的方法被广泛用 于工业领域中。在大多数情况下,希望模拟在物理系统中发生的输运 过程。被输运的典型地是质量能量,动量,或其某种组合。通过使 用数值模拟,能够模拟并观察物理现象,以及确定设计参数,而不需 要实际的实验室试验和实地试验。
储集层模拟法是很有意义的,因为它从储集层模型的性能推断 真实含烃储集层的性状。储集层模拟的典型目的在于充分地了解在储 集层中发生的复杂的化学,物理和流体流动过程来预测储集层将来的 性状使烃的开采达到最大。储集层模拟经常指的是储集层中流的流体 学,但是在更大的意义上,储集层模拟也可以指整个烃系统,其可 以不仅包括储集层,而且包括注入井,生产井,地面流送管,相关含 水层,以及地面处理设施。这种烃系统中的储集层模拟计算基于通过 被模拟的整个烃系统的流体流动。这些计算以不同的精确度来执行, 依赖于具体模拟研究的需求和所使用的模拟软件的能力。
数值模拟的原理是使用计算机来数值地求解描述物理现象的方 程。这种方程通常是常微分方程和偏微分方程。作为用于数值地求解 这种方程的方法,已知的有有限元法,有限差分法,有限容积法等。 不管使用哪种方法,被模拟的物理系统被分成单元(称为格或网格的 集),并且在整个模型的空间中变化的状态变量由每个单元的值的集 来表示。储集岩的性质例如孔隙率和渗透率在单元内典型地被假设为 常数。其他变量例如流体压力和相饱和度在单元内规定点,有时称作 节点指定。两个节点之间的链接称作“连接”。
因为储集层模拟可以包括非常不同的流体流动环境(例如,多 孔岩石,油管,处理设施),单元集可以包括不同流动环境的多个 段。虽然各个段,例如生产设施和地面管段,可以由单个单元来表 示,但是有时储集层模拟程序将这些段细分成多个单元。
一组方程被开发来表示每个单元内质量,能量和/或动量守恒的 基本原理以及单元之间质量,能量和/或动量运动的基本原理。这些 方程可以百万来计算。用每个单元的有限数目的变量值来代替在整个 模型的空间中变化的状态变量称作“离散化”。为了分析随时间变 化的现象,需要在称作时间步的离散时间间隔计算物理量,而不管为 时间函数的连续变化条件。因此,输运过程的时间依赖模拟以时间步 序列进行。在希望的一段时间中的流的模拟通过增量地向前移过时 间,并且在每个时间步对每个节点的压力和流体含量求解方程来进 行。
已经作出努力来以单一计算机代码执行广泛变化的储集层模拟 方法。但是,这种“通用”模拟系统非常复杂,主要因为它们被设 计来具有下面能力的一个或多个:
(1)表示许多不同类型的单元(例如,储集层的不同畴,油管, 地面油气集输和分配设施,以及地面处理设施);
(2)使用不同的时间步计算方法(例如,IMPES,全隐式,顺 序隐式,自适应隐式,和/或逐级测量法);
(3)使用不同的表示储集层流体的方法;
(4)使用多种计算单元之间输运的方法;
(5)执行把烃看作由两种成分组成的所谓的“黑油模型”,并 且也具有执行组成表示的能力,其中烃被假设包含化合物例如甲烷, 乙烷,丙烷以及更重的烃;
(6)模拟蒸汽喷射或就地燃烧过程,其必须考虑为时间函数的温 度变化,这需要能量平衡和相关计算;
(7)使用专的流体性质和输运计算来模拟可混合开采过程;
(8)模拟烃开采过程,其考虑表面活性剂聚合物或其他化合物 的注入,以及这些流体流入储集层的流动;
(9)模拟相互之间,与储集层烃或储集岩起化学反应的化合物的 注入;
(10)模拟烃和地质沉积物在地质时期的迁移。
在历史上,因为通用模拟系统是复杂的,储集层模拟程序典型 地仅模拟地下储集层中的流体运动,或者它们模拟地下流体运动并包 括简化计算,例如水力学模型,来模拟储集层和地面之间的井管中的 流动。为了更逼真地模拟通过井的以及在附接的地面生产设施(例如 歧管压缩机,分离机和管道)中的流,典型地需要不同于储集 层模拟模型的分立的设施模拟模型。因为这些储集层和设施模拟模型 试图描述很长一段时期,典型地许多年的流动特性,并且模拟被离散 化成覆盖希望的模拟时期的时间步,试图基于这两个不同的模型设计 集成的模拟过程是麻烦而且昂贵的。这种过程通常涉及在两个模型之 间交替时间步,使得在一个模型中发生的变化可以并入第二模型的随 后时间步的输入中。
在过去的储集层模拟中的一个挑战性问题是缺乏通过储集层模 拟系统中的井管和地面设施的输运现象的精确模拟。传统的储集层模 拟器典型地具有两个重大的限制。首先,许多储集层管理研究需要比 可能在储集层模拟器中的更高级的地面设施流动模型。为了解决该问 题,模拟器用户典型地为储集层特性开发并维持一个模拟模型而为设 施特性开发并维持另一个模拟模型,没有方便的方法来综合来自两个 模型的结果,或者来容易地计算一个模型中的变化对另一个的特性的 影响。其次,储集层管理典型地涉及井或设施比率的动态变化。因为 设施率用作储集层模拟计算的边界条件,那些边界条件的动态变化经 常导致难于管理的模拟计算中的数值不稳定性
储集层模拟中的另一个挑战性问题是模拟器用户指定模拟中的 设施管理逻辑的能力。为了优化烃从油田的生产需要一个连续的过程 来在持续30或更多年的油田生命期内监测并控制生产和注入设施。 为了使用储集层模拟器来更准确地预测储集层的特性要求地面设施控 制的影响在模拟过程中被考虑。专门的控制,以及它们的顺序和同步 难以编程到模拟器中,如果不是特别不可能的话,因为排列将是无限 的并且依赖于每个油田和每个模拟器用户管理油田的方法。因此,储 集层模拟器用户需要一个工具来能够给模拟器指定用户相信会优化储 集层生产的自定义检验和控制。然后,那些检验和控制需要变成模拟 器计算的组成部分。简而言之,需要一个直观的工具来捕捉每个模拟 器用户的自定义设施管理逻辑,将其转换成与储集层模拟器代码集成 的可执行代码,然后执行作为结果产生的系统来预测储集层在其生命 期内的全部特性。
该问题的典型解决方法是向用户提供结构能力的软件的开发。 模拟器用户被提供有基于文本的编辑器或者他或她能够从中获得结构 集和固定的关键字集的界面。使用这些结构,模拟器用户可以定义可 能的条件,这些条件如果在模拟中被满足,那么触发修改井的特性的 某种响应。该方法对于用户不是很直观。汇编结构和关键字的过程会 是令人厌烦的,并且结果不容易读或解释,尤其是对于原来不涉及储 集层工程的人。没有清晰的逻辑视图,意味着不容易跟踪逻辑背后推 理的高级线。用户在过程中具有有限的控制,并且可用于执行的补救 也被模拟器识别的有限的一组组合所限制,导致系统适应非传统储集 层管理策略的有限的适应性。
在工业中需要一种储集层模拟系统(1)提供通过井管和地面设 施的流的更逼真的模拟(2)捕捉由储集层模拟器用户自定义的设施 管理逻辑并将它作为储集层模拟的一部分来执行。
本发明概述
本发明涉及一种用于模拟复杂系统中的输运现象的计算机系统 和方法。该计算机系统包括内存装置,存储装置,以及一种面向对象 的软件产品。该软件产品包括面向对象的可扩展的类层次结构,其具 有表示多种对象类型的通用类和表示对象类型的成员变量的分立的通 用类。该可扩展类层次结构允许添加额外的对象类型或额外的成员变 量,而不修改类层次结构本身。
本发明对模拟储集层系统特别有用。在将本发明应用于储集层 系统模型中,设施网络模型(“FNM”)被开发,其扩展离散化的 储集层模拟模型(包括节点和流连接)超出储集层来包括用于模拟井 管以及地面生产和注入设施(例如歧管,泵,压缩机,集输管线,分 离器和管道)中的流体流动的节点和连接。每个不同的设施类型被模 拟成专门类型的节点,连接或几个节点和连接的组合。在其最基本的 形式中,整个模拟模型可以包括油田的每个部分,从地下储集层,所 有井和井硬件,以及地面设施一直到包括产品输出口。
储集层模拟系统优选地随储集层模拟器使用设施管理逻辑 (“FML”)。FML提供容易被模拟方法的用户使用的逻辑视图。 FML的使用是灵活的并且可以与储集层模拟器集成。FML包括三个 部分:(1)逻辑图界面,(2)从逻辑图的C++代码(工业标准编程 语言)生成器(3)将代码与储集层模拟器本身集成的专门的软件设 计。
附图简述
新的储集层模拟系统及其优点通过参考下面的详细描述和附图 将变得更加明白。
图1说明离散化的储集层模拟模型以及它的油井和地面设施的 附接网络。
图2和3说明显示设施网络模型的通用C++类层次结构。图3 是图2中所示的类层次结构的一部分。
图4用其表示的设施的名字来标记的图标和箭头的图形表示来 说明一个简单的设施网络。
图5说明显示简化的设施管理逻辑的逻辑图。
图6说明实例模拟器类层次结构一小部分的示意图。
图7扩展图6中的图,说明动态专门化如何被用来支持用户编 写操作。
附图并不打算着将作为这些具体实施方案的正常和期望修改的 结果的其他实施方案排斥在新的储集层模拟系统的范围之外。
本发明详述
本发明的具有内存装置,存储装置,和面向对象的软件产品的 计算机系统可以用于模拟复杂的系统,例如被离散化为结构网格,非 结构网格,或两者组合的烃系统的二维和三维畴。该计算机系统也可 以用于计算方法得到具有多于三维的拓扑,例如在模拟通过断裂多孔 介质的流体流动时发生的情况中。模拟系统对模拟其中发生输运现象 的复杂系统的特性是有用的。术语“输运现象”在广泛意义上用于 本描述中,包括动量输运(粘滞流动),能量输运(热传导,对流辐射)以及质量输运(扩散)。例如,模拟系统对模拟烃从储集岩中 使用各种辅助开采技术的提取特别有用,这些技术例如,但不局限 于,基于热方法的开采方法例如注蒸汽操作,注水操作,以及可以在 可混合或不可混合条件下操作的基于气体驱动的方法。模拟系统也可 以用于模拟通过地层的杂质运送。在本描述中,模拟系统将关于在非 结构网格系统上执行通用的储集层模拟来描述,并且对于模拟不仅包 括储集层,而且包括相关含水层,生产井,注入井,地面流送管,歧 管,分离器,,泵,压缩机,或者任何其他地面处理或输运设施的 含烃系统中的并行计算特别有用。
出于详细描述本发明的目的,几个术语被定义来阐明它们的意 思。“储集层模拟模型”是真实烃储集层的专门数学表示。管理烃 储集层的工程师可以创建可能具有不同复杂度的许多不同的储集层模 拟模型,以便量化储集层过去的性能并预测它未来的性能。在本发明 中,储集层模拟模型是储集层的物理空间以及在烃流体开采中使用的 井和地面设施的离散化表示。在本描述中使用的“设施”是烃流体 通过其从储集层中生产或者注入储集层的有形物理装备。在其最广泛 的意义上,术语设施适用于沿着储集层和作为烃流体离开模型(生产 流体)或者进入模型(注入流体)的位置的其输出口之间的流动路径 出现的任何装备。设施可以包括生产井,注入井,井管,井源装备, 集输管线,歧管,泵,压缩机,分离器,地面流线和输出口。在某些 情况下,术语“地面设施”用来区分那些设施和油井。“设施网 络”是在模型中出现的设施的全集,其包括所有的井以及井源和输出 口之间的地面设施。
包括三维含烃储集层及其相关设施的储集层模拟模型在图1中 说明。在图1中示意地说明的储集层模拟模型包括被用虚线表示的井 106a,108a和110a穿过的离散化的储集层100,并且包含另外的设 施节点102,103和104以及设施连接112,114,116,118和120。 在图1中,储集层100被表示为包括用窄实线画出的许多体积单元 101。虽然在图1中没有明确地显示,每个单元101表示在其中心包 含一个节点的三维的空间容积。虽然没有明确地显示,每对相邻的储 集层节点具有相应节点之间的连接。在储集层模拟模型中,烃流体基 于节点之间的压力差和连接的传输性质流过一对节点之间的连接。这 样,烃流体可以从一个体积单元输运到一个相邻的体积单元。每个井 106a,108a和110a分别包括各自的一个节点106b,108b和110b。 虽然同样在图1中没有明确地显示,每个井节点经由连接附接到相应 井轨道所经过的每个储集层节点。设施节点103和104以及设施连接 112,114,116,118和120表示将从储集层100生产到井106a, 108a和110a中的流体运送到公共传送点102的流线的集输网络。
面向对象编程
本发明的实现使用面向对象编程(“OOP”)技术。最通用 OOP的编程语言是Simula,Eiffel,C++,Smalltalk,Objective-C, 或其变种。但是,本发明的实践并不局限于具体的OOP语言。C++ 在本详述中用来帮助读者更好地理解和认识OOP的好处。OOP的设 计对OOP系统领域的技术人员是众所周知的,并且仅一般地描述。
在面向对象的程序中,焦点主要集中在数据上,其次集中在访 问该数据的函数上,而不是主要集中在函数上,而其次集中在它们需 要的数据上。与数据输入到每个过程或从每个过程输出的主要通过过 程来描述的程序(例如用FORTRAN或COBOL编写的程序)不 同,面向对象的程序围绕“对象”来组织。对象是一种数据结构以 及可以访问该数据结构的一组操作或函数。OOP系统典型地将包含 大量的对象。可以访问数据结构的每个操作(函数)称作“方 法”。出于本发明的目的,对象包含的数据称作“成员变量”,而 对象具有的方法称作“成员函数”。对象可以被认为是巧妙的数据 集,因为对象的成员函数给予对象改变自身,也就是,改变其成员变 量的值的能力。
“类”是专门类型对象的模板。类定义与对象相关联的信息 (它的数据)以及它可以执行的操作(它的方法)。当对象被创建 时,类被用作模板来定义该对象具有的什么数据和方法。对象被称作 定义它的类的“实例”。可以有许多不同的对象,都是同一个类的 实例,但是每个实例具有其自己的数据和方法。
典型的面向对象的软件设计在其核心包含可以集体地称作“数 据模型”的一组类。数据模型中给定的类定义一个专门类型的“对 象”,其可以包含数据(“成员变量”)和方法(“成员函 数”)。数据模型是面向对象软件的“体系结构”的主要部分。面 向对象软件产品的“体系结构”包括软件的全部设计,包括它围绕 之建立的数据模型。
OOP使得对象能够用由数据表示的其特征和由可以使用数据来 执行的方法表示的其行为来模拟实际上任何真实世界的实体。这样, 对象可以模拟具体事物象储集层模拟中的单元以及抽象概念象数字。 出于本发明的目的,OOP的好处起于三个基本的原理:封装,继承 和多态。
对象隐藏或封装其数据的内部结构,即对象包含的成员变量的 显式集,以及其成员函数用来工作的算法。代替暴露这些实现细节, 对象给出明确表示其抽象的没有任何无关信息的接口。接口仅允许外 部世界和对象之间有限数目的交互。在C++编程中,大部分这些交互 涉及调用对象的成员函数。通过调用对象的成员函数,外部世界可以 告诉对象去做一些事情,但是对象如何执行该动作的细节对外部世界 是不可见的。实际上,对象封装其数据和方法,并且对外部世界隐藏 它们。
例如,计算节点性质的软件系统的面向对象数据模型可能具有 称作“BaseNode”的类。BaseNode类可以具有成员变量例如包含数 值来定义BaseNode对象在空间中的位置的“x_位置”,“y_位 置”和“z_位置”,以及包括成员函数来改变BaseNode对象的x, y或z坐标值的值。建立于该实例数据模型上的软件系统可能包含代 码来创建和修改任何数目的不同的BaseNode对象。每个BaseNode 对象都包含其自己独一无二的其成员变量的值,并且每个都具有内部 的成员函数来修改那些成员变量。从软件系统的度,BaseNode对 象如何维护其位置信息是无关紧要的。软件系统仅需要BaseNode成 员函数来设置和取得该数据。这种将数据(成员变量)和代码(成员 函数)组织成类称作封装。
继承允许软件开发者以“类层次结构”的形式来设计数据模 型,使得相关的类模仿对象类型的自然分类。继承的三个主要好处在 于,它允许软件开发者来设计有效地封装数据的代码,它允许在专门 类上实现方法使得这些方法可以用于许多专门化类型的对象,以及它 促进先存在设计和代码的重用。在类层次结构中,通用的数据和方法 属于“基”类或“超类”。更专门化的类(“子类”)“继承” 基类的数据和方法,并且定义它们自己的另外的数据和方法。这些专 门化的类从基类派生。继承允许软件开发者定义类以及随后从它们创 建的并且通过类层次结构相关联的对象。特别地,类可以指定为其他 基类的子类。子类继承并且具有到其基类的所有函数的通路据就好像 这些函数出现在子类中。继承允许以前编写的程序通过创建对象新的 超类和子类来扩展。新的对象通过它们如何不同于先存在的对象使得 不需要编写完全新的程序来处理新的数据类型或函数来描述。
作为说明继承的类层次结构的一个实例,扩展先前的BaseNode 类的实例,称作“WellNode”的第二个类从BaseNode类继承。 WellNode的对象既是WellNode又是BaseNode,但是WellNode类 可以定义专门对WellNode的数据和代码。如果定义第三个类 “NetworkNode”,其也从BaseNode继承,但是不从WellNode继 承,那么NetworkNode的对象将不包含WellNode专用的数据或代 码。但是,WellNode的对象和NetworkNode的对象都将包含 BaseNode专用的数据和代码。该简单的实例仅显示具有一级附加专 门化(WellNode和NetworkNode类)的BaseNode类。但是,继承 允许任意数目的专门化层次,使得WellNode类可以具有进一步的子 类,并且BaseNode也可以具有进一步的超类。
多态使得封装更进一步。一个软件成分可以请求另一个成分而 不用确切地知道该成分是什么。接收请求的成分解释它并根据其变量 和数据来确定如何执行请求。使用先前作为例子来描述的简单的类层 次结构,软件成分可以调用BaseNode的对象的成员函数。软件成分 不需要知道BaseNode的对象实际上是WellNode的对象还是 NetworkNode的对象。但是,类层次结构使得WellNode的对象和 NetworkNode的对象能够包含被调用成员函数的不同的实现。层次结 构中的每个类可以包含成员函数的相同的抽象接口,但是他们可以具 有适合于执行成员函数的专门类型对象的不同的功能性。
设施网络模型
本发明的储集层模拟系统包括设施网络模型(“FNM”)。 FNM被设计来使代码改变和重新编译的需要达到最小。这通过在 FNM C++类层次结构中定义通用类来实现。典型的通用C++类层次 结构在图2和3中显示。图2中的每个方框(编号200到218)表示 一个C++类。类之间的在一端具有空三角形的实线表示类之间的继承 关系,基类在具有三角形的一端而派生类在相对的一端。两个类之间 的虚线表示那两个类的对象之间的关联。标注虚线的文本表示关联的 名字,并且在每个关联两端的数字标注表示关联的基数。例如,关联 “node_is_child_of”220在“Node”端具有“1”标注,在 “Connection”端具有“0..*”标注。这些标注表示每个 Connection的对象正好具有为该Connection的对象的孩子的1个 Node,并且每个Node的对象具有该Node的对象为其孩子的零或许 多Connection的对象。每个通用类仅包含成员变量和成员函数的最 小集来定义所有的该类对象的通用行为。例如,通用节点类(图2中 的Node 203)是通过节点的某些专门化来模拟的所有设施类型的类 层次结构中最专门化类型的类,不管该节点表示井中的位置,地面流 线,分离器,还是可以通过节点来表示的某种其他设施。分立的通用 类被用来定义专门化设施类型的命名“属性”(参看 AttributeValue 211及其派生类212和213)。使用通用的设施类型 类(200到205)和通用的命名属性类(207和213)允许希望的设施 类型的基本上所有专门化行为在“定义数据文件”(以下称作 “DDF”)中定义。在本描述末尾的附录6列出该文件的一个实 例。使用通用设施和通用属性类的关键设计特点使得FNM能够可变 通和可扩展,使得新的设施类型或新的属性可以通过增加或修改 DDF的内容而被并入。该特点避免增加或改变数据模型中的类,这 需要大大地修改源代码并且重新编译修改后代码。
FNM数据模型在图3中继续,其显示记住在DDF中定义的设 施类型和属性类型的一系列类。
DDF包含每个可能设施类型的文本描述,例如 “WellNode”,“NetworkNode”,“SeparatorNode”, “Well”以及“NetworkConnection”。它也包含那些设施类型的 每个专门化命名属性的文本描述。当DDF被软件处理时,它为DDF 中的每个专门化设施类型创建FacilityTypeSystemAttributes对象 (303),并且为DFF中的每个命名属性创建AttributeDefinition对 象(304)。FacilityTypeSystemAttributes对象从基类VarBase 300,VariableAttributesBase 301和FacilityType 302继承。 facility_has_system_attribute关联(305)将专门的 FacilityTypeSystemAttributes对象(具体设施类型的定义)关联到该 设施类型的所有AttributeDefinition的对象(专门的命名属性的定 义)。在DDF已被完全处理之后,储集层模拟系统包含定义可能的 设施类型(FacilityTypeSystemAttributes对象303的集合)的对象和 那些设施类型中的每个必须具有的属性(AttributeDefinition对象 304的集合)。可用的设施类型和命名属性的定义在软件中保持不 变,直到DDF被修改并被再次处理,这典型地仅当新的设施类型或 属性被需要时发生。
使用本发明的储集层模拟系统包括用于定义作为给定模拟模型 一部分的设施的网络(“设施网络”)的图形用户界面(GUI)。 GUI将设施网络显示为通过连接箭头相互附接的图标的集合。
图4说明简单设施网络的这种图形用户界面。不同的图标可以 被用来表示不同的设施类型(井,分离器,网络结点),而连接箭头 表示“象节点”的设施之间的流线。在图4中,每个文本框(以 “b”为后缀的401b到410b)表示用图标或箭头(以“a”为后缀 的401a到410a)表示的设施的名字。图4中的实例设施网络包含三 个井406a,408a,410a,以及这些井附接到的地面流动网络。该地 面网络包含网络节点403a和404a,终端节点401a,网络连接 405a,407a和409a,以及终端连接402a。井406a和408a生产通过 网络连接405a和407a移到网络节点404a的流体。来自井410a的流 体在网络节点403a与来自其他两个井的产品融合。从网络节点 403a,流体继续到输出口终端节点401a。
FNM GUI提供自定义的对话框,菜单和工具条,使得用户可以 相对容易地构建并修改设施网络。当用户为了储集层模拟研究向设施 网络增加专门设施时,储集层模拟系统使用适当的 FacilityTypeSystemAttributes对象303(给出用户增加的设施的类 型)来定位AttributeDefinition对象(304)的集合,这向系统提供 需要用来创建实际设施对象(202,203,204或205)以及所有其系 统定义的属性对象(212)的信息。
自定义设施管理逻辑的支持
FNM的通用C++数据模型简化下面描述的补充自定义设施管理 逻辑系统(“FML”)。FML系统被设计用于在正在运行的模拟模 型中监测和控制设施的操作来最优化烃在油田生命期内的生产。 FML在模拟运行期间操作从FNM数据模型的对象创建并类似于 FNM数据模型的对象的设施对象。为了使FML的可定制性达到最 大,FNM数据模型包括用户定义的命名属性(UserAttributeValue, 213,图2)。用户可以为任何一个可用的设施类型创建另外的命名 属性(超出用户在DDF中定义的那些),然后在其自定义FML中 使用那些自定义的命名属性。用户定义的命名属性的定义保存为 AttributeDefinition对象(218,图2),并且与对应于属性已经为其 定义的设施类型的FacilityTypeUserAttributes对象(217,图2)相 关联。
FNM可以用任何适合的面向对象编程语言来使用。包括通用设 施类型,通用命名属性,和用户定义属性的数据模型设计并不局限于 C++实现。但是,FNM将优选地使用与储集层模拟程序中使用的相 同的面向对象编程语言来促进与储集层模拟器的其他成分的兼容性。
OOP类层次结构的新颖用法
对于本发明的计算机系统,新的方法已经被用来分开大量成员 变量和它们所属的对象。类层次结构包括两个类子层次结构,一个子 层次结构包含定义多种“设施类型”的类,而另一个子层次结构包 含定义多种“属性值”的类。两个子层次结构通过它们各自的基类 来相互引用-基本的设施类型类(FacBase,图2中的200)具有通 过ValueUse类(206,图2)到基本的命名属性值类(Value,图2 中的207)的关联或引用。在本用法中,设施对象将引用许多不同的 属性值对象。每个属性值对象包含帮助定义设施对象的特征的专门化 的数据单元。概念地,设施由相关对象的集合-设施对象本身加上所 有其相关属性值对象来定义。这种类体系结构并不严格遵循传统的 OOP封装惯例,因为设施的数据并不全部地包含于单个对象中。但 是,属性值对象被有效地封装,因为它们的访问仍然通过设施对象的 方法来提供。
本发明的计算机系统的另一个独特的特征在于设施类型类和属 性值类都是“通用的”。特别地,这意味着在两个先前描述的子层 次结构的每个中最专门化的类能够表示许多不同的,更专门化的设施 类型,以及许多不同的属性值。例如,一种类型的专门化设施类是 Node(203,图2)。该类是通用的因为Node的对象可以被实例化来 表示多种不同的节点设施类型,即使类层次结构不具有每个节点设施 类型的不同的专门化节点类。同样地,SystemAttributeValue(212, 图2)是通用属性类因为SystemAttributeValue对象可以被实例化来 表示多种不同的属性类型,例如浮点标量,整型标量,字符串,枚举 类型,浮点数组,以及整型数组。
包含通用的设施类型和属性值类的类层次结构的关键优点在于 软件系统中支持的设施类型和属性值的集合可以被修改(另外的设施 类型和属性值被定义,或现有的设施类型和属性值被删除)而不改变 类层次结构,从而避免需要重新编译源代码来适应对设施类型或属性 值的改变。在当前系统中,可以称作“数据定义文件”的明文文 件,例如,ASCII文件包含定义每种设施类型和每种设施类型的所有 属性值的文本输入。该数据定义文件被程序处理来创建软件系统中的 定义。设施类型定义是FacilityType类(302,图3)的对象。属性值 定义是AttributeDefinition类(305,图3)的对象。当用户操作系统 来创建模拟模型时,定义对象被软件使用,无论什么时候用户需要创 建设施的实例及其附随属性值的实例时。
本发明的FNM解决了地下含烃储集层及相关生产设施的复杂模 拟模型的开发者所面临的三个挑战性问题:
1.设施和储集层的流体流动计算的集成,在过去这需要每个的 模型,这些模型足够相似以致允许统一的解决方法。
2.本发明的设施流体流动计算模型是可变通而且可容易扩展 的,使得现有设施类型的性状可以被扩展或另外的设施类型可以被加 入,而相对较小地改变软件。
3.设施模型体系结构支持自定义设施管理逻辑系统,其被希望 在模拟运行期间动态地控制设施的性状。
设施管理逻辑
设施管理逻辑(“FML”)是为物理系统例如储集层模拟系统 中的井及相关地面设施的操作控制而设计的一种编程系统。FML包 括三个部分:(1)逻辑界面,这里称作“逻辑图”,(2)从逻辑 图的C++代码(工业标准编程语言)产生器,以及(3)将FML代 码和储集层模拟器本身集成的专门软件设计。
逻辑图
逻辑图包括图形用户界面,模拟器用户可以用它来动态地构建 设施管理逻辑的流程图,从而使得用户能够自定义被模拟的物理系统 的模拟。动态构建逻辑的能力指用户构建需要用来解决设施管理问题 的逻辑的能力。逻辑可以由用户通过逻辑界面来构建。逻辑界面可以 用来执行选自下面的至少一步:开发新的逻辑;选择并使用用户或其 他人以前可能为其他设施管理问题而构建的现有逻辑;选择并修改现 有逻辑。流程图包括表示基本的逻辑控制结构的图标和表示逻辑从一 个图标前进到另一个的箭头。逻辑图的出发点包括开始图标(表示逻 辑的入口点),结束图标(表示逻辑的出口点),以及两者之间的单 箭头。箭头具有单方向,它们表示图标被计算的顺序。用户的任务是 思考希望的逻辑,并且通过建立代表性的流程图来模拟该逻辑。所有 逻辑可以在一个高级图中,或者它可以被分解为多个图,每个表示逻 辑的一个模。逻辑的每个模块称作操作。主操作是最高级的操作。 这种逻辑的一个简化实例在图5中显示。
图5图解地说明显示一个简单设施管理逻辑的简化逻辑图的一 个实例。该逻辑使用三种图标类型(三个处理图标512,520和 526,两个逻辑测试图标516和522,以及一个循环图标514)。在执 行储集层模拟的过程中,该逻辑以规则的间隔重复地执行,每次在生 产井上执行检验和控制。特别地,在生产井上有一个循环(循环图标 514),其在“生产者”集的所有成员上重复。在循环体(图标 516,520,522,526,528,530以及将这些图标相互连接和连接到 循环图标514的箭头)中,“生产者”集中专门的生产井的水率被 检验两次(在逻辑测试图标516和522处)。如果在逻辑测试图标 516处水率超过每天4000桶,那么井被修理(处理图标520)试图减 少水率。如果在逻辑测试图标522处水率超过每天5000桶,那么井 被关闭(处理图标526)。
三种类型的图标形成流程图的构件块。处理图标用来表示等式 或者对作用于设施来用某种方法改变它们的状态的操作(例如打开或 关闭井)的调用。处理图标表示语句执行,并且总是具有单一向内箭 头和单一向外箭头,表明只有一条执行路径通过该处理图标。逻辑测 试图标用来在流程图中作出判断。逻辑测试图标包含计算为真(是) 或假(否)的用户指定的表达式。逻辑测试图标具有两个向外箭头, 沿着一个如果表达式为真(在图5中,逻辑测试图标516的箭头518 和逻辑测试图标522的箭头524),沿着另一个如果表达式为假(在 图5中,逻辑测试图标516的箭头519和逻辑测试图标522的箭头 525)。“逻辑测试结构”包括逻辑测试“图标”,以及沿着是和 否逻辑分支直到逻辑测试结构的结束标记(逻辑测试图标522的图标 528和逻辑测试图标516的图标530)的所有逻辑。循环图标用于在 逻辑上循环,例如无论什么时候逻辑必须在流程图中被重复地计算 时。循环图标包含控制什么类型的循环将发生的逻辑(在图5中,循 环图标514是在一个集的成员上的循环)。“循环结构”包括循环 图标以及在循环图标的开始箭头(515)和下一个箭头(531)之间的 所有逻辑图标。经常地,设施管理逻辑实际上是重复的,并且循环图 标和循环结构是支持这一概念的方法。
FML用户通过在适当的图形用户界面(逻辑图)中使用鼠标光 标瞄准并点击来为模拟模型中希望的应用建立流程图。使用在GUI 中显示的流程图,用户决定下一步需要三种图标类型中的哪种,然后 通过在希望的按钮上点击来激活三个工具条按钮中的一个。接下来, 用户将光标移到流程图中表示下一个图标的插入点的现有箭头上。当 用户通过在其上点击来选择箭头时,系统插入图标并管理现有和新的 箭头的创建和附接。
模拟器用户的下一个任务是给插入的图标填上关于该图标具体 地作什么的信息。例如,如果它是逻辑测试图标,那么用户定义作为 真/假测试的基础的表达式。如果它是循环图标,那么需要信息来指 定重复的基础,以及重复应该执行多少次。对于处理图标,用户可能 需要编写等式或指定关于操作将如何被调用的细节。对于这些任务中 每个,用户可以键入信息,或者可以利用指导用户通过建立图标内容 所需的许多步骤的一系列上下文相关菜单和对话框。
对于信息在每个图标中被指定的方式,专门的语法是优选的。 语法可以通过称作设施管理控制语言的FML专门格式来定义。当使 用菜单和对话框时,许多语法细节被自动处理。如果用户直接为每个 图标键入信息,那么遵守语法规则是用户的责任。如果用户不喜欢用 图形逻辑图来操作,他或她可以可选地专门在基于文本的逻辑代码界 面(称作文本模式视图)中工作,其中用户可以输入直接作为文本的 所有设施管理控制语言,而没有在FML逻辑图视图中提供的可见的 帮助(图标,箭头,菜单或对话框)。一旦用户开始在文本模式视图 中工作,他或她不能回到与他们正在指定的逻辑相对应的逻辑图。
在本说明书末尾的附录1包含来自图5中以流程图形式表示的 逻辑的文本模式视图的文本。在附录1中出现的文本符合设施管理控 制语言的语法。一旦用户已经使用流程图视图输入逻辑,FML自动 生成该文本模式视图。用户不需要看到该视图或以该视图来操作,如 果他或她不想的话。另一方面,一些用户可能选择直接在文本模式视 图中输入所有的逻辑,或者它们可能喜欢编辑,包括输入,修改或删 除一旦处于这种形式中的逻辑。如果他们是这样,那么逻辑图视图对 该组逻辑不再可用。只要用户仅使用逻辑图视图来创建或编辑逻辑, 那么用户可以在两种视图之间来回切换。
C++代码的生成
当逻辑被完成,并且用户准备开始模拟时,系统必须将设施管 理控制语言转换成C++代码,使得它可以和模拟器一起执行。如果使 用逻辑图,那么系统首先将流程图转换成设施管理控制语言。逻辑到 面向对象代码的转换可以使用任何适合的转换方法来执行。这是对用 户隐藏的自动步骤。如果使用文本模式,那么已经在视图中的设施管 理控制语言被使用。
然后系统开始解析设施管理控制语言的处理来验证语法。随着 解析的进行,句法上正确而且完整的表示逻辑的设施管理控制语言自 动地转换成ANSI标准面向对象C++代码。如果发现语法错误,那么 它们被报告。如果没有错误,那么C++代码的完整集与其他的模拟器 输入数据一起写入文件。
位于本说明书末尾的附录2到5描述为图5和附录1中的样本 逻辑而生成的C++代码。
在附录2中,指向网络中每个设施的全局指针声明并初始 化。该列表基于网络中的设施的数目和类型以及由用户指定的设施名 字而不同。指针指向在随后部分以及图6和7中描述的接口类。
在附录3中,附录2中所示的所有的全局设施指针被初始化来 指向模拟器中的实际设施对象。
在附录4中,在每个时间步,模拟器调用名为wm initialize()的 函数。这保证全局设施指针指向模拟器对象(通过调用附录3中的 wm_initialize_globals()),然后它调用实际的设施管理逻辑。剩余的 声明描述动态专门化的一个实例,其中当Functor0类出于定义用来 形成生产井集的方法的唯一目的而被声明时,SimWmWellInterface 类被专门化。动态专门化关于图6来讨论,在本说明书后面将更详细 地讨论。
附录5列出图5和附录1中描述的设施管理逻辑的C++代码。
当主模拟器产生时,它从输入文件中提取C++代码,并将该代 码放入编译文件。主模拟器启动模拟器运行平台本地的C++编译器, 然后编译器将代码转换成目标文件。然后C++链接器被启动来创建动 态链接库(NT上)或共享程序库(UNIX上)。然后模拟器装载该 库,准备执行代码。当主模拟器已经装载库时,集成模拟系统被创 建,包括主模拟器和自定义逻辑。
当集成模拟系统正在执行的适当时间,模拟器调用与如前所述 包含所有设施管理逻辑或者调用包含逻辑模块的其他操作的主操作相 对应的C++代码。在任何一种情况下,所有逻辑被执行,并且一旦完 成,代码将控制返回给模拟器。然后模拟器继续它的计算,这可能受 逻辑改变设施状态的方式的影响。然后模拟器继续随时间“前移” 来计算储集层的性状。有规律地贯穿该推进,相同的设施管理逻辑被 执行,从而不断地影响油田在其模拟生命期内的性状。然后模拟器用 户可以检查结果,并且可能改进设施管理逻辑或模拟器输入数据。最 终,当结果可以接受时,该设施管理逻辑可以形成实际的设施管理策 略的基础然后将被用于实际的储集层。
与储集层模拟器的结合
为了使逻辑影响模拟器使用的设施的状态,模拟器执行逻辑是 不够的。逻辑,或者更特别地从逻辑生成的面向对象C++代码,与主 模拟器的数据模型集成。主模拟器系统和与主模拟器的数据模型集成 的面向对象C++代码的组合总体地称作集成模拟系统。为了将面向对 象C++代码和数据模型集成,并且为了使处理更有效,利用面向对象 的数据模拟技术,尤其是多继承和多态,以及动态专门化。现在将描 述使用面向对象技术的优选方法。
多继承和多态
为了编译和链接C++代码并将它与模拟器集成,C++代码必须 知道模拟器的数据和方法的各个方面。这通过包含数据和方法的描述 的“包含”文件来实现。这些文件称作头文件。这些头文件优选地 与模拟器一起提供,使得编译和链接可以被执行。当更多的头文件被 包含于C++代码中时,编译和链接的处理会慢下来。为了提高性能, 优选地减少头文件的数目及其包含的数据。多继承和多态优选地用来 实现这一目的。
一系列空的“接口”对象被创建,其表示实际上包含数据和方 法的模拟器对象。该方法在图6中概述。
图6示意地说明模拟器数据模型的一小部分。虚线对角线608 隔开“接口”端的类和“模拟器”端的类。在一端具有空三角形的 实线表示继承关系,基类在关系的三角形一端,派生类在相对的一 端。虚线608左边的接口类600和602基本上是空的。它们不包含成 员变量,仅包含空的成员函数声明(数据模型的C++实现中的“纯 虚”操作)。接口类WellInterface 602包含空操作“shut_in”和 “open”。Well的模拟器端版本(606)具有Well的对象的成员变 量和成员函数“sbut_in”和“open”的真实实现。多继承允许接 口类的使用和声明。模拟器端的Well类606既经由继承箭头609从 接口类WellInterface 602继承,又经由继承箭头610从模拟器类 Object 604继承。WellInterface类602是ObjectInterface 600的专门 化。模拟器端的基类Object 604经由继承箭头611从 ObjectInterface类600继承。多态允许空接口操作“open”在接口 类WellInterface 602上被调用,然后在实际的模拟器类Well 606上 执行真实的“open”操作。该范例用来用相应的接口类表示每个模 拟器设施类。
只有接口对象需要能够编译和链接逻辑。因为编译器只看到简 单的接口类,复杂部分和私有信息仍然对编译器和可能查看文件的任 何人隐藏。附录2中所示的设施管理控制语言仅包含接口对象指针, 而不包含模拟器对象指针。因为接口对象是空的,编译/连接处理 快,并且有关模拟器需要的数据和方法集的细节不公开(例如对可能 扫描计算机磁盘以获取文件的人)。多继承允许接口类与模拟器类相 关联,而多态允许使用在接口类中声明的空方法来间接调用真实的方 法。
动态专门化
由模拟器用户开发的每个逻辑操作与一般的设施网络或专门的 设施相关联。用户依赖于逻辑的本质来作选择。为了使这些操作可以 在已经描述的模拟器数据模型框架中执行,操作需要变成类的方法。 因为C++不允许向现有的类增加方法而不重新编译模拟器(或其重要 部分),方法必须增加到只有逻辑代码知道的新的类中。这导致在运 行时间新的类从现有的接口类专门化的设计。该方法在图7中示意地 显示。
图7扩展图6中的图,说明动态专门化如何被用来支持用户编 写操作。对角虚线710隔开接口类700,702和704以及模拟器类 706和708。这里,用户已经为Well类型的设施编写名为 “special_well_logic”的新的操作。为了支持新操作的声明,接口类 通过使用由设施管理控制语言到C++的语法分析器编写的类声明在运 行时间自动地被专门化。在本实例中,类“WellInterface_User” 704被语法分析器创建,并且它包含新的逻辑操作的声明以及包括新 的逻辑操作的代码。因此,对于属于Well类型的设施,既可以调用 内部操作(来自WellInterface 702和ObjectInterface 700),又可以 调用用户操作(来自WellInterface_User704)。
数据模型被扩展,但是仅对于逻辑代码。模拟器的其他部分并 不知道该扩展,所以从模拟器的角度,数据模型并没有改变,因此模 拟器代码不需要被编译来使用用户定义的逻辑。同时,逻辑知道新的 类并认识新的操作。从用户的角度,模拟器知道的内部操作和模拟器 不知道的自定义操作都用完全相同的方法来调用。而且,属于从接口 类派生的类的新操作,具有与接口类相同的到内部操作和数据的通 道。结果是模拟器代码和自定义代码之间的表面无缝集成。
FML系统可以通过本领域技术人员而与使用面向对象设计的优 选地使用C++来编码的储集层模拟器集成在一起。FML系统的先决 条件是它必须与具有面向对象设计的模拟器集成在一起。
正是面向对象原理支持多继承,多态和类专门化的概念,这对 于无缝集成FML和模拟器是必须的。FML可以和使用C++之外的 面向对象语言来实现的模拟器一起使用。其他面向对象编程 (“OOP”)技术可以被使用,包括但不局限于,Simula,Eiffel, Smalltalk,Objective-C,或其变种。FML的实施并不局限于具体的 OOP语言。
如果使用C++之外的其他OOP系统,C++代码生成步骤将需要 修改来生成替换的OOP语言,并且这也隐含着模拟器也具有面向对 象的数据模型。
具有FML系统结构的储集层模拟模型允许用户开发自定义设施 管理逻辑来实际地模拟任何策略。因而,逻辑的排列实际上是无穷 的。
可变通而且可扩展的数据模型设计
储集层模拟系统优选地也使用C++的面向对象特征来解决可扩 展性问题。软件设计优选地使用C++类的集合(集体地称作“数据 模型”)来定义具有指定数据(成员变量)和行为(成员函数)的对 象。成员变量和成员函数是硬编码的,也就是说,它们在类自身中定 义,意味着对类作扩展;例如,新的成员变量,新的成员函数,新的 类需要代码改变和重新编译。
在典型的OOP类层次结构中,给定类的所有成员变量都被封装 在该类中。因此,作为该类的实例的对象通过作为成员函数的其公用 接口来保护并控制到它们的成员变量的访问。
已经描述了新的储集层模拟系统的原理以及试图应用该原理的 最佳方式。对本领域技术人员明显的是,可以不背离于上面描述的本 储集层模拟系统的精神和范围而对上面描述的实施方案作各种改变。 因此,应该理解的是,本发明并不局限于所显示和描述的具体细节。
附录1
∥ Start of Global Variable Declarations ∥ End of Global Variable Declarations wm_main( ) { ∥ Start of module code ∥ Start of Local Variable Declarations Set<Well> producers; Ref<Well> well in set; ∥ End of Local Variable Declarations { ∥ Start of Process icon construct producers.form_set(candidate.facility_descriptor==″producer″); } ∥ End of Process icon construct { ∥ Start of loop construct foreach well_in_set in producers { ∥ Start of loop body { ∥ Start of logical test construct if (( well_in_set.get_phase_rate(WATER) >4000. )) { { ∥ Start of Process icon construct well_in_set.workover(WRKOVR_CLOSE,BY_RESCONN, ″WCUT>. 6″); } ∥ End of Process icon construct { ∥ Start of logical test construct if ((well_in_set.get_phase_rate(WATER)>5000.)) { { ∥ Start of Process icon construct well_in_set.shut_in(NO_CROSS_FLOW); } ∥ End of Process icon construct } else { } } ∥ End of logical test construct } else { } ∥ End of logical test construct } ∥ End of loop body } ∥ End of loop construct { return; } } ∥ End of module code
附录2
#include″q:\rell_sim\bin\runtime_includes\wm_headers.h″ SimWmWellNodeInterface* wellnode_potnorth = NULL; SimWmWellNodeInterface* wellnode_potsouth = NULL; SimWmWellNodeInterface* wellnode_prod100 = NULL; SimWmWellNodeInterface* wellnode_prod82 = NULL; SimWmNetworkNodeInterface* netnode_injector = NULL; SimWmNetworkNodeInterface* netnode_producer = NULL; SimWmTerminalNodeInterface* termnode_injector = NULL; SimWmTerminalNodeInterface* termnode_producer = NULL; SimWmReservoirConnectionInterface* potnorth_rc_0 = NULL; SimWmReservoirConnectionInterface* potnorth_rc_1 = NULL; SimWmReservoirConnectionInterface* potnorth_rc_2 = NULL; SimWmReservoirConnectionInterface* potsouth_rc_0 = NULL; SimWmReservoirConnectionInterface* potsouth_rc_1 = NULL; SimWmReservoirConnectionInterface* potsouth_rc_2 =NULL; SimWmReservoirConnectionInterface* prod100_rc_0 = NULL; SimWmReservoirConnectionInterface* prod100_rc_1 = NULL; SimWmReservoirConnectionInterface* prod100_rc_2 = NULL; SimWmReservoirConnectionInterface* prod82_rc_0 = NULL; SimWmReservoirConnectionInterface* prod82_rc_1 = NULL; SimWmReservoirConnectionInterface* prod82_rc_2 = NULL; SimWmTerminalConnectionInterface* termconn_injector = NULL; SimWmNetworkConnectionInterface* netconn_potnorth = NULL; SimWmNetworkConnectionInterface* netconn_potsouth = NULL; SimWmNetworkConnectionInterface* netconn_prod100 = NULL; SimWmTerminalConnectionInterface* termconn_producer = NULL; SimWmNetworkConnectionInterface* netconn_prod82 = NULL; SimWmWellInterface* potnorth = NULL; SimWmWellBranchInterface* wellbranch1 = NULL; SimWmWellInterface* potsouth = NULL; SimWmWellBranchInterface* wellbranch2 = NULL; SimWmWellInterface* prod100 = NULL; SimWmWellBranchInterface* wellbranch3 = NULL; SimWmWellInterface* prod82 = NULL; SimWmWellBranchInterface* wellbranch4 = NULL;
附录3
void wm_initialize_globals() { static int wmig_was_called = 0; if (wmig_was_called) return; wmig_was_called = 1; wellnode_potnorth = (SimWmWellNodeInterface*) SimWmFNControllerUtility∷lookup_object(″wellnode_potnorth″, VM_GetInterfaceID<SimWmWellNodeInterface>() ()); wellnode_potsouth = (SimWmWellNodeInterface*) SimWmFNControllerUtility∷lookup_object(″wellnode_potsouth″, VM_GetInterfaceID<SimWmWellNodeInterface>() ()); wellnode_prod100 = (SimWmWellNodeInterface*) SimWmFNControllerUtility∷lookup_object(″wellnode_prod100″, VM_GetInterfaceID<SimWmWellNodeInterface>() ()); wellnode_prod82 = (SimWmWellNodeInterface*) SimWmFNControllerUtility∷lookup_object(″wellnode_prod82″, VM_GetInterfaceID<SimWmWellNodeInterface>()()); netnode_injector = (SimWmNetworkNodeInterface*) SimWmFNControllerUtility∷lookup_object(″netnode_injector″, VM_GetInterfaceID<SimWmNetworkNodeInterface>()()); netnode_producer = (SimWmNetworkNodeInterface*) SimWmFNControllerUtility∷lookup_object(″netnode_producèr″, VM_GetInterfaceID<SimWmNetworkNodeInterface>()()); termnode_injector = (SimWmTerminalNodeInterface*) SimWmFNControllerUtility∷lookup_object(″termnode_injector″, VM_GetInterfaceID<SimWmTerminalNodeInterface>()()); termnode_producer = (SimWmTerminalNodeInterface*) SimWmFNControllerUtility∷lookup_object(″termnode_producer″, VM_GetInterfaceID<SimWmTerminalNodeInterface>() ()); potnorth_rc_0 = (SimWmReservoirConnectionInterface*) SimWmFNControllerUtility∷lookup_object(″potnorth_rc_0″, VM_GetInterfaceID<SimWmReservoirConnectionInterface>()()); potnorth__rc_1 = (SimWmReservoirConnectionInterface*) SimWmFNControllerUtility∷lookup_object(″potnorth_rc_1″, VM_GetInterfaceID<SimWmReservoirConnectionInterface>()()); potnorth_rc_2 = (SimWmReservoirConnectionInterface*) SimWmFNControllerUtility∷lookup_object(″potnorth_rc_2″, VM_GetInterfaceID<SimWmReservoirConnectionInterface>() ()); potsouth_rc_0 = (SimWmReservoirConnectionInterface*) SimWmFNControllerUtility∷lookup_object(″potsouth_rc_0″, VM_GetInterfaceID<SimWmReservoirConnectionInterface>() ()); potsouth_rc_1 = (SimWmReservoirConnectionInterface*) SimWmFNControllerUtility∷lookup_object(″potsouth_rc_1″, VM_GetInterfaceID<SimWmReservoirConnectionInterface>()()); potsouth_rc_2 = (SimWmReservoirConnectionInterface*) SimWmFNControllerUtility∷lookup_object(″potsouth_rc_2″, VM_GetInterfaceID<SimWmReservoirConnectionInterface>()()); prod100_rc_0 = (SimWmReservoirConnectionInterface*) SimWmFNControllerUtility∷lookup_object(″prod100_rc_0″, VM_GetInterfaceID<SimWmReservoirConnectionInterface>()()); prod100_rc_1= (SimWmReservoirConnectionInterface* ) SimWmFNControllerUtility∷lookup_object(″prod100_rc_1″, VM_GetInterfaceID<SimWmReservoirConnectionInterface>()()); prod100_rc_2 = (SimWmReservoirConnectionInterface*) SimWmFNControllerUtility∷lookup_object(″prod100_rc_2″, VM_GetInterfaceID<SimWmReservoirConnectionInterface>() ()); prod82_rc_0 = (SimWmReservoirConnectionInterface*) SimWmFNControllerUtility∷lookup_object(″prod82_rc_0″, VM_GetInterfaceID<SimWmReservoirConnectionInterface>()()); prod82_rc_1 = (SimWmReservoirConnectionInterface*)    SimWmFNControllerUtility∷lookup_object(″prod82_rc_1″,    VM_GetInterfaceID<SimWmReservoirConnectionInterface>()());   prod82_rc_2 = (SimWmReservoirConnectionInterface*)    SimWmFNControllerUtility∷lookup_object(″prod82_rc_2″,    VM_GetInterfaceID<SimWmReservoirConnectionInterface>()());   termconn_injector = (SimWmTerminalConnectionInterface*)    SimWmFNControllerUtility∷lookup_object(″termconn_injector″,    VM_GetInterfaceID<SimWmTerminalConnectionInterface>()());   netconn_potnorth = (SimWmNetworkConnectionInterface*)    SimWmFNControllerUtility∷lookup_object(″netconn_potnorth″,    VM_GetInterfaceID<SimWmNetworkConnectionInterface>()());   netconn_potsouth = (SimWmNetworkConnectionInterface*)    SimWmFNControllerUtility∷lookup_object(″netconn_potsouth″,    VM_GetInterfaceID<SimWmNetworkConnectionInterface>()());   netconn_prod100 = (SimWmNetworkConnectionInterface*)    SimWmFNControllerUtility∷lookup_object(″netconn_prod100″,    VM_GetInterfaceID<SimWmNetworkConnectionInterface>()());   termconn_producer = (SimWmTerminalConnectionInterface*)    SimWmFNControllerUtility∷lookup_object(″termconn_producer″,    VM_GetInterfaceID<SimWmTerminalConnectionInterface>()());   netconn_prod82 = (SimWmNetworkConnectionInterface*)    SimWmFNControllerUtility∷lookup_object(″netconn_prod82″,    VM_GetInterfaceID<SimWmNetworkConnectionInterface>()());   potnorth = (SimWmWellInterface*)    SimWmFNControllerUtility∷lookup_object(″potnorth″,    VM_GetInterfaceID<SimWmWellInterface>()());   wellbranchl = (SimWmWellBranchInterface*)    SimWmFNControllerUtility∷lookup_object(″wellbranchl″,    VM_GetInterfaceID<SimWmWellBranchInterface>()());   potsouth = (SimWmWellInterface*)    SimWmFNControllerUtility∷lookup_object(″potsouth″,    VM_GetInterfaceID<SimWmWellInterface>() ());   wellbranch2 = (SimWmWellBranchInterface*)    SimWmFNControllerUtility∷lookup_object(″wellbranch2″,    VM_GetInterfaceID<SimWmWellBranchInterface>()());   prod100 = (SimWmWellInterface*)    SimWmFNControllerUtility∷lookup_object(″prod100″,    VM_GetInterfaceID<SimWmWellInterface>()());   wellbranch3 = (SimWmWellBranchInterface*)    SimWmFNControllerUtility∷lookup_object(″wellbranch3″,    VM_GetInterfaceID<SimWmWellBranchInterface>()());   prod82 = (SimWmWellInterface*)    SimWmFNControllerUtility∷lookup_object(″prod82″,    VM_GetInterfaceID<SimWmWellInterface>()());   wellbranch4 = (SimWmWellBranchInterface*)    SimWmFNControllerUtility∷lookup_object(″wellbranch4″,    VM_GetInterfaceID<SimWmWellBranchInterface>() ()); }
附录4
  void wm_main();   extern ″C″{   void wm_initialize()   {    wm_initialize_globals();    wm_main();   }   }   class Functor0:public Selector<SimWmWellInterface>   {   public:    Functor0();    virtual ~Functor0();    virtual Bool operator() (SimWmWellInterface* candidate) const;   };   Functor0∷Functor0()   {    ∥ do nothing else   }   Functor0∷~Functor0()   {    ∥ do nothing else   }   Bool Functor0∷operator() (SimWmWellInterface* candidate) const   {    return (*((String*)(candidate- >lookup_attribute(″facility_descriptor″,0,    TYPE_String))) == ″producer″);   }
附录5
  void wm_main()   {    Set<SimWmWellInterface>producers;    SimWmWellInterface* well_in_set = NULL;    {    producers.foRM_set(new Functor0());    }    {    producers.reset();    while(producers.get_next(well_in_set))    {    PhaseTypeEnum scratch_0 = (PhaseTypeEnum)(WATER);    if ((well_in_set->get_phase_rate(scratch_0) > 4000.))    {    {    WorkoverTypeEnum scratch_1 = (WorkoverTypeEnum)(WRKOVR_CLOSE);    WorkoverLevelTypeEnum scratch_2 =    (WorkoverLevelTypeEnum)(BY_RESCONN);    String scratch_3 = ″WCUT>.6″;    well_in_set->workover(scratch_1,scratch_2, scratch_3);    }    {    PhaseTypeEnum scratch_4 = (PhaseTypeEnum)(WATER);    if ((well_in_set->get_phase_rate(scratch_4)> 5000.))    {    ShutInTypeEnum scratch_5 = ShutInTypeEnum)(NO_CROSS_FLOW);    well_in_set->shut_in(scratch_5);    }    else    {    }    }    }    else    {    }    }    }    return;   }
                        附录6
这一来自数据定义文件的摘录说明设施类型定义和命名属性定 义的层次结构本质。包含于该摘录中的设施类型示范了定义终端用户 设施类型“网络节点”的基本设施类型级。摘录包括网络节点具有的 三个命名属性的定义。命名属性中两个在设施对象级定义,第三个在 节点级定义。
∥ Comments in the Data Definitions File begin with ″∥″ ∥ ″\″at the end of a line indicates continuation on the subsequent line ∥ Highest level base facility type is FacBase Name: ″FacBase″ Definition: ″FacBase Definition″ Is Obsolete: F IOArchive Class Name: ″NA″ Long Name: ″FacBase″ View Name: ″View Name″ Decomp Hierarchy: ″″ Dimensionality: ″″ Req by Restart Rule: ″restart rule″ Req by Simulator Rule: ″simulator rule″ Req by User Rule: ″user rule″ Valid Rule: ″valid rule″ Bitmap Resource ID: 0 Instantiable: F Member of Granule: F Simulator Variable: F Time Variant: F Decomposable: F Spec for all Nodes: F Change Invalidates: F Parent Facility: ″″ Is Abstract: T ∥ Parent type of FacObject is FacBase Name: ″FacObject″ Definition: ″FacObject Definition″ Is Obsolete: F IOArchive Class Name: ″NA″ Long Name: ″FacObject″ View Name: ″View Name″ Decomp Hierarchy: ″″ Dimensionality: ″″ Req by Restart Rule: ″restart rule″ Req by Simulator Rule: ″simulator rule″ Req by User Rule: ″user rule″ Valid Rule: ″valid rule″ Bitmap Resource ID: 0 Instantiable: F Member of Granule: F Simulator Variable: F Time Variant: F Decomposable: F Spec for all Nodes: F Change Invalidates: F Parent Facility: ″FacBase″ Is Abstract: T ∥is_active is a named attribute defined at the FacObject level    Attriute Name: ″is_active″    Description: ″is_active″    Unit Group Name: ″″    Default Value: ″TRUE″    Enum Type: ″″    Is Array: F     Is Fixed Length: T    Number of Values: 1    Dimensionality: ″″    Attribute Type: BOOL    Is Class Attribute: F    Is Visible to User: F    Is Time Variant: T    Is Results Only: F    Is Used by Simulator: T    ∥ facility_descriptor is a named attribute defined at the   FacObject level    Attribute Name: ″facility_descriptor″    Description: ″User-defined string that can   be used″\    ″to logically group this   facility″\    ″with similar facilities″    Unit Group Name: ″″    Default Value: ″″    Enum Type: ″″    Is Array: F    Is Fixed Length: T    Number of Values: 1    Dimensionality: ″″    Attribute Type: STRING    Is Class Attribute: F    Is Visible to User: T    Is Time Variant: T    Is Results Only: F    Is Used by Simulator: T ∥ Parent type of Node is FacObject Name: ″Node″    Definition: ″Node Definition″    Is Obsolete: F    IOArchive Class Name: ″NA″    Long Name: ″Node″    View Name: ″View Name″    Decomp Hierarchy: ″″    Dimensionality: ″″    Req by Restart Rule: ″restart rule″    Req by Simulator Rule: ″simulator rule″    Req by User Rule: ″user rule″    Valid Rule: ″valid rule″    Bitmap Resource ID: 0    Instantiable: F    Member of Granule: F    Simulator variable: F    Time Variant: F    Decomposable: F    Spec for all Nodes: F    Change Invalidates: F    Parent Facility: ″FacObject″    Is Abstract: T    ∥depth_node is a named attribute defined at the Node level    Attribute Name: ″depth_node″    Description: ″Depth of the node″    Unit Group Name: ″Depths″    Default Value: ″0.0″    Enum Type: ″″    Is Array: F    Is Fixed Length: T    Number of Values: 1    Dimensionality: ″″    Attribute Type: FLOAT    Is Class Attribute: F    Is Visible to User: T    Is Time Variant: T    Is Results Only: F    Is Used by Simulator: T ∥ Parent type of GeneralFacilityNode is Node. Note that the FNM C++ data model ∥ does not contain this class - it is only defined in the Data Definitions File. Name: ″GeneralFacilityNode″    Definition: ″generic class used to represent most facility types″    Is Obsolete: F    IOArchive Class Name: ″NA″    Long Name: ″GeneralFacilityNode″    View Name: ″View Name″    Decomp Hierarchy: ″″    Dimensionality: ″″    Req by Restart Rule: ″restart rule″    Req by Simulator Rule: ″simulator rule″    Req by User Rule: ″user rule″    Valid Rule: ″valid rule″    Bitmap Resource ID: 0    Instantiable: F    Member of Granule: F    Simulator Variable: F    Time Variant: F    Decomposable: F    Spec for all Nodes: F    Change Invalidates: F    Parent Facility: ″Node″    Is Abstract: T   ∥Parent type of NetworkNode is GeneralFacilityNode. Note that the FNM C++ data   ∥model does not contain this class - it is only defined in the Data Definitions   ∥File.   Name: ″NetworkNode″    Definition: ″NetworkNode Definition″    Is Obsolete: F    IOArchive Class Name: ″NA″    Long Name: ″NetworkNode″    View Name: ″View Name″    Decomp Hierarchy: ″″    Dimensionality: ″″    Req by Restart Rule: ″restart rule″    Req by Simulator Rule: ″simulator rule″    Req by User Rule: ″user rule″    Valid Rule: ″valid rule″    Bitmap Resource ID: 0    Instantiable: F    Member of Granule: F    Simulator Variable: F    Time Variant: F    Decomposable: F    Spec for all Nodes: F    Change Invalidates: F    Parent Facility: ″GeneralFacilityNode″    Is Abstract: F
高效检索全球专利

专利汇是专利免费检索,专利查询,专利分析-国家发明专利查询检索分析平台,是提供专利分析,专利查询,专利检索等数据服务功能的知识产权数据服务商。

我们的产品包含105个国家的1.26亿组数据,免费查、免费专利分析。

申请试用

分析报告

专利汇分析报告产品可以对行业情报数据进行梳理分析,涉及维度包括行业专利基本状况分析、地域分析、技术分析、发明人分析、申请人分析、专利权人分析、失效分析、核心专利分析、法律分析、研发重点分析、企业专利处境分析、技术处境分析、专利寿命分析、企业定位分析、引证分析等超过60个分析角度,系统通过AI智能系统对图表进行解读,只需1分钟,一键生成行业专利分析报告。

申请试用

QQ群二维码
意见反馈