def smooth_run(nx): # create the multigrid object a = multigrid.CellCenterMG1d(nx, xl_BC_type="dirichlet", xr_BC_type="dirichlet", verbose=0) # initialize the solution to 0 a.init_zeros() # initialize the RHS using the function f a.init_RHS(f(a.x)) # smooth n = np.arange(20000) + 1 e1 = [] r1 = [] e2 = [] r2 = [] einf = [] rinf = [] for i in n: # do 1 smoothing at the finest level a.smooth(a.nlevels-1,1) # compute the true error (wrt the analytic solution) v = a.get_solution() e1.append(error1(a.soln_grid, v - true(a.x))) e2.append(error2(a.soln_grid, v - true(a.x))) einf.append(errorinf(a.soln_grid, v - true(a.x))) # compute the residual a._compute_residual(a.nlevels-1) r1.append(error1(a.soln_grid, a.grids[a.nlevels-1].get_var("r")) ) r2.append(error2(a.soln_grid, a.grids[a.nlevels-1].get_var("r")) ) rinf.append(errorinf(a.soln_grid, a.grids[a.nlevels-1].get_var("r")) ) r1 = np.array(r1) e1 = np.array(e1) r2 = np.array(r2) e2 = np.array(e2) rinf = np.array(rinf) einf = np.array(einf) return n, r1, e1, r2, e2, rinf, einf
def evolve(nx, C, tmax, xmax=None): xmin = 0.0 if xmax == None: xmax = 1.0 # create a dummy patch to store some info in the same way the MG # solver will myg = patch1d.Grid1d(nx, ng=1, xmin=xmin, xmax=xmax) # initialize the data phi = myg.scratch_array() # initial solution -- this fills the GC too phi[:] = phi_a(myg, 0.0) # time info dt = C * 0.5 * myg.dx**2 / k t = 0.0 # evolve while t < tmax: if t + dt > tmax: dt = tmax - t # create the multigrid object a = multigrid.CellCenterMG1d(nx, xmin=xmin, xmax=xmax, alpha=1.0, beta=0.5 * dt * k, xl_BC_type="neumann", xr_BC_type="neumann", verbose=0) # initialize the RHS a.init_RHS(phi + 0.5 * dt * k * lap(a.soln_grid, phi)) # initialize the solution to 0 a.init_zeros() # solve to a relative tolerance of 1.e-11 a.solve(rtol=1.e-11) # get the solution v = a.get_solution() # store the new solution phi[:] = v[:] t += dt return a.soln_grid, phi
def mgsolve(nx): # create the multigrid object a = multigrid.CellCenterMG1d(nx, xl_BC_type="dirichlet", xr_BC_type="dirichlet", verbose=0) # initialize the solution to 0 a.init_zeros() # initialize the RHS using the function f a.init_RHS(f(a.x)) # solve to a relative tolerance of 1.e-11 a.solve(rtol=1.e-11) # get the solution v = a.get_solution() # compute the error from the analytic solution return error(a.soln_grid, v - true(a.x))
# normalize return numpy.sqrt(myg.dx*numpy.sum((r[myg.ilo:myg.ihi+1]**2))) # the righthand side def f(x): return numpy.sin(x) # test the multigrid solver nx = 256 # create the multigrid object a = multigrid.CellCenterMG1d(nx, xl_BC_type="dirichlet", xr_BC_type="dirichlet", verbose=1, true_function=true) # initialize the solution to 0 a.init_zeros() # initialize the RHS using the function f a.init_RHS(f(a.x)) # solve to a relative tolerance of 1.e-11 elist, rlist = a.solve(rtol=1.e-11) Ncycle = numpy.arange(len(elist)) + 1 # get the solution
def smooth_run(nx, nsmooth=20000, modes=None, return_sol=False, rhs=f): """ do smoothing for a 1-d Poisson problem with nx zones on a cell-centered grid. nsmooth is the number of smoothing iterations to do modes (optional) is a list of equally-weighted sine modes to initialize the solution with return_sol=True will return the solution object (CellCenteredMG1d), otherwise it will return arrays of the error and residual as a function of iteration rhs is the function to call to define the RHS of the Poisson equation. """ # create the multigrid object a = multigrid.CellCenterMG1d(nx, xl_BC_type="dirichlet", xr_BC_type="dirichlet", verbose=0) if modes is None: # initialize the solution to 0 a.init_zeros() else: phi = a.soln_grid.scratch_array() for m in modes: phi += np.sin(2.0 * np.pi * m * a.x) phi /= len(modes) a.init_solution(phi) # initialize the RHS using the function f a.init_RHS(rhs(a.x)) # smooth n = np.arange(nsmooth) + 1 e = [] r = [] for i in n: # do 1 smoothing at the finest level a.smooth(a.nlevels - 1, 1) # compute the true error (wrt the analytic solution) v = a.get_solution() e.append(error(a.soln_grid, v - true(a.x))) # compute the residual a._compute_residual(a.nlevels - 1) r.append(error(a.soln_grid, a.grids[a.nlevels - 1].get_var("r"))) r = np.array(r) e = np.array(e) print(nsmooth, r[-1]) if return_sol: return a else: return n, r, e