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")