Source code for pyro.multigrid.examples.mg_test_vc_periodic
#!/usr/bin/env python3"""Test the variable-coefficient MG solver with periodic data.Here we solve:: div . ( alpha grad phi ) = fwith:: alpha = 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 alpha, we do not have to impose thesame BCs, since that may represent a different physical quantity.Here we take alpha to have Neumann BCs. (Dirichlet BCs for alpha willforce it to 0 on the boundary, which is not correct here)"""importmatplotlib.pyplotaspltimportnumpyasnpimportpyro.mesh.boundaryasbndimportpyro.multigrid.variable_coeff_MGasMGimportpyro.util.io_pyroasiofrompyro.meshimportpatchfrompyro.utilimportcompare,msg# the analytic solution
[docs]deftest_vc_poisson_periodic(N,store_bench=False,comp_bench=False,bench_dir="tests/",make_plot=False,verbose=1,rtol=1.e-12):""" test the variable-coefficient 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="periodic",xrb="periodic",ylb="periodic",yrb="periodic")d.register_var("c",bc_c)d.create()c=d.get_var("c")c[:,:]=alpha(g.x2d,g.y2d)# check whether the RHS sums to zero (necessary for periodic data)rhs=f(g.x2d,g.y2d)print(f"rhs sum: {np.sum(rhs[g.ilo:g.ihi+1,g.jlo:g.jhi+1])}")# create the multigrid objecta=MG.VarCoeffCCMG2d(nx,ny,xl_BC_type="periodic",yl_BC_type="periodic",xr_BC_type="periodic",yr_BC_type="periodic",coeffs=c,coeffs_bc=bc_c,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,10000)# get the solutionv=a.get_solution()# get the true solutionb=true(a.x2d,a.y2d)# compute the error from the analytic solution -- note that with# periodic BCs all around, there is nothing to normalize the# solution. We subtract off the average of phi from the MG# solution (we do the same for the true solution to put them on# the same footing)e=v-np.sum(v.v())/(nx*ny)-(b-np.sum(b[a.ilo:a.ihi+1,a.jlo:a.jhi+1])/(nx*ny))enorm=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_vc_periodic_test.png")# store the output for later comparisonbench="mg_vc_poisson_periodic"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(f"comparing to {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(f"ERROR: {compare.errors[result]}\n")returnresult# normal return -- error wrt true solutionreturnenorm
[docs]defmain():N=[16,32,64,128,256,512]err=[]plot=Falsestore=Falsedo_compare=FalsefornxinN:ifnx==max(N):plot=Trueenorm=test_vc_poisson_periodic(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_vc_periodic_converge.png")