def bc_setup(rp): # first figure out the BCs xlb_type = rp.get_param("mesh.xlboundary") xrb_type = rp.get_param("mesh.xrboundary") ylb_type = rp.get_param("mesh.ylboundary") yrb_type = rp.get_param("mesh.yrboundary") bc = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type) # if we are reflecting, we need odd reflection in the normal # directions for the velocity bc_xodd = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type, odd_reflect_dir="x") bc_yodd = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type, odd_reflect_dir="y") return bc, bc_xodd, bc_yodd
def initialize(rp): """ initialize the grid and variables for diffusion """ # setup the grid nx = rp.get_param("mesh.nx") ny = rp.get_param("mesh.ny") xmin = rp.get_param("mesh.xmin") xmax = rp.get_param("mesh.xmax") ymin = rp.get_param("mesh.ymin") ymax = rp.get_param("mesh.ymax") my_grid = patch.Grid2d(nx, ny, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, ng=1) # create the variables # first figure out the boundary conditions -- we allow periodic, # Dirichlet, and Neumann. xlb_type = rp.get_param("mesh.xlboundary") xrb_type = rp.get_param("mesh.xrboundary") ylb_type = rp.get_param("mesh.ylboundary") yrb_type = rp.get_param("mesh.yrboundary") bcparam = [] for bc in [xlb_type, xrb_type, ylb_type, yrb_type]: if (bc == "periodic"): bcparam.append("periodic") elif (bc == "neumann"): bcparam.append("neumann") elif (bc == "dirichlet"): bcparam.append("dirichlet") else: msg.fail("invalid BC") bc = patch.BCObject(xlb=bcparam[0], xrb=bcparam[1], ylb=bcparam[2], yrb=bcparam[3]) my_data = patch.CellCenterData2d(my_grid, runtime_parameters=rp) my_data.register_var("phi", bc) my_data.create() return my_grid, my_data
def initialize(rp): """ initialize the grid and variables for advection """ # setup the grid nx = rp.get_param("mesh.nx") ny = rp.get_param("mesh.ny") xmin = rp.get_param("mesh.xmin") xmax = rp.get_param("mesh.xmax") ymin = rp.get_param("mesh.ymin") ymax = rp.get_param("mesh.ymax") my_grid = patch.Grid2d(nx, ny, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, ng=4) # create the variables # first figure out the boundary conditions -- we need to translate # between the descriptive type of the boundary specified by the # user and the action that will be performed by the fill_BC routine. # Usually the actions can vary depending on the variable, but we # only have one variable. xlb_type = rp.get_param("mesh.xlboundary") xrb_type = rp.get_param("mesh.xrboundary") ylb_type = rp.get_param("mesh.ylboundary") yrb_type = rp.get_param("mesh.yrboundary") bc = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type) my_data = patch.CellCenterData2d(my_grid, runtime_parameters=rp) my_data.register_var("density", bc) my_data.create() return my_grid, my_data
def initialize(self): """ Initialize the grid and variables for diffusion and set the initial conditions for the chosen problem. """ # setup the grid my_grid = grid_setup(self.rp, ng=1) # create the variables # first figure out the boundary conditions -- we allow periodic, # Dirichlet, and Neumann. xlb_type = self.rp.get_param("mesh.xlboundary") xrb_type = self.rp.get_param("mesh.xrboundary") ylb_type = self.rp.get_param("mesh.ylboundary") yrb_type = self.rp.get_param("mesh.yrboundary") bcparam = [] for bc in [xlb_type, xrb_type, ylb_type, yrb_type]: if bc == "periodic": bcparam.append("periodic") elif bc == "neumann": bcparam.append("neumann") elif bc == "dirichlet": bcparam.append("dirichlet") else: msg.fail("invalid BC") bc = patch.BCObject(xlb=bcparam[0], xrb=bcparam[1], ylb=bcparam[2], yrb=bcparam[3]) my_data = patch.CellCenterData2d(my_grid) my_data.register_var("phi", bc) my_data.create() self.cc_data = my_data # now set the initial conditions for the problem exec(self.problem_name + '.init_data(self.cc_data, self.rp)')
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
# test the prolongation and restriction operations from the patch stuff import mesh.patch as patch import numpy # create our base grid and initialize it with sequential data myg = patch.Grid2d(4,8,ng=1) myd = patch.CellCenterData2d(myg) bc = patch.BCObject() myd.register_var("a", bc) myd.create() a = myd.get_var("a") a[myg.ilo:myg.ihi+1,myg.jlo:myg.jhi+1].flat = numpy.arange(myg.nx*myg.ny) print "restriction test" print "original (fine) array" myd.pretty_print("a") # create a coarse grid and fill the variable in it with restricted data print " " print "restricted array" cg = patch.Grid2d(2,4,ng=1) cd = patch.CellCenterData2d(cg) cd.register_var("a", bc) cd.create() a_coarse = cd.get_var("a")
def initialize(self): """ Initialize the grid and variables for compressible flow and set the initial conditions for the chosen problem. """ # setup the grid nx = self.rp.get_param("mesh.nx") ny = self.rp.get_param("mesh.ny") xmin = self.rp.get_param("mesh.xmin") xmax = self.rp.get_param("mesh.xmax") ymin = self.rp.get_param("mesh.ymin") ymax = self.rp.get_param("mesh.ymax") verbose = self.rp.get_param("driver.verbose") my_grid = patch.Grid2d(nx, ny, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, ng=4) # create the variables my_data = patch.CellCenterData2d(my_grid) # define solver specific boundary condition routines patch.define_bc("hse", BC.user) # first figure out the boundary conditions. Note: the action # can depend on the variable (for reflecting BCs) xlb_type = self.rp.get_param("mesh.xlboundary") xrb_type = self.rp.get_param("mesh.xrboundary") ylb_type = self.rp.get_param("mesh.ylboundary") yrb_type = self.rp.get_param("mesh.yrboundary") bc = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type) # density and energy my_data.register_var("density", bc) my_data.register_var("energy", bc) my_data.register_var("erad", bc) # for velocity, if we are reflecting, we need odd reflection # in the normal direction. # x-momentum -- if we are reflecting in x, then we need to # reflect odd bc_xodd = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type, odd_reflect_dir="x") my_data.register_var("x-momentum", bc_xodd) # y-momentum -- if we are reflecting in y, then we need to # reflect odd bc_yodd = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type, odd_reflect_dir="y") my_data.register_var("y-momentum", bc_yodd) # store grav because we'll need that in some BCs my_data.set_aux("grav", self.rp.get_param("compressible.grav")) my_data.create() self.cc_data = my_data self.vars = Variables(idens=my_data.vars.index("density"), ixmom=my_data.vars.index("x-momentum"), iymom=my_data.vars.index("y-momentum"), iener=my_data.vars.index("energy"), ierad=my_data.vars.index("erad")) # initial conditions for the problem exec(self.problem_name + '.init_data(self.cc_data, self.rp)') if verbose > 0: print(my_data)
def test_bcs(): myg = patch.Grid2d(4, 4, ng=2, xmax=1.0, ymax=1.0) myd = patch.CellCenterData2d(myg, dtype=np.int) bco = patch.BCObject(xlb="outflow", xrb="outflow", ylb="outflow", yrb="outflow") myd.register_var("outflow", bco) bcp = patch.BCObject(xlb="periodic", xrb="periodic", ylb="periodic", yrb="periodic") myd.register_var("periodic", bcp) bcre = patch.BCObject(xlb="reflect-even", xrb="reflect-even", ylb="reflect-even", yrb="reflect-even") myd.register_var("reflect-even", bcre) bcro = patch.BCObject(xlb="reflect-odd", xrb="reflect-odd", ylb="reflect-odd", yrb="reflect-odd") myd.register_var("reflect-odd", bcro) myd.create() a = myd.get_var("outflow") a.v()[:, :] = np.fromfunction(lambda i, j: i + 10 * j + 1, (4, 4), dtype=int) b = myd.get_var("periodic") c = myd.get_var("reflect-even") d = myd.get_var("reflect-odd") b.d[:, :] = a.d[:, :] c.d[:, :] = a.d[:, :] d.d[:, :] = a.d[:, :] myd.fill_BC("outflow") # left ghost assert_array_equal(a.d[myg.ilo - 1, myg.jlo:myg.jhi + 1], np.array([1, 11, 21, 31])) # right ghost assert_array_equal(a.d[myg.ihi + 1, myg.jlo:myg.jhi + 1], np.array([4, 14, 24, 34])) # bottom ghost assert_array_equal(a.d[myg.ilo:myg.ihi + 1, myg.jlo - 1], np.array([1, 2, 3, 4])) # top ghost assert_array_equal(a.d[myg.ilo:myg.ihi + 1, myg.jhi + 1], np.array([31, 32, 33, 34])) myd.fill_BC("periodic") # x-boundaries assert_array_equal(b.d[myg.ilo - 1, myg.jlo:myg.jhi + 1], b.d[myg.ihi, myg.jlo:myg.jhi + 1]) assert_array_equal(b.d[myg.ilo, myg.jlo:myg.jhi + 1], b.d[myg.ihi + 1, myg.jlo:myg.jhi + 1]) # y-boundaries assert_array_equal(b.d[myg.ilo:myg.ihi + 1, myg.jlo - 1], b.d[myg.ilo:myg.ihi + 1, myg.jhi]) assert_array_equal(b.d[myg.ilo:myg.ihi + 1, myg.jlo], b.d[myg.ilo:myg.ihi + 1, myg.jhi + 1]) myd.fill_BC("reflect-even") # left -- we'll check 2 ghost cells here -- now we use flipud here # because our 'x' is the row index # left assert_array_equal( c.d[myg.ilo:myg.ilo + 2, myg.jlo:myg.ihi + 1], np.flipud(c.d[myg.ilo - 2:myg.ilo, myg.jlo:myg.jhi + 1])) # right assert_array_equal( c.d[myg.ihi - 1:myg.ihi + 1, myg.jlo:myg.jhi + 1], np.flipud(c.d[myg.ihi + 1:myg.ihi + 3, myg.jlo:myg.jhi + 1])) # bottom assert_array_equal( c.d[myg.ilo:myg.ihi + 1, myg.jlo:myg.jlo + 2], np.fliplr(c.d[myg.ilo:myg.ihi + 1, myg.jlo - 2:myg.jlo])) # top assert_array_equal( c.d[myg.ilo:myg.ihi + 1, myg.jhi - 1:myg.jhi + 1], np.fliplr(c.d[myg.ilo:myg.ihi + 1, myg.jhi + 1:myg.jhi + 3])) myd.fill_BC("reflect-odd") # left -- we'll check 2 ghost cells here -- now we use flipud here # because our 'x' is the row index # left assert_array_equal( d.d[myg.ilo:myg.ilo + 2, myg.jlo:myg.ihi + 1], -np.flipud(d.d[myg.ilo - 2:myg.ilo, myg.jlo:myg.jhi + 1])) # right assert_array_equal( d.d[myg.ihi - 1:myg.ihi + 1, myg.jlo:myg.jhi + 1], -np.flipud(d.d[myg.ihi + 1:myg.ihi + 3, myg.jlo:myg.jhi + 1])) # bottom assert_array_equal( d.d[myg.ilo:myg.ihi + 1, myg.jlo:myg.jlo + 2], -np.fliplr(d.d[myg.ilo:myg.ihi + 1, myg.jlo - 2:myg.jlo])) # top assert_array_equal( d.d[myg.ilo:myg.ihi + 1, myg.jhi - 1:myg.jhi + 1], -np.fliplr(d.d[myg.ilo:myg.ihi + 1, myg.jhi + 1:myg.jhi + 3]))
def initialize(self): """ Initialize the grid and variables for low Mach atmospheric flow and set the initial conditions for the chosen problem. """ myg = grid_setup(self.rp, ng=4) bc_dens, bc_xodd, bc_yodd = bc_setup(self.rp) my_data = patch.CellCenterData2d(myg) my_data.register_var("density", bc_dens) my_data.register_var("x-velocity", bc_xodd) my_data.register_var("y-velocity", bc_yodd) # we'll keep the internal energy around just as a diagnostic my_data.register_var("eint", bc_dens) # phi -- used for the projections. The boundary conditions # here depend on velocity. At a wall or inflow, we already # have the velocity we want on the boundary, so we want # Neumann (dphi/dn = 0). For outflow, we want Dirichlet (phi # = 0) -- this ensures that we do not introduce any tangental # acceleration. bcs = [] for bc in [self.rp.get_param("mesh.xlboundary"), self.rp.get_param("mesh.xrboundary"), self.rp.get_param("mesh.ylboundary"), self.rp.get_param("mesh.yrboundary")]: if bc == "periodic": bctype = "periodic" elif bc in ["reflect", "slipwall"]: bctype = "neumann" elif bc in ["outflow"]: bctype = "dirichlet" bcs.append(bctype) bc_phi = patch.BCObject(xlb=bcs[0], xrb=bcs[1], ylb=bcs[2], yrb=bcs[3]) my_data.register_var("phi-MAC", bc_phi) my_data.register_var("phi", bc_phi) # gradp -- used in the projection and interface states. We'll do the # same BCs as density my_data.register_var("gradp_x", bc_dens) my_data.register_var("gradp_y", bc_dens) my_data.create() self.cc_data = my_data # some auxillary data that we'll need to fill GC in, but isn't # really part of the main solution aux_data = patch.CellCenterData2d(myg) aux_data.register_var("coeff", bc_dens) aux_data.register_var("source_y", bc_yodd) aux_data.create() self.aux_data = aux_data # we also need storage for the 1-d base state -- we'll store this # in the main class directly. self.base["rho0"] = Basestate(myg.ny, ng=myg.ng) self.base["p0"] = Basestate(myg.ny, ng=myg.ng) # now set the initial conditions for the problem exec(self.problem_name + '.init_data(self.cc_data, self.base, self.rp)') # Construct beta_0 gamma = self.rp.get_param("eos.gamma") self.base["beta0"] = Basestate(myg.ny, ng=myg.ng) self.base["beta0"].d[:] = self.base["p0"].d**(1.0/gamma) # we'll also need beta_0 on vertical edges -- on the domain edges, # just do piecewise constant self.base["beta0-edges"] = Basestate(myg.ny, ng=myg.ng) self.base["beta0-edges"].jp(1)[:] = \ 0.5*(self.base["beta0"].v() + self.base["beta0"].jp(1)) self.base["beta0-edges"].d[myg.jlo] = self.base["beta0"].d[myg.jlo] self.base["beta0-edges"].d[myg.jhi+1] = self.base["beta0"].d[myg.jhi]
def initialize(self): """ Initialize the grid and variables for incompressible flow and set the initial conditions for the chosen problem. """ # setup the grid nx = self.rp.get_param("mesh.nx") ny = self.rp.get_param("mesh.ny") xmin = self.rp.get_param("mesh.xmin") xmax = self.rp.get_param("mesh.xmax") ymin = self.rp.get_param("mesh.ymin") ymax = self.rp.get_param("mesh.ymax") my_grid = patch.Grid2d(nx, ny, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, ng=4) # create the variables # first figure out the BCs xlb_type = self.rp.get_param("mesh.xlboundary") xrb_type = self.rp.get_param("mesh.xrboundary") ylb_type = self.rp.get_param("mesh.ylboundary") yrb_type = self.rp.get_param("mesh.yrboundary") bc = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type) # if we are reflecting, we need odd reflection in the normal # directions for the velocity bc_xodd = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type, odd_reflect_dir="x") bc_yodd = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type, odd_reflect_dir="y") my_data = patch.CellCenterData2d(my_grid) # velocities my_data.register_var("x-velocity", bc_xodd) my_data.register_var("y-velocity", bc_yodd) # density my_data.register_var("density", bc) # phi -- used for the projections my_data.register_var("phi-MAC", bc) my_data.register_var("phi", bc) # gradp -- used in the projection and interface states. The BCs here # are tricky. If we are periodic, then it is periodic. Otherwise, # we just want to do first-order extrapolation (homogeneous Neumann) my_data.register_var("gradp_x", bc) my_data.register_var("gradp_y", bc) my_data.create() self.cc_data = my_data # now set the initial conditions for the problem exec(self.problem_name + '.init_data(self.cc_data, self.rp)')
def initialize(rp): """ initialize the grid and variables for incompressible flow """ # setup the grid nx = rp.get_param("mesh.nx") ny = rp.get_param("mesh.ny") xmin = rp.get_param("mesh.xmin") xmax = rp.get_param("mesh.xmax") ymin = rp.get_param("mesh.ymin") ymax = rp.get_param("mesh.ymax") my_grid = patch.Grid2d(nx, ny, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, ng=4) # create the variables # first figure out the BCs xlb_type = rp.get_param("mesh.xlboundary") xrb_type = rp.get_param("mesh.xrboundary") ylb_type = rp.get_param("mesh.ylboundary") yrb_type = rp.get_param("mesh.yrboundary") bc = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type) # if we are reflecting, we need odd reflection in the normal # directions for the velocity bc_xodd = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type, odd_reflect_dir="x") bc_yodd = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type, odd_reflect_dir="y") my_data = patch.CellCenterData2d(my_grid, runtime_parameters=rp) # velocities my_data.register_var("x-velocity", bc_xodd) my_data.register_var("y-velocity", bc_yodd) # phi -- used for the projections my_data.register_var("phi-MAC", bc) my_data.register_var("phi", bc) my_data.register_var("gradp_x", bc) my_data.register_var("gradp_y", bc) my_data.create() return my_grid, my_data
def __init__(self, nx, ny, ng=1, xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, xl_BC_type="dirichlet", xr_BC_type="dirichlet", yl_BC_type="dirichlet", yr_BC_type="dirichlet", xl_BC=None, xr_BC=None, yl_BC=None, yr_BC=None, alpha=0.0, beta=-1.0, nsmooth=10, nsmooth_bottom=50, verbose=0, aux_field=None, aux_bc=None, true_function=None, vis=0, vis_title=""): """ Create the CellCenterMG2d object. Note that this requires a grid to be a power of 2 in size and square. Parameters ---------- nx : int number of cells in x-direction ny : int number of cells in y-direction. xmin : float, optional minimum physical coordinate in x-direction xmax : float, optional maximum physical coordinate in x-direction ymin : float, optional minimum physical coordinate in y-direction ymax : float, optional maximum physical coordinate in y-direction xl_BC_type : {'neumann', 'dirichlet', 'periodic'}, optional boundary condition to enforce on lower x face xr_BC_type : {'neumann', 'dirichlet', 'periodic'}, optional boundary condition to enforce on upper x face yl_BC_type : {'neumann', 'dirichlet', 'periodic'}, optional boundary condition to enforce on lower y face yr_BC_type : {'neumann', 'dirichlet', 'periodic'}, optional boundary condition to enforce on upper y face xl_BC : function, optional function (of y) to call to get -x boundary values (homogeneous assumed otherwise) xr_BC : function, optional function (of y) to call to get +x boundary values (homogeneous assumed otherwise) yl_BC : function, optional function (of x) to call to get -y boundary values (homogeneous assumed otherwise) yr_BC : function, optional function (of x) to call to get +y boundary values (homogeneous assumed otherwise) alpha : float, optional coefficient in Helmholtz equation (alpha - beta L) phi = f beta : float, optional coefficient in Helmholtz equation (alpha - beta L) phi = f nsmooth : int, optional number of smoothing iterations to be done at each intermediate level in the V-cycle (up and down) nsmooth_bottom : int, optional number of smoothing iterations to be done during the bottom solve verbose : int, optional increase verbosity during the solve (for verbose=1) aux_field : list of str, optional extra fields to define and carry at each level. Useful for subclassing. aux_bc : list of BCObject, optional the boundary conditions corresponding to the aux fields true_function : function, optional a function (of x,y) that provides the exact solution to the elliptic problem we are solving. This is used only for visualization purposes vis : int, optional output a detailed visualization of every smoothing step all throughout the V-cycle (if vis=1) vis_title : string, optional a descriptive title to write on the visualization plots Returns ------- out: CellCenterMG2d object """ if nx != ny: print("ERROR: multigrid currently requires nx = ny") return -1 self.nx = nx self.ny = ny self.ng = ng self.xmin = xmin self.xmax = xmax self.ymin = ymin self.ymax = ymax if (xmax - xmin) != (ymax - ymin): print("ERROR: multigrid currently requires a square domain") return -1 self.alpha = alpha self.beta = beta self.nsmooth = nsmooth self.nsmooth_bottom = nsmooth_bottom self.max_cycles = 100 self.verbose = verbose # for visualization purposes, we can set a function name that # provides the true solution to our elliptic problem. if not true_function == None: self.true_function = true_function # a small number used in computing the error, so we don't divide by 0 self.small = 1.e-16 # keep track of whether we've initialized the RHS self.initialized_RHS = 0 # assume that self.nx = 2^(nlevels-1) and that nx = ny # this defines nlevels such that we end exactly on a 2x2 grid self.nlevels = int(math.log(self.nx) / math.log(2.0)) # a multigrid object will be a list of grids self.grids = [] # create the grids. Here, self.grids[0] will be the coarsest # grid and self.grids[nlevel-1] will be the finest grid # we store the solution, v, the rhs, f. # create the boundary condition object bc = patch.BCObject(xlb=xl_BC_type, xrb=xr_BC_type, ylb=yl_BC_type, yrb=yr_BC_type) nx_t = ny_t = 2 for i in range(self.nlevels): # create the grid my_grid = patch.Grid2d(nx_t, ny_t, ng=self.ng, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax) # add a CellCenterData2d object for this level to our list self.grids.append(patch.CellCenterData2d(my_grid, dtype=np.float64)) # create the phi BC object -- this only applies for the finest # level. On the coarser levels, phi represents the residual, # which has homogeneous BCs bc_p = patch.BCObject(xlb=xl_BC_type, xrb=xr_BC_type, ylb=yl_BC_type, yrb=yr_BC_type, xl_func=xl_BC, xr_func=xr_BC, yl_func=yl_BC, yr_func=yr_BC, grid=my_grid) if i == self.nlevels - 1: self.grids[i].register_var("v", bc_p) else: self.grids[i].register_var("v", bc) self.grids[i].register_var("f", bc) self.grids[i].register_var("r", bc) if not aux_field == None: for f, b in zip(aux_field, aux_bc): self.grids[i].register_var(f, b) self.grids[i].create() if self.verbose: print(self.grids[i]) nx_t = nx_t * 2 ny_t = ny_t * 2 # provide coordinate and indexing information for the solution mesh soln_grid = self.grids[self.nlevels - 1].grid self.ilo = soln_grid.ilo self.ihi = soln_grid.ihi self.jlo = soln_grid.jlo self.jhi = soln_grid.jhi self.x = soln_grid.x self.dx = soln_grid.dx self.x2d = soln_grid.x2d self.y = soln_grid.y self.dy = soln_grid.dy # note, dy = dx is assumed self.y2d = soln_grid.y2d self.soln_grid = soln_grid # store the source norm self.source_norm = 0.0 # after solving, keep track of the number of cycles taken, the # relative error from the previous cycle, and the residual error # (normalized to the source norm) self.num_cycles = 0 self.residual_error = 1.e33 self.relative_error = 1.e33 # keep track of where we are in the V self.current_cycle = -1 self.current_level = -1 self.up_or_down = "" # for visualization -- what frame are we outputting? self.vis = vis self.vis_title = vis_title self.frame = 0
# normalize return numpy.sqrt(myg.dx * myg.dy * numpy.sum( (r[myg.ilo:myg.ihi + 1, myg.jlo:myg.jhi + 1]**2).flat)) nx = 128 ny = 128 nproj = 2 # create a mesh containing the x- and y-velocities, and periodic boundary # conditions myg = patch.Grid2d(nx, ny, ng=1) bc = patch.BCObject(xlb="periodic", xrb="periodic", ylb="periodic", yrb="periodic") U = patch.CellCenterData2d(myg) U.register_var('u-old', bc) U.register_var('v-old', bc) U.register_var('u+gphi', bc) U.register_var('v+gphi', bc) U.register_var('u', bc) U.register_var('v', bc) U.register_var('divU', bc) U.register_var('phi-old', bc) U.register_var('phi', bc)
def initialize(rp): """ initialize the grid and variables for compressible flow """ import vars # setup the grid nx = rp.get_param("mesh.nx") ny = rp.get_param("mesh.ny") xmin = rp.get_param("mesh.xmin") xmax = rp.get_param("mesh.xmax") ymin = rp.get_param("mesh.ymin") ymax = rp.get_param("mesh.ymax") my_grid = patch.Grid2d(nx, ny, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, ng=4) # create the variables my_data = patch.CellCenterData2d(my_grid, runtime_parameters=rp) # define solver specific boundary condition routines patch.define_bc("hse", BC.user) # first figure out the boundary conditions. Note: the action # can depend on the variable (for reflecting BCs) xlb_type = rp.get_param("mesh.xlboundary") xrb_type = rp.get_param("mesh.xrboundary") ylb_type = rp.get_param("mesh.ylboundary") yrb_type = rp.get_param("mesh.yrboundary") bc = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type) # density and energy my_data.register_var("density", bc) my_data.register_var("energy", bc) # for velocity, if we are reflecting, we need odd reflection # in the normal direction. # x-momentum -- if we are reflecting in x, then we need to # reflect odd bc_xodd = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type, odd_reflect_dir="x") my_data.register_var("x-momentum", bc_xodd) # y-momentum -- if we are reflecting in y, then we need to # reflect odd bc_yodd = patch.BCObject(xlb=xlb_type, xrb=xrb_type, ylb=ylb_type, yrb=yrb_type, odd_reflect_dir="y") my_data.register_var("y-momentum", bc_yodd) # store the EOS gamma as an auxillary quantity so we can have a # self-contained object stored in output files to make plots gamma = rp.get_param("eos.gamma") my_data.set_aux("gamma", gamma) # initialize the EOS gamma eos.init(gamma) my_data.create() vars.idens = my_data.vars.index("density") vars.ixmom = my_data.vars.index("x-momentum") vars.iymom = my_data.vars.index("y-momentum") vars.iener = my_data.vars.index("energy") print my_data return my_grid, my_data
def f(x, y): return -2.0 * ((1.0 - 6.0 * x**2) * y**2 * (1.0 - y**2) + (1.0 - 6.0 * y**2) * x**2 * (1.0 - x**2)) # test the multigrid solver nx = 256 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 = patch.BCObject(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])