def main_ms(pb_data, name): data = Data(pb_data) data.add_to_gb() # Choose and define the solvers and coupler solver_flow = pp.RT0MixedDim("flow") A, b = solver_flow.matrix_rhs(data.gb, return_bmat=True) # off-line computation fo the bases ms = Multiscale(data.gb) ms.extract_blocks_h(A, b) info = ms.compute_bases() # solve the co-dimensional problem x_l = ms.solve_l(A, b) # post-compute the higher dimensional solution x_h = ms.solve_h(x_l) # update the number of solution of the higher dimensional problem info["solve_h"] += 1 x = ms.concatenate(x_h, x_l) folder = "ms_" + name + "_" + str(pb_data["mesh_size"]) export(data.gb, x, folder, solver_flow) write_out(data.gb, "ms_" + name + ".txt", info["solve_h"]) # print the summary data print("ms") print("kf_n", pb_data["kf_n"], "kf_t", pb_data["kf_t"]) print("solve_h", info["solve_h"], "\n")
def main_dd(pb_data, name): data = Data(pb_data) data.add_to_gb() # parameters for the dd algorightm tol = 1e-6 maxiter = 1e4 # Choose and define the solvers and coupler solver_flow = pp.RT0MixedDim("flow") A, b = solver_flow.matrix_rhs(data.gb, return_bmat=True) dd = DomainDecomposition(data.gb) dd.extract_blocks(A, b) dd.factorize() x, info = dd.solve(tol, maxiter, info=True) folder = "dd_" + name + "_" + str(pb_data["mesh_size"]) export(data.gb, x, folder, solver_flow) write_out(data.gb, "dd_" + name + ".txt", info["solve_h"]) # print the summary data print("dd") print("kf_n", pb_data["kf_n"], "kf_t", pb_data["kf_t"]) print("solve_h", info["solve_h"], "\n")
def main_dd(pb_data, name): # in principle we can re-compute only the matrices related to the # fracture network, however to simplify the implementation we re-compute everything data = Data(pb_data) data.add_to_gb() # parameters for the dd algorightm tol = 1e-6 maxiter = 1e4 solve_h = 0 # Choose and define the solvers and coupler solver_flow = pp.RT0MixedDim("flow") A, b = solver_flow.matrix_rhs(data.gb, return_bmat=True) dd = DomainDecomposition(data.gb) # compute the initial guess dd.extract_blocks(A, b) dd.factorize() x, info = dd.solve(tol, maxiter, info=True) solve_h += info["solve_h"] solver_flow.split(data.gb, "up", x) solver_flow.extract_p(data.gb, "up", "pressure_old") solver_flow.extract_u(data.gb, "up", "discharge_old") i = 0 err = np.inf while np.any( err > pb_data["fix_pt_err"]) and i < pb_data["fix_pt_maxiter"]: # update the non-linear term solver_flow.project_u(data.gb, "discharge_old", "P0u") data.update(solver_flow) # compute the current solution A, b = solver_flow.matrix_rhs(data.gb, return_bmat=True) dd.extract_blocks(A, b) dd.factorize() x, info = dd.solve(tol, maxiter, info=True) solve_h += info["solve_h"] solver_flow.split(data.gb, "up", x) solver_flow.extract_p(data.gb, "up", "pressure") solver_flow.extract_u(data.gb, "up", "discharge") # error evaluation err = compute_error(data.gb) i += 1 folder = "dd_" + str(pb_data["beta"]) + name export(data.gb, x, folder, solver_flow) write_out(data.gb, "dd" + name + ".txt", solve_h) # print the summary data print("dd") print("beta", pb_data["beta"], "kf_n", pb_data["kf_n"]) print("iter", i, "err", err, "solve_h", solve_h, "\n")
def main_ms(pb_data, name): # in principle we can re-compute only the matrices related to the # fracture network, however to simplify the implementation we re-compute everything data = Data(pb_data) data.add_to_gb() # Choose and define the solvers and coupler solver_flow = pp.RT0MixedDim("flow") A, b = solver_flow.matrix_rhs(data.gb, return_bmat=True) # off-line computation fo the bases ms = Multiscale(data.gb) ms.extract_blocks_h(A, b) info = ms.compute_bases() # solve the co-dimensional problem x_l = ms.solve_l(A, b) solver_flow.split(data.gb, "up", ms.concatenate(None, x_l)) solver_flow.extract_p(data.gb, "up", "pressure_old") solver_flow.extract_u(data.gb, "up", "discharge_old") i = 0 err = np.inf while np.any( err > pb_data["fix_pt_err"]) and i < pb_data["fix_pt_maxiter"]: # update the non-linear term solver_flow.project_u(data.gb, "discharge_old", "P0u") data.update(solver_flow) # we need to recompute the lower dimensional matrices # for simplicity we do for everything A, b = solver_flow.matrix_rhs(data.gb, return_bmat=True) x_l = ms.solve_l(A, b) solver_flow.split(data.gb, "up", ms.concatenate(None, x_l)) solver_flow.extract_p(data.gb, "up", "pressure") solver_flow.extract_u(data.gb, "up", "discharge") err = compute_error(data.gb) i += 1 # post-compute the higher dimensional solution x_h = ms.solve_h(x_l) # update the number of solution of the higher dimensional problem info["solve_h"] += 1 x = ms.concatenate(x_h, x_l) folder = "ms_" + str(pb_data["beta"]) + name export(data.gb, x, folder, solver_flow) write_out(data.gb, "ms" + name + ".txt", info["solve_h"]) # print the summary data print("ms") print("beta", pb_data["beta"], "kf_n", pb_data["kf_n"]) print("iter", i, "err", err, "solve_h", info["solve_h"], "\n")
def main(pb_data): data = Data(pb_data) data.add_to_gb() # Choose and define the solvers and coupler solver_flow = pp.RT0MixedDim("flow") # Compute the initial guess A, b = solver_flow.matrix_rhs(data.gb) x = sps.linalg.spsolve(A, b) solver_flow.split(data.gb, "up", x) solver_flow.extract_p(data.gb, "up", "pressure_old") solver_flow.extract_p(data.gb, "up", "pressure") solver_flow.extract_u(data.gb, "up", "discharge_old") i = 0 err = np.inf while np.any(err > pb_data["fix_pt_err"]) and i < pb_data["fix_pt_maxiter"]: solver_flow.project_u(data.gb, "discharge_old", "P0u") data.update(solver_flow) A, b = solver_flow.matrix_rhs(data.gb) x = sps.linalg.spsolve(A, b) solver_flow.split(data.gb, "up", x) solver_flow.extract_p(data.gb, "up", "pressure") solver_flow.extract_u(data.gb, "up", "discharge") err = compute_error(data.gb) i += 1 # print the summary data print("ref") print( "beta", pb_data["beta"], "gamma", pb_data["gamma"], "iter", i, "err", err, "solve_h", i, ) folder = "ref_" + str(pb_data["beta"]) + "_" + str(pb_data["gamma"]) export(data.gb, x, folder, solver_flow)
def solve_rt0(gb, folder, return_only_matrix=False): # Choose and define the solvers and coupler solver_flow = pp.RT0MixedDim("flow") A_flow, b_flow = solver_flow.matrix_rhs(gb) A = A_flow if return_only_matrix: return A, mortar_dof_size(A, gb, solver_flow) up = sps.linalg.spsolve(A, b_flow) solver_flow.split(gb, "up", up) solver_flow.extract_p(gb, "up", "pressure") save = Exporter(gb, "sol", folder=folder) save.write_vtk(["pressure"])
def main(pb_data, name): data = Data(pb_data) data.add_to_gb() # Choose and define the solvers and coupler solver_flow = pp.RT0MixedDim("flow") A, b = solver_flow.matrix_rhs(data.gb) x = sps.linalg.spsolve(A, b) folder = "ref_" + name + "_" + str(pb_data["mesh_size"]) export(data.gb, x, folder, solver_flow) # print the summary data print("ref") print("kf_n", pb_data["kf_n"], "kf_t", pb_data["kf_t"]) print("solve_h", 1, "\n")
def solve_rt0(gb, folder): # Choose and define the solvers and coupler logger.info("RT0 discretization") tic = time.time() solver_flow = pp.RT0MixedDim("flow") A_flow, b_flow = solver_flow.matrix_rhs(gb) logger.info("Done. Elapsed time: " + str(time.time() - tic)) logger.info("Linear solver") tic = time.time() up = sps.linalg.spsolve(A_flow, b_flow) logger.info("Done. Elapsed time " + str(time.time() - tic)) solver_flow.split(gb, "up", up) solver_flow.extract_p(gb, "up", "pressure") solver_flow.extract_u(gb, "up", "discharge") # solver_flow.project_u(gb, "discharge", "P0u") export(gb, folder)
def solve_rt0(gb, folder): # Choose and define the solvers and coupler logger.info('RT0 discretization') tic = time.time() solver_flow = pp.RT0MixedDim("flow") A_flow, b_flow = solver_flow.matrix_rhs(gb) logger.info('Done. Elapsed time: ' + str(time.time() - tic)) logger.info('Linear solver') tic = time.time() up = sps.linalg.spsolve(A_flow, b_flow) logger.info('Done. Elapsed time ' + str(time.time() - tic)) solver_flow.split(gb, "up", up) solver_flow.extract_p(gb, "up", "pressure") solver_flow.extract_u(gb, "up", "discharge") export(gb, folder) sps_io.mmwrite(folder+"/matrix.mtx", A_flow)
def main_ms(pb_data, name): # in principle we can re-compute only the matrices related to the # fracture network, however to simplify the implementation we re-compute # everything data = Data(pb_data) data.add_to_gb() # Choose and define the solvers and coupler solver_flow = pp.RT0MixedDim("flow") A, b = solver_flow.matrix_rhs(data.gb, return_bmat=True) # off-line computation fo the bases ms = Multiscale(data.gb) ms.extract_blocks_h(A, b) info = ms.compute_bases() # solve the co-dimensional problem - this is to set the initial iteration # for Newton x_l = ms.solve_l(A, b) solver_flow.split(data.gb, "up", ms.concatenate(None, x_l)) solver_flow.extract_p(data.gb, "up", "pressure_old") solver_flow.extract_u(data.gb, "up", "discharge_old") # initiate iteration count and initial condition i = 0 err = np.inf while np.any( err > pb_data["newton_err"]) and i < pb_data["newton_maxiter"]: # update the non-linear term solver_flow.project_u(data.gb, "discharge_old", "P0u") data.update(solver_flow) # we need to recompute the lower dimensional matrices # for simplicity we do for everything A, b = solver_flow.matrix_rhs(data.gb, return_bmat=True) A_l, b_l = ms.assemble_l(A, b) F_u = b_l - A_l * x_l # update Jacobian # for simplicity we do for everything data.update_jacobian(solver_flow) DA, Db = solver_flow.matrix_rhs(data.gb, return_bmat=True) DF_u, _ = ms.assemble_l(DA, Db) # solve for (xn+1 - xn), update new iteration dx = sps.linalg.spsolve(DF_u, F_u) x_l += dx solver_flow.split(data.gb, "up", ms.concatenate(None, x_l)) solver_flow.extract_p(data.gb, "up", "pressure") solver_flow.extract_u(data.gb, "up", "discharge") err = compute_error(data.gb) i += 1 # post-compute the higher dimensional solution x_h = ms.solve_h(x_l) # update the number of solution of the higher dimensional problem info["solve_h"] += 1 x = ms.concatenate(x_h, x_l) folder = "ms_newton_" + str(pb_data["beta"]) + name export(data.gb, x, folder, solver_flow) write_out(data.gb, "ms_newton" + name + ".txt", info["solve_h"]) # print the summary data print("ms_newton") print("beta", pb_data["beta"], "kf_n", pb_data["kf_n"]) print("iter", i, "err", err, "solve_h", info["solve_h"], "\n\n")
def main_dd(pb_data, name): # in principle we can re-compute only the matrices related to the # fracture network, however to simplify the implementation we re-compute # everything data = Data(pb_data) data.add_to_gb() # parameters for the dd algorithm tol = 1e-6 maxiter = 1e4 solve_h = 0 # Choose and define the solvers and coupler solver_flow = pp.RT0MixedDim("flow") A, b = solver_flow.matrix_rhs(data.gb, return_bmat=True) dd = DomainDecomposition(data.gb) # compute the initial guess dd.extract_blocks(A, b) dd.factorize() x_l, info = dd.solve(tol, maxiter, info=True, return_lower=True) solve_h += info["solve_h"] solver_flow.split(data.gb, "up", dd.concatenate(None, x_l)) solver_flow.extract_p(data.gb, "up", "pressure_old") solver_flow.extract_u(data.gb, "up", "discharge_old") # initiate iteration count and initial condition i = 0 err = np.inf while np.any( err > pb_data["newton_err"]) and i < pb_data["newton_maxiter"]: # update the non-linear term solver_flow.project_u(data.gb, "discharge_old", "P0u") data.update(solver_flow) # we need to recompute the lower dimensional matrices # for simplicity we do for everything A, _ = solver_flow.matrix_rhs(data.gb, return_bmat=True) dd.update_lower_blocks(A) F_u = dd.residual_l(x_l) # update Jacobian # for simplicity we do for everything data.update_jacobian(solver_flow) DA, _ = solver_flow.matrix_rhs(data.gb, return_bmat=True) dd.update_lower_blocks(DA) # solve for (xn+1 - xn), update new iteration dx, info = dd.solve_jacobian(F_u, tol, maxiter, info=True) x_l += dx solver_flow.split(data.gb, "up", dd.concatenate(None, x_l)) solver_flow.extract_p(data.gb, "up", "pressure") solver_flow.extract_u(data.gb, "up", "discharge") err = compute_error(data.gb) i += 1 solve_h += info["solve_h"] + 1 # post-compute the higher dimensional solution x_h = dd.solve_h(x_l) solve_h += 1 x = dd.concatenate(x_h, x_l) folder = "dd_newton_" + str(pb_data["beta"]) + name export(data.gb, x, folder, solver_flow) write_out(data.gb, "dd_newton" + name + ".txt", solve_h) # print the summary data print("dd_newton") print("beta", pb_data["beta"], "kf_n", pb_data["kf_n"]) print("iter", i, "err", err, "solve_h", solve_h, "\n\n")