def solve(self): # consturct the matrices self.assembler.discretize() # in the case the fractures are scaled modify the problem if self.data.get("length_ratio", None) is not None: for g, d in self.gb: if g.dim == 1: ratio = self.data["length_ratio"][g.frac_num] d[pp.DISCRETIZATION_MATRICES][self.model]["flux"] *= ratio d[pp.DISCRETIZATION_MATRICES][self.model]["bound_flux"] *= ratio d[pp.DISCRETIZATION_MATRICES][self.model]["bound_pressure_face"] *= ratio d[pp.DISCRETIZATION_MATRICES][self.model]["bound_pressure_cell"] *= ratio A, b = self.assembler.assemble_matrix_rhs() # solve the problem p = sps.linalg.spsolve(A, b) # distribute the variables self.assembler.distribute_variable(p) # split the variables for g, d in self.gb: d[pp.STATE][self.pressure] = d[pp.STATE][self.variable] d[pp.STATE][self.P0_flux] = np.zeros(g.num_cells) d[pp.PARAMETERS][self.model][self.flux] = np.zeros(g.num_faces) # reconstruct the Darcy flux pp.fvutils.compute_darcy_flux(self.gb, keyword=self.model, d_name=self.flux, p_name=self.pressure, lam_name=self.mortar) # split the darcy flux on each grid-bucket grid for _, d in self.gb: d[pp.STATE][self.flux] = d[pp.PARAMETERS][self.model][self.flux] for e, d in self.gb.edges(): _, g_master = self.gb.nodes_of_edge(e) if g_master.dim == 1: ratio = self.data["length_ratio"][g_master.frac_num] d[pp.PARAMETERS][self.model][self.flux] *= ratio d[pp.STATE][self.mortar] = d[pp.PARAMETERS][self.model][self.flux] # export the P0 flux reconstruction pp.project_flux(self.gb, pp.MVEM(self.model), self.flux, self.P0_flux, self.mortar) # compute the module of the flow velocity and the azimuth for g, d in self.gb: P0_flux = d[pp.STATE][self.P0_flux] norm = np.sqrt(np.einsum("ij,ij->j", P0_flux, P0_flux)) d[pp.STATE][self.norm_flux] = norm north = self.data["north"] / np.linalg.norm(self.data["north"]) P0_flux_dir = np.divide(P0_flux, norm) azimuth = np.arctan2(P0_flux_dir[1, :], P0_flux_dir[0, :]) - \ np.arctan2(north[1], north[0]); d[pp.STATE][self.azimuth] = azimuth
def extract(self, x): self.assembler.distribute_variable(x) discr = self.discr(self.model) for g, d in self.gb: var = d[pp.STATE][self.variable] d[pp.STATE][self.pressure] = discr.extract_pressure(g, var, d) d[pp.STATE][self.flux] = discr.extract_flux(g, var, d) # export the P0 flux reconstruction pp.project_flux(self.gb, discr, self.flux, self.P0_flux, self.mortar)
def extract(self, x, block_dof, full_dof): logger.info("Variable post-process") self.assembler.distribute_variable(x) for g, d in self.gb: d[self.pressure] = self.discr.extract_pressure( g, d[self.variable], d) d[self.flux] = self.discr.extract_flux(g, d[self.variable], d) # export the P0 flux reconstruction pp.project_flux(self.gb, self.discr, self.flux, self.P0_flux, self.mortar) logger.info("done")
def extract(self, x): self.assembler.distribute_variable(x) discr = self.discr(self.model) for g, d in self.gb: var = d[pp.STATE][self.variable] d[pp.STATE][self.pressure] = discr.extract_pressure(g, var, d) d[pp.STATE][self.flux] = discr.extract_flux(g, var, d) if "original_id" in g.tags: d[pp.STATE]["original_id"] = g.tags["original_id"] * np.ones( g.num_cells) if "condition" in g.tags: d[pp.STATE]["condition"] = g.tags["condition"] * np.ones( g.num_cells) # export the P0 flux reconstruction pp.project_flux(self.gb, discr, self.flux, self.P0_flux, self.mortar)
def extract(self, x): self.assembler.distribute_variable(x) for g, d in self.gb: d[pp.STATE][self.pressure] = d[pp.STATE][self.variable] d[pp.STATE]["cell_volumes"] = g.cell_volumes pp.fvutils.compute_darcy_flux(self.gb, keyword=self.model, d_name=self.flux, p_name=self.pressure, lam_name=self.mortar) for _, d in self.gb: d[pp.STATE][self.flux] = d[pp.PARAMETERS][self.model][self.flux] # export the P0 flux reconstruction pp.project_flux(self.gb, pp.MVEM(self.model), self.flux, self.P0_flux, self.mortar)
def flow(gb, param): model = "flow" model_data = data.flow(gb, model, param) # discretization operator name flux_id = "flux" # master variable name variable = "flux_pressure" mortar = "lambda_" + variable # post process variables pressure = "pressure" flux = "darcy_flux" # it has to be this one P0_flux = "P0_flux" # save variable name for the advection-diffusion problem param["pressure"] = pressure param["flux"] = flux param["P0_flux"] = P0_flux param["mortar_flux"] = mortar # discretization operators discr = pp.MVEM(model_data) coupling = pp.RobinCoupling(model_data, discr) # define the dof and discretization for the grids for g, d in gb: d[pp.PRIMARY_VARIABLES] = {variable: {"cells": 1, "faces": 1}} d[pp.DISCRETIZATION] = {variable: {flux_id: discr}} # 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] = { variable: { g_slave: (variable, flux_id), g_master: (variable, flux_id), e: (mortar, coupling) } } # solution of the darcy problem assembler = pp.Assembler() logger.info("Assemble the flow problem") A, b, block_dof, full_dof = assembler.assemble_matrix_rhs(gb) logger.info("done") logger.info("Solve the linear system") up = sps.linalg.spsolve(A, b) logger.info("done") logger.info("Variable post-process") assembler.distribute_variable(gb, up, block_dof, full_dof) for g, d in gb: d[pressure] = discr.extract_pressure(g, d[variable]) d[flux] = discr.extract_flux(g, d[variable]) pp.project_flux(gb, discr, flux, P0_flux, mortar) logger.info("done") return model_data
def flow(gb, param, bc_flag): model = "flow" model_data = data_flow(gb, 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 # define the dof and discretization for the grids for g, d in gb: d[pp.PRIMARY_VARIABLES] = {variable: {"cells": 1, "faces": 1}} if g.dim == gb.dim_max(): discr = pp.RT0(model_data) else: discr = RT0Multilayer(model_data) d[pp.DISCRETIZATION] = {variable: {flux_id: discr}} # 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}} # retrive the discretization of the master and slave grids discr_master = gb.node_props(g_master, pp.DISCRETIZATION)[variable][flux_id] discr_slave = gb.node_props(g_slave, pp.DISCRETIZATION)[variable][flux_id] if g_master.dim == gb.dim_max(): # classical 2d-1d/3d-2d coupling condition coupling = pp.RobinCoupling(model_data, discr_master, discr_slave) d[pp.COUPLING_DISCRETIZATION] = { flux: { g_slave: (variable, flux_id), g_master: (variable, flux_id), e: (mortar, coupling), } } elif g_master.dim < gb.dim_max(): # the multilayer coupling condition coupling = RobinCouplingMultiLayer(model_data, discr_master, discr_slave) 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() logger.info("Assemble the flow problem") A, b, block_dof, full_dof = assembler.assemble_matrix_rhs(gb) 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(gb, x, block_dof, full_dof) for g, d in gb: d[pressure] = discr.extract_pressure(g, d[variable], d) d[flux] = discr.extract_flux(g, d[variable], d) # export the P0 flux reconstruction P0_flux = "P0_flux" param["P0_flux"] = P0_flux pp.project_flux(gb, discr, flux, P0_flux, mortar) # identification of layer and fault for g, d in gb: # save the identification of the fault if "fault" in g.name: d["fault"] = np.ones(g.num_cells) d["layer"] = np.zeros(g.num_cells) # save the identification of the layer elif "layer" in g.name: d["fault"] = np.zeros(g.num_cells) half_cells = int(g.num_cells / 2) d["layer"] = np.hstack( (np.ones(half_cells), 2 * np.ones(half_cells))) # save zero for the other cases else: d["fault"] = np.zeros(g.num_cells) d["layer"] = np.zeros(g.num_cells) save = pp.Exporter(gb, "solution", folder=param["folder"]) save.write_vtk([pressure, P0_flux, "fault", "layer"]) 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")