def test_import_single_grid(self): folder = "../../geometry/mesh_test_porepy/mesh_senzafrattura/" fname = "_bulk" g = import_grid(folder, fname, 2) pp.Exporter(g, "grid").write_vtk() pp.plot_grid(g, info="c", alpha=0) print(g)
def main(): # example in 2d file_name = "network.csv" write_network(file_name) # load the network and split it, we assume 2d domain = {"xmin": 0, "xmax": 1, "ymin": 0, "ymax": 1} global_network = pp.fracture_importer.network_2d_from_csv(file_name, domain=domain) global_network = global_network.split_intersections() # select a subsample of the fractures macro_network, micro_network = split_network(global_network, Criterion.every) # NOTE: the explicit network is empty so far # create the macroscopic grid mesh_size = 2 mesh_kwargs = { "mesh_size_frac": mesh_size, "mesh_size_min": mesh_size / 20 } gb = macro_network.mesh(mesh_kwargs) # plot the suff pp.plot_fractures(micro_network.pts, micro_network.edges, micro_network.domain) pp.plot_grid(gb, info="c", alpha=0) # construct the solver tpfa_dfm = Tpfa_DFM() # Set data for the upscaling problem g = gb.grids_of_dimension(gb.dim_max())[0] d = gb.node_props(g) # store the # EK: We probably need to initialize some of the nested dictionaries d[pp.PARAMETERS][tpfa_dfm.keyword][ tpfa_dfm.network_keyword] = micro_network # set parameters and discretization variables # EK: This must be done in this run-script - it is not the responsibility of the # discretization. We may want to construct a model for this. # tpfa_dfm.set_parameters(gb) # tpfa_dfm.set_variables_discretizations(gb) # discretize with the assembler assembler = pp.Assembler(gb) assembler.discretize() A, b = assembler.assemble_matrix_rhs() # Solve and distribute x = spsolve(A, b) assembler.distribute_variable(x)
def import_gb(folder, max_dim, **kwargs): index_names = kwargs.get("index_names", 1) index_shift = kwargs.get("index_shift", 1) # bulk grid fname_bulk = kwargs.get("bulk", "_bulk") grid_bulk = [import_grid(folder, fname_bulk, max_dim, **kwargs)] # fracture grids fname_fracture = kwargs.get("fracture", "_fracture_") grid_fracture = [] # check the number of fractures fname = "/" + kwargs.get("nodes", "points") + fname_fracture + "*.txt" num_frac = len(glob.glob(folder + fname)) print("there are " + str(num_frac) + " fractures") for idx in np.arange(num_frac): fname = fname_fracture + str(idx + index_names) g = import_grid(folder, fname, max_dim - 1, **kwargs) grid_fracture.append(g) # intersection grids fname_intersection = kwargs.get("intersection", "_") grid_intersection = [] # check the number of intersections fname = "/" + kwargs.get("nodes", "InterCellsCoord") + fname_intersection + "*.txt" num_int = len(glob.glob(folder + fname)) print("there are " + str(num_int) + " intersections") for idx in np.arange(num_int): fname = fname_intersection + str(idx + index_names) g = import_grid_0d(folder, fname, **kwargs) grid_intersection.append(g) grids = [grid_bulk, grid_fracture, grid_intersection] #grids = [[], grid_fracture, []]#, grid_intersection] gb = pp.meshing.grid_list_to_grid_bucket(grids) pp.plot_grid(gb, alpha=0) for _, d in gb: d[pp.PRIMARY_VARIABLES] = {} d[pp.DISCRETIZATION] = {} d[pp.DISCRETIZATION_MATRICES] = {} for _, d in gb.edges(): d[pp.PRIMARY_VARIABLES] = {} d[pp.COUPLING_DISCRETIZATION] = {} d[pp.DISCRETIZATION_MATRICES] = {} return gb
def make_grid(mesh_size=0.1, grid_type="cartesian", plot_grid=False): if grid_type == "cartesian": n = int(1/mesh_size) gb = pp.meshing.cart_grid([], nx=[n, n], physdims=[1.0, 1.0]) elif grid_type == "triangular": domain = {"xmin": 0.0, "xmax": 1.0, "ymin": 0.0, "ymax": 1.0} network_2d = pp.FractureNetwork2d(None, None, domain) mesh_args = {"mesh_size_bound": mesh_size, "mesh_size_frac": mesh_size} gb = network_2d.mesh(mesh_args) else: raise ValueError("Grid type not available.") if plot_grid: pp.plot_grid(g, plot_2d=True) return gb
def make_mesh(mesh_size, plot=False): # define the domain domain = {"xmin": 0, "xmax": 1, "ymin": 0, "ymax": 2} # Point coordinates, as a 2xn array p = np.array([[0, 1], [1, 1]]) # Point connections as a 2 x num_frac array e = np.array([[0], [1]]) # Define a fracture network in 2d network_2d = pp.FractureNetwork2d(p, e, domain) # Generate a mixed-dimensional mesh gb = network_2d.mesh({"mesh_size_frac": mesh_size}) if plot: pp.plot_grid(gb, alpha=0, info="all") return gb
x_new = x + x_prev # Distribute the solution, in an additive manner dof_manager.distribute_variable(values=x_new, additive=False, to_iterate=True) # Rediscretize the equations. # Mainly to update the Darcy flux equation_manager = equation(gb, dof_manager, equation_manager, True) A, b = equation_manager.assemble_matrix_rhs() res = np.linalg.norm(b) iter += 1 # end while # Distribute the solution to the next time step x_new = dof_manager.assemble_variable(from_iterate=True) dof_manager.distribute_variable(x_new.copy(), to_iterate=False, additive=False) pp.plot_grid(gb, pressure_variable, figsize=(15, 12)) print(res) print(f"time step {i}") print(f"newton iters {iter}") # end i-loop
[0.4, 0.2] ]).T e = np.array([ [0, 1], [2, 3], [4, 5], ]).T domain = {"xmin": 0, "xmax": 2, "ymin": 0, "ymax": 1} # domain is 0<x<2,0<y<1 network_2d = pp.FractureNetwork2d(pts, e, domain) mesh_args = {"mesh_size_frac": 0.2, "mesh_size_bound": 0.2} gb = network_2d.mesh(mesh_args) pp.plot_grid(gb, figsize=(15, 12)) # g = pp.CartGrid([5,5]) # g.compute_geometry() # gb = pp.GridBucket() # gb.add_nodes(g) # Keywords kw_f = "flow" kw_t = "transport" # Set flow data domain = {"xmin": 0, "xmax": 2, "ymin": 0, "ymax": 1} gb = flow_in_gb(gb, domain) # Set transport data aq_components = np.array([0])
def solve_two_phase_flow_upwind(g): time = [] sat_err = [] pres_err = [] maxflux = [] xc = g.cell_centers # Permeability tensor k_xx = np.zeros(g.num_cells) k_xy = np.zeros(g.num_cells) k_yy = np.zeros(g.num_cells) k_xx[:] = perm_xx_f(xc[0], xc[1]) k_yy[:] = perm_yy_f(xc[0], xc[1]) k_xy[:] = perm_xy_f(xc[0], xc[1]) perm = pp.SecondOrderTensor(k_xx, kyy=k_yy, kxy=k_xy) # Set type of boundary conditions xf = g.face_centers p_bound = np.zeros(g.num_faces) bnd_faces = g.get_all_boundary_faces() neu_faces = bnd_faces[:-1].copy() dir_faces = np.array([g.num_faces-1]) bot_faces = np.ravel(np.argwhere(g.face_centers[1] < 1e-10)) top_faces = np.ravel(np.argwhere(g.face_centers[1] > domain[1] - 1e-10)) left_faces = np.ravel(np.argwhere(g.face_centers[0] < 1e-10)) right_faces = np.ravel(np.argwhere(g.face_centers[0] > domain[0] - 1e-10)) bound_cond = pp.BoundaryCondition(g, dir_faces, ['dir'] * dir_faces.size) # set value of boundary condition p_bound[neu_faces] = 0 p_bound[dir_faces] = p_f(xf[0, dir_faces], xf[1, dir_faces]) # set rhs rhs1 = np.zeros(g.num_cells) rhs2 = np.zeros(g.num_cells) specified_parameters = {"second_order_tensor": perm, "source": rhs1, "bc": bound_cond, "bc_values": p_bound} data = pp.initialize_default_data(g, {}, "flow", specified_parameters) # Set initial conditions s = np.zeros(g.num_cells) s = s_f(xc[0], xc[1]) s_0 = s_f(xc[0], xc[1]) #pp.plot_grid(g, s_0, figsize=(15, 12), alpha = 0.9, color_map=(0,1)) V_start = np.sum(s*g.cell_volumes) fluxtot = np.zeros(g.num_faces) p_ex = p_f(xc[0], xc[1]) s_ex = s_eq_f(xc[0], xc[1]) time_steps_vec = [] #save = pp.Exporter(g, 'twophase_gcmpfa8_time', folder='plots') #save.write_vtk({"s": s}, 0) # Gravity term # < K > * rho_alpha * g gforce = np.zeros((2, g.num_cells)) gforce[0,:] = gx * np.ones(g.num_cells) gforce[1,:] = gy * np.ones(g.num_cells) gforce = gforce.ravel('F') g1 = rho1 * gforce g2 = rho2 * gforce flux_g1 = standard_discr(g, perm, g1) flux_g2 = standard_discr(g, perm, g2) # mpfa discretization flux, bound_flux, _, _ = pp.Mpfa("flow")._local_discr( g, perm, bound_cond, inverter="python" ) div = pp.fvutils.scalar_divergence(g) # define iteration parameters t = .0 k = 0 i = 0 time_steps_vec.append(t) time_step = 5 courant_max = 0.05 while t < T: s_old = s.copy() # Increment time k += 1 t += time_step # discretize gravity term kr1, kr2, f2, f1 = get_phase_mobility(g, s, fluxtot, flux_g1, flux_g2) fluxtot_g = kr1 * flux_g1 + kr2 * flux_g2 p_bound[neu_faces] = fluxtot[neu_faces] - fluxtot_g[neu_faces] p_bound[bot_faces] *= -1 p_bound[left_faces] *= -1 a = div * (kr1 + kr2) * flux b = (rhs1 + rhs2) - div * bound_flux * p_bound - div * fluxtot_g p = sps.linalg.spsolve(a, b) fluxtot = (kr1 + kr2) * flux * p + bound_flux * p_bound + fluxtot_g assert np.all(abs(fluxtot[neu_faces]) < thresh) assert np.all(abs(fluxtot[dir_faces]) < 1.0e-16) if pert == 0: assert np.all(fluxtot < thresh) threshold_indices = abs(fluxtot) < thresh fluxtot[threshold_indices] = 0 maxfluxtot = np.amax(np.absolute(fluxtot)) maxflux.append(maxfluxtot) # update s q2 = f2 * (fluxtot + kr1 * (flux_g2 - flux_g1)) q1 = f1 * (fluxtot + kr2 * (flux_g1 - flux_g2)) q2[bnd_faces]=0 q1[bnd_faces]=0 assert np.allclose(q1+q2, fluxtot) # check courant number q2max = np.zeros(g.num_cells) q1max = np.zeros(g.num_cells) for j in range (0, g.num_cells): faces_of_cell = g.cell_faces.indices[g.cell_faces.indptr[j] : g.cell_faces.indptr[j+1]] for i in range (0, faces_of_cell.size): q2max[j] += np.absolute(q2[faces_of_cell[i]]) / g.cell_volumes[j] q1max[j] += np.absolute(q1[faces_of_cell[i]]) / g.cell_volumes[j] courant = 0.5 * max(np.amax(q2max), np.amax(q1max)) * time_step div_q2 = div * q2 threshold_indices = abs(div_q2) < thresh div_q2[threshold_indices] = 0 s = s + time_step / phi / g.cell_volumes * (rhs2 - div_q2) if not np.all(s >= 0.0): inds=np.argwhere(s<0.0) print(k, inds, s[inds]) assert False if not np.all(s <= 1.0): inds=np.argwhere(s>1.0) #print(k, inds, s[inds]) assert np.all(s[inds] < 1. + 1.0e-12) s[inds] = 1. #assert False mass_error = (np.sum(s*g.cell_volumes) - np.sum(s*g.cell_volumes)) / np.sum(s*g.cell_volumes) if abs(mass_error) > tol_mc: print('error in mass conservation') print(t, mass_error) break s_diff = s - s_ex s_err=np.sqrt(np.sum(g.cell_volumes * s_diff**2))/np.sqrt(np.sum(g.cell_volumes * s_ex**2)) p_diff = p - p_ex p_err=np.sqrt(np.sum(g.cell_volumes * p_diff**2))/np.sqrt(np.sum(g.cell_volumes * p_ex**2)) sat_err.append(s_err) pres_err.append(p_err) time.append(t) #time_steps.append(t) #save.write_vtk({"s": s}, time_step=k) if k % 100 == 0: print(t, mass_error, maxfluxtot, s_err, p_err) F = courant_max / courant if F > 1.: adjust_time_step = min(min(F, 1. + 0.1 * F), 1.2) time_step *= adjust_time_step print(time_step) #time_steps_vec.append(t) #i += 1 """ if k % 500 == 0 and t < 1.0e8: Q_n = fluxtot * g.face_normals solver_flow = pp.MVEM("flow") P0u = solver_flow.project_flux(g, fluxtot, data) #pp.plot_grid(g, p, P0u * 5e7, figsize=(15, 12)) #pp.plot_grid(g, s_0, figsize=(15, 12), alpha = 0.9, color_map=(0,1)) pp.plot_grid(g, s, vector_value=Q_n, figsize=(15, 12), vector_scale=1e7, alpha = 0.9, color_map=(0,1)) #save.write_vtk({"s": s}, time_step=i) Q_n = fluxtot * g.face_normals pp.plot_grid(g, vector_value=Q_n, figsize=(15, 12), vector_scale=5e7) Q_1 = q1 * g.face_normals pp.plot_grid(g, vector_value=Q_1, figsize=(15, 12), vector_scale=5e7) Q_2 = q2 * g.face_normals pp.plot_grid(g, vector_value=Q_2, figsize=(15, 12), vector_scale=5e7) """ #save.write_pvd(np.array(time_steps_vec)) p_diff = p - p_ex s_diff = s - s_ex p_err=np.sqrt(np.sum(g.cell_volumes * p_diff**2))/np.sqrt(np.sum(g.cell_volumes * p_ex**2)) s_err=np.sqrt(np.sum(g.cell_volumes * s_diff**2))/np.sqrt(np.sum(g.cell_volumes * s_ex**2)) mass_error = (np.sum(s*g.cell_volumes) - np.sum(s*g.cell_volumes)) / np.sum(s*g.cell_volumes) print('error in mass conservation', mass_error) print('error in saturation ', s_err) print('error in pressure ', p_err) pp.plot_grid(g, s, figsize=(15, 12)) pp.plot_grid(g, p, figsize=(15, 12)) Q_n = fluxtot * g.face_normals solver_flow = pp.MVEM("flow") P0u = solver_flow.project_flux(g, fluxtot, data) #pp.plot_grid(g, p, P0u * 5e7, figsize=(15, 12)) #pp.plot_grid(g, s_0, figsize=(15, 12), alpha = 0.9, color_map=(0,1)) #pp.plot_grid(g, s, vector_value=Q_n, figsize=(15, 12), vector_scale=1e7, alpha = 0.9, color_map=(0,1)) #save.write_vtk({"s": s}, time_step=i) #save.write_vtk({"p": p, 's_0' : s_0, 's_f' : s}) return time, sat_err, pres_err, maxflux