油藏生产业务+机器学习代理优化算法

news2025/8/12 3:17:35

前前处理,把后台需要的参数都读出来。写进name.txt

在这里插入图片描述

生成新的sch文件,需要在data里追加新sch名字

在这里插入图片描述

没改变的井就不用重新卸载关键字里了。

重启动模型:制作出来是空的,得自己加别的东西

模型要准确,否则不好和历史模型对比,历史模型就是从优化开始的那个时间步全都不处理,按照原来的进行。

sch关键字随便加

跑到几月算几月。不改变就按照之前的井跑。软件加载到sch的时间步,未计算就是灰色的。
最好直接利用别人建立好的重启动模型去做,自己不要轻易做模型,一定保证模型不能出错,不能自己乱加,这样结果也好对比。

也可以不用重启动模型,直接使用命令重启动原来的模型。
不管是eclipse还是tnavigater他们的结果几乎是相同的。

1设置在solution关键字,RESTARTDATE可以设置日期,而不是时间步

  1. 要和已有的历史制度对比
    从十月优化,十月以后就都是按照原有进行,利用好别人给的重启动模型

3.重启后的sch时间步都要删掉,否则会重复跑出多出自己设置的时间步数。

RESTARTDATE
‘…/HM_FINAL/HM_FINAL’ 1* 01 SEP 2022
/
在这里插入图片描述
模型里追加新sch重启动文件,直接跑即可

输出格式转换,按照时间步输出

RPTRST
‘BASIC=3’ ‘FREQ=1’ /

F:\\tNavigator-con-Win-64\\tNavigator-con-Win-64\\tNavigator-con --use-gpu  -e -i -s -r -u –m --server-url=http://103.90.189.57:5805/tnav_cgi1/tnav_license_server.cgi D:\\moxing\\HM_FINAL_RESTART_CASE5_1\\HM_FINAL_RESTART_CASE5_1.data

  for %%i in (D:\Injection_production_optimization\item\HM_FINAL_RESTART_CASE5_1\RESULTS\*.S*) do ( 
F:\\tNavigator-con-Win-64\\tNavigator-con-Win-64\\tNavigator-con --use-gpu --server-url=http://103.90.189.57:5805/tnav_cgi1/tnav_license_server.cgi  --convert-ecl-bin-to-text %%i 
  ) 
  for %%i in (D:\Injection_production_optimization\item\HM_FINAL_RESTART_CASE5_1\RESULTS\*.X0*) do ( 
F:\\tNavigator-con-Win-64\\tNavigator-con-Win-64\\tNavigator-con --use-gpu --server-url=http://103.90.189.57:5805/tnav_cgi1/tnav_license_server.cgi  --convert-ecl-bin-to-text %%i 
 ) 

降维方法

每个时间步的变量进行统计,都加起来就是最后的维数。
1.按照井组优化。
2.转注前变量不优化,专注后才算维数。
在随机生成种子的时候就200次130维度。130=10*13口井。根据上下限和拉丁分布算法生成种子。也可以根据变异生成种子,局部效果好,二次规划。
在这里插入图片描述
在这里插入图片描述

注水井的注水量

只有注水井有
在这里插入图片描述

生产井的累积产量

生产井可以产水和产油
在这里插入图片描述
对比两个模型的累计产油量
在这里插入图片描述

含油饱和度图

是重要指标
在这里插入图片描述

所有模式都带入输出变量维度,并装入字典,相当于java map

装入字典map中
  if horimode != 'None':
            #
            initialmode= 'process_needed'
            
            sampdic['hw_new_well_name'] = hw_new_well_name
            sampdic['hw_new_group_name'] = hw_new_group_name
            sampdic['hw_new_well_r'] = hw_new_well_r
            #
            sampdic['hw_new_ninj'] = hw_new_ninj
            sampdic['hw_new_npro'] = hw_new_npro
            sampdic['hw_new_nwell'] = sampdic['hw_new_ninj'] + sampdic['hw_new_npro']
                
            #
            sampdic['hw_consmethod'] = hw_consmethod  # 约束处理方法
            sampdic['hw_layermode'] = hw_layermode
            #

Xrange, varlen = preRan_Len(Xsampmode, sampdic)
在这里插入图片描述

目标函数为npv

在这里插入图片描述

python二维数组
在这里插入图片描述

井位优化spec

加井,spec里面加。
在这里插入图片描述

1.水平井井位优化参数输入,水平井范围

和直井井位优化的前处理区别,水平井优化过程
一口井有多个井位,在射孔那里看
射孔那里水平井多了很多层

整体优化里选择水平井井位优化模式
在这里插入图片描述

    # ====================================================================
        if func == 'Joint':
            #
            vertmode = 'None'  # 直井模式选择
            horimode = 'cooropt-Lfixed-alpopt-4'  # 水平井模式选择
            transinjmode = 'None'  # 转注模式选择
            sealmode = 'None'  # 封堵模式选择
            prodmode = 'None'  # 注采模式选择
            extramode = 'None'  # 提液模式选择
            #

水平井范围设置
  if horimode != 'None':

                # 
                hw_new_well_name = ['New-1', 'New-2', 'New-3']
                hw_new_group_name = ['G1', 'G1', 'G1']
                hw_new_well_r = [0.178, 0.178, 0.178]
                hw_new_ninj = 1  # 新加水平井中注水井数
                hw_new_npro = 2  # 新加水平井中产油井数

                # ----与COMPDAT关键字写入时有关的接口(方便新加水平井井位与新加水平井的层位进行综合优化)----
                hw_layermode = 'all-open'

                # ----与WCONINJE和WCONPROD关键字写入时有关的接口(方便新加水平井井位与新加水平井的注采进行综合优化)----
                hw_valuemode = 'allwell-opt'
                # [1] allwell-same 所有井都是一样的注采量或者压力(此处输入为float数字,后面转化为list形式)
                # [2] allwell-diff 所有井可以是不一样的注采量或者压力(可以①分井指定,list形式;也可以是②优化获取分井数据,如果与注采优化耦合需要选择[2]的②模式)
                if hw_valuemode == 'allwell-same':
                    hw_injvalue = 0
                    hw_provalue = 900
                elif hw_valuemode == 'allwell-opt':
                    hw_value_low = [10, 10, 10]
                    hw_value_up = [1000, 1000, 1000]
                elif hw_valuemode == 'allwell-diff':
                    hw_injvalue = [100]
                    hw_provalue = [185, 200]
                
                
                # ----与井的选取范围有关的关键字----
                hw_regionmode = 'allwell-diff'
                # [1] allwell_same 所有井都是在同一个选定的区域内进行位置优化(矩形区域、需在活网格内)
                # [2] allwell_diff 每口井一个选的的区域进行位置优化,每口井的位置待选区域可以不同(矩形区域,需在活网格内)
                if hw_regionmode == 'allwell-same':
                    hw_new_wxlow = 10  # 新加水平井井眼的X坐标范围的下限
                    hw_new_wxup = 80  # 新加水平井井眼的X坐标范围的上限
                    hw_new_wylow = 10
                    hw_new_wyup = 80
                elif hw_regionmode == 'allwell-diff':
                    hw_new_wxlow = [10, 20, 30]
                    hw_new_wxup = [40, 50, 60]
                    hw_new_wylow = [35, 36, 37]
                    hw_new_wyup = [41, 42, 43]
                
                

2.封堵—层位优化参数

open shut关键字

#封堵优化用油藏模型参数 !!!!!!!!!!!!!
history_timestep = 5
well_name = ['PRO-1', 'PRO-2', 'PRO-3', 'PRO-4', 'PRO-5', 'PRO-6', 'PRO-7', 'PRO-8', 'PRO-9', 'INJ-01', 'INJ-02',
             'INJ-03', 'INJ-04']
      井类型 1油井0水井
initial_welltype = [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
timestep = 10
max_layer = 12
seal_timestep = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
init_status = np.ones((1, max_layer * len(well_name)))

//封堵井组分组
seal_list = ['PRO-1', 'PRO-2', 'PRO-3', 'PRO-4', 'PRO-5', 'PRO-6', 'PRO-7', 'PRO-8', 'PRO-9', 'INJ-01', 'INJ-02'
    , 'INJ-03', 'INJ-04']
seal_list_group = [['PRO-1', 'PRO-2'], ['PRO-3', 'PRO-4', 'PRO-5', 'PRO-6'], ['PRO-7', 'PRO-8', 'PRO-9'], ['INJ-01',
                                                                                                           'INJ-02',
                                                                                                           'INJ-03',
                                                                                                           'INJ-04']]
seal_list_group_num = len(seal_list_group)
maxnum_seal = 2
well_group_name = ['G1', 'G1', 'G1', 'G1', 'G1', 'G1', 'G1', 'G1', 'G1', 'G2', 'G2', 'G2', 'G2']
well_r = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
井位
well_location = [[1, 1], [13, 1], [25, 1], [1, 13], [13, 13], [25, 13], [1, 25], [13, 25], [25, 25], [7, 7], [19, 7],
                 [7, 19], [19, 19]]
well_hori_location = np.tile(np.array(well_location), (1, max_layer))
transinj_list = ['PRO-1', 'PRO-2', 'PRO-3', 'PRO-4', 'PRO-5', 'PRO-6', 'PRO-7', 'PRO-8', 'PRO-9']
transinj_list_group = [['PRO-1', 'PRO-2', 'PRO-3', 'PRO-4'], ['PRO-5', 'PRO-6', 'PRO-7', 'PRO-8', 'PRO-9']]
pro_opt_list = ['PRO-1', 'PRO-2', 'PRO-3', 'PRO-4', 'INJ-01']
history_pro = np.ones((len(well_name)))*350  ##跟well_name对应,np
low = np.zeros((len(well_name)))
up = np.ones((len(well_name))) * 700
up[9] = 1500
up[10] = 1500
up[11] = 1500
up[12] = 1500
prod_low = 0  ##跟well_name对应,np
prod_up = 700
inj_low = 0
inj_up = 1500
extra_low = 50
extra_up = 100
//分为五层
segment = [[1, 2], [3, 4], [5], [6, 7, 8, 9, 10], [11, 12]]
specific_seal = [[[0, 0, 1, 1, 0], [1, 1, 0, 1, 0], [0, 1, 0, 1, 0]],
                 [[0, 0, 1, 1, 0], [1, 1, 0, 1, 0], [0, 1, 0, 1, 0]],
                 [[0, 0, 1, 1, 0], [1, 1, 0, 1, 0], [0, 1, 0, 1, 0]],
                 [[0, 0, 1, 1, 0], [1, 1, 0, 1, 0], [0, 1, 0, 1, 0]],
                 [[0, 0, 1, 1, 0], [1, 1, 0, 1, 0], [0, 1, 0, 1, 0]],
                 [[0, 0, 1, 1, 0], [0, 1, 0, 1, 0]],
                 [[0, 0, 1, 1, 0], [1, 1, 0, 1, 0]]]
segment_num = 5
timestep_len = 180
maxnum_tran = 2
objmode = 'NPV'

井位*层数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
特殊封堵处理

if max_layer > 10:
    for well_num in range(len(specific_seal)):
        for i in range(len(specific_seal[well_num])):
            temp_scheme = np.ones((max_layer))
            count = 0
            for l in range(segment_num):
                for num in range(len(segment[l])):
                    temp_scheme[count] = specific_seal[well_num][i][l]
                    count = count + 1
            specific_seal[well_num][i] = temp_scheme

在这里插入图片描述

3.转注优化过程参数输入

water oil关键字,采油井转为注水井

参数
             if transinjmode == 'None':
                transinj_list = []
                if transinjmode == 'specific_max':
                    maxnum_tran = 3
                    转注+封堵一起操作
                elif transinjmode == 'specific_joint':
                    specific_seal = []  #list,指定的封堵方案,与transinj_list的顺序对应
                    maxnum_tran = 2
                    seal_timestep = np.ones((len(well_name), 1))
                    大于10段,分段来减少维数
                    if max_layer > 10:
                        segment = []  #list,分段
                        segment_num = []  #段数

4.注采优化过程参数输入

BHP控制和液体控制
在这里插入图片描述

本示例为两个井设置控制。1043井处于注入速率控制,速率等于253.1。没有底部压力限制,所以模拟器将设置注入速率为253.1。如果用户指定的注入速率如此之高,以至于必要的底部孔压力超过默认极限(6801patm),该井将自动切换到必和必拓控制。1054井也有注入速率控制,速率等于253.1。该井的井底孔压力限制为400;因此,如果计算压力超过400,该井将自动切换到必和必拓控制。
在这里插入图片描述

                
             if prodmode != 'None':
                low = []  # list,注采下界,与well_name顺序对应
                up = []  # list,注采上界,与well_name顺序对应
                if prodmode == 'specific':
                    history_pro = [] #历史注采量/压力,与well_name顺序对应
                    pro_opt_list = [] #进行注采优化的井
                

选择注采模式,层位和注采、转注等可以一起优化。
在这里插入图片描述
13口井10个时间步
在这里插入图片描述
生成变量
在这里插入图片描述

            Xrange, varlen = preRan_Len(Xsampmode, sampdic)
            sampdic['varlen'] = varlen

5.提液模式

注采上下限特殊处理,直接上限设置好就行

6. 直井井位优化参数输入

wellspec关键字,新加井就是井位优化

            if vertmode != 'None':
                # 
                vw_new_well_name = ['NEW-1', 'NEW-2', 'NEW-3']
                vw_new_group_name = ['GROUP1', 'GROUP1', 'GROUP1']
                vw_new_well_r = [0.178, 0.178, 0.178]
                vw_new_ninj = 1  # 新加直井中注水井数
                vw_new_npro = 2  # 新加直井中产油井数
                # ----与COMPDAT关键字写入时有关的接口(方便新加直井井位与新加直井的层位进行综合优化)----
                vw_layermode = 'all-open'  # 选择不同模式,对应ecl_joint中的xp处的生成传递
                # [1] all-open 默认新加井的所有层打开,从第1层到最后一层(max_layer)
                # ----与WCONINJE和WCONPROD关键字写入时有关的接口(方便新加直井井位与新加直井的注采进行综合优化)----
                vw_valuemode = 'allwell-same'
                
                # [1] allwell-same 所有井都是一样的注采量或者压力(此处输入为float数字,后面转化为list形式)
                # [2] allwell-diff 所有井可以是不一样的注采量或者压力(可以①分井指定,list形式;也可以是②优化获取分井数据,如果与注采优化耦合需要选择[2]的②模式)
                #
                if vw_valuemode == 'allwell-same':
                    vw_injvalue = 100
                    vw_provalue = 500
                elif vw_valuemode == 'allwell-diff':
                    vw_injvalue = [100, 120, 300]
                    vw_provalue = [125, 185, 200]
                # 
                vw_inj_controlmode = 'RATE'    # 新加的注水直井的控制模式选择
                # [1] RATE 流量控制
                # [2] BHP 井底流压控制 
                vw_pro_controlmode = 'LRAT'    # 新加的采油直井的控制模式选择
                # [1] LRAT 液量控制
                # [2] BHP 井底流压控制 

指定了一个矩形范围内优化
                if vertmode == 'specific_region':
                    # specific_region 指定优化区域,单独优化加井的井位。这种模式下直井井眼的选择范围是预先选定的一个规则矩形(需要在活网格内)
                    vw_new_wxlow = 1    # 新加直井的X坐标范围的下限
                    vw_new_wxup = 50   # 新加直井的X坐标范围的上限
                    vw_new_wylow = 20
                    vw_new_wyup = 100
新加水平井
                #
                hw_consmethod = 'notcons-del-relhsget' # 约束处理方法
                # [1] notcons-del-relhsget 不满足约束的样本删除,并利用拉丁超立方生成
                
                horimode = 'cooropt-Lfixed-alpopt-4'
                if horimode == 'cooropt-Lfixed-alpopt-4':
                    #
                    hw_new_wxlow = 25    # 新加水平井井眼的X坐标范围的下限
                    hw_new_wxup = 55   # 新加水平井井眼的X坐标范围的上限
                    hw_new_wylow = 35
                    hw_new_wyup = 65
                    #
                    hw_new_wdim = 3  # 单口井的优化维数
                    hw_new_wL = 500 / 100  # 水平段长度
                    hw_new_walplow = 0.51  # 1
                    hw_new_walpup = 4.49  # 4
                    #
                elif horimode == 'cooropt-Lopt-alpopt-4':
                    #
                    hw_new_wxlow = 25    # 新加水平井井眼的X坐标范围的下限
                    hw_new_wxup = 55   # 新加水平井井眼的X坐标范围的上限
                    hw_new_wylow = 35
                    hw_new_wyup = 65
                    hw_new_wdim = 4  # 单口井的优化维数
                    hw_new_wLlow = 251 / 100  # 3
                    hw_new_wLup = 549 / 100  # 5
                    hw_new_walplow = 0.51  # 1
                    hw_new_walpup = 4.49  # 4

python 报错

在这里插入图片描述

策略优化模式选择:优化主要分类6类

除了公共参数输入,还有各种模式的自己的参数。井的参数都随着时间步变化。

        # ====================================================================
        if func == 'Joint':
             
             # 
             vertmode = 'None'  # 直井井位优化
             horimode = 'cooropt-Lfixed-alpopt-4'  # 水平井井位优化
             transinjmode = 'None'  # 转注模式选择
             sealmode = 'None'  # 层位封堵模式选择
             prodmode = 'None'  # 注采模式选择
             extramode = 'None'  # 提液模式选择
             #
             
             if vertmode != 'None':
                
                # 
              

在这里插入图片描述
每种模式的变量数,注采是一起的
请添加图片描述

油藏参数处理:面向井对象,井单位(井位(xy上下限)、井类型(01就是上下限)、注采量(上下限)、射孔(井数总层数01上下限))+分优化模式(针对不同的井组)+是否随时间步变(井数时间步)

优化必有上下界,一个上下界确定一个变量

如果不涉及优化就给定一个固定值特殊处理,或者不操作。
一般不根据时间步优化,维数太大,调控一次即可。specific_time和这是specific的差别

目标函数,公共参数和各种模式的参数,算法
map
所有要优化的变量都是输入参数
timestep_history要历史注采量干嘛,水平井的模式,
1.先选目标函数
分为模拟和函数,模拟里面有水平井,联合优化,tnavigater优化
在这里插入图片描述

2.选输入公共参数和各种模式的参数赋值
直井综合优化里面有油藏模型基本信息和很多模式,每个模式的输入参数不同

timestep_history = 0
well_name = [‘PRO-1’, ‘PRO-2’, ‘PRO-3’, ‘PRO-4’, ‘PRO-5’, ‘PRO-6’, ‘PRO-7’, ‘PRO-8’, ‘PRO-9’, ‘INJ-1’, ‘INJ-2’,
‘INJ-3’, ‘INJ-4’]
1是油井
initial_welltype = [1, 1, 1, 1, 1, 1, 1, 1, 1,0, 0, 0, 0]
max_layer = 1
init_status = np.ones((1, max_layer * len(well_name)))
well_group_name = [‘G1’, ‘G1’, ‘G1’, ‘G1’, ‘G1’, ‘G1’, ‘G1’, ‘G1’, ‘G1’, ‘G1’, ‘G1’, ‘G1’, ‘G1’]
well_r = [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.5, 0.5, 0.5, 0.5]
well_location = [[1, 1], [1, 51], [1, 101], [51, 1], [51, 51], [51, 101], [101, 1], [101, 51], [101, 101],
[77, 81], [74, 18],
[23, 94], [71, 5]]
up = np.ones((len(well_name), 1)) * 1800
low = np.ones((len(well_name), 1)) * 10
up[9] = 4050
up[10] = 4050
up[11] = 4050
up[12] = 4050

    # ----优化的信息----时间步变量
    timestep = 10
    timestep_len = 180
    objmode = 'NPV'

    # ----路径设置有关----
    casefolder_name = 'HORI'
    rundata_name = 'HORI'

字典套字典Xrange

solvepara[‘realfunc’] = func # 适应度函数的具体选择 ---- 字符串形式
solvepara[‘Xrange’] = Xrange # 样本的上下界范围 ---- np二维数组,size为(2,ndim)
solvepara[‘sampdic’] = sampdic

综合优化和tnavigater优化的直井输入一样。
在这里插入图片描述

3.选择算法

优化变量处理 1.确定上下界2.变量归一化0-1之间的随机值 2.(上界-下界)*归一随机值

明确要优化的变量是谁
拉丁分布前处理

    #上下限确定,维数长度确定
    Xrange, varlen = preRan_Len(Xsampmode, sampdic)
    sampdic['varlen'] = varlen
    根据时间步变化和不根据时间步变化
elif prodmode == 'specific':
    pro_opt_list = sampdic['pro_opt_list']
    len_prod = len(pro_opt_list) * timestep
    ran_prod = np.vstack([np.zeros((1, len_prod)), np.ones((1, len_prod))])
elif prodmode == 'specific_time':
    specific_time = sampdic['specific_time']
    len_prod = len(specific_time)
    ran_prod = np.vstack([np.zeros((1, len_prod)), np.ones((1, len_prod))])

归一化

在这里插入图片描述
乘以上界减去下界

在这里插入图片描述

预计算:计算各个模式加起来的总共维度、上下限

在这里插入图片描述
统计各个模式加起来的总共维度

    if prodmode == 'None':
        len_prod = 0
        ran_prod = np.zeros((2, len_prod))
    elif prodmode == 'wgiven-optTgiven':
        len_prod = nwell * timestep
        ran_prod = np.vstack([np.zeros((1, len_prod)), np.ones((1, len_prod))])
    elif prodmode == 'specific':
        pro_opt_list = sampdic['pro_opt_list']
        len_prod = len(pro_opt_list) * timestep
        ran_prod = np.vstack([np.zeros((1, len_prod)), np.ones((1, len_prod))])

        # ----提液相关----
    #!!!!!!!!!!!!!!!这一部分还没写
    
    #
    varlen = {'len_vert' : len_vert,
              'len_hori' : len_hori,
              'len_transinj' : len_transinj,
              'len_seal' : len_seal,
              'len_prod' : len_prod
              # 'len_extra' : len_extra
              }
    #
    Xrange = np.hstack([ran_vert, ran_hori, ran_transinj, ran_seal, ran_prod])
    # Xrange = np.hstack([ran_vert, ran_hori, ran_transinj, ran_seal, ran_prod, ran_extra])
    
    return Xrange, varlen
 #生成随机值0-1
 
        Xrange, varlen = preRan_Len(Xsampmode, sampdic)
        sampdic['varlen'] = varlen

        # ----拉丁超立方初始种群模式initmode产生方式---- #!!!!!
        if initialmode == 'process_needless':
            initmode = 'Basic'
        elif initialmode == 'process_needed':
            # 如果lhs生成的初始解需要进行进一步处理(删除、重新生成等),这个时候需要根据不同的特定模式执行不同的处理操作
            if horimode != 'None': 
                initmode = 'Joint-Hori'
            # elif #!!! 【留的接口】
            # 如果有其他模式(比如直井不规则的四个点判断井位区域、实际油藏活死网格不规则边界判断等),在这个接口后面加入elif,定义新的initmode,并在latin函数中增加与新定义的initmode对应的新模块

生成随机值
def wellprod_proce(X, well_type, optional):
    mode = optional['Xsampmode']
    sampdic = optional['sampdic']
    xp = copy.deepcopy(X)
    if mode['prodmode'] == 'wgiven-optTgiven':
        xp = xp.reshape(-1, len(sampdic['well_name']))
        for time in range(sampdic['timestep']):
            for well in range(len(sampdic['well_name'])):
                xp[time, well] = sampdic['low'][well] + xp[time, well] * (sampdic['up'][well] - sampdic['low'][well])
    elif mode['prodmode'] == 'specific':
        history_pro = sampdic['history_pro']
        pro_opt_list = sampdic['pro_opt_list']
        xp = xp.reshape(-1, len(sampdic['pro_opt_list']))
        temp = np.ones((sampdic['timestep'], len(sampdic['well_name'])))
        for time in range(sampdic['timestep']):
            for well in range(len(sampdic['well_name'])):
                for opt_well in range(len(pro_opt_list)):
                    if pro_opt_list[opt_well] == sampdic['well_name'][well]:
                        temp[time, well] = xp[time, opt_well]
        xp = temp
        for time in range(sampdic['timestep']):
            for well in range(len(sampdic['well_name'])):
                flag = 0
                for opt_well in range(len(pro_opt_list)):
                    if pro_opt_list[opt_well] == sampdic['well_name'][well]:
                        flag = 1
                        break
                if flag == 1:
                    xp[time, well] = sampdic['low'][well] + xp[time, well] * (sampdic['up'][well] - sampdic['low'][well])
                else:
                    xp[time, well] = history_pro[well]

    xp = xp.reshape(1, -1)
    return xp

设置初始位置和优化位置,不同

![
在这里插入图片描述](https://img-blog.csdnimg.cn/7977d85e1b744a2db1afcb47b9518394.png)

选择算法,并行,跑单次

在这里插入图片描述

并行代码,i为并行的次序
def tnav_joint(X, optional, i, index=''):
    X = latin(Xrange, npop, initmode, solvepara)
    #
    Y = Parallel(n_jobs=1)(delayed(ecl_joint_parallel)(X, solvepara, i, str(i % (2 * cpu_count()))) for i in range(npop))
    Y = np.array(Y).reshape(-1, 1)
调用ecl_joint_parallel跑单次模拟

单次模拟:前处理 处理 后处理

循环写入井控关键字
复制文件夹,制作xp,写入文件夹。跑data、读结果、算npv。

  para = optional['sampdic']
    timestep = para['timestep']
    if os.path.exists(simupath):  # 判断括号里的文件夹路径或文件路径是否存在,存在返回Ture,不存在返回False
        rmtree(simupath)  # 递归删除一个目录以及目录内的所有内容
    copytree(initpath,simupath)  # shutil.copytree( olddir, newdir, True/Flase) #把olddir拷贝一份newdir,如果第3个参数是True,则复制目录时将保持文件夹下的符号连接,如果第3个参数是False,则将在复制的目录下生成物理副本来替代符号连接
    #
    xp = {}
    #
    if vertmode != 'None':
        xs_vert = copy.deepcopy(XS['Xvert'][i, :])
        wvert = wellvert_proce(xs_vert, optional)
        xp['WX_vert'] = wvert['wx_vert']
        xp['WY_vert'] = wvert['wy_vert']
        xp['Wstatus_vert'] = wvert['wstatus_vert']
        xp['Wpro_vert'] = wvert['wpro_vert']
        xp['Winj_vert'] = wvert['winj_vert']
分时间步写
    writeSCH(simupath, optional)
井位优化
    WELSPECS(simupath, xp, optional)
层位优化(封堵)
    COMPDAT(simupath, xp, optional)
转注和注采优化、提液模式
    WCONINJE(simupath, xp, optional)
    WCONPROD(simupath, xp, optional)

根据时间步写入每个文件sch文件

判断开始时间步是否写入,判断井类型写油水井。
每个时间步用多个循环写。
在这里插入图片描述

6直井井位优化模式,优化xy变量,

每个井都有个x和y位置,可随着时间步变化。

前处理,数据格式的解释,二维数组的处理(三维数组)
井类型数组是13*10,13口井和10个时间步,每个时间步的值对应好了

在这里插入图片描述

循环写入井定义文件
这是一个时间步的,井类型根据时间步变化,其他不变
只写include文件,时间步在sch文件里面写了在这里插入图片描述

2.封堵射孔(层位优化模式原理)优化well_status变量,每个井的每一层都有个状态,随着时间步变化,也可以不变化。

前处理三重循环:时间步、井名、层数
优化well_status变量,每个井的每一层都有个状态,随着时间步变化,也可以不变化。
首先,在重启动sch中,手动把data里面写进去新得sch文件,手动改summary

层位优化模式分为两种,按照时间步优化和不按照时间步优化。
在这56个方案里面随机选择层位方案。0-56方案就是上下限。有了上下限就可以生成具体的值了(单次维数*种群数)
在这里插入图片描述

在这里插入图片描述
种群*井数
在这里插入图片描述
井状态
在这里插入图片描述
well_status井状态随着时间步变化,其他的不变
well_status = xp[‘Wstatus’] Wstatus就是选中的方案
没有层位优化则默认全打开

 

def COMPDAT(simupath, xp, optional):
    '''
    :param well_hor_location: numpy,
                          dim:井数*(最大层数*2)
                          第一行为:[第一个井在第一层的横坐标,第一个井在第一层的纵坐标,第一个井在第二层的横坐标,第一个井在第二层的纵坐标,....]
    :param simulatuon_folder: 文件路径
    :param timestep: int,
                    总时间步,一个数
    :param well_status: numpy,
                        所有时间步内所有井的状态;dim:总时间步*(总井数*总层数),
                        要求为numpy数组!
    :param well_r: numpy,
                   所有井的井眼直径,油井在前水井在后;dim:1*总井数
    :param well_name: list,
                      所有井的井名,与well_status和well_r相对应
    :return: 重新编写Compdat_ctrl+timestep .dat 文件(文件名里的timestep从1开始)
    注:所有有关井的变量井的顺序都与well_name相对应
    '''
    well_status = xp['Wstatus']
    sampdic = optional['sampdic']
    total_well_num = len(sampdic['well_name'])

    for time in range(sampdic['timestep']):
        wellcon_file = open(simupath + '/Compdat' + str(time + 1) + '.dat', 'w')
        contents = ['COMPDAT\n']
        for well in range(total_well_num):
            for layer in range(sampdic['max_layer']):
                if well_status[time, well * sampdic['max_layer'] + layer] == 1:
                    status = '\'OPEN\''
                else:
                    status = '\'SHUT\''
                contents.append(
                    sampdic['well_name'][well] + '   ' + str(sampdic['well_hori_location'][well, layer * 2]) + '  '
                    + str(sampdic['well_hori_location'][well, layer * 2 + 1])
                    + '  ' + str(layer + 1) + '  ' + str(layer + 1) + '  ' +
                    status + '  2*  ' + str(sampdic['well_r'][well]) + '  3*  \'Z\' 1*  / \n')

        contents.append('/\n')
        wellcon_file.writelines(contents)
        wellcon_file.close()

在这里插入图片描述

井定义和注采啥都不写,按照原来的跑
只写个WCONINJE

    if prodmode == 'None' and horimode == 'None' and vertmode == 'None':
        for time in range(sampdic['timestep']):
            iline = ['WCONINJE \n']
            iline.append('/ \n')
            # ----先获取这个时间步要写入的WCONPROD的地址----
            wconinje_path = os.path.join(simupath, 'Wconinje' + str(time + 1) + '.dat')
            #
            with open(wconinje_path, 'a+') as f:  # !!!!!!这里a+还是w+模式的选择
                f.writelines(iline)

在这里插入图片描述
而射孔是按照大层分段层都写一遍
在这里插入图片描述
先根据层上下限随机生成数据,预处理得到01射孔矩阵

    if sealmode != 'None':
        xs_seal = copy.deepcopy(XS['Xseal'][i, :])
        xp['Wstatus'] = wellseal_proce(xs_seal, xs_transinj, optional)  # 结合wellstatus_generate和范围

层状态wstaue表示,1是开open,10156,10是时间步,156=1312,一一对应了,这里可以写死。
init_status = np.ones((1, max_layer * len(well_name)))在这里插入图片描述
写入射孔文件中
在这里插入图片描述
特殊模式:不优化的写死的,27口井需要特殊处理,分别对应,每口井的关闭层和打开层。以井为研究对象。一口井就是一个对象,它的属性有处理时间步、定义、射孔、注采、井位等处理。

在这里插入图片描述

1水平井井位优化,xy,长度、角度,四个变量*井数的优化

水平井参数

在这里插入图片描述

转注(优化模式)优化注采变量,每个井都有井类型,随着时间步变化

4采油(注采优化模式)优化注采变量,每个井都有个主材量,随着时间步变化

前处理井两层循环:时间步、井名

注采量Wprod维数是一维数组130=13口井*10个时间步,一一对应了。关键是上下界。

# ----注采相关----
if prodmode == 'None':
    len_prod = 0
    ran_prod = np.zeros((2, len_prod))
elif prodmode == 'wgiven-optTgiven':
    len_prod = nwell * timestep
    ran_prod = np.vstack([np.zeros((1, len_prod)), np.ones((1, len_prod))])

在这里插入图片描述

在这里插入图片描述

把各个模式的变量合在一起,先确定上下界。
    varlen = {'len_vert' : len_vert,
              'len_hori' : len_hori,
              'len_transinj' : len_transinj,
              'len_seal' : len_seal,
              'len_prod' : len_prod
              # 'len_extra' : len_extra
              }
    #
    Xrange = np.hstack([ran_vert, ran_hori, ran_transinj, ran_seal, ran_prod])
    # Xrange = np.hstack([ran_vert, ran_hori, ran_transinj, ran_seal, ran_prod, ran_extra])
    
    return Xrange, varlen
根据上下界生产随机值wellprod_proce
def wellprod_proce(X, well_type, optional):
    mode = optional['Xsampmode']
    sampdic = optional['sampdic']
    xp = copy.deepcopy(X)
    if mode['prodmode'] == 'wgiven-optTgiven':
        xp = xp.reshape(-1, len(sampdic['well_name']))
        for time in range(sampdic['timestep']):
            for well in range(len(sampdic['well_name'])):
                xp[time, well] = sampdic['low'][well] + xp[time, well] * (sampdic['up'][well] - sampdic['low'][well])
只对特定井名进行优化
    elif mode['prodmode'] == 'specific':
        history_pro = sampdic['history_pro']
        pro_opt_list = sampdic['pro_opt_list']
        xp = xp.reshape(-1, len(sampdic['pro_opt_list']))
        temp = np.ones((sampdic['timestep'], len(sampdic['well_name'])))
        for time in range(sampdic['timestep']):
            for well in range(len(sampdic['well_name'])):
                for opt_well in range(len(pro_opt_list)):
                    if pro_opt_list[opt_well] == sampdic['well_name'][well]:
                        temp[time, well] = xp[time, opt_well]
        xp = temp
        for time in range(sampdic['timestep']):
            for well in range(len(sampdic['well_name'])):
                flag = 0
                for opt_well in range(len(pro_opt_list)):
                    if pro_opt_list[opt_well] == sampdic['well_name'][well]:
                        flag = 1
                        break
                if flag == 1:
                    xp[time, well] = sampdic['low'][well] + xp[time, well] * (sampdic['up'][well] - sampdic['low'][well])
                else:
                    xp[time, well] = history_pro[well]

返回随机值=10时间步*井数
请添加图片描述

如果井类型是1油井
def WCONPROD(simupath, xp, optional):
    well_type = xp['Wtype']
    pro = copy.deepcopy(xp['Wprod'])
    sampdic = optional['sampdic']
    total_well_num = len(sampdic['well_name'])
    pro = pro.reshape(-1, len(sampdic['well_name']))
    for time in range(sampdic['timestep']):
        f = open(simupath + '/Wconprod' + str(time + 1) + '.dat', 'w')
        f.write('WCONPROD \n')
        for well in range(total_well_num):
        如果井类型是1油井
            if well_type[well][time] == 1:
                f.write('\'' + sampdic['well_name'][well] + '\'' + "    OPEN   LRAT    3*    " + str(
                    pro[time, well]) + '/\n')
        f.write('/\n')
        f.close()
如果井类型是0水井
def WCONINJE(simupath, xp, optional):
    sampdic = optional['sampdic']
    well_type = xp['Wtype']
    pro = copy.deepcopy(xp['Wprod'])
    total_well_num = len(sampdic['well_name'])
    pro = pro.reshape(-1, len(sampdic['well_name']))
    for time in range(sampdic['timestep']):
        f = open(simupath + '/Wconinj' + str(time + 1) + '.dat', 'w')
        f.write('WCONINJE \n')
        for well in range(total_well_num):
        如果井类型是0水井
            if well_type[well][time] == 0:
                f.write('\'' + sampdic['well_name'][well] + '\'' + "     WATER    OPEN    RATE    " + str(
                    pro[time, well]) + '/\n')
        f.write('/\n')
        f.close()

数值模拟,换模拟器,要有模拟器位置。模拟器限制很多

tnavigater不一样就把他定死summary顺序。
最新破解版关键字必须有
MULTOUT它
RPTRST
‘BASIC=3’ ‘FREQ=1’ /


SUMMARY   =============================================================
EXCEL
FWPR
FOPR
FWCT
FWIR
FOPT
FWPT
FWIT
FPR
/
    # ----进行数值模拟----
    DATA_path = os.path.join(simupath, rundata_name + '.DATA')
    command = 'eclrun eclipse' + ' ' + DATA_path
    os.system(command)
    print('数值评估', i + 1, '次')

    # ----读取结果----
    output, outnum = read_sumkeywd(DATA_path)  # 读取DATA文件SUMMARY部分关键字
    SCH_path = fullfile(simupath, 'schedule.dat')
    # steps = get_schsteps(SCH_path)    # 查找schedule文件中的时间步数
    '''
    steps = para['timestep'] + para['history_timestep']
    '''
    #
    # timestep_n = 30
    # timesteplen = sampdic['timestep_len']
    # tn = int(timesteplen/timestep_n)
    # steps = para['timestep']*tn + para['history_timestep']
    #
    steps = para['timestep'] + para['timestep_history']
    A_path = find_A(simupath, rundata_name, steps)  # 确定要读取的结果的文件名称(A文件)
    # 在确定的A文件中读取出相关结果(有两种思路,一种是和DATA文件读出类似,先全部读出来再查找和抽取,一种是利用指针,利用A文件特点,需要的结果在最后几行,直接指针到最后几行)
    with open(A_path, 'rb') as f:  # 要用seek()方法需要用二进制的读,所以用’rb‘而不是’r‘
        outnum = outnum + 2  # 在A文件输出的关键字数目加2(前面还有天和年两个关键字)
        # 计算需要将指针向前移动的字符距离
        movecha = (outnum // 4) * (17 * 4 + 2) + (
                    outnum % 4) * 17 + 2  # //是取整符号,%是取余符号,计算的数目是根据A文件中每个SUMMARY关键字输出结果所占的字符数
        f.seek(-movecha, 2)  # seek(offset, whence),offset是文件指针偏移量,whence为0是文件开头,1是文件当前位置,2是文件末尾
        outext = f.read().decode().split()  # 二进制形式read()出来需要用decode()进行解码,并用split()进行分开
        del outext[0:2]  # 删去前两个元素(不是SUMMARY中规定的关键字结果)
        outnum = outnum - 2  # 删去前两个元素的数量
        for j in range(outnum):
            order = output[j] + ' = ' + str(float(outext[j]))  # 把结果用order命令逐个写入,并用exec运行
            exec(order, globals())  # exec()函数的作用域问题,在自己定义的子函数里面使用exec()去define一个变量,后续再使用时会报错,需要加入globals()
    #
    objmode = para['objmode']

    if objmode == 'FOPT':
        SimRes[i] = FOPT

    elif objmode == 'NPV':
        #
        oil_price = 100  # 油价(默认单位为美元/桶)
        cost_prowat = 42  # 处理水成本(默认单位为美元/桶)
        cost_injwat = 2  # 注水成本(默认单位为美元/桶)
        #
        units = 'METRIC'  # Eclipse模型的单位进制
        if units == 'FIELD':
            npv = FOPT * oil_price - FWPT * cost_prowat - FWIT * cost_injwat

三种调用方式

    conexe = "F:\\tNavigator-con-Win-64\\tNavigator-con-Win-64\\tNavigator-con.exe"
    config = "F:\\tNavigator-con-Win-64\\tNavigator-con-Win-64\\license.conf"

    conexe_sever = "C:\\Users\\Administrator\\AppData\\Local\\RFD\\tNavigator\\22.3\\tNavigator-con"
    config_sever = 'http://103.90.189.57:5805/tnav_cgi1/tnav_license_server.cgi'

读取结果、历史时间步是为了读取到当前最后一个时间步

历史时间步是old里的时间步
在这里插入图片描述

在这里插入图片描述

bug

mpi并行环境安装

算法

自适应代理

针对维度和问题鲁棒性的
多代理的组合混合,但是会选择

并行变异

两种思路可以结合:
1.利用DE和代理模型并行产生多种x结果,再从x中选择几个进行并行跑。
2.并行多代理(多代理不组合,各跑各的),同时采用多种代理模型,全局和局部、截断学习,等等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/33620.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【吴恩达机器学习笔记】二、单变量线性回归

✍个人博客:https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 📣专栏定位:为学习吴恩达机器学习视频的同学提供的随堂笔记。 📚专栏简介:在这个专栏,我将整理吴恩达机器学习视频的所有内容的笔记&…

OpenGL原理与实践——核心模式(三):Texture-纹理系统理论与应用

目录 初识——纹理系统是什么?怎么用? Texture —— UV坐标系统 Texture Wrapping:UV超过了[0,1]怎么办? Texture Filter:UV经过计算得到的是浮点数怎么办? 在OpenGL中该怎么做呢? Texture Unit——…

列表和标签企业报告版的完整报告解决方案

列表和标签企业报告版的完整报告解决方案 无缝集成到所有主要开发环境和编程语言:Visual Studio、.NET/。NET核心(C#、VB.NET)、C/C、Delphi/VCL、Java、Progress、DataFlex、dBASE PLUS、Xbase等。 通过现代数据绑定灵活连接到任何数据源:List&Labe…

自适应点云配准(RANSAC、ICP)

点云配准 实验目标 任务一:将两个形状、大小相同的点云进行配准,进而估计两个点云之间的位姿。 任务二:将一些列深度图反向投影得到点云,经过配准后,得到每个深度图之间的位姿变换,并将相应的点云融合到一…

【云原生】Docker镜像的创建,Dockerfile

内容预知 1.Dokcer镜像的创建 1.1 基于现有镜像创建 1.2 基于本地模板创建 1.3 基于Dockerfile 创建 联合文件系统(UnionFS ) 镜像加载原理 容器中操作系统容量小的原因 Docker镜像结构的分层 Dockefile的引入 2. Dockerfile 操作命令的指令 2.1 FROM 镜像 2.2 MA…

股票接口实时交易数据怎么查询?

股票数据接口作为软件应用而言,很多资源和数据是由自身提供的,像其他一些功能还是需要调用第三方提供的服务,这其中就涉及到股票数据接口api的调用功能,通过api来获取实时交易数据查询更方便,因此,如果交易…

【学习笔记17】JavaScript作用域

笔记首发 一、作用域 😴我们学变量,不是在任何地方都可以使用😴变量有一个使用区间, 这个可以使用的区间就叫做作用域 1、全局作用域 😫 script标签内部声明的变量,就是全局作用域的变量😏在全局作用域声明…

计算机网络的定义和分类

计算机网络早期定义:自治互联的计算机集合 计算机网络系统的基本组成为:通信子网资源子网 计算机网络分类: 公用网通常是由电信公司出资建造的大型网络。 专用网通常是由某个部门为满足本单位特殊业务的需要建造的网络&#xff…

基于springboot+jpa+camunda实现简单的请假审批流程

整个camunda的绘图、具体使用,参照上一篇文章Camunda工作流引擎简记。 源码地址,相关技术储备如下 springboot–v2.5.4jpa–v2.5.4postgresql–v11camunda–v7.16.0 整个过程不需要建表,这就是JPA面向对象编程的好处,这也是我认…

33 - C++中的字符串类

---- 整理自狄泰软件唐佐林老师课程 1. 历史遗留问题 C语言 不支持真正意义上的字符串 C语言用 字符数组 和 一组函数 实现字符串操作 C语言 不支持自定义类型,因此无法获得字符串类型 解决方案 从C到C的进化过程 引入了 自定义类型在C中可以通过类完成字符串类型…

iOS上架app store详细教材

1、安装iOS上架辅助软件Appuploader 2、申请iOS发布证书(p12) 3、申请iOS发布描述文件(mobileprovision) 4、打包ipa 5、上传ipa到iTunes Conn 1、安装iOS上架辅助软件Appuploader2、申请iOS发布证书(p12)…

ImmunoChemistry艾美捷牛膜联蛋白V-荧光素凋亡检测试剂盒方案

ImmunoChemistry艾美捷牛膜联蛋白V-荧光素细胞凋亡检测试剂盒提供了一种经验证的方法,可使用重组荧光素结合的牛膜连蛋白V和碘化丙啶(PI)快速、轻松地区分两个死亡细胞群和活细胞群。这些细胞将被膜联蛋白V-荧光素(绿色荧光&#…

docker容器持久化

第六章容器持久化 容器数据卷 什么是容器数据卷? 容器之间可以有一个数据共享技术!docker容器中产生的数据,同步到本地! 这就是卷技术!目录的挂载,将我们容器内的目录,挂在到linux上面&#x…

线性时间选择(Top K)问题(Java)

线性时间选择(Top K)问题(Java) 文章目录线性时间选择(Top K)问题(Java)1、前置介绍2、分治法求解3、代码实现4、复杂度分析5、扩展6、参考资料1、前置介绍 定义 选择问题&#xff0…

docker可视化与制作和提交自己的镜像

第四章docker可视化 portainer docker的图形化管理工具!提供一个后台面板供我们操作! docker run -d -p 8080:9000 \--restartalways -v /var/run/docker.sock:/var/run/docker.sock --privilegedtrue portainer/portainer 访问测试:外网…

Python_数据容器_元组tuple

一、元组tuple定义 为什么需要元组 列表是可以修改的,如果想要传递的信息不被篡改,列表就不适合了 元组和列表一样,都是可以封装多个不同类型的元素在内 最大的不同点在于: 元祖一旦定义完成,就不可修改 所以&am…

SpringBoot中使用JDBC

JDBC基础使用&#xff1a; JDBC基础使用_做测试的喵酱的博客-CSDN博客 一、SpringBoot使用JDBC&#xff0c;依赖 依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId&…

linux zookeeper kafka_2.12-2.2.0 集群

文章目录一、zookeeper服务搭建1. 下载2. 解压3. 创建目录4. 调整配置5. 配置myid6. 开放防火墙7.启动验证zk二、kafka集群搭建2.1. 下载软件2.2. 解压2.3. 配置2.5. 启动kafka三、测试验证3.1. 创建一个主题3.2. 发送消息3.3. 消费消息预先准备&#xff1a;上传软件至服务器19…

使用Avalonia跨Linux平台

Avalonia&#xff0c;读&#xff1a;阿瓦隆尼亚 这里的跨平台指的是&#xff0c;使用c#语言开发跨Linux平台。c#在Windows桌面开发中很强&#xff0c;但是在Linux桌面中&#xff0c;不能跨平台&#xff0c;Qt可以在Linux中跨平台&#xff0c;但是那是另外一门语言了。Avalonia…

计算机组成原理4小时速成:计算机运算方法,无符号数和有符号数,定点数和浮点数,移位运算,加减运算,乘法运算,原码,反码,补码

计算机组成原理4小时速成&#xff1a;计算机运算方法&#xff0c;无符号数和有符号数&#xff0c;定点数和浮点数&#xff0c;移位运算&#xff0c;加减运算&#xff0c;乘法运算&#xff0c;原码&#xff0c;反码&#xff0c;补码 2022找工作是学历、能力和运气的超强结合体&…