def test_compute_initial_aperture(self, biot_params_small): """ Test computation of initial aperture in intact rock and fractured rock.""" # Setup model params = BiotParameters(**biot_params_small) setup = ISCBiotContactMechanics(params) setup.create_grid() g3: pp.Grid = setup._nd_grid() a = setup.compute_initial_aperture(g3, scaled=False) assert np.isclose(np.sum(a), g3.num_cells) g2: pp.Grid = setup.gb.grids_of_dimension(2)[0] a = setup.compute_initial_aperture(g2, scaled=False) assert np.isclose(np.sum(a), 6.0 * g2.num_cells)
def test_realistic_only_fracture_zone(self): # See changelist: reset changes for only fracture zone setup of 2020/06/25. # _sz = 2, bounding_box=None -> ~53k 3d, ~6k 2d, 80 1d cells _sz = 3.5 params = BiotParameters( # Base parameters length_scale=0.05, scalar_scale=1e6, head="60k-5frac/medium-sized-intact-grid/t_end-10min", time_step=pp.MINUTE, end_time=10 * pp.MINUTE, rock=GrimselGranodiorite(), # Geometry parameters mesh_args={ "mesh_size_frac": 0.9 * _sz, "mesh_size_min": 0.2 * _sz, "mesh_size_bound": 3 * _sz, }, bounding_box={ "xmin": -1 - 50, "ymin": 80 - 50, "zmin": -4 - 50, "xmax": 86 + 50, "ymax": 151 + 50, "zmax": 41 + 50, }, shearzone_names=["S1_1", "S1_2", "S1_3", "S3_1", "S3_2"], # Mechanical parameters stress=stress_tensor(), newton_options={ "max_iterations": 30, "nl_convergence_tol": 1e-10, "nl_divergence_tol": 1e5, }, # Flow parameters source_scalar_borehole_shearzone={ "shearzone": "S1_2", "borehole": "INJ1", }, well_cells=nd_and_shearzone_injection_cell, injection_rate=(1 / 6) / 3, # = 10 l/min - Divide by 3 due to 3 injection cells. frac_permeability=[2.3e-15, 4.5e-17, 2.3e-17, 6.4e-14, 1e-16], intact_permeability=2e-20, ) setup = NeverFailtBiotCM(params) newton_params = params.newton_options pp.run_time_dependent_model(setup, newton_params)
def test_realistic_setup(self): """ For a 50 000 cell setup, test Contact mechanics Biot model on 5 shear zones. Parameters are close to the ISC setup. Model is run for 10 minutes, with time steps of 1 minute. Injection to a shear zone. """ # _sz=6 => ~50k cells, # _sz=5.5 => ~66k cells _sz = 6 params = BiotParameters( # Base parameters length_scale=12.8, scalar_scale=1e10, head="2frac/20l_min/inj-frac-center/dilation", time_step=pp.MINUTE, end_time=7 * pp.MINUTE, rock=GrimselGranodiorite(), # Geometry parameters shearzone_names=["S1_2", "S3_1"], mesh_args={ "mesh_size_frac": _sz, # 0.3 * _sz "mesh_size_min": 0.2 * _sz, "mesh_size_bound": 3 * _sz, # 3.2 * _sz }, # Mechanical parameters stress=stress_tensor(), dilation_angle=(np.pi / 180) * 5, # 5 degrees dilation angle. newton_options={ "max_iterations": 40, "nl_convergence_tol": 1e-10, "nl_divergence_tol": 1e5, }, # Flow parameters source_scalar_borehole_shearzone={ "shearzone": "S1_2", "borehole": "INJ1", }, well_cells=center_of_shearzone_injection_cell, injection_rate=(10 / 60) * 2, # (10/60)*2 = 20l per 60s = 20 l/min frac_transmissivity=[1e-9, 3.7e-7], ) setup = NeverFailtBiotCM(params) newton_params = params.newton_options pp.run_time_dependent_model(setup, newton_params)
def biot_params() -> BiotParameters: """ Initialize BiotParameters""" here = Path(__file__).parent / "simulations" _sz = 6 params = BiotParameters( folder_name=here, stress=stress_tensor(), injection_rate=1 / 6, frac_permeability=1e-9, intact_permeability=1e-12, well_cells=shearzone_injection_cell, rock=GrimselGranodiorite(), mesh_args={ "mesh_size_frac": _sz, "mesh_size_min": 0.2 * _sz, "mesh_size_bound": 3 * _sz, }, ) return params
def test_nd_sides_shearzone_injection_cell(): """ Test that the 2 Nd-cells are tagged correctly""" # --- Paste biot_params_small here = Path(__file__).parent / "simulations" values = { "folder_name": here, "stress": stress_tensor(), "injection_rate": 1 / 6, "frac_permeability": 3, # -> frac_aperture = 6.0 "intact_permeability": 1e-12, "well_cells": shearzone_injection_cell, "rock": GrimselGranodiorite(), "mesh_args": { "mesh_size_frac": 10, "mesh_size_min": 10, "mesh_size_bound": 30, }, "length_scale": 7, "scalar_scale": 11, } # --- biot_params_small = values frac_name = "S1_2" biot_params_small["shearzone_names"] = [frac_name] params = BiotParameters(**biot_params_small) setup = ISCBiotContactMechanics(params) setup.create_grid() gb = setup.gb # Tag the cells nd_sides_shearzone_injection_cell(params, gb) for g, d in gb: tags = d["well"] if g.dim == setup.Nd: assert np.sum(np.abs(tags)) == np.sum(tags) == 2 else: assert np.sum(tags) == np.sum(np.abs(tags)) == 0
def test_mechanical_aperture(self, biot_params_small): """ Test computation of mechanical aperture in fractured rock""" # Prepare the model biot_params_small["shearzone_names"] = ["F1"] biot_params_small["length_scale"] = 1 params = BiotParameters(**biot_params_small) setup = ISCBiotContactMechanics(params) # --- Structured Grid with one fracture nx = np.array([2, 2, 2]) physdims = np.array([10, 10, 10]) # fmt: off frac_pts = np.array([[0, 10, 10, 0], [5, 5, 5, 5], [0, 0, 5, 5] ]) / params.length_scale # fmt: on gb = pp.meshing.cart_grid( [frac_pts], nx=nx, physdims=physdims / params.length_scale, ) # --- --- setup.gb = gb setup.assign_biot_variables() # Assign dummy displacement values to the fracture edge nd_grid = setup.grids_by_name(params.intact_name)[0] frac = setup.grids_by_name(params.shearzone_names[0])[0] edge = (frac, nd_grid) data_edge = setup.gb.edge_props(edge) mg: pp.MortarGrid = data_edge["mortar_grid"] nd = setup.Nd var_mortar = setup.mortar_displacement_variable if pp.STATE not in data_edge: data_edge[pp.STATE] = {} nc = frac.num_cells # Set mechanical mortar displacement to STATE. # Set u_n = 1 and ||u_t|| = 0 on side 1 # Set all zero on side 1. s1 = np.vstack(( np.zeros(nc), np.ones(nc), np.zeros(nc), )) # mortar side 1 mortar_u = np.hstack(( s1, np.zeros((nd, nc)), ) # mortar side 1 # mortar side 2 ).ravel("F") # Set mechanical mortar displacement to previous iterate. # Set u = (1, 1, 1) on side 1 # Set u = (3, 3, 3) on side 2. # This should give an aperture of 2. s2 = np.vstack((3 * np.ones((nd, nc)), )) mortar_u_prev_iter = np.hstack(( np.ones((nd, nc)), s2, ) # mortar side 1 # mortar side 2 ).ravel("F") data_edge[pp.STATE].update({ var_mortar: mortar_u, pp.ITERATE: { var_mortar: mortar_u_prev_iter }, }) # Get mechanical aperture # Nd aperture_nd = setup.mechanical_aperture(nd_grid, from_iterate=False) assert np.allclose(aperture_nd, 0) aperture_nd_iter = setup.mechanical_aperture(nd_grid, from_iterate=False) assert np.allclose(aperture_nd_iter, 0) # fracture aperture_frac = setup.mechanical_aperture(frac, from_iterate=False) assert np.allclose(aperture_frac, np.ones(nc)) aperture_frac_iter = setup.mechanical_aperture(frac, from_iterate=True) assert np.allclose(aperture_frac_iter, 2 * np.ones(nc))
def simple_validation(): """ Validation on easy setup""" path = Path(__file__).parent / "results" # Grid mesh_size = 20 gb, box, mesh_args = two_intersecting_blocking_fractures( str(path), mesh_size) # Injection phases and time configuration start_time = -1e2 * pp.YEAR phase_limits = [start_time, 0, 12 * pp.HOUR] rates = [0, 0] injection_protocol = InjectionRateProtocol.create_protocol( phase_limits, rates) phase_time_steps = [-start_time, 2.0 * pp.MINUTE] time_params = TimeStepProtocol.create_protocol(phase_limits, phase_time_steps) # Newton newton_params = NewtonParameters( convergence_tol=1e-6, max_iterations=50, ) rock = GrimselGranodiorite() rock.FRICTION_COEFFICIENT = 0.2 stress = np.diag(-np.array([6, 13.1, 6]) * pp.MEGA * pp.PASCAL) # Model parameters biot_params = BiotParameters( # BaseParameters length_scale=15, scalar_scale=1e9, folder_name=path, time=time_params.start_time, time_step=time_params.initial_time_step, end_time=time_params.end_time, gravity=False, rock=rock, # GeometryParameters shearzone_names=["f1", "f2"], box=box, mesh_args=mesh_args, # MechanicsParameters stress=stress, dilation_angle=np.radians(5.0), newton_options=newton_params.dict(), # FlowParameters well_cells=nd_injection_cell_center, injection_protocol=injection_protocol, frac_transmissivity=5.17e-3, # Gives a0=2e-3, which are Ivar's values. # BiotParameters alpha=0.8, ) setup = ISCBiotContactMechanics(biot_params) setup.gb = gb time_machine = TimeMachinePhasesConstantDt(setup, newton_params, time_params) time_machine.run_simulation() return time_machine