def __init__(self, n_points=100): # call base class constructor super().__init__() self.hcap = np.array(self.reservoir.mesh.heat_capacity, copy=False) self.conduction = np.array(self.reservoir.mesh.rock_cond, copy=False) self.hcap.fill(2200) self.conduction.fill(181.44) # Create property containers: self.property_container = property_container( phase_name=['water', 'steam', 'temperature', 'energy'], component_name=['H2O']) # Define properties in property_container (IAPWS is the default property package for Geothermal in DARTS) # Users can define their custom properties in custom_properties.py; several property examples are defined there. self.rock = [value_vector([1, 0, 273.15])] self.property_container.temperature = iapws_temperature_evaluator() self.property_container.water_enthalpy = iapws_water_enthalpy_evaluator( ) self.property_container.steam_enthalpy = iapws_steam_enthalpy_evaluator( ) self.property_container.water_saturation = iapws_water_saturation_evaluator( ) self.property_container.steam_saturation = iapws_steam_saturation_evaluator( ) self.property_container.water_relperm = iapws_water_relperm_evaluator() self.property_container.steam_relperm = iapws_steam_relperm_evaluator() self.property_container.water_density = iapws_water_density_evaluator() self.property_container.steam_density = iapws_steam_density_evaluator() self.property_container.water_viscosity = iapws_water_viscosity_evaluator( ) self.property_container.steam_viscosity = iapws_steam_viscosity_evaluator( ) self.property_container.rock_compaction = custom_rock_compaction_evaluator( self.rock) self.property_container.rock_energy = custom_rock_energy_evaluator( self.rock) self.physics = Geothermal_Custom( timer=self.timer, n_points=128, min_p=1, max_p=151, min_e=1000, max_e=55000, property_container=self.property_container) self.params.first_ts = 1e0 self.params.mult_ts = 2 self.params.max_ts = 92 # Newton tolerance is relatively high because of L2-norm for residual and well segments self.params.tolerance_newton = 1e-1 self.params.tolerance_linear = 1e-3 self.params.max_i_newton = 20 self.params.max_i_linear = 30 self.runtime = 3650 self.inj = value_vector([0.999])
def __init__(self, n_points=100): # call base class constructor super().__init__() property_container = PropertyContainer(phase_name=['water', 'oil'], component_name=['w', 'o']) # Define property evaluators based on custom properties property_container.density_ev = dict([('water', DensityWater()), ('oil', DensityOil())]) property_container.viscosity_ev = dict([('water', ViscosityWater()), ('oil', ViscosityOil())]) property_container.watersat_ev = WaterSaturation() property_container.rel_perm_ev = dict([('water', PhaseRelPerm("water")), ('oil', PhaseRelPerm("oil"))]) property_container.capillary_ev = CapillaryPressure() property_container.rock_compress_ev = RockCompactionEvaluator() # create physics self.grav = 0 self.physics = DeadOil(self.timer, n_points=400, min_p=0, max_p=1000, min_z=1e-13, property_container=property_container, grav=self.grav) self.params.first_ts = 1e-2 self.params.mult_ts = 2 self.params.max_ts = 15 # Newton tolerance is relatively high because of L2-norm for residual and well segments self.params.tolerance_newton = 1e-3 self.params.tolerance_linear = 1e-3 self.params.max_i_newton = 20 self.params.max_i_linear = 30 self.runtime = 900 self.inj = value_vector([0.999])
def __init__(self, n_points=100): # call base class constructor super().__init__() self.pvt = 'bo_physics.in' self.property_container = PropertyContainer( phase_name=['gas', 'oil', 'water'], component_name=['gas', 'oil', 'water'], pvt=self.pvt) # Define property evaluators based on custom properties self.property_container.pb_ev = BubblePointPres(self.pvt) self.property_container.rs_ev = Rs(self.pvt) self.property_container.xgo_ev = Xgo(self.pvt) self.property_container.density_ev = dict([ ('gas', DensityGas(self.pvt)), ('oil', DensityOil(self.pvt)), ('water', DensityWater(self.pvt)) ]) self.property_container.viscosity_ev = dict([ ('gas', VsicoGas(self.pvt)), ('oil', ViscoOil(self.pvt)), ('water', ViscoWat(self.pvt)) ]) self.property_container.sat_ev = dict([('gas', Gassat(self.pvt)), ('oil', Oilsat(self.pvt)), ('water', Watsat(self.pvt))]) # stone I model is used, then OW is water-oil system, and GO is gas-oil system self.property_container.rel_perm_ev = dict([ ('gas', GasRelPerm(self.pvt)), ('oil', OilRelPerm(self.pvt)), ('water', WatRelPerm(self.pvt)), ('OW', Krow(self.pvt)), ('GO', Krog(self.pvt)) ]) self.property_container.rock_compress_ev = RockCompactionEvaluator( self.pvt) # create physics self.grav = 0 self.physics = BlackOil(self.timer, n_points=500, min_p=0, max_p=450, min_z=1e-13, property_container=self.property_container, grav=self.grav) self.params.first_ts = 1e-2 self.params.mult_ts = 2 self.params.max_ts = 15 # Newton tolerance is relatively high because of L2-norm for residual and well segments self.params.tolerance_newton = 1e-2 self.params.tolerance_linear = 1e-3 self.params.max_i_newton = 20 self.params.max_i_linear = 30 self.params.newton_type = sim_params.newton_local_chop self.params.nonlinear_norm_type = sim_params.L1 self.inj = value_vector([1e-8, 1e-8])
def __init__(self, n_points=100): # call base class constructor super().__init__() """Physical properties""" # Create property containers: self.property_container = property_container( phase_name=['gas', 'Aq'], component_name=['CO2', 'H2O']) self.components = self.property_container.component_name self.phases = self.property_container.phase_name """ properties correlations """ self.property_container.flash_ev = Flash(self.components) self.property_container.density_ev = dict([('Aq', DensityBrine()), ('gas', DensityVap())]) self.property_container.viscosity_ev = dict([('Aq', ViscosityBrine()), ('gas', ViscosityVap())]) self.property_container.rel_perm_ev = dict([('Aq', PhaseRelPerm("Aq")), ('gas', PhaseRelPerm("gas"))]) self.property_container.rel_well_perm_ev = dict([ ('Aq', WellPhaseRelPerm("Aq")), ('gas', WellPhaseRelPerm("gas")) ]) """ Activate physics """ self.physics = CO2Brine(self.timer, n_points=501, min_p=100, max_p=500, min_z=1e-10, max_z=1 - 1e-10, property_container=self.property_container) self.params.first_ts = 1e-2 self.params.mult_ts = 2 self.params.max_ts = 5 # Newton tolerance is relatively high because of L2-norm for residual and well segments self.params.tolerance_newton = 1e-3 self.params.tolerance_linear = 1e-3 self.params.max_i_newton = 20 self.params.max_i_linear = 30 self.runtime = 900 self.inj = value_vector([0.999])
def export_vtk_comp(self, file_name='data'): properties_vector = properties_evaluator(self.property_container) nb = self.reservoir.nb X = np.array(self.physics.engine.X) pres = X[0:2 * nb:2] zg = X[1:2 * nb:2] Sg = np.zeros(nb) xg = np.zeros(nb) for i in range(nb): state = value_vector([pres[i], zg[i]]) [ Sg[i], xg[i], ] = properties_vector.evaluate(state) self.export_vtk(file_name=file_name, local_cell_data={ 'GasSat': Sg, 'xCO2': xg })
def export_vtk_bo(self, file_name='data'): properties_vector = Properties(self.property_container) nb = self.reservoir.nb X = np.array(self.physics.engine.X) pres = X[0:3 * nb:3] zg = X[1:3 * nb:3] zo = X[2:3 * nb:3] So = np.zeros(nb) Sg = np.zeros(nb) Sw = np.zeros(nb) pbub = np.zeros(nb) for i in range(nb): state = value_vector([pres[i], zg[i], zo[i]]) [So[i], Sw[i], Sg[i], pbub[i]] = properties_vector.evaluate(state) self.export_vtk(file_name=file_name, local_cell_data={ 'OilSat': So, 'GasSat': Sg, 'WatSat': Sw })
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