def __init__(self): # create mesh object self.mesh = conn_mesh() # reservoir is supposed to be discretized by external tool # read connections and transmissibilities from file self.mesh.init('conn2p_2D.txt') self.nb = self.mesh.n_blocks self.nx = 60 self.ny = 40 self.nz = 1 # Create numpy arrays wrapped around mesh data (no copying) self.volume = np.array(self.mesh.volume, copy=False) self.porosity = np.array(self.mesh.poro, copy=False) self.depth = np.array(self.mesh.depth, copy=False) self.hcap = np.array(self.mesh.heat_capacity, copy=False) self.cond = np.array(self.mesh.rock_cond, copy=False) # Set uniform value for all elements of volume array # 30m x 30m x 2.5m = 2250 m3 self.volume.fill(2250) self.volume[0:self.nb:60] = 8e9 self.volume[59:self.nb:60] = 8e9 # Load heterogeneous porosity values from file, # make the resulting ndarray flat, # and assign it`s values to the existing array ([:] is very important!) self.porosity[:] = np.genfromtxt('poro_2D.txt', skip_header=True, skip_footer=True).flatten() # Constant definitions self.depth.fill(2500) self.cond.fill(200) self.hcap.fill(2200) self.wells = []
def __init__(self, timer, nx: int, ny: int, nz: int, dx, dy, dz, permx, permy, permz, poro, depth, actnum=1, global_to_local=0, op_num=0, coord=0, zcorn=0, is_cpg=False): """ Class constructor method :param timer: timer object to measure discretization time :param nx: number of reservoir blocks in the x-direction :param ny: number of reservoir blocks in the y-direction :param nz: number of reservoir blocks in the z-direction :param dx: size of the reservoir blocks in the x-direction (scalar or vector form) [m] :param dy: size of the reservoir blocks in the y-direction (scalar or vector form) [m] :param dz: size of the reservoir blocks in the z-direction (scalar or vector form) [m] :param permx: permeability of the reservoir blocks in the x-direction (scalar or vector form) [mD] :param permy: permeability of the reservoir blocks in the y-direction (scalar or vector form) [mD] :param permz: permeability of the reservoir blocks in the z-direction (scalar or vector form) [mD] :param poro: porosity of the reservoir blocks :param actnum: attribute of activity of the reservoir blocks (all are active by default) :param global_to_local: one can define arbitrary indexing (mapping from global to local) for local arrays. Default indexing is by X (fastest),then Y, and finally Z (slowest) :param op_num: index of required operator set of the reservoir blocks (the first by default). Use to introduce PVTNUM, SCALNUM, etc. :param coord: COORD keyword values for more accurate geometry during VTK export (no values by default) :param zcron: ZCORN keyword values for more accurate geometry during VTK export (no values by default) """ self.timer = timer self.nx = nx self.ny = ny self.nz = nz self.coord = coord self.zcorn = zcorn self.permx = permx self.permy = permy self.permz = permz self.n = nx * ny * nz self.global_data = { 'dx': dx, 'dy': dy, 'dz': dz, 'permx': permx, 'permy': permy, 'permz': permz, 'poro': poro, 'depth': depth, 'actnum': actnum, 'op_num': op_num, } self.discretizer = StructDiscretizer(nx=nx, ny=ny, nz=nz, dx=dx, dy=dy, dz=dz, permx=permx, permy=permy, permz=permz, global_to_local=global_to_local, coord=coord, zcorn=zcorn, is_cpg=is_cpg) self.timer.node['initialization'].node[ 'connection list generation'] = timer_node() self.timer.node['initialization'].node[ 'connection list generation'].start() if self.discretizer.is_cpg: cell_m, cell_p, tran, tran_thermal = self.discretizer.calc_cpg_discr( ) else: cell_m, cell_p, tran, tran_thermal = self.discretizer.calc_structured_discr( ) self.timer.node['initialization'].node[ 'connection list generation'].stop() volume = self.discretizer.calc_volumes() self.global_data['volume'] = volume # apply actnum filter if needed - all arrays providing a value for a single grid block should be passed arrs = [poro, depth, volume, op_num] cell_m, cell_p, tran, tran_thermal, arrs_local = self.discretizer.apply_actnum_filter( actnum, cell_m, cell_p, tran, tran_thermal, arrs) poro, depth, volume, op_num = arrs_local self.global_data['global_to_local'] = self.discretizer.global_to_local # create mesh object self.mesh = conn_mesh() # Initialize mesh using built connection list self.mesh.init(index_vector(cell_m), index_vector(cell_p), value_vector(tran), value_vector(tran_thermal)) # taking into account actnum self.nb = volume.size # Create numpy arrays wrapped around mesh data (no copying) self.poro = np.array(self.mesh.poro, copy=False) self.depth = np.array(self.mesh.depth, copy=False) self.volume = np.array(self.mesh.volume, copy=False) self.op_num = np.array(self.mesh.op_num, copy=False) self.hcap = np.array(self.mesh.heat_capacity, copy=False) self.rcond = np.array(self.mesh.rock_cond, copy=False) self.poro[:] = poro self.depth[:] = depth self.volume[:] = volume self.op_num[:] = op_num self.wells = [] self.vtk_z = 0 self.vtk_y = 0 self.vtk_x = 0 self.vtk_filenames_and_times = {} self.vtkobj = 0 if np.isscalar(self.coord): # Usual structured grid generated from DX, DY, DZ, DEPTH self.vtk_grid_type = 0 else: # CPG grid from COORD ZCORN self.vtk_grid_type = 1