示例#1
0
def test_vc_poisson_dirichlet(N,
                              store_bench=False,
                              comp_bench=False,
                              make_plot=False,
                              verbose=1):
    """
    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 solver
    nx = N
    ny = nx

    # create the coefficient variable
    g = patch.Grid2d(nx, ny, ng=1)
    d = patch.CellCenterData2d(g)
    bc_c = patch.BCObject(xlb="neumann",
                          xrb="neumann",
                          ylb="neumann",
                          yrb="neumann")
    d.register_var("c", bc_c)
    d.create()

    c = d.get_var("c")
    c.d[:, :] = alpha(g.x2d, g.y2d)

    # create the multigrid object
    a = MG.VarCoeffCCMG2d(nx,
                          ny,
                          xl_BC_type="dirichlet",
                          yl_BC_type="dirichlet",
                          xr_BC_type="dirichlet",
                          yr_BC_type="dirichlet",
                          coeffs=c,
                          coeffs_bc=bc_c,
                          verbose=verbose,
                          vis=0,
                          true_function=true)

    # initialize the solution to 0
    a.init_zeros()

    # initialize the RHS using the function f
    rhs = f(a.x2d, a.y2d)
    a.init_RHS(rhs)

    # solve to a relative tolerance of 1.e-11
    a.solve(rtol=1.e-11)

    # alternately, we can just use smoothing by uncommenting the following
    #a.smooth(a.nlevels-1,50000)

    # get the solution
    v = a.get_solution()

    # compute the error from the analytic solution
    b = true(a.x2d, a.y2d)
    e = v - b

    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 solution
    if make_plot:
        plt.clf()

        plt.figure(figsize=(10.0, 4.0), dpi=100, facecolor='w')

        plt.subplot(121)

        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("nx = {}".format(nx))

        plt.colorbar()

        plt.subplot(122)

        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()

        plt.tight_layout()

        plt.savefig("mg_vc_dirichlet_test.png")

    # store the output for later comparison
    bench = "mg_vc_poisson_dirichlet"
    bench_dir = os.environ["PYRO_HOME"] + "/multigrid/tests/"

    my_data = a.get_solution_object()

    if store_bench:
        my_data.write("{}/{}".format(bench_dir, bench))

    # do we do a comparison?
    if comp_bench:
        compare_file = "{}/{}".format(bench_dir, bench)
        msg.warning("comparing to: %s " % (compare_file))
        bench_grid, bench_data = patch.read(compare_file)

        result = compare.compare(my_data.grid, my_data, bench_grid, bench_data)

        if result == 0:
            msg.success("results match benchmark\n")
        else:
            msg.warning("ERROR: " + compare.errors[result] + "\n")

        return result

    # normal return -- error wrt true solution
    return enorm
示例#2
0
    def evolve(self):
        """
        Evolve the low Mach system through one timestep.
        """

        rho = self.cc_data.get_var("density")
        u = self.cc_data.get_var("x-velocity")
        v = self.cc_data.get_var("y-velocity")

        gradp_x = self.cc_data.get_var("gradp_x")
        gradp_y = self.cc_data.get_var("gradp_y")
        
        # note: the base state quantities do not have valid ghost cells
        beta0 = self.base["beta0"]
        beta0_edges = self.base["beta0-edges"]

        rho0 = self.base["rho0"]

        phi = self.cc_data.get_var("phi")

        myg = self.cc_data.grid


        #---------------------------------------------------------------------
        # create the limited slopes of rho, u and v (in both directions)
        #---------------------------------------------------------------------
        limiter = self.rp.get_param("lm-atmosphere.limiter")
        if limiter == 0: limitFunc = reconstruction_f.nolimit
        elif limiter == 1: limitFunc = reconstruction_f.limit2
        else: limitFunc = reconstruction_f.limit4


        ldelta_rx = limitFunc(1, rho.d, myg.qx, myg.qy, myg.ng)
        ldelta_ux = limitFunc(1, u.d, myg.qx, myg.qy, myg.ng)
        ldelta_vx = limitFunc(1, v.d, myg.qx, myg.qy, myg.ng)

        ldelta_ry = limitFunc(2, rho.d, myg.qx, myg.qy, myg.ng)
        ldelta_uy = limitFunc(2, u.d, myg.qx, myg.qy, myg.ng)
        ldelta_vy = limitFunc(2, v.d, myg.qx, myg.qy, myg.ng)

        
        #---------------------------------------------------------------------
        # get the advective velocities
        #---------------------------------------------------------------------

        """
        the advective velocities are the normal velocity through each cell
        interface, and are defined on the cell edges, in a MAC type
        staggered form

                         n+1/2
                        v
                         i,j+1/2
                    +------+------+
                    |             |
            n+1/2   |             |   n+1/2
           u        +     U       +  u
            i-1/2,j |      i,j    |   i+1/2,j
                    |             |
                    +------+------+
                         n+1/2
                        v
                         i,j-1/2

        """

        # this returns u on x-interfaces and v on y-interfaces.  These
        # constitute the MAC grid
        if self.verbose > 0: print("  making MAC velocities")

        # create the coefficient to the grad (pi/beta) term
        coeff = self.aux_data.get_var("coeff")
        coeff.v()[:,:] = 1.0/rho.v()
        coeff.v()[:,:] = coeff.v()*beta0.v2d()
        self.aux_data.fill_BC("coeff")

        # create the source term
        source = self.aux_data.get_var("source_y")

        g = self.rp.get_param("lm-atmosphere.grav")
        rhoprime = self.make_prime(rho, rho0)
        source.v()[:,:] = rhoprime.v()*g/rho.v()
        self.aux_data.fill_BC("source_y")

        _um, _vm = lm_interface_f.mac_vels(myg.qx, myg.qy, myg.ng,
                                           myg.dx, myg.dy, self.dt,
                                           u.d, v.d,
                                           ldelta_ux, ldelta_vx,
                                           ldelta_uy, ldelta_vy,
                                           coeff.d*gradp_x.d, coeff.d*gradp_y.d,
                                           source.d)


        u_MAC = patch.ArrayIndexer(d=_um, grid=myg)
        v_MAC = patch.ArrayIndexer(d=_vm, grid=myg)        


        #---------------------------------------------------------------------
        # do a MAC projection to make the advective velocities divergence
        # free
        #---------------------------------------------------------------------

        # we will solve D (beta_0^2/rho) G phi = D (beta_0 U^MAC), where
        # phi is cell centered, and U^MAC is the MAC-type staggered
        # grid of the advective velocities.

        if self.verbose > 0: print("  MAC projection")

        # create the coefficient array: beta0**2/rho
        # MZ!!!! probably don't need the buf here
        coeff.v(buf=1)[:,:] = 1.0/rho.v(buf=1)
        coeff.v(buf=1)[:,:] = coeff.v(buf=1)*beta0.v2d(buf=1)**2

        # create the multigrid object
        mg = vcMG.VarCoeffCCMG2d(myg.nx, myg.ny,
                                 xl_BC_type=self.cc_data.BCs["phi-MAC"].xlb,
                                 xr_BC_type=self.cc_data.BCs["phi-MAC"].xrb,
                                 yl_BC_type=self.cc_data.BCs["phi-MAC"].ylb,
                                 yr_BC_type=self.cc_data.BCs["phi-MAC"].yrb,
                                 xmin=myg.xmin, xmax=myg.xmax,
                                 ymin=myg.ymin, ymax=myg.ymax,
                                 coeffs=coeff,
                                 coeffs_bc=self.cc_data.BCs["density"],
                                 verbose=0)

        # first compute div{beta_0 U}
        div_beta_U = mg.soln_grid.scratch_array()

        # MAC velocities are edge-centered.  div{beta_0 U} is cell-centered.
        div_beta_U.v()[:,:] = \
            beta0.v2d()*(u_MAC.ip(1) - u_MAC.v())/myg.dx + \
            (beta0_edges.v2dp(1)*v_MAC.jp(1) -
             beta0_edges.v2d()*v_MAC.v())/myg.dy

        # solve the Poisson problem
        mg.init_RHS(div_beta_U.d)
        mg.solve(rtol=1.e-12)


        # update the normal velocities with the pressure gradient -- these
        # constitute our advective velocities.  Note that what we actually
        # solved for here is phi/beta_0
        phi_MAC = self.cc_data.get_var("phi-MAC")
        phi_MAC.d[:,:] = mg.get_solution(grid=myg).d

        coeff = self.aux_data.get_var("coeff")
        coeff.v()[:,:] = 1.0/rho.v()
        coeff.v()[:,:] = coeff.v()*beta0.v2d()
        self.aux_data.fill_BC("coeff")

        coeff_x = myg.scratch_array()
        b = (3, 1, 0, 0)  # this seems more than we need
        coeff_x.v(buf=b)[:,:] = 0.5*(coeff.ip(-1, buf=b) + coeff.v(buf=b))

        coeff_y = myg.scratch_array()
        b = (0, 0, 3, 1)
        coeff_y.v(buf=b)[:,:] = 0.5*(coeff.jp(-1, buf=b) + coeff.v(buf=b))
        
        # we need the MAC velocities on all edges of the computational domain
        # here we do U = U - (beta_0/rho) grad (phi/beta_0)
        b = (0, 1, 0, 0)
        u_MAC.v(buf=b)[:,:] -= \
                coeff_x.v(buf=b)*(phi_MAC.v(buf=b) - phi_MAC.ip(-1, buf=b))/myg.dx

        b = (0, 0, 0, 1)
        v_MAC.v(buf=b)[:,:] -= \
                coeff_y.v(buf=b)*(phi_MAC.v(buf=b) - phi_MAC.jp(-1, buf=b))/myg.dy


        #---------------------------------------------------------------------
        # predict rho to the edges and do its conservative update
        #---------------------------------------------------------------------
        _rx, _ry = lm_interface_f.rho_states(myg.qx, myg.qy, myg.ng,
                                             myg.dx, myg.dy, self.dt,
                                             rho.d, u_MAC.d, v_MAC.d,
                                             ldelta_rx, ldelta_ry)

        rho_xint = patch.ArrayIndexer(d=_rx, grid=myg)
        rho_yint = patch.ArrayIndexer(d=_ry, grid=myg)

        rho_old = rho.copy()

        rho.v()[:,:] -= self.dt*(
            #  (rho u)_x
            (rho_xint.ip(1)*u_MAC.ip(1) - rho_xint.v()*u_MAC.v())/myg.dx +
            #  (rho v)_y
            (rho_yint.jp(1)*v_MAC.jp(1) - rho_yint.v()*v_MAC.v())/myg.dy )

        self.cc_data.fill_BC("density")

        # update eint as a diagnostic
        eint = self.cc_data.get_var("eint")
        gamma = self.rp.get_param("eos.gamma")        
        eint.v()[:,:] = self.base["p0"].v2d()/(gamma - 1.0)/rho.v()
        
        
        #---------------------------------------------------------------------
        # recompute the interface states, using the advective velocity
        # from above
        #---------------------------------------------------------------------
        if self.verbose > 0: print("  making u, v edge states")

        coeff = self.aux_data.get_var("coeff")
        coeff.v()[:,:] = 2.0/(rho.v() + rho_old.v())
        coeff.v()[:,:] = coeff.v()*beta0.v2d()
        self.aux_data.fill_BC("coeff")

        _ux, _vx, _uy, _vy = \
               lm_interface_f.states(myg.qx, myg.qy, myg.ng,
                                     myg.dx, myg.dy, self.dt,
                                     u.d, v.d,
                                     ldelta_ux, ldelta_vx,
                                     ldelta_uy, ldelta_vy,
                                     coeff.d*gradp_x.d, coeff.d*gradp_y.d,
                                     source.d,
                                     u_MAC.d, v_MAC.d)

        u_xint = patch.ArrayIndexer(d=_ux, grid=myg)
        v_xint = patch.ArrayIndexer(d=_vx, grid=myg)
        u_yint = patch.ArrayIndexer(d=_uy, grid=myg)
        v_yint = patch.ArrayIndexer(d=_vy, grid=myg)


        #---------------------------------------------------------------------
        # update U to get the provisional velocity field
        #---------------------------------------------------------------------
        if self.verbose > 0: print("  doing provisional update of u, v")

        # compute (U.grad)U

        # we want u_MAC U_x + v_MAC U_y
        advect_x = myg.scratch_array()
        advect_y = myg.scratch_array()

        advect_x.v()[:,:] = \
            0.5*(u_MAC.v() + u_MAC.ip(1))*(u_xint.ip(1) - u_xint.v())/myg.dx +\
            0.5*(v_MAC.v() + v_MAC.jp(1))*(u_yint.jp(1) - u_yint.v())/myg.dy

        advect_y.v()[:,:] = \
            0.5*(u_MAC.v() + u_MAC.ip(1))*(v_xint.ip(1) - v_xint.v())/myg.dx +\
            0.5*(v_MAC.v() + v_MAC.jp(1))*(v_yint.jp(1) - v_yint.v())/myg.dy


        proj_type = self.rp.get_param("lm-atmosphere.proj_type")

        if proj_type == 1:
            u.v()[:,:] -= (self.dt*advect_x.v() + self.dt*gradp_x.v())
            v.v()[:,:] -= (self.dt*advect_y.v() + self.dt*gradp_y.v())

        elif proj_type == 2:
            u.v()[:,:] -= self.dt*advect_x.v()
            v.v()[:,:] -= self.dt*advect_y.v()


        # add the gravitational source
        rho_half = 0.5*(rho + rho_old)
        rhoprime = self.make_prime(rho_half, rho0)
        source.d[:,:] = (rhoprime*g/rho_half).d
        self.aux_data.fill_BC("source_y")

        v.d[:,:] += self.dt*source.d

        self.cc_data.fill_BC("x-velocity")
        self.cc_data.fill_BC("y-velocity")

        if self.verbose > 0:
            print("min/max rho = {}, {}".format(self.cc_data.min("density"), self.cc_data.max("density")))
            print("min/max u   = {}, {}".format(self.cc_data.min("x-velocity"), self.cc_data.max("x-velocity")))
            print("min/max v   = {}, {}".format(self.cc_data.min("y-velocity"), self.cc_data.max("y-velocity")))


        #---------------------------------------------------------------------
        # project the final velocity
        #---------------------------------------------------------------------

        # now we solve L phi = D (U* /dt)
        if self.verbose > 0: print("  final projection")

        # create the coefficient array: beta0**2/rho
        coeff = 1.0/rho
        coeff.v()[:,:] = coeff.v()*beta0.v2d()**2

        # create the multigrid object
        mg = vcMG.VarCoeffCCMG2d(myg.nx, myg.ny,
                                 xl_BC_type=self.cc_data.BCs["phi"].xlb,
                                 xr_BC_type=self.cc_data.BCs["phi"].xrb,
                                 yl_BC_type=self.cc_data.BCs["phi"].ylb,
                                 yr_BC_type=self.cc_data.BCs["phi"].yrb,
                                 xmin=myg.xmin, xmax=myg.xmax,
                                 ymin=myg.ymin, ymax=myg.ymax,
                                 coeffs=coeff,
                                 coeffs_bc=self.cc_data.BCs["density"],
                                 verbose=0)

        # first compute div{beta_0 U}

        # u/v are cell-centered, divU is cell-centered
        div_beta_U.v()[:,:] = \
            0.5*beta0.v2d()*(u.ip(1) - u.ip(-1))/myg.dx + \
            0.5*(beta0.v2dp(1)*v.jp(1) - beta0.v2dp(-1)*v.jp(-1))/myg.dy

        mg.init_RHS(div_beta_U.d/self.dt)

        # use the old phi as our initial guess
        phiGuess = mg.soln_grid.scratch_array()
        phiGuess.v(buf=1)[:,:] = phi.v(buf=1)
        mg.init_solution(phiGuess.d)

        # solve
        mg.solve(rtol=1.e-12)


        # store the solution in our self.cc_data object -- include a single
        # ghostcell
        phi.d[:,:] = mg.get_solution(grid=myg).d

        # get the cell-centered gradient of p and update the velocities
        # this differs depending on what we projected.
        gradphi_x, gradphi_y = mg.get_solution_gradient(grid=myg)


        # U = U - (beta_0/rho) grad (phi/beta_0)
        coeff = 1.0/rho
        coeff.v()[:,:] = coeff.v()*beta0.v2d()

        u.v()[:,:] -= self.dt*coeff.v()*gradphi_x.v()
        v.v()[:,:] -= self.dt*coeff.v()*gradphi_y.v()

        # store gradp for the next step

        if proj_type == 1:
            gradp_x.v()[:,:] += gradphi_x.v()
            gradp_y.v()[:,:] += gradphi_y.v()

        elif proj_type == 2:
            gradp_x.v()[:,:] = gradphi_x.v()
            gradp_y.v()[:,:] = gradphi_y.v()

        self.cc_data.fill_BC("x-velocity")
        self.cc_data.fill_BC("y-velocity")

        self.cc_data.fill_BC("gradp_x")
        self.cc_data.fill_BC("gradp_y")

        # increment the time
        if not self.in_preevolve:
            self.cc_data.t += self.dt
            self.n += 1
示例#3
0
    def preevolve(self):
        """
        preevolve is called before we being the timestepping loop.  For
        the low Mach solver, this does an initial projection on the
        velocity field and then goes through the full evolution to get the
        value of phi.  The fluid state (rho, u, v) is then reset to values
        before this evolve.
        """

        self.in_preevolve = True

        myg = self.cc_data.grid

        rho = self.cc_data.get_var("density")
        u = self.cc_data.get_var("x-velocity")
        v = self.cc_data.get_var("y-velocity")

        self.cc_data.fill_BC("density")        
        self.cc_data.fill_BC("x-velocity")
        self.cc_data.fill_BC("y-velocity")

        # 1. do the initial projection.  This makes sure that our original
        # velocity field satisties div U = 0

        # the coefficent for the elliptic equation is beta_0^2/rho
        coeff = 1/rho
        beta0 = self.base["beta0"]
        coeff.v()[:,:] = coeff.v()*beta0.v2d()**2

        # next create the multigrid object.  We defined phi with
        # the right BCs previously
        mg = vcMG.VarCoeffCCMG2d(myg.nx, myg.ny,
                                 xl_BC_type=self.cc_data.BCs["phi"].xlb,
                                 xr_BC_type=self.cc_data.BCs["phi"].xrb,
                                 yl_BC_type=self.cc_data.BCs["phi"].ylb,
                                 yr_BC_type=self.cc_data.BCs["phi"].yrb,
                                 xmin=myg.xmin, xmax=myg.xmax,
                                 ymin=myg.ymin, ymax=myg.ymax,
                                 coeffs=coeff,
                                 coeffs_bc=self.cc_data.BCs["density"],
                                 verbose=0)

        # first compute div{beta_0 U}
        div_beta_U = mg.soln_grid.scratch_array()

        # u/v are cell-centered, divU is cell-centered
        div_beta_U.v()[:,:] = \
            0.5*beta0.v2d()*(u.ip(1) - u.ip(-1))/myg.dx + \
            0.5*(beta0.v2dp(1)*v.jp(1) - beta0.v2dp(-1)*v.jp(-1))/myg.dy

        # solve D (beta_0^2/rho) G (phi/beta_0) = D( beta_0 U )

        # set the RHS to divU and solve
        mg.init_RHS(div_beta_U.d)
        mg.solve(rtol=1.e-10)
        
        
        # store the solution in our self.cc_data object -- include a single
        # ghostcell
        phi = self.cc_data.get_var("phi")
        phi.d[:,:] = mg.get_solution(grid=myg).d

        # get the cell-centered gradient of phi and update the
        # velocities
        # FIXME: this update only needs to be done on the interior
        # cells -- not ghost cells
        gradp_x, gradp_y = mg.get_solution_gradient(grid=myg)


        coeff = 1.0/rho
        coeff.v()[:,:] = coeff.v()*beta0.v2d()

        u.v()[:,:] -= coeff.v()*gradp_x.v()
        v.v()[:,:] -= coeff.v()*gradp_y.v()

        # fill the ghostcells
        self.cc_data.fill_BC("x-velocity")
        self.cc_data.fill_BC("y-velocity")


        # 2. now get an approximation to gradp at n-1/2 by going through the
        # evolution.

        # store the current solution -- we'll restore it in a bit
        orig_data = patch.cell_center_data_clone(self.cc_data)

        # get the timestep
        self.compute_timestep()

        # evolve
        self.evolve()

        # update gradp_x and gradp_y in our main data object
        new_gp_x = self.cc_data.get_var("gradp_x")
        new_gp_y = self.cc_data.get_var("gradp_y")

        orig_gp_x = orig_data.get_var("gradp_x")
        orig_gp_y = orig_data.get_var("gradp_y")

        orig_gp_x.d[:,:] = new_gp_x.d[:,:]
        orig_gp_y.d[:,:] = new_gp_y.d[:,:]

        self.cc_data = orig_data

        if self.verbose > 0: print("done with the pre-evolution")

        self.in_preevolve = False
示例#4
0
def test_vc_constant(N):

    # test the multigrid solver
    nx = N
    ny = nx

    # create the coefficient variable -- note we don't want Dirichlet here,
    # because that will try to make alpha = 0 on the interface.  alpha can
    # have different BCs than phi
    g = 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("c", bc_c)
    d.create()

    c = d.get_var("c")
    c[:, :] = alpha(g.x2d, g.y2d)

    plt.clf()

    plt.figure(num=1, figsize=(5.0, 5.0), dpi=100, facecolor='w')

    plt.imshow(np.transpose(c[g.ilo:g.ihi + 1, g.jlo:g.jhi + 1]),
               interpolation="nearest",
               origin="lower",
               extent=[g.xmin, g.xmax, g.ymin, g.ymax])

    plt.xlabel("x")
    plt.ylabel("y")
    plt.title("nx = {}".format(nx))

    plt.colorbar()

    plt.savefig("mg_alpha.png")

    # check whether the RHS sums to zero (necessary for periodic data)
    rhs = f(g.x2d, g.y2d)
    print("rhs sum: {}".format(np.sum(rhs[g.ilo:g.ihi + 1, g.jlo:g.jhi + 1])))

    # create the multigrid object
    a = MG.VarCoeffCCMG2d(nx,
                          ny,
                          xl_BC_type="dirichlet",
                          yl_BC_type="dirichlet",
                          xr_BC_type="dirichlet",
                          yr_BC_type="dirichlet",
                          coeffs=c,
                          coeffs_bc=bc_c,
                          verbose=1)

    # initialize the solution to 0
    a.init_zeros()

    # initialize the RHS using the function f
    rhs = f(a.x2d, a.y2d)
    a.init_RHS(rhs)

    # solve to a relative tolerance of 1.e-11
    a.solve(rtol=1.e-11)

    # alternately, we can just use smoothing by uncommenting the following
    #a.smooth(a.nlevels-1,50000)

    # get the solution
    v = a.get_solution()

    # compute the error from the analytic solution
    b = true(a.x2d, a.y2d)
    e = v - b

    print(
        " L2 error from true solution = %g\n rel. err from previous cycle = %g\n num. cycles = %d"
        % (a.soln_grid.norm(e), a.relative_error, a.num_cycles))

    # plot it
    plt.clf()

    plt.figure(num=1, figsize=(10.0, 5.0), dpi=100, facecolor='w')

    plt.subplot(121)

    plt.imshow(np.transpose(v[a.ilo:a.ihi + 1, a.jlo:a.jhi + 1]),
               interpolation="nearest",
               origin="lower",
               extent=[a.xmin, a.xmax, a.ymin, a.ymax])

    plt.xlabel("x")
    plt.ylabel("y")
    plt.title("nx = {}".format(nx))

    plt.colorbar()

    plt.subplot(122)

    plt.imshow(np.transpose(e[a.ilo:a.ihi + 1, a.jlo:a.jhi + 1]),
               interpolation="nearest",
               origin="lower",
               extent=[a.xmin, a.xmax, a.ymin, a.ymax])

    plt.xlabel("x")
    plt.ylabel("y")
    plt.title("error")

    plt.colorbar()

    plt.tight_layout()

    plt.savefig("mg_test.png")

    # store the output for later comparison
    my_data = a.get_solution_object()
    my_data.write("mg_test")
示例#5
0
def test_vc_poisson_periodic(N,
                             store_bench=False,
                             comp_bench=False,
                             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 solver
    nx = N
    ny = nx

    # create the coefficient variable
    g = 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("rhs sum: {}".format(np.sum(rhs[g.ilo:g.ihi + 1, g.jlo:g.jhi + 1])))

    # create the multigrid object
    a = 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 0
    a.init_zeros()

    # initialize the RHS using the function f
    rhs = f(a.x2d, a.y2d)
    a.init_RHS(rhs)

    # solve to a relative tolerance of 1.e-11
    a.solve(rtol=1.e-11)

    # alternately, we can just use smoothing by uncommenting the following
    # a.smooth(a.nlevels-1,10000)

    # get the solution
    v = a.get_solution()

    # get the true solution
    b = 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 solution
    if make_plot:
        plt.clf()

        plt.figure(figsize=(10.0, 4.0), dpi=100, facecolor='w')

        plt.subplot(121)

        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("nx = {}".format(nx))

        plt.colorbar()

        plt.subplot(122)

        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()

        plt.tight_layout()

        plt.savefig("mg_vc_periodic_test.png")

    # store the output for later comparison
    bench = "mg_vc_poisson_periodic"
    bench_dir = os.environ["PYRO_HOME"] + "/multigrid/tests/"

    my_data = a.get_solution_object()

    if store_bench:
        my_data.write("{}/{}".format(bench_dir, bench))

    # do we do a comparison?
    if comp_bench:
        compare_file = "{}/{}".format(bench_dir, bench)
        msg.warning("comparing to {}".format(compare_file))
        bench = io.read(compare_file)

        result = compare.compare(my_data, bench, rtol)

        if result == 0:
            msg.success(
                "results match benchmark to within relative tolerance of {}\n".
                format(rtol))
        else:
            msg.warning("ERROR: {}\n".format(compare.errors[result]))

        return result

    # normal return -- error wrt true solution
    return enorm
示例#6
0
plt.title("nx = {}".format(nx))

plt.colorbar()

plt.savefig("mg_alpha.png")

# check whether the RHS sums to zero (necessary for periodic data)
rhs = f(g.x2d, g.y2d)
print("rhs sum: {}".format(np.sum(rhs[g.ilo:g.ihi + 1, g.jlo:g.jhi + 1])))

# create the multigrid object
a = MG.VarCoeffCCMG2d(nx,
                      ny,
                      xl_BC_type="dirichlet",
                      yl_BC_type="dirichlet",
                      xr_BC_type="dirichlet",
                      yr_BC_type="dirichlet",
                      coeffs=c,
                      coeffs_bc=bc_c,
                      verbose=1)

# initialize the solution to 0
a.init_zeros()

# initialize the RHS using the function f
rhs = f(a.x2d, a.y2d)
a.init_RHS(rhs)

# solve to a relative tolerance of 1.e-11
a.solve(rtol=1.e-11)