def test_uniform_displacement(): g_list = setup_grids.setup_2d() for g in g_list: bound_faces = np.argwhere( np.abs(g.cell_faces).sum(axis=1).A.ravel('F') == 1) bound = bc.BoundaryCondition(g, bound_faces.ravel(1), ['dir'] * bound_faces.size) constit = setup_stiffness(g) # Python inverter is most efficient for small problems stress, bound_stress = mpsa.mpsa(g, constit, bound, inverter='python') div = fvutils.vector_divergence(g) a = div * stress d_x = np.random.rand(1) d_y = np.random.rand(1) d_bound = np.zeros((g.dim, g.num_faces)) d_bound[0, bound.is_dir] = d_x d_bound[1, bound.is_dir] = d_y rhs = div * bound_stress * d_bound.ravel('F') d = np.linalg.solve(a.todense(), rhs) traction = stress * d - bound_stress * d_bound.ravel('F') assert np.max(np.abs(d[::2] - d_x)) < 1e-8 assert np.max(np.abs(d[1::2] - d_y)) < 1e-8 assert np.max(np.abs(traction)) < 1e-8
def tpfa_matrix(g, perm=None, faces=None): """ Compute a two-point flux approximation matrix useful related to a call of create_partition. Parameters ---------- g: the grid perm: (optional) permeability, the it is not given unitary tensor is assumed faces (np.array, int): Index of faces where TPFA should be applied. Defaults all faces in the grid. Returns ------- out: sparse matrix Two-point flux approximation matrix """ if perm is None: perm = second_order_tensor.SecondOrderTensor(g.dim, np.ones(g.num_cells)) bound = bc.BoundaryCondition(g, np.empty(0), '') trm, _ = tpfa.tpfa(g, perm, bound, faces) div = g.cell_faces.T return div * trm
def test_no_dynamics_2d(self): g_list = setup_grids.setup_2d() for g in g_list: bound_faces = g.get_boundary_faces() bound = bc.BoundaryCondition(g, bound_faces.ravel('F'), ['dir'] * bound_faces.size) flux, bound_flux, div_flow = self.mpfa_discr(g, bound) a_flow = div_flow * flux stress, bound_stress, grad_p, div_d, \ stabilization, div_mech = self.mpsa_discr(g, bound) a_mech = div_mech * stress a_biot = sps.bmat([[a_mech, grad_p], [div_d, a_flow + stabilization]]) bval_mech = np.ones(g.num_faces * g.dim) bval_flow = np.ones(g.num_faces) rhs = np.hstack((div_mech * bound_stress * bval_mech, div_flow * bound_flux * bval_flow)) sol = np.linalg.solve(a_biot.todense(), rhs) assert np.isclose(sol, np.ones(g.num_cells * (g.dim + 1))).all()
def upwind_example2(**kwargs): ####################### # Simple 2d upwind problem with explicit Euler scheme in time coupled with # a Darcy problem ####################### T = 2 Nx, Ny = 10, 10 g = structured.CartGrid([Nx, Ny], [1, 1]) g.compute_geometry() kxx = np.ones(g.num_cells) perm = second_order_tensor.SecondOrderTensor(g.dim, kxx) def funp_ex(pt): return -np.sin(pt[0]) * np.sin(pt[1]) - pt[0] f = np.zeros(g.num_cells) b_faces = g.get_boundary_faces() bnd = bc.BoundaryCondition(g, b_faces, ['dir'] * b_faces.size) bnd_val = {'dir': funp_ex(g.face_centers[:, b_faces])} solver = dual.DualVEM() data = {'k': perm, 'f': f, 'bc': bnd, 'bc_val': bnd_val} D, rhs = solver.matrix_rhs(g, data) up = sps.linalg.spsolve(D, rhs) beta_n = solver.extractU(g, up) u, p = solver.extractU(g, up), solver.extractP(g, up) P0u = solver.projectU(g, u, data) export_vtk(g, "darcy", {"p": p, "P0u": P0u}) advect = upwind.Upwind() bnd_val = {'dir': np.hstack(([1], np.zeros(b_faces.size - 1)))} data = {'beta_n': beta_n, 'bc': bnd, 'bc_val': bnd_val} U, rhs = advect.matrix_rhs(g, data) data = {'deltaT': advect.cfl(g, data)} M, _ = mass_matrix.Mass().matrix_rhs(g, data) conc = np.zeros(g.num_cells) M_minus_U = M - U invM, _ = mass_matrix.InvMass().matrix_rhs(g, data) # Loop over the time Nt = int(T / data['deltaT']) time = np.empty(Nt) for i in np.arange(Nt): # Update the solution conc = invM.dot((M_minus_U).dot(conc) + rhs) time[i] = data['deltaT'] * i export_vtk(g, "conc_darcy", {"conc": conc}, time_step=i) export_pvd(g, "conc_darcy", time)
def test_uniform_flow_cart_2d(): nx = np.array([13, 13]) g = structured.CartGrid(nx) g.compute_geometry() kxx = np.ones(g.num_cells) perm = second_order_tensor.SecondOrderTensor(g.dim, kxx) bound_faces = np.argwhere(np.abs(g.cell_faces).sum(axis=1).A.ravel(1) == 1) bound = bc.BoundaryCondition(g, bound_faces, ['dir'] * bound_faces.size) flux = tpfa.tpfa(g, perm, bound)
def test_tpfa_cart_2d(): """ Apply TPFA on Cartesian grid, should obtain Laplacian stencil. """ # Set up 3 X 3 Cartesian grid nx = np.array([3, 3]) g = structured.CartGrid(nx) g.compute_geometry() kxx = np.ones(g.num_cells) perm = second_order_tensor.SecondOrderTensor(g.dim, kxx) bound_faces = np.array([0, 3, 12]) bound = bc.BoundaryCondition(g, bound_faces, ['dir'] * bound_faces.size) trm, bound_flux = tpfa.tpfa(g, perm, bound) div = g.cell_faces.T a = div * trm b = (div * bound_flux).A print(b) # Checks on interior cell mid = 4 assert a[mid, mid] == 4 assert a[mid - 1, mid] == -1 assert a[mid + 1, mid] == -1 assert a[mid - 3, mid] == -1 assert a[mid + 3, mid] == -1 assert np.all(b[mid, :] == 0) # The first cell should have two Dirichlet bnds assert a[0, 0] == 6 assert a[0, 1] == -1 assert a[0, 3] == -1 assert b[0, 0] == 2 assert b[0, 12] == 2 # Cell 3 has one Dirichlet, one Neumann face assert a[2, 2] == 4 assert a[2, 1] == -1 assert a[2, 5] == -1 assert b[2, 3] == 2 assert b[2, 14] == 1 # Cell 2 has one Neumann face assert a[1, 1] == 3 assert a[1, 0] == -1 assert a[1, 2] == -1 assert a[1, 4] == -1 assert b[1, 13] == 1 return a
def test_uniform_strain(): g_list = setup_grids.setup_2d() for g in g_list: bound_faces = np.argwhere( np.abs(g.cell_faces).sum(axis=1).A.ravel('F') == 1) bound = bc.BoundaryCondition(g, bound_faces.ravel('F'), ['dir'] * bound_faces.size) mu = 1 l = 1 constit = setup_stiffness(g, mu, l) # Python inverter is most efficient for small problems stress, bound_stress = mpsa.mpsa(g, constit, bound, inverter='python') div = fvutils.vector_divergence(g) a = div * stress xc = g.cell_centers xf = g.face_centers gx = np.random.rand(1) gy = np.random.rand(1) dc_x = np.sum(xc * gx, axis=0) dc_y = np.sum(xc * gy, axis=0) df_x = np.sum(xf * gx, axis=0) df_y = np.sum(xf * gy, axis=0) d_bound = np.zeros((g.dim, g.num_faces)) d_bound[0, bound.is_dir] = df_x[bound.is_dir] d_bound[1, bound.is_dir] = df_y[bound.is_dir] rhs = div * bound_stress * d_bound.ravel('F') d = np.linalg.solve(a.todense(), rhs) traction = stress * d - bound_stress * d_bound.ravel('F') s_xx = (2 * mu + l) * gx + l * gy s_xy = mu * (gx + gy) s_yx = mu * (gx + gy) s_yy = (2 * mu + l) * gy + l * gx n = g.face_normals traction_ex_x = s_xx * n[0] + s_xy * n[1] traction_ex_y = s_yx * n[0] + s_yy * n[1] assert np.max(np.abs(d[::2] - dc_x)) < 1e-8 assert np.max(np.abs(d[1::2] - dc_y)) < 1e-8 assert np.max(np.abs(traction[::2] - traction_ex_x)) < 1e-8 assert np.max(np.abs(traction[1::2] - traction_ex_y)) < 1e-8
def __init__(self, grid, perm, stiffness, poro, bound_flow=None, bound_mech=None, water_compr=1, water_viscosity=1, verbose=0, inverter='cython', eta=0): self.g = grid self.perm = perm self.stiffness = stiffness self.poro = poro # Boundaries and boundary conditions bound_faces = grid.get_boundary_faces() if bound_flow is None: self.bound_flow = bc.BoundaryCondition(grid, bound_faces.ravel('F'), ['neu'] * bound_faces.size) elif isinstance(bound_flow, str) \ and (bound_flow.lower().strip() == 'dir' or bound_flow.lower().strip() == 'dirichlet'): self.bound_flow = bc.BoundaryCondition(grid, bound_faces.ravel('F'), ['dir'] * bound_faces.size) elif isinstance(bound_flow, str) \ and (bound_flow.lower().strip() == 'neu' or bound_flow.lower().strip() == 'neumann'): self.bound_flow = bc.BoundaryCondition(grid, bound_faces.ravel('F'), ['neu'] * bound_faces.size) else: self.bound_flow = bound_flow if bound_mech is None: self.bound_mech = bc.BoundaryCondition(grid, bound_faces.ravel('F'), ['neu'] * bound_faces.size) elif isinstance(bound_mech, str) \ and (bound_mech.lower().strip() == 'dir' or bound_mech.lower().strip() == 'dirichlet'): self.bound_mech = bc.BoundaryCondition(grid, bound_faces.ravel('F'), ['dir'] * bound_faces.size) elif isinstance(bound_mech, str) \ and (bound_mech.lower().strip() == 'neu' or bound_mech.lower().strip() == 'neumann'): self.bound_mech = bc.BoundaryCondition(grid, bound_faces.ravel('F'), ['neu'] * bound_faces.size) else: self.bound_mech = bound_mech self.water_compr = water_compr self.water_viscosity = water_viscosity self.inverter = inverter self.eta = eta self.verbose = verbose self.biot_alpha = 1
def upwind_example1(**kwargs): ####################### # 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() beta_n = advect.beta_n(g, [1, 0, 0]) b_faces = g.get_boundary_faces() bnd = bc.BoundaryCondition(g, b_faces, ['dir'] * b_faces.size) bnd_val = {'dir': np.hstack(([1], np.zeros(b_faces.size - 1)))} data = {'beta_n': beta_n, 'bc': bnd, 'bc_val': bnd_val} U, rhs = advect.matrix_rhs(g, data) data = {'deltaT': 2 * advect.cfl(g, data)} M, _ = mass_matrix.Mass().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) 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 export_vtk(g, "conc_IE", {"conc": conc}, time_step=i) export_pvd(g, "conc_IE", time)
def upwind_example0(**kwargs): ####################### # Simple 2d upwind problem with explicit Euler scheme in time ####################### T = 1 Nx, Ny = 10, 1 g = structured.CartGrid([Nx, Ny], [1, 1]) g.compute_geometry() advect = upwind.Upwind() beta_n = advect.beta_n(g, [1, 0, 0]) b_faces = g.get_boundary_faces() bnd = bc.BoundaryCondition(g, b_faces, ['dir'] * b_faces.size) bnd_val = {'dir': np.hstack(([1], np.zeros(b_faces.size - 1)))} data = {'beta_n': beta_n, 'bc': bnd, 'bc_val': bnd_val} U, rhs = advect.matrix_rhs(g, data) data = {'deltaT': advect.cfl(g, data)} M, _ = mass_matrix.Mass().matrix_rhs(g, data) conc = np.zeros(g.num_cells) M_minus_U = M - U invM, _ = mass_matrix.InvMass().matrix_rhs(g, data) # Loop over the time Nt = int(T / data['deltaT']) time = np.empty(Nt) for i in np.arange(Nt): # Update the solution conc = invM.dot((M_minus_U).dot(conc) + rhs) time[i] = data['deltaT'] * i export_vtk(g, "conc_EE", {"conc": conc}, time_step=i) export_pvd(g, "conc_EE", time)