def test_low_k_optimized_mesh_1_frac(self): """ Run FlowISC on optimized mesh with 1 fracture""" _sz = 4 # 2 intact_k = 1e-20 frac_k = 1e-16 time_step = pp.MINUTE params = FlowParameters( head=f"TestFlowISC/test_low_k_optimized_mesh_1_frac/" f"sz_{_sz}/kf_{intact_k}_ki_{frac_k}/1min", time_step=time_step, end_time=time_step * 4, shearzone_names=["S1_2"], bounding_box=None, mesh_args={ "mesh_size_frac": _sz, "mesh_size_min": 0.2 * _sz, "mesh_size_bound": 3 * _sz, }, well_cells=shearzone_injection_cell, injection_rate=1 / 6, frac_permeability=frac_k, intact_permeability=intact_k, ) _helper_run_flowisc_optimized_grid(params)
def test_optimize_mesh(self): # Create a regular, non-optimized mesh _sz = 10 time_step = pp.MINUTE params = FlowParameters( head="TestOptimizeMesh/test_optimize_mesh_only", time_step=time_step, end_time=time_step * 4, shearzone_names=None, mesh_args={ "mesh_size_frac": _sz, "mesh_size_min": 0.2 * _sz, "mesh_size_bound": 3 * _sz, }, source_scalar_borehole_shearzone=None, well_cells=nd_injection_cell_center, injection_rate=1 / 6, frac_permeability=0, intact_permeability=1e-13, ) gb, network = create_grid(**params.dict( include={ "mesh_args", "length_scale", "bounding_box", "shearzone_names", "folder_name", })) logger.info(f"gb cells: {gb.num_cells()}") # Optimize the mesh in_file = params.folder_name / "gmsh_frac_file.geo" out_file = params.folder_name / "gmsh_frac_file-optimized.msh" optimize_mesh( in_file=in_file, out_file=out_file, method="Netgen", ) gb2: pp.GridBucket = pp.fracture_importer.dfm_from_gmsh(str(out_file), dim=3) logger.info(f"gb cells: {gb2.num_cells()}") assert gb.num_cells() < gb2.num_cells()
def test_grid_error_structured_grid(self): """ Set up and solve a simple 3d-problem with 2 fractures. Verify decreasing error. # TODO: Modify FlowISC so that it modifies permeability on setup. """ time_step = pp.HOUR params = FlowParameters( head="TestGridError/test_grid_error_structured_grid", time_step=time_step, end_time=time_step * 4, fluid_type=pp.UnitFluid, shearzone_names=["f1"], mesh_args={}, source_scalar_borehole_shearzone=None, well_cells=nd_injection_cell_center, injection_rate=1, frac_permeability=1, intact_permeability=1, ) n_ref = 2 gb_list = [ structured_grid_1_frac_horizontal_with_refinements(ref) for ref in range(n_ref + 1) ] for gb in gb_list: setup = FlowISC(params) setup.gb = gb pp.run_time_dependent_model(setup, {}) # --- Compute errors --- gb_ref = gb_list[-1] errors = [] for i in range(0, n_ref): gb_i = gb_list[i] gb_coarse_fine_cell_mapping(gb=gb_i, gb_ref=gb_ref) _error = grid_error( gb=gb_i, gb_ref=gb_ref, variable=["p_exp"], variable_dof=[1], ) errors.append(_error) logger.info(errors)
def test_set_fracture_aperture_from_cubic_law(self, tmpdir): shearzones = ["S1_1", "S1_2"] params = FlowParameters( # BaseParameters folder_name=tmpdir, # GeometryParameters shearzone_names=shearzones, # FlowParameters injection_rate=1, frac_transmissivity=1, ) # Check that correct Transmissivity is calculated res = np.cbrt(params.mu_over_rho_g * 12) apertures = np.array( [params.initial_background_aperture(sz) for sz in shearzones]) assert np.allclose(res, apertures) assert np.isclose(params.mu_over_rho_g, 1 / params.rho_g_over_mu) # Another test params.frac_transmissivity = params.rho_g_over_mu / 12 apertures = np.array( [params.initial_background_aperture(sz) for sz in shearzones]) assert np.allclose(1, apertures)
def _run_convergence_study_helper( head: str, shearzone_names: Optional[List[str]], sz: float, n_refinements: int, frac_permeability: float = 1, intact_permeability: float = 1, ) -> None: """ Helper method for run_convergence_study tests head is the path head. Usually, method name shearzone_names is a list of names given to fractures sz is related to mesh_args n_refinements is the number of refinements to run frac_permeability, intact_permeability: Optionally set custom permeability """ fluid = pp.UnitFluid(11) fluid.COMPRESSIBILITY = 0 # Consider an incompressible problem params = FlowParameters( head=f"TestRunModelForConvergenceStudy/{head}", fluid=fluid, shearzone_names=shearzone_names, mesh_args={ "mesh_size_frac": sz, "mesh_size_min": sz, "mesh_size_bound": sz * 4, }, source_scalar_borehole_shearzone=None, well_cells=nd_injection_cell_center, injection_rate=1, frac_permeability=frac_permeability, intact_permeability=intact_permeability, ) network = network_n_fractures(params.n_frac) gb_list, errors = run_model_for_convergence_study( model=FlowISC, run_model_method=pp.run_time_dependent_model, network=network, params=params, n_refinements=n_refinements, newton_params=None, variable=["p_exp"], variable_dof=[1], ) print(errors)
def test_low_k_1_frac(self): """ Run FlowISC on a mesh with 1 fracture""" _sz = 4 # _sz = 2 intact_k = 1e-13 frac_k = 1e-9 time_step = pp.MINUTE params = FlowParameters( # head=f"test_low_k_1_frac/sz_{_sz}/kf_{intact_k}_ki_{frac_k}/1min", head="TestFlowISC/delete-me", time_step=time_step, end_time=time_step * 4, shearzone_names=["S1_2"], bounding_box=None, mesh_args={ "mesh_size_frac": _sz, "mesh_size_min": _sz, # 0.2 * _sz, "mesh_size_bound": _sz, # 3 * _sz, }, well_cells=shearzone_injection_cell, injection_rate=1 / 6, frac_permeability=frac_k, intact_permeability=intact_k, ) setup = FlowISC(params) _gb, network = create_grid(**params.dict( include={ "mesh_args", "length_scale", "bounding_box", "shearzone_names", "folder_name", })) pp.run_time_dependent_model(setup, {}) assert setup.neg_ind.size == 0
def _helper_run_flowisc_optimized_grid(params: FlowParameters, optimize_method="Netgen"): """ Run FlowISC on optimized meshes""" _gb, network = create_grid(**params.dict( include={ "mesh_args", "length_scale", "bounding_box", "shearzone_names", "folder_name", })) logger.info(f"gb cells non-optimized: {_gb.num_cells()}") # Optimize the mesh in_file = params.folder_name / "gmsh_frac_file.geo" out_file = params.folder_name / "gmsh_frac_file-optimized.msh" optimize_mesh( in_file=in_file, out_file=out_file, method=optimize_method, force=True, dim_tags=[3], ) gb: pp.GridBucket = pp.fracture_importer.dfm_from_gmsh(str(out_file), dim=3) logger.info(f"gb cells optimized: {gb.num_cells()}") assert _gb.num_cells() < gb.num_cells() # Run FlowISC setup = FlowISC(params) setup.gb = gb pp.run_time_dependent_model(setup, {}) assert setup.neg_ind.size == 0
def test_low_k_optimized_mesh(self): """ Run FlowISC on optimized meshes""" _sz = 10 intact_k = 1e-16 time_step = pp.MINUTE * 40 params = FlowParameters( head= f"TestFlowISC/test_low_k_optimized_mesh/sz_{_sz}/k_{intact_k}/40min", time_step=time_step, end_time=time_step * 40, shearzone_names=None, mesh_args={ "mesh_size_frac": _sz, "mesh_size_min": 0.2 * _sz, "mesh_size_bound": 3 * _sz, }, source_scalar_borehole_shearzone=None, well_cells=nd_injection_cell_center, injection_rate=1 / 6, frac_permeability=0, intact_permeability=intact_k, ) _helper_run_flowisc_optimized_grid(params)
def test_set_increased_aperture_near_injection_point(self, tmpdir, mocker): shearzones = ["S1_2"] near_inj_T = 1 params = FlowParameters( # BaseParameters folder_name=tmpdir, # GeometryParameters shearzone_names=shearzones, # FlowParameters injection_rate=1, frac_transmissivity=0, near_injection_transmissivity=near_inj_T, near_injection_t_radius=1, ) g = pp.CartGrid(nx=[3, 3]) g.compute_geometry() # Mock the borehole shearzone intersection method method = mocker.patch( "GTS.isc_modelling.parameter.shearzone_borehole_intersection") # Assert we get 4 cells of T=1 each method.return_value = np.array([1.5, 1.5, 0]) aperture = params.compute_initial_aperture(g, shearzones[0]) known_aperture = params.b_from_T(near_inj_T) assert np.isclose(np.sum(aperture), known_aperture * 5) # Assert the locations of these cells known_idx = [1, 3, 4, 5, 7] ap_idx = np.where(np.isclose(aperture, known_aperture))[0] assert np.allclose(np.sort(ap_idx), known_idx) # Assert no transmissivity added if no cells within the radius is found params.near_injection_t_radius = 0.4 method.return_value = np.array([2, 2, 0]) aperture = params.compute_initial_aperture(g, shearzones[0]) assert np.sum(aperture) == 0
def _run_flow_models_helper( sz: float, incompressible: bool, head: str, shearzone_names: Optional[List[str]], time_step: float = None, ) -> None: """ Helper method for the test_flow setups sz is related to mesh_args incompressible turns on or off compressibility (and time stepping) - If compressible, you should also set time_step head is the path head. Usually, method name shearzone_names is a list of names given to fractures n_frac is the number of fractures to be constructed """ fluid = pp.UnitFluid(11) if incompressible: # Consider an incompressible problem fluid.COMPRESSIBILITY = 0 time_step = 1 end_time = 1 else: time_step = time_step end_time = time_step * 4 params = FlowParameters( head=f"TestFlow/{head}", fluid=fluid, time_step=time_step, end_time=end_time, shearzone_names=shearzone_names, mesh_args={ "mesh_size_frac": sz, "mesh_size_min": sz, "mesh_size_bound": sz * 4, }, source_scalar_borehole_shearzone=None, well_cells=nd_injection_cell_center, injection_rate=1, frac_permeability=1, intact_permeability=1, bounding_box={ "xmin": 0, "ymin": 0, "zmin": 0, "xmax": 1, "ymax": 1, "zmax": 1 }, ) setup = FlowISC(params) network = network_n_fractures(params.n_frac) gb = network.mesh( mesh_args=params.mesh_args, file_name=str(params.folder_name / "gmsh_frac_file"), ) setup.gb = gb pp.run_time_dependent_model(setup, {}) assert setup.neg_ind.size == 0
def test_flow_model_regular_vs_optimized_mesh(self): """ Investigate if optimizing the mesh can give different results on a problem with known issues in the solution We expect regular mesh generation to produce a mesh of poor enough quality for the solution to be unphysical (here: we get 6 cells with negative pressure values). However, if we use the Netgen mesh optimizer, the find that the negative cells are eradicated from the solution. """ # Create a regular, non-optimized mesh _sz = 10 time_step = pp.MINUTE params = FlowParameters( head="TestOptimizeMesh/test_optimize_mesh", time_step=time_step, end_time=time_step * 4, shearzone_names=None, mesh_args={ "mesh_size_frac": _sz, "mesh_size_min": 0.2 * _sz, "mesh_size_bound": 3 * _sz, }, source_scalar_borehole_shearzone=None, well_cells=nd_injection_cell_center, injection_rate=1 / 6, frac_permeability=0, intact_permeability=1e-13, ) setup = FlowISC(params) pp.run_time_dependent_model(setup, {}) assert setup.neg_ind.size == 6 # --- Re-run test with optimized mesh --- # Optimize the mesh in_file = params.folder_name / "gmsh_frac_file.geo" out_file = params.folder_name / "optimized/gmsh_frac_file.msh" optimize_mesh( in_file=in_file, out_file=out_file, method="Netgen", ) gb: pp.GridBucket = pp.fracture_importer.dfm_from_gmsh(str(out_file), dim=3) # Check that the grid was indeed optimized assert setup.gb.num_cells() < gb.num_cells() # Set up a new model params.folder_name = params.folder_name / "optimized" setup_opt = FlowISC(params) # Set the optimized grid bucket to the flow model setup_opt.gb = gb # Run the model pp.run_time_dependent_model(setup_opt, {}) assert setup_opt.neg_ind.size == 0