def solve(self, save_as=None, save_every=1): """ Solve both problems. """ p = self.flow.step() self.flow.pressure() if self.flow.el: SC.compute_elimination_fluxes(self.flow.full_grid, self.flow.grid(), self.flow.el_data) self.flow.discharge() s = self.transport.solve(save_as=save_as, save_every=save_every) return p, s[self.transport.physics]
def solve(self, transport_save_as=None, flow_save_as=None, save_every=1): """ Solve both problems. Arguments: save_as (string), defaults to None. If a string is given, the solution variable is saved to a vtk-file as save_as save_every (int), defines which time steps to save. save_every=2 will store every second time step. """ self.flow.step() if flow_save_as is not None: self.flow.pressure(flow_save_as) self.flow.split(flow_save_as) self.flow.save(variables=[flow_save_as]) else: self.flow.pressure() if self.flow.el: SC.compute_elimination_fluxes( self.flow.full_grid, self.flow.grid(), self.flow.el_data ) self.flow.discharge() self.transport.solve(transport_save_as, save_every)
# gb = meshing.cart_grid(f, [2, 4], physdims=[2, 4]) Nx, Ny = 10, 10 # gb = meshing.cart_grid([np.array([[Nx / 2, Nx / 2], [1, Ny]])], # [Nx, Ny], physdims=[Nx, Ny]) # gb = meshing.cart_grid(f_set, [Nx, Nx, Nx]) path_to_gmsh = '~/gmsh-2.16.0-Linux/bin/gmsh' gb = meshing.simplex_grid(f_set, domain, gmsh_path=path_to_gmsh) gb.assign_node_ordering() ################## Transport solver ################## print("Compute global matrix and rhs for the advection problem") gb_r, elimination_data = gb.duplicate_without_dimension(0) condensation.compute_elimination_fluxes(gb, gb_r, elimination_data) add_data_transport(gb) add_data_transport(gb_r) upwind_solver = upwind.Upwind() upwind_cc = upwind.UpwindCoupling(upwind_solver) coupler_solver = coupler.Coupler(upwind_solver, upwind_cc) U, rhs = coupler_solver.matrix_rhs(gb) U_r, rhs_r = coupler_solver.matrix_rhs(gb_r) deltaT = np.amin([upwind_solver.cfl(g, d) for g, d in gb]) deltaT_r = np.amin([upwind_solver.cfl(g, d) for g, d in gb_r]) T = deltaT * max(Nx, Ny) * 4
def test_tpfa_fluxes_2d_1d_cross_with_elimination(self): f1 = np.array([[0, 1], [.5, .5]]) f2 = np.array([[.5, .5], [0, 1]]) gb = pp.meshing.cart_grid([f1, f2], [2, 2], **{'physdims': [1, 1]}) gb.compute_geometry() gb.assign_node_ordering() # Enforce node orderning because of Python 3.5 and 2.7. # Don't do it in general. cell_centers_1 = np.array([[7.50000000e-01, 2.500000000e-01], [5.00000000e-01, 5.00000000e-01], [-5.55111512e-17, 5.55111512e-17]]) cell_centers_2 = np.array([[5.00000000e-01, 5.00000000e-01], [7.50000000e-01, 2.500000000e-01], [-5.55111512e-17, 5.55111512e-17]]) for g, d in gb: if g.dim == 1: if np.allclose(g.cell_centers, cell_centers_1): d['node_number'] = 1 elif np.allclose(g.cell_centers, cell_centers_2): d['node_number'] = 2 else: raise ValueError('Grid not found') tol = 1e-3 solver = pp.TpfaMixedDim('flow') gb.add_node_props(['param']) a = 1e-2 for g, d in gb: param = pp.Parameters(g) a_dim = np.power(a, gb.dim_max() - g.dim) aperture = np.ones(g.num_cells) * a_dim param.set_aperture(aperture) kxx = np.ones(g.num_cells) * np.power(1e3, g.dim < gb.dim_max()) p = pp.SecondOrderTensor(3, kxx, kyy=kxx, kzz=kxx) param.set_tensor('flow', p) bound_faces = g.tags['domain_boundary_faces'].nonzero()[0] if bound_faces.size != 0: bound_face_centers = g.face_centers[:, bound_faces] right = bound_face_centers[0, :] > 1 - tol left = bound_face_centers[0, :] < tol labels = np.array(['neu'] * bound_faces.size) labels[right] = ['dir'] bc_val = np.zeros(g.num_faces) bc_dir = bound_faces[right] bc_neu = bound_faces[left] bc_val[bc_dir] = g.face_centers[0, bc_dir] bc_val[bc_neu] = -g.face_areas[bc_neu] * a_dim param.set_bc('flow', pp.BoundaryCondition(g, bound_faces, labels)) param.set_bc_val('flow', bc_val) else: param.set_bc("flow", pp.BoundaryCondition(g, np.empty(0), np.empty(0))) d['param'] = param gb.add_edge_props('param') for e, d in gb.edges(): g_h = gb.nodes_of_edge(e)[1] d['param'] = pp.Parameters(g_h) A, rhs = solver.matrix_rhs(gb) p = sps.linalg.spsolve(A, rhs) p = sps.linalg.spsolve(A, rhs) p_cond, p_red, _, _ = condensation.solve_static_condensation(A, rhs, gb, dim=0) solver.split(gb, "p_cond", p_cond) solver.split(gb, "pressure", p) # Make a copy of the grid bucket without the 0d grid dim_to_remove = 0 gb_r, elimination_data = gb.duplicate_without_dimension(dim_to_remove) # Compute the flux discretization on the new edges condensation.compute_elimination_fluxes(gb, gb_r, elimination_data) # Compute the discharges from the flux discretizations and computed # pressures solver.split(gb_r, "pressure", p_red) pp.fvutils.compute_discharges(gb) pp.fvutils.compute_discharges(gb_r) # Known discharges d_0, d_1, d_2 = fluxes_2d_1d_cross_with_elimination() # Check node fluxes, ... rtol = 1e-6 atol = rtol for g, d in gb: if d['node_number'] == 0: assert np.allclose(d['discharge'], d_0, rtol, atol) if d['node_number'] == 1: assert np.allclose(d['discharge'], d_1, rtol, atol) if d['node_number'] == 2: assert np.allclose(d['discharge'], d_2, rtol, atol) for g, d in gb_r: if d['node_number'] == 0: assert np.allclose(d['discharge'], d_0, rtol, atol) if d['node_number'] == 1: assert np.allclose(d['discharge'], d_1, rtol, atol) if d['node_number'] == 2: assert np.allclose(d['discharge'], d_2, rtol, atol) # ... edge fluxes ... d_01, d_10, d_02, d_20, d_13, d_23 \ = coupling_fluxes_2d_1d_cross_no_el() for e, data in gb.edges(): g1, g2 = gb.nodes_of_edge(e) pa = data['param'] node_numbers = [gb.node_props(g, 'node_number') for g in [g2, g1]] if pa is not None: if node_numbers == (0, 1): assert np.allclose(data['discharge'], d_01, rtol, atol) or \ np.allclose(data['discharge'], d_10, rtol, atol) if node_numbers == (0, 2): assert np.allclose(data['discharge'], d_02, rtol, atol) or \ np.allclose(data['discharge'], d_20, rtol, atol) if node_numbers == (1, 3): assert np.allclose(data['discharge'], d_13, rtol, atol) if node_numbers == (2, 3): assert np.allclose(data['discharge'], d_23, rtol, atol) d_11, d_21, d_22 = coupling_fluxes_2d_1d_cross_with_el() for e, data in gb_r.edges(): g1, g2 = gb_r.nodes_of_edge(e) pa = data['param'] node_numbers = [ gb_r.node_props(g, 'node_number') for g in [g2, g1] ] if pa is not None: if node_numbers == (0, 1): assert np.allclose(data['discharge'], d_01, rtol, atol) or \ np.allclose(data['discharge'], d_10, rtol, atol) if node_numbers == (0, 2): assert np.allclose(data['discharge'], d_02, rtol, atol) or \ np.allclose(data['discharge'], d_20, rtol, atol) if node_numbers == (1, 1): assert np.allclose(data['discharge'], d_11, rtol, atol) if node_numbers == (2, 1): assert np.allclose(data['discharge'], d_21, rtol, atol) if node_numbers == (2, 2): assert np.allclose(data['discharge'], d_22, rtol, atol) # ... and pressures tol = 1e-10 assert ((np.amax(np.absolute(p - p_cond))) < tol) assert (np.sum( pp.error.error_L2(g, d['pressure'], d['p_cond']) for g, d in gb) < tol)
def atest_upwind_2d_1d_cross_with_elimination(self): """ Simplest possible elimination scenario, one 0d-grid removed. Check on upwind matrix, rhs, solution and time step estimate. Full solution included (as comments) for comparison purposes if test breaks. """ f1 = np.array([[0, 1], [.5, .5]]) f2 = np.array([[.5, .5], [0, 1]]) domain = {"xmin": 0, "ymin": 0, "xmax": 1, "ymax": 1} mesh_size = 0.4 mesh_kwargs = {} mesh_kwargs["mesh_size"] = { "mode": "constant", "value": mesh_size, "bound_value": mesh_size, } gb = pp.meshing.cart_grid([f1, f2], [2, 2], **{"physdims": [1, 1]}) # gb = pp.meshing.simplex_grid( [f1, f2],domain,**mesh_kwargs) gb.compute_geometry() gb.assign_node_ordering() # Enforce node orderning because of Python 3.5 and 2.7. # Don't do it in general. cell_centers_1 = np.array([ [7.50000000e-01, 2.500000000e-01], [5.00000000e-01, 5.00000000e-01], [-5.55111512e-17, 5.55111512e-17], ]) cell_centers_2 = np.array([ [5.00000000e-01, 5.00000000e-01], [7.50000000e-01, 2.500000000e-01], [-5.55111512e-17, 5.55111512e-17], ]) for g, d in gb: if g.dim == 1: if np.allclose(g.cell_centers, cell_centers_1): d["node_number"] = 1 elif np.allclose(g.cell_centers, cell_centers_2): d["node_number"] = 2 else: raise ValueError("Grid not found") tol = 1e-3 solver = pp.TpfaMixedDim() gb.add_node_props(["param"]) a = 1e-2 for g, d in gb: param = pp.Parameters(g) a_dim = np.power(a, gb.dim_max() - g.dim) aperture = np.ones(g.num_cells) * a_dim param.set_aperture(aperture) kxx = np.ones(g.num_cells) * np.power(1e3, g.dim < gb.dim_max()) p = pp.SecondOrderTensor(3, kxx, kyy=kxx, kzz=kxx) param.set_tensor("flow", p) bound_faces = g.tags["domain_boundary_faces"].nonzero()[0] if bound_faces.size != 0: bound_face_centers = g.face_centers[:, bound_faces] right = bound_face_centers[0, :] > 1 - tol left = bound_face_centers[0, :] < tol labels = np.array(["neu"] * bound_faces.size) labels[right] = ["dir"] bc_val = np.zeros(g.num_faces) bc_dir = bound_faces[right] bc_neu = bound_faces[left] bc_val[bc_dir] = g.face_centers[0, bc_dir] bc_val[bc_neu] = -g.face_areas[bc_neu] * a_dim param.set_bc("flow", pp.BoundaryCondition(g, bound_faces, labels)) param.set_bc_val("flow", bc_val) # Transport bottom = bound_face_centers[1, :] < tol top = bound_face_centers[1, :] > 1 - tol labels = np.array(["neu"] * bound_faces.size) labels[np.logical_or(np.logical_or(left, right), np.logical_or(top, bottom))] = ["dir"] bc_val = np.zeros(g.num_faces) param.set_bc("transport", pp.BoundaryCondition(g, bound_faces, labels)) param.set_bc_val("transport", bc_val) else: param.set_bc("transport", pp.BoundaryCondition(g, np.empty(0), np.empty(0))) param.set_bc("flow", pp.BoundaryCondition(g, np.empty(0), np.empty(0))) # Transport: source = g.cell_volumes * a_dim param.set_source("transport", source) d["param"] = param gb.add_edge_props("param") for e, d in gb.edges(): g_h = gb.nodes_of_edge(e)[1] d["param"] = pp.Parameters(g_h) A, rhs = solver.matrix_rhs(gb) # p = sps.linalg.spsolve(A,rhs) _, p_red, _, _ = condensation.solve_static_condensation(A, rhs, gb, dim=0) dim_to_remove = 0 gb_r, elimination_data = gb.duplicate_without_dimension(dim_to_remove) condensation.compute_elimination_fluxes(gb, gb_r, elimination_data) solver.split(gb_r, "pressure", p_red) # pp.fvutils.compute_discharges(gb) pp.fvutils.compute_discharges(gb_r) # ------Transport------# advection_discr = upwind.Upwind(physics="transport") advection_coupling_conditions = upwind.UpwindCoupling(advection_discr) advection_coupler = coupler.Coupler(advection_discr, advection_coupling_conditions) U_r, rhs_u_r = advection_coupler.matrix_rhs(gb_r) _, rhs_src_r = pp.IntegralMixedDim( physics="transport").matrix_rhs(gb_r) rhs_u_r = rhs_u_r + rhs_src_r deltaT = np.amin( gb_r.apply_function(advection_discr.cfl, advection_coupling_conditions.cfl).data) theta_r = sps.linalg.spsolve(U_r, rhs_u_r) U_known, rhs_known, theta_known, deltaT_known = known_for_elimination() tol = 1e-7 self.assertTrue(np.isclose(deltaT, deltaT_known, tol, tol)) self.assertTrue((np.amax(np.absolute(U_r - U_known))) < tol) self.assertTrue((np.amax(np.absolute(rhs_u_r - rhs_known))) < tol) self.assertTrue((np.amax(np.absolute(theta_r - theta_known))) < tol)
edge_params(gb) gb_el, el_data = gb.duplicate_without_dimension(1) problem = FlowModel(gb) problem_el = FlowModel(gb_el, el='_el') Both = BothProblems(problem, problem_el) k_h = 10**4 k_v = 10**-4 p, p_el = Both.solve(k_h, k_v) problem.flux_disc().split(gb, 'pressure', p) problem_el.flux_disc().split(gb_el, 'pressure', p_el) Both.save() SC.compute_elimination_fluxes(gb, gb_el, el_data) compute_discharges(gb_el) compute_discharges(gb) assign_data(gb, TransportData, 'transport_data') transport_problem = TransportSolver(gb) sol = transport_problem.solve() ndof_el = problem_el.flux_disc().ndof(gb_el) assign_data(gb_el, TransportData, 'transport_data') transport_problem_el = TransportSolver(gb_el, el='_el') sol_el = transport_problem_el.solve() t = sol['transport'] t_el = sol_el['transport'] transport_problem.split(x_name='solution')