Exemplo n.º 1
0
def setup_discr_tpfa(gb, key="flow"):
    """ Setup the discretization Tpfa. """
    discr = pp.Tpfa(key)
    p_trace = pp.CellDofFaceDofMap(key)
    interface = pp.FluxPressureContinuity(key, discr, p_trace)

    for g, d in gb:
        if g.dim == gb.dim_max():
            d[pp.PRIMARY_VARIABLES] = {key: {"cells": 1}}
            d[pp.DISCRETIZATION] = {key: {"flux": discr}}
        else:
            d[pp.PRIMARY_VARIABLES] = {key: {"cells": 1}}
            d[pp.DISCRETIZATION] = {key: {"flux": p_trace}}

    for e, d in gb.edges():
        g_slave, g_master = gb.nodes_of_edge(e)
        d[pp.PRIMARY_VARIABLES] = {key: {"cells": 1}}
        d[pp.COUPLING_DISCRETIZATION] = {
            "flux": {
                g_slave: (key, "flux"),
                g_master: (key, "flux"),
                e: (key, interface),
            }
        }

    return pp.Assembler(gb), (discr, p_trace)
def advdiff(gb, discr, param, bc_flag):

    model = "transport"

    model_data_adv, model_data_diff, model_data_src = data_advdiff(
        gb, model, param, bc_flag
    )

    # discretization operator names
    adv_id = "advection"
    diff_id = "diffusion"
    src_id = "source"

    # variable names
    variable = "scalar"
    mortar_adv = "lambda_" + variable + "_" + adv_id
    mortar_diff = "lambda_" + variable + "_" + diff_id

    # save variable name for the post-process
    param["scalar"] = variable

    discr_adv = pp.Upwind(model_data_adv)
    discr_adv_interface = pp.CellDofFaceDofMap(model_data_adv)

    discr_diff = pp.Tpfa(model_data_diff)
    discr_diff_interface = pp.CellDofFaceDofMap(model_data_diff)

    coupling_adv = pp.UpwindCoupling(model_data_adv)
    coupling_diff = pp.FluxPressureContinuity(
        model_data_diff, discr_diff, discr_diff_interface
    )

    # mass term
    mass_id = "mass"
    discr_mass = pp.MassMatrix(model_data_adv)
    discr_mass_interface = pp.CellDofFaceDofMap(model_data_adv)

    discr_src = pp.ScalarSource(model_data_src)

    for g, d in gb:
        d[pp.PRIMARY_VARIABLES] = {variable: {"cells": 1}}
        if g.dim == gb.dim_max():
            d[pp.DISCRETIZATION] = {
                variable: {adv_id: discr_adv,
                diff_id: discr_diff,
                mass_id: discr_mass,
                src_id: discr_src}
            }
        else:
            d[pp.DISCRETIZATION] = {
                variable: {adv_id: discr_adv_interface,
                diff_id: discr_diff_interface,
                mass_id: discr_mass_interface}
            }

    for e, d in gb.edges():
        g_slave, g_master = gb.nodes_of_edge(e)
        d[pp.PRIMARY_VARIABLES] = {mortar_adv: {"cells": 1}, mortar_diff: {"cells": 1}}

        d[pp.COUPLING_DISCRETIZATION] = {
            adv_id: {
                g_slave: (variable, adv_id),
                g_master: (variable, adv_id),
                e: (mortar_adv, coupling_adv),
            },
            diff_id: {
                g_slave: (variable, diff_id),
                g_master: (variable, diff_id),
                e: (mortar_diff, coupling_diff),
            },
        }

    # setup the advection-diffusion problem
    assembler = pp.Assembler(gb, active_variables=[variable, mortar_diff, mortar_adv])
    logger.info("Assemble the advective and diffusive terms of the transport problem")
    block_A, block_b = assembler.assemble_matrix_rhs(add_matrices=False)
    logger.info("done")

    # unpack the matrices just computed
    diff_name = diff_id + "_" + variable
    adv_name = adv_id + "_" + variable
    mass_name = mass_id + "_" + variable
    source_name = src_id + "_" + variable

    diff_coupling_name = diff_id + "_" + mortar_diff + "_" + variable + "_" + variable
    adv_coupling_name = adv_id + "_" + mortar_adv + "_" + variable + "_" + variable

    # need a sign for the convention of the conservation equation
    M = block_A[mass_name]
    A = block_A[diff_name] + block_A[diff_coupling_name] + \
        block_A[adv_name] + block_A[adv_coupling_name]
    b = block_b[diff_name] + block_b[diff_coupling_name] + \
        block_b[adv_name] + block_b[adv_coupling_name] + \
        block_b[source_name]

    M_t = M.copy() / param["time_step"] * param.get("mass_weight", 1)
    M_r = M.copy() * param.get("reaction", 0)

    # Perform an LU factorization to speedup the solver
    IE_solver = sps.linalg.factorized((M_t + A + M_r).tocsc())

    # time loop
    logger.info("Prepare the exporting")
    save = pp.Exporter(gb, "solution", folder=param["folder"])
    logger.info("done")

    variables = [variable, param["pressure"], "frac_num", "cell_volumes"]
    if discr["scheme"] is pp.MVEM or discr["scheme"] is pp.RT0:
        variables.append(param["P0_flux"])

    # assign the initial condition
    x = np.zeros(A.shape[0])
    assembler.distribute_variable(x)
    for g, d in gb:
        if g.dim == gb.dim_max():
            d[pp.STATE][variable] = param.get("init_trans", 0) * np.ones(g.num_cells)

    x = assembler.merge_variable(variable)

    outflow = np.zeros(param["n_steps"])

    logger.info("Start the time loop with " + str(param["n_steps"]) + " steps")
    for i in np.arange(param["n_steps"]):
        logger.info("Solve the linear system for time step " + str(i))
        x = IE_solver(b + M_t.dot(x))
        logger.info("done")

        logger.info("Variable post-process")
        assembler.distribute_variable(x)
        logger.info("done")

        logger.info("Export variable")
        save.write_vtk(variables, time_step=i)
        logger.info("done")

        logger.info("Compute the production")
        outflow[i] = compute_outflow(gb, param)
        logger.info("done")

    time = np.arange(param["n_steps"]) * param["time_step"]
    save.write_pvd(time)

    logger.info("Save outflow on file")
    file_out = param["folder"] + "/outflow.csv"
    data = np.vstack((time, outflow)).T
    np.savetxt(file_out, data, delimiter=",")
    logger.info("done")

    logger.info("Save dof on file")
    file_out = param["folder"] + "/dof_transport.csv"
    np.savetxt(file_out, get_dof(assembler), delimiter=",", fmt="%d")
    logger.info("done")
def flow(gb, discr, param, bc_flag):

    model = "flow"

    model_data = data_flow(gb, discr, model, param, bc_flag)

    # discretization operator name
    flux_id = "flux"

    # master variable name
    variable = "flow_variable"
    mortar = "lambda_" + variable

    # post process variables
    pressure = "pressure"
    flux = "darcy_flux"  # it has to be this one

    # save variable name for the advection-diffusion problem
    param["pressure"] = pressure
    param["flux"] = flux
    param["mortar_flux"] = mortar

    discr_scheme = discr["scheme"](model_data)
    discr_interface = pp.CellDofFaceDofMap(model_data)

    coupling = pp.FluxPressureContinuity(model_data, discr_scheme, discr_interface)

    # define the dof and discretization for the grids
    for g, d in gb:
        if g.dim == gb.dim_max():
            d[pp.PRIMARY_VARIABLES] = {variable: discr["dof"]}
            d[pp.DISCRETIZATION] = {variable: {flux_id: discr_scheme}}
        else:
            d[pp.PRIMARY_VARIABLES] = {variable: {"cells": 1}}
            d[pp.DISCRETIZATION] = {variable: {flux_id: discr_interface}}

    # define the interface terms to couple the grids
    for e, d in gb.edges():
        g_slave, g_master = gb.nodes_of_edge(e)
        d[pp.PRIMARY_VARIABLES] = {mortar: {"cells": 1}}
        d[pp.COUPLING_DISCRETIZATION] = {
            flux: {
                g_slave: (variable, flux_id),
                g_master: (variable, flux_id),
                e: (mortar, coupling),
            }
        }

    # solution of the darcy problem
    assembler = pp.Assembler(gb)

    logger.info("Assemble the flow problem")
    A, b = assembler.assemble_matrix_rhs()
    logger.info("done")

    logger.info("Solve the linear system")
    x = sps.linalg.spsolve(A, b)
    logger.info("done")

    logger.info("Variable post-process")
    assembler.distribute_variable(x)

    # extract the pressure from the solution
    for g, d in gb:
        if g.dim == 2:
            d[pp.STATE][pressure] = discr_scheme.extract_pressure(g, d[pp.STATE][variable], d)
            d[pp.STATE][flux] = discr_scheme.extract_flux(g, d[pp.STATE][variable], d)
        else:
            d[pp.STATE][pressure] = np.zeros(g.num_cells)
            d[pp.STATE][flux] = np.zeros(g.num_faces)

    # export the P0 flux reconstruction only for some scheme
    if discr["scheme"] is pp.MVEM or discr["scheme"] is pp.RT0:
        P0_flux = "P0_flux"
        param["P0_flux"] = P0_flux
        pp.project_flux(gb, discr_scheme, flux, P0_flux, mortar)

    logger.info("done")

    logger.info("Save dof on file")
    file_out = param["folder"] + "/dof_flow.csv"
    np.savetxt(file_out, get_dof(assembler), delimiter=",", fmt="%d")
    logger.info("done")