예제 #1
0
    def __init__(self, gb, data, physics='mechanics', **kwargs):
        self.physics = physics
        self._gb = gb
        if not isinstance(self._gb, Grid):
            raise ValueError('StaticModel only defined for Grid class')

        self._data = data

        self.lhs = []
        self.rhs = []
        self.x = []

        file_name = kwargs.get('file_name', physics)
        folder_name = kwargs.get('folder_name', 'results')

        tic = time.time()
        logger.info('Create exporter')
        self.exporter = Exporter(self._gb, file_name, folder_name)
        logger.info('Elapsed time: ' + str(time.time() - tic))

        self._stress_disc = self.stress_disc()

        self.displacement_name = 'displacement'
        self.frac_displacement_name = 'frac_displacement'
        self.is_factorized = False
예제 #2
0
    def __init__(self,
                 gb,
                 physics='transport',
                 time_step=1.0,
                 end_time=1.0,
                 **kwargs):
        self._gb = gb
        self.is_GridBucket = isinstance(self._gb, GridBucket)
        self.physics = physics
        self._data = kwargs.get('data', dict())
        self._time_step = time_step
        self._end_time = end_time
        self._set_data()

        self._solver = self.solver()
        self._solver.parameters['store_results'] = False

        file_name = kwargs.get('file_name', str(physics))
        folder_name = kwargs.get('folder_name', 'results')

        logger.info('Create exporter')
        tic = time.time()
        self.exporter = Exporter(self._gb, file_name, folder_name)
        logger.info('Done. Elapsed time: ' + str(time.time() - tic))

        self.x_name = 'solution'
        self._time_disc = self.time_disc()
예제 #3
0
def main(id_problem, tol=1e-5, N_pts=1000, if_export=False):

    folder_export = 'example_2_2_tpfa/' + str(id_problem) + "/"
    file_export = 'tpfa'

    gb = example_2_2_create_grid.create(id_problem, tol=tol)

    # Assign parameters
    example_2_2_data.add_data(gb, tol)

    # Choose and define the solvers and coupler
    solver_flux = tpfa.TpfaDFN(gb.dim_max(), 'flow')
    A_flux, b_flux = solver_flux.matrix_rhs(gb)
    solver_source = source.IntegralDFN(gb.dim_max(), 'flow')
    A_source, b_source = solver_source.matrix_rhs(gb)

    p = sps.linalg.spsolve(A_flux + A_source, b_flux + b_source)
    solver_flux.split(gb, 'pressure', p)

    if if_export:
        save = Exporter(gb, file_export, folder_export)
        save.write_vtk(['pressure'])

    b_box = gb.bounding_box()
    y_range = np.linspace(b_box[0][1] + tol, b_box[1][1] - tol, N_pts)
    pts = np.stack((1.5 * np.ones(N_pts), y_range, 0.5 * np.ones(N_pts)))
    values = example_2_2_data.plot_over_line(gb, pts, 'pressure', tol)

    arc_length = y_range - b_box[0][1]
    np.savetxt(folder_export + "plot_over_line.txt", (arc_length, values))

    # compute the flow rate
    fvutils.compute_discharges(gb, 'flow')
    diam, flow_rate = example_2_2_data.compute_flow_rate(gb, tol)
    np.savetxt(folder_export + "flow_rate.txt", (diam, flow_rate))
예제 #4
0
    def __init__(self, gb, data, physics="mechanics", **kwargs):
        self.physics = physics
        self._gb = gb
        if not isinstance(self._gb, Grid):
            raise ValueError("StaticModel only defined for Grid class")

        self._data = data

        self.lhs = []
        self.rhs = []
        self.x = []

        file_name = kwargs.get("file_name", physics)
        folder_name = kwargs.get("folder_name", "results")

        tic = time.time()
        logger.info("Create exporter")
        self.exporter = Exporter(self._gb, file_name, folder_name)
        logger.info("Elapsed time: " + str(time.time() - tic))

        self._stress_disc = self.stress_disc()

        self.displacement_name = "displacement"
        self.frac_displacement_name = "frac_displacement"
        self.is_factorized = False
예제 #5
0
def main(id_problem, is_coarse=False, tol=1e-5, if_export=False):

    gb = example_1_create_grid.create(0.5 / float(id_problem), tol)

    if is_coarse:
        co.coarsen(gb, 'by_tpfa')
        folder_export = "example_1_vem_coarse/"
    else:
        folder_export = "example_1_vem/"

    file_name_error = folder_export + "vem_error.txt"

    if if_export:
        save = Exporter(gb, "vem", folder_export)

    example_1_data.assign_frac_id(gb)

    # Assign parameters
    example_1_data.add_data(gb, tol)

    # Choose and define the solvers and coupler
    solver_flow = vem_dual.DualVEMDFN(gb.dim_max(), 'flow')
    A_flow, b_flow = solver_flow.matrix_rhs(gb)

    solver_source = vem_source.DualSourceDFN(gb.dim_max(), 'flow')
    A_source, b_source = solver_source.matrix_rhs(gb)

    up = sps.linalg.spsolve(A_flow + A_source, b_flow + b_source)
    solver_flow.split(gb, "up", up)

    gb.add_node_props(["discharge", 'pressure', "P0u", "err"])
    solver_flow.extract_u(gb, "up", "discharge")
    solver_flow.extract_p(gb, "up", 'pressure')
    solver_flow.project_u(gb, "discharge", "P0u")

    only_max_dim = lambda g: g.dim == gb.dim_max()
    diam = gb.diameter(only_max_dim)
    error_pressure = example_1_data.error_pressure(gb, "p")
    error_discharge = example_1_data.error_discharge(gb, "P0u")
    print("h=", diam, "- err(p)=", error_pressure, "- err(P0u)=",
          error_discharge)
    error_pressure = example_1_data.error_pressure(gb, 'pressure')

    with open(file_name_error, 'a') as f:
        info = str(gb.num_cells(only_max_dim)) + " " +\
               str(gb.num_cells(only_max_dim)) + " " +\
               str(error_pressure) + " " +\
               str(error_discharge) + " " +\
               str(gb.num_faces(only_max_dim))  + "\n"
        f.write(info)

    if if_export:
        save.write_vtk(['pressure', "err", "P0u"])
예제 #6
0
def main(id_problem, tol=1e-5, N_pts=1000, if_export=False):

    mesh_size = 0.025  # 0.01 0.05
    folder_export = ("example_2_3_vem_coarse_" + str(mesh_size) + "/" +
                     str(id_problem) + "/")
    file_export = "vem"

    gb = example_2_3_create_grid.create(id_problem,
                                        is_coarse=True,
                                        mesh_size=mesh_size,
                                        tol=tol)

    internal_flag = FaceTag.FRACTURE
    [g.remove_face_tag_if_tag(FaceTag.BOUNDARY, internal_flag) for g, _ in gb]

    # Assign parameters
    example_2_3_data.add_data(gb, tol)

    # Choose and define the solvers and coupler
    solver_flow = vem_dual.DualVEMDFN(gb.dim_max(), "flow")
    A_flow, b_flow = solver_flow.matrix_rhs(gb)

    solver_source = vem_source.IntegralDFN(gb.dim_max(), "flow")
    A_source, b_source = solver_source.matrix_rhs(gb)

    up = sps.linalg.spsolve(A_flow + A_source, b_flow + b_source)
    solver_flow.split(gb, "up", up)

    gb.add_node_props(["discharge", "p", "P0u"])
    solver_flow.extract_u(gb, "up", "discharge")
    solver_flow.extract_p(gb, "up", "p")
    solver_flow.project_u(gb, "discharge", "P0u")

    if if_export:
        save = Exporter(gb, file_export, folder_export)
        save.write_vtk(["p", "P0u"])

    b_box = gb.bounding_box()
    y_range = np.linspace(b_box[0][1] + tol, b_box[1][1] - tol, N_pts)
    pts = np.stack((0.35 * np.ones(N_pts), y_range, np.zeros(N_pts)))
    values = example_2_3_data.plot_over_line(gb, pts, "p", tol)

    arc_length = y_range - b_box[0][1]
    np.savetxt(folder_export + "plot_over_line.txt", (arc_length, values))

    # compute the flow rate
    diam, flow_rate = example_2_3_data.compute_flow_rate_vem(gb, tol)
    np.savetxt(folder_export + "flow_rate.txt", (diam, flow_rate))

    # compute the number of cells
    num_cells = gb.num_cells(lambda g: g.dim == 2)
    with open(folder_export + "cells.txt", "w") as f:
        f.write(str(num_cells))
예제 #7
0
def main(grid_name, direction):
    file_export = 'solution'
    tol = 1e-4

    folder_grids = '/home/elle/Dropbox/Work/tipetut/'
    gb = pickle.load(open(folder_grids + grid_name, 'rb'))
    co.coarsen(gb, 'by_volume')

    folder_export = './example_4_vem_coarse_' + grid_name + '_' + direction + '/'

    domain = {
        'xmin': -800,
        'xmax': 600,
        'ymin': 100,
        'ymax': 1500,
        'zmin': -100,
        'zmax': 1000
    }

    internal_flag = FaceTag.FRACTURE
    [g.remove_face_tag_if_tag(FaceTag.BOUNDARY, internal_flag) for g, _ in gb]

    example_4_data.add_data(gb, domain, direction, tol)

    # Choose and define the solvers and coupler
    solver_flow = vem_dual.DualVEMDFN(gb.dim_max(), 'flow')
    A_flow, b_flow = solver_flow.matrix_rhs(gb)

    solver_source = vem_source.IntegralDFN(gb.dim_max(), 'flow')
    A_source, b_source = solver_source.matrix_rhs(gb)

    up = sps.linalg.spsolve(A_flow + A_source, b_flow + b_source)
    solver_flow.split(gb, "up", up)

    gb.add_node_props(["discharge", "p", "P0u"])
    solver_flow.extract_u(gb, "up", "discharge")
    solver_flow.extract_p(gb, "up", "p")
    solver_flow.project_u(gb, "discharge", "P0u")

    save = Exporter(gb, file_export, folder_export)
    save.write_vtk(["p", "P0u"])

    # compute the flow rate
    diam, flow_rate = example_4_data.compute_flow_rate_vem(
        gb, direction, domain, tol)
    np.savetxt(folder_export + "flow_rate.txt", (diam, flow_rate))

    # compute the number of cells
    num_cells = gb.num_cells(lambda g: g.dim == 2)
    with open(folder_export + "cells.txt", "w") as f:
        f.write(str(num_cells))
예제 #8
0
def solve_tpfa(gb, folder):

    # Choose and define the solvers and coupler
    solver_flow = tpfa.TpfaMixedDim("flow")
    A_flow, b_flow = solver_flow.matrix_rhs(gb)

    solver_source = source.IntegralMixedDim("flow")
    A_source, b_source = solver_source.matrix_rhs(gb)

    p = sps.linalg.spsolve(A_flow + A_source, b_flow + b_source)
    solver_flow.split(gb, "pressure", p)

    save = Exporter(gb, "sol", folder=folder)
    save.write_vtk(["pressure"])
예제 #9
0
def solve_p1(gb, folder, return_only_matrix=False):

    # Choose and define the solvers and coupler
    solver_flow = pp.P1MixedDim("flow")
    A_flow, b_flow = solver_flow.matrix_rhs(gb)

    A = A_flow
    if return_only_matrix:
        return A, mortar_dof_size(A, gb, solver_flow)

    p = sps.linalg.spsolve(A, b_flow)
    solver_flow.split(gb, "pressure", p)

    save = Exporter(gb, "sol", folder=folder, simplicial=True)
    save.write_vtk("pressure", point_data=True)
예제 #10
0
def main(id_problem, tol=1e-5, N_pts=1000, if_export=False):

    mesh_size = 0.15
    folder_export = 'example_2_1_vem_coarse_' + str(mesh_size) + '/' + str(
        id_problem) + "/"
    file_export = 'vem'

    gb = example_2_1_create_grid.create(id_problem,
                                        is_coarse=True,
                                        mesh_size=mesh_size,
                                        tol=tol)

    internal_flag = FaceTag.FRACTURE
    [g.remove_face_tag_if_tag(FaceTag.BOUNDARY, internal_flag) for g, _ in gb]

    # Assign parameters
    example_2_1_data.add_data(gb, tol)

    # Choose and define the solvers and coupler
    solver_flow = vem_dual.DualVEMDFN(gb.dim_max(), 'flow')
    A_flow, b_flow = solver_flow.matrix_rhs(gb)

    solver_source = vem_source.DualSourceDFN(gb.dim_max(), 'flow')
    A_source, b_source = solver_source.matrix_rhs(gb)

    up = sps.linalg.spsolve(A_flow + A_source, b_flow + b_source)
    solver_flow.split(gb, "up", up)

    gb.add_node_props(["discharge", 'pressure', "P0u"])
    solver_flow.extract_u(gb, "up", "discharge")
    solver_flow.extract_p(gb, "up", 'pressure')
    solver_flow.project_u(gb, "discharge", "P0u")

    if if_export:
        save = Exporter(gb, file_export, folder_export)
        save.write_vtk(['pressure', "P0u"])

    b_box = gb.bounding_box()
    z_range = np.linspace(b_box[0][2] + tol, b_box[1][2] - tol, N_pts)
    pts = np.stack((0.5 * np.ones(N_pts), 0.5 * np.ones(N_pts), z_range))
    values = example_2_1_data.plot_over_line(gb, pts, 'pressure', tol)

    arc_length = z_range - b_box[0][2]
    np.savetxt(folder_export + "plot_over_line.txt", (arc_length, values))

    # compute the flow rate
    diam, flow_rate = example_2_1_data.compute_flow_rate_vem(gb, tol)
    np.savetxt(folder_export + "flow_rate.txt", (diam, flow_rate))
예제 #11
0
def solve_rt0(gb, folder):

    # Choose and define the solvers and coupler
    solver_flow = rt0.RT0MixedDim("flow")
    A_flow, b_flow = solver_flow.matrix_rhs(gb)

    solver_source = vem_source.IntegralMixedDim("flow")
    A_source, b_source = solver_source.matrix_rhs(gb)

    up = sps.linalg.spsolve(A_flow + A_source, b_flow + b_source)
    solver_flow.split(gb, "up", up)

    solver_flow.extract_p(gb, "up", "pressure")

    save = Exporter(gb, "sol", folder=folder)
    save.write_vtk(["pressure"])
예제 #12
0
def solve_rt0(gb, folder, return_only_matrix=False):

    # Choose and define the solvers and coupler
    solver_flow = pp.RT0MixedDim("flow")
    A_flow, b_flow = solver_flow.matrix_rhs(gb)

    A = A_flow
    if return_only_matrix:
        return A, mortar_dof_size(A, gb, solver_flow)

    up = sps.linalg.spsolve(A, b_flow)
    solver_flow.split(gb, "up", up)

    solver_flow.extract_p(gb, "up", "pressure")

    save = Exporter(gb, "sol", folder=folder)
    save.write_vtk(["pressure"])
예제 #13
0
def main(id_problem, tol=1e-5, N_pts=1000, if_export=False):

    mesh_size = 0.025  # 0.01 0.05
    folder_export = 'example_2_3_tpfa_' + str(mesh_size) + '/' + str(
        id_problem) + "/"
    file_export = 'tpfa'

    gb = example_2_3_create_grid.create(id_problem,
                                        mesh_size=mesh_size,
                                        tol=tol)

    # Assign parameters
    example_2_3_data.add_data(gb, tol)

    # Choose and define the solvers and coupler
    solver_flux = tpfa.TpfaDFN(gb.dim_max(), 'flow')
    A_flux, b_flux = solver_flux.matrix_rhs(gb)
    solver_source = source.IntegralDFN(gb.dim_max(), 'flow')
    A_source, b_source = solver_source.matrix_rhs(gb)

    p = sps.linalg.spsolve(A_flux + A_source, b_flux + b_source)
    solver_flux.split(gb, "p", p)

    if if_export:
        save = Exporter(gb, file_export, folder_export)
        save.write_vtk(["p"])

    b_box = gb.bounding_box()
    y_range = np.linspace(b_box[0][1] + tol, b_box[1][1] - tol, N_pts)
    pts = np.stack((0.35 * np.ones(N_pts), y_range, np.zeros(N_pts)))
    values = example_2_3_data.plot_over_line(gb, pts, 'p', tol)

    arc_length = y_range - b_box[0][1]
    np.savetxt(folder_export + "plot_over_line.txt", (arc_length, values))

    # compute the flow rate
    fvutils.compute_discharges(gb, 'flow')
    diam, flow_rate = example_2_3_data.compute_flow_rate(gb, tol)
    np.savetxt(folder_export + "flow_rate.txt", (diam, flow_rate))

    # compute the number of cells
    num_cells = gb.num_cells(lambda g: g.dim == 2)
    with open(folder_export + "cells.txt", "w") as f:
        f.write(str(num_cells))
예제 #14
0
def main(grid_name, direction):
    file_export = "solution"
    tol = 1e-4

    folder_grids = "/home/elle/Dropbox/Work/tipetut/"
    gb = pickle.load(open(folder_grids + grid_name, "rb"))

    folder_export = "./example_4_tpfa_" + grid_name + "_" + direction + "/"

    domain = {
        "xmin": -800,
        "xmax": 600,
        "ymin": 100,
        "ymax": 1500,
        "zmin": -100,
        "zmax": 1000,
    }

    example_4_data.add_data(gb, domain, direction, tol)

    # Choose and define the solvers and coupler
    solver_flux = tpfa.TpfaDFN(gb.dim_max(), "flow")
    A_flux, b_flux = solver_flux.matrix_rhs(gb)

    solver_source = source.IntegralDFN(gb.dim_max(), "flow")
    A_source, b_source = solver_source.matrix_rhs(gb)

    p = sps.linalg.spsolve(A_flux + A_source, b_flux + b_source)
    solver_flux.split(gb, "p", p)

    save = Exporter(gb, file_export, folder_export)
    save.write_vtk(["p"])

    # compute the flow rate
    fvutils.compute_discharges(gb, "flow")
    diam, flow_rate = example_4_data.compute_flow_rate(gb, direction, domain,
                                                       tol)
    np.savetxt(folder_export + "flow_rate.txt", (diam, flow_rate))

    # compute the number of cells
    num_cells = gb.num_cells(lambda g: g.dim == 2)
    with open(folder_export + "cells.txt", "w") as f:
        f.write(str(num_cells))
예제 #15
0
def main(grid_name, direction):
    file_export = 'solution'
    tol = 1e-4

    folder_grids = '/home/elle/Dropbox/Work/tipetut/'
    gb = pickle.load(open(folder_grids + grid_name, 'rb'))

    folder_export = './example_4_mpfa_' + grid_name + '_' + direction + '/'

    domain = {
        'xmin': -800,
        'xmax': 600,
        'ymin': 100,
        'ymax': 1500,
        'zmin': -100,
        'zmax': 1000
    }

    example_4_data.add_data(gb, domain, direction, tol)

    # Choose and define the solvers and coupler
    solver_flux = mpfa.MpfaDFN(gb.dim_max(), 'flow')
    A_flux, b_flux = solver_flux.matrix_rhs(gb)

    solver_source = source.IntegralDFN(gb.dim_max(), 'flow')
    A_source, b_source = solver_source.matrix_rhs(gb)

    p = sps.linalg.spsolve(A_flux + A_source, b_flux + b_source)
    solver_flux.split(gb, "p", p)

    save = Exporter(gb, file_export, folder_export)
    save.write_vtk(["p"])

    # compute the flow rate
    fvutils.compute_discharges(gb, 'flow')
    diam, flow_rate = example_4_data.compute_flow_rate(gb, direction, domain,
                                                       tol)
    np.savetxt(folder_export + "flow_rate.txt", (diam, flow_rate))

    # compute the number of cells
    num_cells = gb.num_cells(lambda g: g.dim == 2)
    with open(folder_export + "cells.txt", "w") as f:
        f.write(str(num_cells))
예제 #16
0
def main(id_problem, is_coarse=False, tol=1e-5, N_pts=1000, if_export=False):

    folder_export = "example_2_2_vem/" + str(id_problem) + "/"
    file_export = "vem"

    gb = example_2_2_create_grid.create(id_problem,
                                        is_coarse=is_coarse,
                                        tol=tol)

    # Assign parameters
    example_2_2_data.add_data(gb, tol)

    # Choose and define the solvers and coupler
    solver_flow = vem_dual.DualVEMDFN(gb.dim_max(), "flow")
    A_flow, b_flow = solver_flow.matrix_rhs(gb)

    solver_source = vem_source.DualSourceDFN(gb.dim_max(), "flow")
    A_source, b_source = solver_source.matrix_rhs(gb)

    up = sps.linalg.spsolve(A_flow + A_source, b_flow + b_source)
    solver_flow.split(gb, "up", up)

    gb.add_node_props(["discharge", "pressure", "P0u"])
    solver_flow.extract_u(gb, "up", "discharge")
    solver_flow.extract_p(gb, "up", "pressure")
    solver_flow.project_u(gb, "discharge", "P0u")

    if if_export:
        save = Exporter(gb, file_export, folder_export)
        save.write_vtk(["pressure", "P0u"])

    b_box = gb.bounding_box()
    y_range = np.linspace(b_box[0][1] + tol, b_box[1][1] - tol, N_pts)
    pts = np.stack((1.5 * np.ones(N_pts), y_range, 0.5 * np.ones(N_pts)))
    values = example_2_2_data.plot_over_line(gb, pts, "pressure", tol)

    arc_length = y_range - b_box[0][1]
    np.savetxt(folder_export + "plot_over_line.txt", (arc_length, values))

    # compute the flow rate
    diam, flow_rate = example_2_2_data.compute_flow_rate_vem(gb, tol)
    np.savetxt(folder_export + "flow_rate.txt", (diam, flow_rate))
예제 #17
0
def main(kf, description, is_coarse=False, if_export=False):
    mesh_kwargs = {}
    mesh_kwargs['mesh_size'] = {
        'mode': 'constant',
        'value': 0.045,
        'bound_value': 0.045
    }

    domain = {'xmin': 0, 'xmax': 1, 'ymin': 0, 'ymax': 1}

    file_name = 'network_geiger.csv'
    write_network(file_name)
    gb = importer.dfm_2d_from_csv(file_name, mesh_kwargs, domain)
    gb.compute_geometry()
    if is_coarse:
        co.coarsen(gb, 'by_volume')
    gb.assign_node_ordering()

    internal_flag = FaceTag.FRACTURE
    [g.remove_face_tag_if_tag(FaceTag.BOUNDARY, internal_flag) for g, _ in gb]

    # Assign parameters
    add_data(gb, domain, kf)

    # Choose and define the solvers and coupler
    solver_flow = vem_dual.DualVEMMixedDim('flow')
    A_flow, b_flow = solver_flow.matrix_rhs(gb)

    solver_source = vem_source.IntegralMixedDim('flow')
    A_source, b_source = solver_source.matrix_rhs(gb)

    up = sps.linalg.spsolve(A_flow + A_source, b_flow + b_source)
    solver_flow.split(gb, "up", up)

    gb.add_node_props(["discharge", 'pressure', "P0u"])
    solver_flow.extract_u(gb, "up", "discharge")
    solver_flow.extract_p(gb, "up", 'pressure')
    solver_flow.project_u(gb, "discharge", "P0u")

    if if_export:
        save = Exporter(gb, "vem", folder="vem_" + description)
        save.write_vtk(['pressure', "P0u"])
예제 #18
0
    def __init__(self, gb, data=None, physics="flow", **kwargs):
        self.physics = physics
        self._gb = gb
        self.is_GridBucket = isinstance(self._gb, GridBucket)
        self._data = data

        self.lhs = []
        self.rhs = []
        self.x = []

        file_name = kwargs.get("file_name", physics)
        folder_name = kwargs.get("folder_name", "results")
        mesh_kw = kwargs.get("mesh_kw", {})

        tic = time.time()
        logger.info("Create exporter")
        self.exporter = Exporter(self._gb, file_name, folder_name, **mesh_kw)
        logger.info("Elapsed time: " + str(time.time() - tic))

        self._flux_disc = self.flux_disc()
        self._source_disc = self.source_disc()
예제 #19
0
    def __init__(self, gb, data=None, physics='flow', **kwargs):
        self.physics = physics
        self._gb = gb
        self.is_GridBucket = isinstance(self._gb, GridBucket)
        self._data = data

        self.lhs = []
        self.rhs = []
        self.x = []

        file_name = kwargs.get('file_name', physics)
        folder_name = kwargs.get('folder_name', 'results')
        mesh_kw = kwargs.get('mesh_kw', {})

        tic = time.time()
        logger.info('Create exporter')
        self.exporter = Exporter(self._gb, file_name, folder_name, **mesh_kw)
        logger.info('Elapsed time: ' + str(time.time() - tic))

        self._flux_disc = self.flux_disc()
        self._source_disc = self.source_disc()
예제 #20
0
def main(kf, description, multi_point, if_export=False):

    # Define the geometry and produce the meshes
    mesh_kwargs = {}
    mesh_size = 0.045
    mesh_kwargs['mesh_size'] = {
        'mode': 'constant',
        'value': mesh_size,
        'bound_value': mesh_size
    }
    domain = {'xmin': 0, 'xmax': 1, 'ymin': 0, 'ymax': 1}

    file_name = 'network_geiger.csv'
    write_network(file_name)
    gb = importer.dfm_2d_from_csv(file_name, mesh_kwargs, domain)
    gb.compute_geometry()
    gb.assign_node_ordering()

    # Assign parameters
    add_data(gb, domain, kf, mesh_size)

    # Choose discretization and define the solver
    if multi_point:
        solver = mpfa.MpfaMixedDim('flow')
    else:
        solver = tpfa.TpfaMixedDim('flow')

    # Discretize
    A, b = solver.matrix_rhs(gb)

    # Solve the linear system
    p = sps.linalg.spsolve(A, b)

    # Store the solution
    gb.add_node_props(['pressure'])
    solver.split(gb, 'pressure', p)

    if if_export:
        save = Exporter(gb, "fv", folder="fv_" + description)
        save.write_vtk(['pressure'])
예제 #21
0
    def test_upwind_example1(self, if_export=False):
        #######################
        # Simple 2d upwind problem with implicit Euler scheme in time
        #######################
        T = 1
        Nx, Ny = 10, 1
        g = structured.CartGrid([Nx, Ny], [1, 1])
        g.compute_geometry()

        advect = upwind.Upwind("transport")
        param = Parameters(g)
        dis = advect.discharge(g, [1, 0, 0])

        b_faces = g.get_all_boundary_faces()
        bc = BoundaryCondition(g, b_faces, ["dir"] * b_faces.size)
        bc_val = np.hstack(([1], np.zeros(g.num_faces - 1)))
        param.set_bc("transport", bc)
        param.set_bc_val("transport", bc_val)

        data = {"param": param, "discharge": dis}
        data["deltaT"] = advect.cfl(g, data)

        U, rhs = advect.matrix_rhs(g, data)
        M, _ = mass_matrix.MassMatrix().matrix_rhs(g, data)

        conc = np.zeros(g.num_cells)

        # Perform an LU factorization to speedup the solver
        IE_solver = sps.linalg.factorized((M + U).tocsc())

        # Loop over the time
        Nt = int(T / data["deltaT"])
        time = np.empty(Nt)
        folder = "example1"
        save = Exporter(g, "conc_IE", folder)
        for i in np.arange(Nt):

            # Update the solution
            # Backward and forward substitution to solve the system
            conc = IE_solver(M.dot(conc) + rhs)
            time[i] = data["deltaT"] * i
            if if_export:
                save.write_vtk({"conc": conc}, time_step=i)

        if if_export:
            save.write_pvd(time)

        known = np.array([
            0.99969927,
            0.99769441,
            0.99067741,
            0.97352474,
            0.94064879,
            0.88804726,
            0.81498958,
            0.72453722,
            0.62277832,
            0.51725056,
        ])
        assert np.allclose(conc, known)
예제 #22
0
def main(id_problem, tol=1e-5, if_export=False):

    folder_export = "example_1_tpfa/"
    file_name_error = folder_export + "tpfa_error.txt"
    gb = example_1_create_grid.create(0.5 / float(id_problem), tol)

    if if_export:
        save = Exporter(gb, "tpfa", folder_export)

    example_1_data.assign_frac_id(gb)

    # Assign parameters
    example_1_data.add_data(gb, tol)

    # Choose and define the solvers and coupler
    solver_flow = tpfa.TpfaDFN(gb.dim_max(), "flow")
    A_flow, b_flow = solver_flow.matrix_rhs(gb)

    solver_source = source.IntegralDFN(gb.dim_max(), "flow")
    A_source, b_source = solver_source.matrix_rhs(gb)

    p = sps.linalg.spsolve(A_flow + A_source, b_flow + b_source)
    solver_flow.split(gb, "pressure", p)

    def only_max_dim(g):
        return g.dim == gb.dim_max()

    diam = gb.diameter(only_max_dim)
    error_pressure = example_1_data.error_pressure(gb, "pressure")
    print("h=", diam, "- err(p)=", error_pressure)

    with open(file_name_error, "a") as f:
        info = (str(gb.num_cells(only_max_dim)) + " " +
                str(gb.num_cells(only_max_dim)) + " " + str(error_pressure) +
                "\n")
        f.write(info)

    if if_export:
        save.write_vtk(["pressure", "err"])
예제 #23
0
def main(id_problem, tol=1e-5, N_pts=1000, if_export=False):

    mesh_size = 0.425
    folder_export = "example_2_1_mpfa_" + str(mesh_size) + "/" + str(
        id_problem) + "/"
    file_export = "mpfa"

    gb = example_2_1_create_grid.create(id_problem,
                                        mesh_size=mesh_size,
                                        tol=tol)

    # Assign parameters
    example_2_1_data.add_data(gb, tol)

    # Choose and define the solvers and coupler
    solver_flux = mpfa.MpfaDFN(gb.dim_max(), "flow")
    A_flux, b_flux = solver_flux.matrix_rhs(gb)
    solver_source = source.IntegralDFN(gb.dim_max(), "flow")
    A_source, b_source = solver_source.matrix_rhs(gb)

    p = sps.linalg.spsolve(A_flux + A_source, b_flux + b_source)
    solver_flux.split(gb, "pressure", p)

    if if_export:
        save = Exporter(gb, file_export, folder_export)
        save.write_vtk(["pressure"])

    b_box = gb.bounding_box()
    z_range = np.linspace(b_box[0][2], b_box[1][2], N_pts)
    pts = np.stack((0.5 * np.ones(N_pts), 0.5 * np.ones(N_pts), z_range))
    values = example_2_1_data.plot_over_line(gb, pts, "pressure", tol)

    arc_length = z_range - b_box[0][2]
    np.savetxt(folder_export + "plot_over_line.txt", (arc_length, values))

    # compute the flow rate
    fvutils.compute_discharges(gb, "flow")
    diam, flow_rate = example_2_1_data.compute_flow_rate(gb, tol)
    np.savetxt(folder_export + "flow_rate.txt", (diam, flow_rate))
예제 #24
0
    def __init__(self, gb, data, physics='slip', **kwargs):
        self.physics = physics
        if isinstance(gb, GridBucket):
            raise ValueError('FrictionSlip excpected a Grid, not a GridBucket')

        self._gb = gb
        self._data = data

        file_name = kwargs.get('file_name', physics)
        folder_name = kwargs.get('folder_name', 'results')

        tic = time.time()
        logger.info('Create exporter')
        self.exporter = Exporter(self._gb, file_name, folder_name)
        logger.info('Elapsed time: ' + str(time.time() - tic))

        self.x = np.zeros((3, gb.num_faces))
        self.d_n = np.zeros(gb.num_faces)

        self.is_slipping = np.zeros(gb.num_faces, dtype=np.bool)

        self.slip_name = 'slip_distance'
        self.aperture_name = 'aperture_change'
예제 #25
0
    def __init__(self, gb, data, physics="slip", **kwargs):
        self.physics = physics
        if isinstance(gb, GridBucket):
            raise ValueError("FrictionSlip excpected a Grid, not a GridBucket")

        self._gb = gb
        self._data = data

        file_name = kwargs.get("file_name", physics)
        folder_name = kwargs.get("folder_name", "results")

        tic = time.time()
        logger.info("Create exporter")
        self.exporter = Exporter(self._gb, file_name, folder_name)
        logger.info("Elapsed time: " + str(time.time() - tic))

        self.x = np.zeros((3, gb.num_faces))
        self.d_n = np.zeros(gb.num_faces)

        self.is_slipping = np.zeros(gb.num_faces, dtype=np.bool)

        self.slip_name = "slip_distance"
        self.aperture_name = "aperture_change"
예제 #26
0
    def test_upwind_example0(self, if_export=False):
        #######################
        # Simple 2d upwind problem with explicit Euler scheme in time
        #######################
        T = 1
        Nx, Ny = 4, 1
        g = structured.CartGrid([Nx, Ny], [1, 1])
        g.compute_geometry()

        advect = upwind.Upwind("transport")
        param = Parameters(g)
        dis = advect.discharge(g, [1, 0, 0])

        b_faces = g.get_all_boundary_faces()
        bc = BoundaryCondition(g, b_faces, ['dir'] * b_faces.size)
        bc_val = np.hstack(([1], np.zeros(g.num_faces - 1)))
        param.set_bc("transport", bc)
        param.set_bc_val("transport", bc_val)

        data = {'param': param, 'discharge': dis}
        data['deltaT'] = advect.cfl(g, data)

        U, rhs = advect.matrix_rhs(g, data)
        OF = advect.outflow(g, data)
        M, _ = mass_matrix.MassMatrix().matrix_rhs(g, data)

        conc = np.zeros(g.num_cells)

        M_minus_U = M - U
        invM, _ = mass_matrix.InvMassMatrix().matrix_rhs(g, data)

        # Loop over the time
        Nt = int(T / data['deltaT'])
        time = np.empty(Nt)
        folder = 'example0'
        production = np.zeros(Nt)
        save = Exporter(g, "conc_EE", folder)
        for i in np.arange(Nt):

            # Update the solution
            production[i] = np.sum(OF.dot(conc))
            conc = invM.dot((M_minus_U).dot(conc) + rhs)
            time[i] = data['deltaT'] * i
            if if_export:
                save.write_vtk({"conc": conc}, time_step=i)

        if if_export:
            save.write_pvd(time)

        known = 1.09375
        assert np.sum(production) == known
예제 #27
0
gb.add_node_props(["p", "P0u", "discharge"])
solver_flow.extract_u(gb, "up", "discharge")
solver_flow.extract_p(gb, "up", "p")
solver_flow.project_u(gb, "discharge", "P0u")

# compute the flow rate
total_flow_rate = 0
for g, d in gb:
    bound_faces = g.tags["domain_boundary_faces"].nonzero()[0]
    if bound_faces.size != 0:
        bound_face_centers = g.face_centers[:, bound_faces]
        left = bound_face_centers[0, :] < domain["xmin"] + tol
        flow_rate = d["discharge"][bound_faces[left]]
        total_flow_rate += np.sum(flow_rate)

save = Exporter(gb, "darcy", export_folder, binary=False)
save.write_vtk(["p", "P0u"])

#################################################################

physics = "transport"
advection = upwind.UpwindMixedDim(physics)
mass = mass_matrix.MassMatrixMixedDim(physics)
invMass = mass_matrix.InvMassMatrixMixDim(physics)

# Assign parameters
add_data_advection(gb, domain, tol)

gb.add_node_prop("deltaT", prop=deltaT)

U, rhs_u = advection.matrix_rhs(gb)
예제 #28
0
class StaticModel():
    '''
    Class for solving an static elasticity problem flow problem:
     \nabla \sigma = 0,
    where nabla is the stress tensor.

    Parameters in Init:
    gb: (Grid) a grid object.
    data (dictionary): dictionary of data. Should contain a Parameter class
                       with the keyword 'Param'
    physics: (string): defaults to 'mechanics'

    Functions:
    solve(): Calls reassemble and solves the linear system.
             Returns: the displacement d.
             Sets attributes: self.x
    step(): Same as solve, but without reassemble of the matrices
    reassemble(): Assembles the lhs matrix and rhs array.
            Returns: lhs, rhs.
            Sets attributes: self.lhs, self.rhs
    stress_disc(): Defines the discretization of the stress term.
            Returns stress discretization object (E.g., Mpsa)
    grid(): Returns: the Grid or GridBucket
    data(): Returns: Data dictionary
    traction(name='traction'): Calculate the traction over each
                face in the grid and assigne it to the data dictionary as
                keyword name.
    save(): calls split('d'). Then export the pressure to a vtk file to the
            folder kwargs['folder_name'] with file name
            kwargs['file_name'], default values are 'results' for the folder and
            physics for the file name.
    '''
    def __init__(self, gb, data, physics='mechanics', **kwargs):
        self.physics = physics
        self._gb = gb
        if not isinstance(self._gb, Grid):
            raise ValueError('StaticModel only defined for Grid class')

        self._data = data

        self.lhs = []
        self.rhs = []
        self.x = []

        file_name = kwargs.get('file_name', physics)
        folder_name = kwargs.get('folder_name', 'results')

        tic = time.time()
        logger.info('Create exporter')
        self.exporter = Exporter(self._gb, file_name, folder_name)
        logger.info('Elapsed time: ' + str(time.time() - tic))

        self._stress_disc = self.stress_disc()

        self.displacement_name = 'displacement'
        self.frac_displacement_name = 'frac_displacement'

    def solve(self, max_direct=40000, callback=False, **kwargs):
        """ Reassemble and solve linear system.

        After the funtion has been called, the attributes lhs and rhs are
        updated according to the parameter states. Also, the attribute x
        gives the pressure given the current state.

        The function attempts to set up the best linear solver based on the
        system size. The setup and parameter choices here are still
        experimental.

        Parameters:
            max_direct (int): Maximum number of unknowns where a direct solver
                is applied. If a direct solver can be applied this is usually
                the most efficient option. However, if the system size is
                too large compared to available memory, a direct solver becomes
                extremely slow.
            callback (boolean, optional): If True iteration information will be
                output when an iterative solver is applied (system size larger
                than max_direct)

        Returns:
            np.array: Pressure state.

        """
        # Discretize
        tic = time.time()
        logger.info('Discretize')
        self.lhs, self.rhs = self.reassemble(**kwargs)
        logger.info('Done. Elapsed time ' + str(time.time() - tic))

        # Solve
        tic = time.time()
        ls = LSFactory()

        if self.rhs.size < max_direct:
            logger.info('Solve linear system using direct solver')
            self.x = ls.direct(self.lhs, self.rhs)
        else:
            logger.info('Solve linear system using GMRES')
            precond = self._setup_preconditioner()
            #            precond = ls.ilu(self.lhs)
            slv = ls.gmres(self.lhs)
            self.x, info = slv(self.rhs,
                               M=precond,
                               callback=callback,
                               maxiter=10000,
                               restart=1500,
                               tol=1e-8)
            if info == 0:
                logger.info('GMRES succeeded.')
            else:
                logger.error('GMRES failed with status ' + str(info))

        logger.info('Done. Elapsed time ' + str(time.time() - tic))
        return self.x

    def step(self, **kwargs):
        """
        Calls self.solve(**kwargs)
        """
        return self.solve(**kwargs)

    def reassemble(self, discretize=True):
        """
        reassemble matrices. This must be called between every time step to
        update the rhs of the system.
        """
        self.lhs, self.rhs = self._stress_disc.matrix_rhs(
            self.grid(), self.data(), discretize)
        return self.lhs, self.rhs

    def stress_disc(self):
        """
        Define the stress discretization. 
        Returns:
            FracturedMpsa (Solver object)
        """
        return mpsa.FracturedMpsa(physics=self.physics)

    def grid(self):
        """
        get the model grid
        Returns:
            gb (Grid object)
        """
        return self._gb

    def data(self):
        """
        get data
        Returns:
            data (Dictionary)
        """
        return self._data

    def displacement(self, displacement_name='displacement'):
        """
        Save the cell displacement to the data dictionary. The displacement
        will be saved as a (3,  self.grid().num_cells) array
        Parameters: 
        -----------
        displacement_name:    (string) Defaults to 'displacement'. Defines the
                              keyword for the saved displacement in the data
                              dictionary
        Returns:
        --------
        d:  (ndarray) the displacement as a (3, self.grid().num_cells) array
        """

        self.displacement_name = displacement_name
        d = self._stress_disc.extract_u(self.grid(), self.x)
        d = d.reshape((3, -1), order='F')
        self._data[self.displacement_name] = d
        return d

    def frac_displacement(self, frac_displacement_name='frac_displacement'):
        """
        Save the fracture displacement to the data dictionary. This is the 
        displacement on the fracture facers. The displacement
        will be saved as a (3,  self.grid().num_cells) array
        Parameters: 
        -----------
        frac_displacement_name: 
            (string) Defaults to 'frac_displacement'. Defines the keyword for
            the saved displacement in the data dictionary

        Returns:
        --------
        d:  (ndarray) the displacement of size (3, #number of fracture faces)
        """
        self.frac_displacement_name = frac_displacement_name
        d = self._stress_disc.extract_frac_u(self.grid(), self.x)
        d = d.reshape((3, -1), order='F')
        self._data[self.frac_displacement_name] = d
        return d

    def traction(self, traction_name='traction'):
        """
        Save the  traction on faces to the data dictionary. This is the 
        area scaled traction on the fracture facers. The displacement
        will be saved as a (3,  self.grid().num_cells) array
        Parameters: 
        -----------
        traction_name
            (string) Defaults to 'traction'. Defines the keyword for the
            saved traction in the data dictionary

        Returns:
        --------
        d:  (ndarray) the traction as a (3, self.grid().num_faces) array
        """
        T = self._stress_disc.traction(self.grid(), self._data, self.x)
        T = T.reshape((self.grid().dim, -1), order='F')
        T_b = np.zeros(T.shape)
        sigma = self._data['param'].get_background_stress(self.physics)
        if np.any(sigma):
            normals = self.grid().face_normals
            for i in range(normals.shape[1]):
                T_b[:, i] = np.dot(normals[:, i], sigma)
        else:
            T_b = 0
        self._data[traction_name] = T + T_b

    def save(self, variables=None, time_step=None):
        """
        Save the result as vtk. 

        Parameters:
        ----------
        variables: (list) Optional, defaults to None. If None, only the grid
            will be exported. A list of strings where each element defines a
            keyword in the data dictionary to be saved.
        time_step: (float) optinal, defaults to None. The time step of the
            variable(s) that is saved
        """

        if variables is None:
            self.exporter.write_vtk()
        else:
            variables = {k: self._data[k] for k in variables \
                         if k in self._data}
            self.exporter.write_vtk(variables, time_step=time_step)

    ### Helper functions for linear solve below
    def _setup_preconditioner(self):
        solvers, ind, not_ind = self._assign_solvers()

        def precond(r):
            x = np.zeros_like(r)
            for s, i, ni in zip(solvers, ind, not_ind):
                x[i] += s(r[i])
            return x

        def precond_mult(r):
            x = np.zeros_like(r)
            A = self.lhs
            for s, i, ni in zip(solvers, ind, not_ind):
                r_i = r[i] - A[i, :][:, ni] * x[ni]
                x[i] += s(r_i)
            return x

        M = lambda r: precond(r)
        return spl.LinearOperator(self.lhs.shape, M)

    def _assign_solvers(self):
        mat, ind = self._obtain_submatrix()
        all_ind = np.arange(self.rhs.size)
        not_ind = [np.setdiff1d(all_ind, i) for i in ind]

        factory = LSFactory()
        num_mat = len(mat)
        solvers = np.empty(num_mat, dtype=np.object)
        for i, A in enumerate(mat):
            sz = A.shape[0]
            if sz < 5000:
                solvers[i] = factory.direct(A)
            else:
                # amg solver is pyamg is installed, if not ilu
                try:
                    solvers[i] = factory.amg(A, as_precond=True)
                except ImportError:
                    solvers[i] = factory.ilu(A)

        return solvers, ind, not_ind

    def _obtain_submatrix(self):
        return [self.lhs], [np.arange(self.grid().num_cells)]
예제 #29
0
class FrictionSlipModel:
    """
    Class for solving a frictional slip problem: T_s <= mu * (T_n -p)
    

    Parameters in Init:
    gb: (Grid) a Grid Object.
    data: (dictionary) Should contain a Parameter class with the keyword
        'Param'
    physics: (string): defaults to 'slip'

    Functions:
    solve(): Calls reassemble and solves the linear system.
             Returns: new slip if T_s > mu * (T_n - p)
             Sets attributes: self.x, self.is_slipping, self.d_n
    step(): Same as solve
    normal_shear_traction(): project the traction into the corresponding
                             normal and shear components
    grid(): Returns: the Grid or GridBucket
    data(): Returns: Data dictionary
    fracture_dilation(slip_distance): Returns: the amount of dilation for given
                                               slip distance
    slip_distance(): saves the slip distance to the data dictionary and
                     returns it
    aperture_change(): saves the aperture change to the data dictionary and
                       returns it
    mu(faces): returns: the coefficient of friction
    gamma(): returns: the numerical step length parameter
    save(): calls split('pressure'). Then export the pressure to a vtk file to the
            folder kwargs['folder_name'] with file name
            kwargs['file_name'], default values are 'results' for the folder and
            physics for the file name.
    """
    def __init__(self, gb, data, physics="slip", **kwargs):
        self.physics = physics
        if isinstance(gb, GridBucket):
            raise ValueError("FrictionSlip excpected a Grid, not a GridBucket")

        self._gb = gb
        self._data = data

        file_name = kwargs.get("file_name", physics)
        folder_name = kwargs.get("folder_name", "results")

        tic = time.time()
        logger.info("Create exporter")
        self.exporter = Exporter(self._gb, file_name, folder_name)
        logger.info("Elapsed time: " + str(time.time() - tic))

        self.x = np.zeros((3, gb.num_faces))
        self.d_n = np.zeros(gb.num_faces)

        self.is_slipping = np.zeros(gb.num_faces, dtype=np.bool)

        self.slip_name = "slip_distance"
        self.aperture_name = "aperture_change"

    def solve(self):
        """ Linearize and solve corresponding system

        First, the function calculate if the slip-criterion is satisfied for
        each face: T_s <= mu * (T_n - p).
        If this is violated, the fracture is slipping. It estimates the slip
        in direction of shear traction as:
        d += T_s - mu(T_n - p) * sqrt(face_area) / G.

        Stores this result in self.x which is a ndarray of dimension
        (3, number of faces). Also updates the ndarray self.is_slipping to
        True for any face that violated the slip-criterion.

        Requires the following keywords in the data dictionary:
        'face_pressure': (ndarray) size equal number of faces in the grid.
                         Only the pressure on the fracture faces are used, and
                         should be equivalent to the pressure in the
                        pressure in the corresponding lower dimensional cells.
        'traction': (ndarray) size (3, number_of_faces). This should be the 
                    area scaled traction on each face.
        'rock': a Rock Object with shear stiffness Rock.MU defined.

        Returns:
            new_slip (bool) returns True if the slip vector was violated for
                     any faces
        """
        assert self._gb.dim == 3, "only support for 3D (yet)"

        frac_faces = self._gb.frac_pairs
        fi = frac_faces[1]
        fi_left = frac_faces[0]
        T_n, T_s, n, t = self.normal_shear_traction(fi)

        assert np.all(T_s > -1e-10)
        assert np.all(T_n < 0), "Must have a normal force on the fracture"

        # we find the effective normal stress on the fracture face.
        # Here we need to multiply T_n with -1 as we want the absolute value,
        # and all the normal tractions should be negative.
        sigma_n = -T_n - self._data["face_pressure"][fi]
        #        assert np.all(sigma_n > 0 )

        # new slip are fracture faces slipping in this iteration
        new_slip = (T_s - self.mu(fi, self.is_slipping[fi]) * sigma_n >
                    1e-5 * self._data["rock"].MU)

        self.is_slipping[fi] = self.is_slipping[fi] | new_slip

        # calculate the shear stiffness
        shear_stiffness = np.sqrt(
            self._gb.face_areas[fi]) / (self._data["rock"].MU)

        # calculate aproximated slip distance
        excess_shear = np.abs(T_s) - self.mu(fi,
                                             self.is_slipping[fi]) * sigma_n
        slip_d = excess_shear * shear_stiffness * self.gamma() * new_slip

        # We also add the values to the left cells so that when we average the
        # face values to obtain a cell value, it will equal the face value

        slip_vec = -t * slip_d - n * self.fracture_dilation(slip_d, fi)

        self.d_n[fi] += self.fracture_dilation(slip_d, fi)
        self.d_n[fi_left] += self.fracture_dilation(slip_d, fi_left)

        assert np.all(self.d_n[fi] > -1e-6)

        self.x[:, fi] += slip_vec
        self.x[:, fi_left] -= slip_vec

        return new_slip

    def normal_shear_traction(self, faces=None):
        """
        Project the traction vector into the normal and tangential components
        as seen from the fractures. 
        Requires that the data dictionary has keyword:
        traction:  (ndarray) size (3, number of faces). giving the area
                   weighted traction on each face.
        
        Returns:
        --------
        T_n:  (ndarray) size (number of fracture_cells) the normal traction on
              each fracture.
        T_s:  (ndarray) size (number of fracture_cells) the shear traction on
              each fracture.
        normals: (ndarray) size (3, number of fracture_cells) normal vector,
            i.e., the direction of normal traction
        tangents: (ndarray) size (3, number of fracture_cells) tangential
            vector, i.e., the direction of shear traction
        """

        if faces is None:
            frac_faces = self._gb.frac_pairs
            fi = frac_faces[1]
        else:
            fi = faces

        assert self._gb.dim == 3
        T = self._data["traction"].copy()
        T = T / self._gb.face_areas

        sgn = sign_of_faces(self._gb, fi)
        # sgn_test = g.cell_faces[fi, ci]

        T = sgn * T[:, fi]
        normals = sgn * self._gb.face_normals[:, fi] / self._gb.face_areas[fi]
        assert np.allclose(np.sqrt(np.sum(normals**2, axis=0)), 1)

        T_n = np.sum(T * normals, axis=0)
        tangents = T - T_n * normals
        T_s = np.sqrt(np.sum(tangents**2, axis=0))
        tangents = tangents / np.sqrt(np.sum(tangents**2, axis=0))
        assert np.allclose(np.sqrt(np.sum(tangents**2, axis=0)), 1)
        assert np.allclose(T, T_n * normals + T_s * tangents)
        # Sanity check:
        frac_faces = self._gb.frac_pairs
        trac = self._data["traction"].copy()
        fi_left = frac_faces[0]
        sgn_left = sign_of_faces(self._gb, fi_left)
        sgn_right = sign_of_faces(self._gb, fi)
        T_left = sgn_left * trac.reshape((3, -1), order="F")[:, fi_left]
        T_right = sgn_right * trac.reshape((3, -1), order="F")[:, fi]
        assert np.allclose(T_left, -T_right)

        # TESTING DONE

        return T_n, T_s, normals, tangents

    def fracture_dilation(self, distance, _):
        """
        defines the fracture dilation as a function of slip distance
        Parameters:
        ----------
        distance: (ndarray) the slip distances

        Returns:
        ---------
        dilation: (ndarray) the corresponding normal displacement of fractures.
        """

        phi = 1 * np.pi / 180
        return distance * np.tan(phi)

    def mu(self, faces, slip_faces=[]):
        """
        Coefficient of friction.
        Parameters:
        ----------
        faces: (ndarray) indexes of fracture faces
        slip_faces: (ndarray) optional, defaults to []. Indexes of faces that
                    are slipping ( will be given a dynamic friciton).
        returns:
        mu: (ndarray) the coefficient of each fracture face.
        """
        mu_d = 0.55
        mu_ = 0.6 * np.ones(faces.size)
        mu_[slip_faces] = mu_d
        return mu_

    def gamma(self):
        """
        Numerical step length parameter. Defines of far a fracture violating 
        the slip-condition should slip.
        """
        return 2

    def step(self):
        """
        calls self.solve()
        """
        return self.solve()

    def grid(self):
        """
        returns model grid
        """
        return self._gb

    def data(self):
        """
        returns data
        """
        return self._data

    def slip_distance(self, slip_name="slip_distance"):
        """
        Save the slip distance to the data dictionary. The slip distance
        will be saved as a (3, self.grid().num_faces) array
        Parameters: 
        -----------
        slip_name:    (string) Defaults to 'slip_distance'. Defines the
                               keyword for the saved slip distance in the data
                               dictionary
        Returns:
        --------
        d:  (ndarray) the slip distance as a (3, self.grid().num_faces) array
        """
        self.slip_name = slip_name
        self._data[self.slip_name] = self.x
        return self.x

    def aperture_change(self, aperture_name="aperture_change"):
        """
        Save the aperture change to the data dictionary. The aperture change
        will be saved as a (self.grid().num_faces) array
        Parameters: 
        -----------
        slip_name:    (string) Defaults to 'aperture_name'. Defines the
                               keyword for the saved aperture change in the data
                               dictionary
        Returns:
        --------
        d:  (ndarray) the change in aperture as a (self.grid().num_faces) array
        """
        self.aperture_name = aperture_name
        self._data[self.aperture_name] = self.d_n
        return self.d_n

    def save(self, variables=None, save_every=None):
        """
        Save the result as vtk. 

        Parameters:
        ----------
        variables: (list) Optional, defaults to None. If None, only the grid
            will be exported. A list of strings where each element defines a
            keyword in the data dictionary to be saved.
        time_step: (float) optinal, defaults to None. The time step of the
            variable(s) that is saved
        """
        if variables is None:
            self.exporter.write_vtk()
        else:
            variables = {
                k: self._data[k]
                for k in variables if k in self._data
            }
            self.exporter.write_vtk(variables)
예제 #30
0
    def test_upwind_example2(self, if_export=False):
        #######################
        # Simple 2d upwind problem with explicit Euler scheme in time coupled with
        # a Darcy problem
        #######################
        T = 2
        Nx, Ny = 10, 10
        folder = 'example2'

        def funp_ex(pt):
            return -np.sin(pt[0]) * np.sin(pt[1]) - pt[0]

        g = structured.CartGrid([Nx, Ny], [1, 1])
        g.compute_geometry()

        param = Parameters(g)

        # Permeability
        perm = tensor.SecondOrderTensor(g.dim, kxx=np.ones(g.num_cells))
        param.set_tensor("flow", perm)

        # Source term
        param.set_source("flow", np.zeros(g.num_cells))

        # Boundaries
        b_faces = g.get_all_boundary_faces()
        bc = BoundaryCondition(g, b_faces, ['dir'] * b_faces.size)
        bc_val = np.zeros(g.num_faces)
        bc_val[b_faces] = funp_ex(g.face_centers[:, b_faces])
        param.set_bc("flow", bc)
        param.set_bc_val("flow", bc_val)

        # Darcy solver
        data = {'param': param}
        solver = vem_dual.DualVEM("flow")
        D_flow, b_flow = solver.matrix_rhs(g, data)

        solver_source = vem_source.DualSource('flow')
        D_source, b_source = solver_source.matrix_rhs(g, data)

        up = sps.linalg.spsolve(D_flow + D_source, b_flow + b_source)

        p, u = solver.extract_p(g, up), solver.extract_u(g, up)
        P0u = solver.project_u(g, u, data)

        save = Exporter(g, "darcy", folder)

        if if_export:
            save.write_vtk({'pressure': p, "P0u": P0u})

        # Discharge
        dis = u

        # Boundaries
        bc = BoundaryCondition(g, b_faces, ['dir'] * b_faces.size)
        bc_val = np.hstack(([1], np.zeros(g.num_faces - 1)))
        param.set_bc("transport", bc)
        param.set_bc_val("transport", bc_val)

        data = {'param': param, 'discharge': dis}

        # Advect solver
        advect = upwind.Upwind("transport")

        U, rhs = advect.matrix_rhs(g, data)

        data['deltaT'] = advect.cfl(g, data)
        M, _ = mass_matrix.MassMatrix().matrix_rhs(g, data)

        conc = np.zeros(g.num_cells)
        M_minus_U = M - U
        invM, _ = mass_matrix.InvMassMatrix().matrix_rhs(g, data)

        # Loop over the time
        Nt = int(T / data['deltaT'])
        time = np.empty(Nt)
        save.change_name("conc_darcy")
        for i in np.arange(Nt):

            # Update the solution
            conc = invM.dot((M_minus_U).dot(conc) + rhs)
            time[i] = data['deltaT'] * i
            if if_export:
                save.write_vtk({"conc": conc}, time_step=i)

        if if_export:
            save.write_pvd(time)

        known = \
            np.array([9.63168200e-01,   8.64054875e-01,   7.25390695e-01,
                      5.72228235e-01,   4.25640080e-01,   2.99387331e-01,
                      1.99574336e-01,   1.26276876e-01,   7.59011550e-02,
                      4.33431230e-02,   3.30416807e-02,   1.13058617e-01,
                      2.05372538e-01,   2.78382057e-01,   3.14035373e-01,
                      3.09920132e-01,   2.75024694e-01,   2.23163145e-01,
                      1.67386939e-01,   1.16897527e-01,   1.06111312e-03,
                      1.11951850e-02,   3.87907727e-02,   8.38516119e-02,
                      1.36617802e-01,   1.82773271e-01,   2.10446545e-01,
                      2.14651936e-01,   1.97681518e-01,   1.66549151e-01,
                      3.20751341e-05,   9.85780113e-04,   6.07062715e-03,
                      1.99393042e-02,   4.53237556e-02,   8.00799828e-02,
                      1.17199623e-01,   1.47761481e-01,   1.64729339e-01,
                      1.65390555e-01,   9.18585872e-07,   8.08267622e-05,
                      8.47227168e-04,   4.08879583e-03,   1.26336029e-02,
                      2.88705048e-02,   5.27841497e-02,   8.10459333e-02,
                      1.07956484e-01,   1.27665318e-01,   2.51295298e-08,
                      6.29844122e-06,   1.09361990e-04,   7.56743783e-04,
                      3.11384414e-03,   9.04446601e-03,   2.03443897e-02,
                      3.75208816e-02,   5.89595194e-02,   8.11457277e-02,
                      6.63498510e-10,   4.73075468e-07,   1.33728945e-05,
                      1.30243418e-04,   7.01905707e-04,   2.55272292e-03,
                      6.96686157e-03,   1.52290448e-02,   2.78607282e-02,
                      4.40402650e-02,   1.71197497e-11,   3.47118057e-08,
                      1.57974045e-06,   2.13489614e-05,   1.48634295e-04,
                      6.68104990e-04,   2.18444135e-03,   5.58646819e-03,
                      1.17334966e-02,   2.09744728e-02,   4.37822313e-13,
                      2.52373622e-09,   1.83589660e-07,   3.40553325e-06,
                      3.02948532e-05,   1.66504215e-04,   6.45119867e-04,
                      1.90731440e-03,   4.53436628e-03,   8.99977737e-03,
                      1.12627412e-14,   1.84486857e-10,   2.13562387e-08,
                      5.39492977e-07,   6.08223906e-06,   4.05535296e-05,
                      1.84731221e-04,   6.25871542e-04,   1.66459389e-03,
                      3.59980231e-03])

        assert np.allclose(conc, known)