Пример #1
0
    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)
Пример #2
0
    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)
Пример #4
0
    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)
Пример #6
0
    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
Пример #7
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
Пример #8
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)
Пример #9
0
    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
Пример #10
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
Пример #11
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