Source code for pyro.multigrid.examples.mg_test_general_beta_only
#!/usr/bin/env python3"""Test the general MG solver with a variable coefficient Poissonproblem (in essence, we are making this solver act like thevariable_coefficient_MG.py solver). This ensures we didn'tscrew up the base functionality here.Here we solve:: div . ( beta grad phi ) = fwith:: beta = 2.0 + cos(2.0*pi*x)*cos(2.0*pi*y) f = -16.0*pi**2*(cos(2*pi*x)*cos(2*pi*y) + 1)*sin(2*pi*x)*sin(2*pi*y)This has the exact solution:: phi = sin(2.0*pi*x)*sin(2.0*pi*y)on [0,1] x [0,1]We use Dirichlet BCs on phi. For beta, we do not have to impose thesame BCs, since that may represent a different physical quantity.Here we take beta to have Neumann BCs. (Dirichlet BCs for beta willforce it to 0 on the boundary, which is not correct here)"""importmatplotlib.pyplotaspltimportnumpyasnpimportpyro.mesh.boundaryasbndimportpyro.multigrid.general_MGasMGimportpyro.util.io_pyroasiofrompyro.meshimportpatchfrompyro.utilimportcompare,msg# the analytic solution
[docs]deftest_general_poisson_dirichlet(N,store_bench=False,comp_bench=False,bench_dir="tests/",make_plot=False,verbose=1,rtol=1.e-12):""" test the general MG solver. The return value here is the error compared to the exact solution, UNLESS comp_bench=True, in which case the return value is the error compared to the stored benchmark """# test the multigrid solvernx=Nny=nx# create the coefficient variableg=patch.Grid2d(nx,ny,ng=1)d=patch.CellCenterData2d(g)bc_c=bnd.BC(xlb="neumann",xrb="neumann",ylb="neumann",yrb="neumann")d.register_var("alpha",bc_c)d.register_var("beta",bc_c)d.register_var("gamma_x",bc_c)d.register_var("gamma_y",bc_c)d.create()a=d.get_var("alpha")a[:,:]=alpha(g.x2d,g.y2d)b=d.get_var("beta")b[:,:]=beta(g.x2d,g.y2d)gx=d.get_var("gamma_x")gx[:,:]=gamma_x(g.x2d,g.y2d)gy=d.get_var("gamma_y")gy[:,:]=gamma_y(g.x2d,g.y2d)# create the multigrid objecta=MG.GeneralMG2d(nx,ny,xl_BC_type="dirichlet",yl_BC_type="dirichlet",xr_BC_type="dirichlet",yr_BC_type="dirichlet",coeffs=d,verbose=verbose,vis=0,true_function=true)# initialize the solution to 0a.init_zeros()# initialize the RHS using the function frhs=f(a.x2d,a.y2d)a.init_RHS(rhs)# solve to a relative tolerance of 1.e-11a.solve(rtol=1.e-11)# alternately, we can just use smoothing by uncommenting the following# a.smooth(a.nlevels-1,50000)# get the solutionv=a.get_solution()# compute the error from the analytic solutionb=true(a.x2d,a.y2d)e=v-benorm=e.norm()print(" L2 error from true solution = %g\n rel. err from previous cycle = %g\n num. cycles = %d"%(enorm,a.relative_error,a.num_cycles))# plot the solutionifmake_plot:plt.clf()plt.figure(figsize=(10.0,4.0),dpi=100,facecolor='w')plt.subplot(121)img1=plt.imshow(np.transpose(v.v()),interpolation="nearest",origin="lower",extent=[a.xmin,a.xmax,a.ymin,a.ymax])plt.xlabel("x")plt.ylabel("y")plt.title(f"nx = {nx}")plt.colorbar(img1)plt.subplot(122)img2=plt.imshow(np.transpose(e.v()),interpolation="nearest",origin="lower",extent=[a.xmin,a.xmax,a.ymin,a.ymax])plt.xlabel("x")plt.ylabel("y")plt.title("error")plt.colorbar(img2)plt.tight_layout()plt.savefig("mg_general_beta_only_test.png")# store the output for later comparisonbench="mg_general_poisson_dirichlet"my_data=a.get_solution_object()ifstore_bench:my_data.write(f"{bench_dir}/{bench}")# do we do a comparison?ifcomp_bench:compare_file=f"{bench_dir}/{bench}"msg.warning("comparing to: %s "%(compare_file))bench=io.read(compare_file)result=compare.compare(my_data,bench,rtol)ifresult==0:msg.success(f"results match benchmark to within relative tolerance of {rtol}\n")else:msg.warning("ERROR: "+compare.errors[result]+"\n")returnresult# normal return -- error wrt true solutionreturnenorm
[docs]defmain():N=[16,32,64]err=[]plot=Falsestore=Falsedo_compare=FalsefornxinN:ifnx==max(N):plot=Trueenorm=test_general_poisson_dirichlet(nx,make_plot=plot,store_bench=store,comp_bench=do_compare)err.append(enorm)# plot the convergenceN=np.array(N,dtype=np.float64)err=np.array(err)plt.clf()plt.loglog(N,err,"x",color="r")plt.loglog(N,err[0]*(N[0]/N)**2,"--",color="k")plt.xlabel("N")plt.ylabel("error")fig=plt.gcf()fig.set_size_inches(7.0,6.0)plt.tight_layout()plt.savefig("mg_general_beta_only_converge.png")