def insert_em(grid, conf, ffunc): Lx = conf.Nx * conf.NxMesh #XXX scaled length for i in range(grid.get_Nx()): for j in range(grid.get_Ny()): for k in range(grid.get_Nz()): c = grid.get_tile(i, j, k) yee = c.get_yee() for l in range(conf.NxMesh): for m in range(conf.NyMesh): for n in range(conf.NzMesh): # get x_i,j,k xloc0 = pytools.ind2loc((i, j, k), (l, m, n), conf) #get x_i+1/2, x_j+1/2, x_k+1/2 xloc1 = pytools.ind2loc((i, j, k), (l + 1, m, n), conf) yloc1 = pytools.ind2loc((i, j, k), (l, m + 1, n), conf) zloc1 = pytools.ind2loc((i, j, k), (l, m, n + 1), conf) # values in Yee lattice corners xcor = xloc0[0] ycor = xloc0[1] zcor = xloc0[2] # values in Yee lattice mids xmid = 0.5 * (xloc0[0] + xloc1[0]) ymid = 0.5 * (xloc0[1] + yloc1[1]) zmid = 0.5 * (xloc0[2] + zloc1[2]) #val = ffunc(xmid, ymid, zmid) # enforce Yee lattice structure yee.ex[l, m, n] = ffunc(xmid, ycor, zcor) yee.ey[l, m, n] = ffunc(xcor, ymid, zcor) + 1.0 #yee.ez[l,m,n] = ffunc(xcor, ycor, zmid)+2.0 yee.ez[l, m, n] = ffunc(xcor, ycor, zcor) + 2.0 #2D hack #yee.bx[l,m,n] = ffunc(xcor, ymid, zmid)+3.0 yee.bx[l, m, n] = ffunc(xcor, ymid, zcor) + 3.0 #2D hack #yee.by[l,m,n] = ffunc(xmid, ycor, zmid)+4.0 #2D hack yee.by[l, m, n] = ffunc(xmid, ycor, zcor) + 4.0 yee.bz[l, m, n] = ffunc(xmid, ymid, zcor) + 5.0 yee.jx[l, m, n] = ffunc(xmid, ymid, zmid) yee.jy[l, m, n] = ffunc(xmid, ymid, zmid) yee.jz[l, m, n] = ffunc(xmid, ymid, zmid)
def insert_em_fields(grid, conf): # into radians btheta = conf.btheta / 180.0 * np.pi bphi = conf.bphi / 180.0 * np.pi beta = conf.beta for tile in pytools.tiles_all(grid): yee = tile.get_yee(0) ii, jj, kk = tile.index if conf.threeD else (*tile.index, 0) # insert values into Yee lattices; includes halos from -3 to n+3 for n in range(-3, conf.NzMesh + 3): for m in range(-3, conf.NyMesh + 3): for l in range(-3, conf.NxMesh + 3): # get global coordinates iglob, jglob, kglob = pytools.ind2loc((ii, jj, kk), (l, m, n), conf) r = np.sqrt(iglob**2 + jglob**2 + kglob**2) yee.bx[l, m, n] = conf.binit * np.cos(bphi) yee.by[l, m, n] = conf.binit * np.sin(bphi) * np.sin(btheta) yee.bz[l, m, n] = conf.binit * np.sin(bphi) * np.cos(btheta) yee.ex[l, m, n] = 0.0 yee.ey[l, m, n] = -beta * yee.bz[l, m, n] yee.ez[l, m, n] = beta * yee.by[l, m, n] return
def insert_em_fields(grid, conf): # into radians #btheta = conf.btheta / 180.0 * np.pi #bphi = conf.bphi / 180.0 * np.pi #beta = conf.beta # setup global perturbations for electric field np.random.seed(1) # global simulation seed rnd_phases = np.random.rand(conf.n_modes) Lx = conf.Nx * conf.NxMesh kx = 2.0 * np.pi / Lx modes = np.arange(1, conf.n_modes + 1) ampl = conf.mode_ampl #/np.sqrt(conf.n_modes) for tile in pytools.tiles_all(grid): yee = tile.get_yee(0) ii, jj, kk = tile.index if conf.threeD else (*tile.index, 0) # insert values into Yee lattices; includes halos from -3 to n+3 for n in range(-3, conf.NzMesh + 3): for m in range(-3, conf.NyMesh + 3): for l in range(-3, conf.NxMesh + 3): # get global coordinates iglob, jglob, kglob = pytools.ind2loc((ii, jj, kk), (l, m, n), conf) #r = np.sqrt(iglob ** 2 + jglob ** 2 + kglob ** 2) yee.bx[l, m, n] = 0.0 #conf.binit * np.cos(bphi) yee.by[ l, m, n] = 0.0 #conf.binit * np.sin(bphi) * np.sin(btheta) yee.bz[ l, m, n] = 0.0 #conf.binit * np.sin(bphi) * np.cos(btheta) yee.ey[l, m, n] = 0.0 #-beta * yee.bz[l, m, n] yee.ez[l, m, n] = 0.0 #+beta * yee.by[l, m, n] # harmonic perturbations yee.ex[l, m, n] = ampl * np.sum( np.sin(kx * iglob * modes + rnd_phases)) return
def insert_em_fields(grid, conf): from numpy import arctan2, sin, cos, sqrt, pi Lx = conf.Nx*conf.NxMesh Ly = conf.Ny*conf.NyMesh Lz = conf.Nz*conf.NzMesh b0 = conf.binit # equilibrium magnetic field zeta = conf.zeta # perturbation amplitude # maximum perpendicular and parallel wavenumbers kperp = 1.0*pi/Lx #half of the sine only kpar = 2.0*pi/Lz #phase shift om0 = 0.0 #amplitude; A = b0*zeta/2.0 # position of the centers as Stagger objects pkg_loc1 = conf.pkg_loc1 pkg_loc2 = conf.pkg_loc2 #-------------------------------------------------- #ell = Lx/2. #maximum size ell = conf.ell for cid in grid.get_tile_ids(): tile = grid.get_tile(cid) yee = tile.get_yee(0) if conf.twoD: ii, jj = tile.index kk = 0 elif conf.threeD: ii, jj, kk = tile.index # insert values into Yee lattices for n in range(conf.NzMesh): for m in range(conf.NyMesh): for l in range(conf.NxMesh): # get global coordinates iglob, jglob, kglob = pytools.ind2loc((ii, jj, kk), (l, m, n), conf) loc = pytools.Stagger(iglob, jglob, kglob) # distance from the center of the packets d1 = pkg_loc1 - loc d2 = pkg_loc2 - loc x = iglob y = jglob z = kglob # add stationary guide field yee.bz[l, m, n] = b0 bpkg1 = {} bpkg2 = {} # build exact initial amplitude for different staggered grid locations for st in [ "rh", "bx", "by", "bz", "ex", "ey", "ez",]: # spherical distance r1 = np.sqrt( d1.at(st).x ** 2 + d1.at(st).y ** 2 + d1.at(st).z ** 2 ) r2 = np.sqrt( d2.at(st).x ** 2 + d2.at(st).y ** 2 + d2.at(st).z ** 2 ) envelope1 = np.cos(pi*r1/ell/2.0) envelope2 = np.cos(pi*r2/ell/2.0) # cut after r > ell if r1 > 1.10*ell or envelope1 < 0.0: envelope1 = 0.0 if r2 > 1.10*ell or envelope2 < 0.0: envelope2 = 0.0 # volume normalized amplitdue #bpkg1[st] = b0*(pi * ell) * envelope #bpkg2[st] = b0*(pi * ell) * envelope # peak normalized amplitdue bpkg1[st] = 2.0*b0*zeta*envelope1/ell bpkg2[st] = 2.0*b0*zeta*envelope2/ell #first pkg yee.bx[l, m, n] += -bpkg1["bx"] * d1.at("bx").y yee.by[l, m, n] += +bpkg1["by"] * d1.at("by").x wdir = +1.0*conf.beta #direction of wave yee.ex[l, m, n] += wdir*bpkg1["ex"] * d1.at("ex").x yee.ey[l, m, n] += wdir*bpkg1["ey"] * d1.at("ey").y #second pkg if conf.two_wave: if conf.two_wave_reversed: rdir = -1.0 #direction of twist; antialigned else: rdir = +1.0 #direction of twist; aligned yee.bx[l, m, n] += -rdir*bpkg2["bx"] * d2.at("bx").y yee.by[l, m, n] += +rdir*bpkg2["by"] * d2.at("by").x wdir = -1.0*conf.beta #direction of wave yee.ex[l, m, n] += wdir*rdir*bpkg2["ex"] * d2.at("ex").x yee.ey[l, m, n] += wdir*rdir*bpkg2["ey"] * d2.at("ey").y return
def insert_em_harris_sheet(grid, conf): from numpy import pi, tanh, sin, cos, sinh, cosh, sqrt delta = conf.sheet_thickness / (2.0 * pi) # sheet thickness incl. 2pi pinch_delta = conf.pinch_width / (2.0 * pi) # pinch thickness incl. 2pi eta = conf.sheet_density beta = 0.0 # conf.beta #sheet bulk flow; NOTE: for force-free setup no flow sigma = conf.sigma # magnetization # field angles btheta = 1.0 bphi = pi / 2.0 # conf.bphi/180. * pi # note: if periodicx then mxhalf is actually Lx/4 else Lx/2 mxhalf = conf.mxhalf myhalf = conf.myhalf mzhalf = conf.mzhalf Lx = conf.lstripe # binit = conf.binit # initial B_0 binit = 0.1 for tile in pytools.tiles_all(grid): ii, jj, kk = tile.index if conf.threeD else (*tile.index, 0) yee = tile.get_yee(0) # insert values into Yee lattices; includes halos from -3 to n+3 for n in range(conf.NzMesh): for m in range(conf.NyMesh): for l in range(conf.NxMesh): # get global coordinates iglob, jglob, kglob = pytools.ind2loc((ii, jj, kk), (l, m, n), conf) # trigger field modulation in z coordinate if conf.threeD: triggerz = cosh((kglob - mzhalf) / pinch_delta) # 3D else: triggerz = 1.0 # inifnitely small thickness if conf.sheet_thickness == 0.0: if iglob <= mxhalf: stripetanh = -1.0 elif mxhalf < iglob <= 3.0 * mxhalf: stripetanh = +1.0 elif 3.0 * mxhalf < iglob: stripetanh = -1.0 # one cell flip of zero # if iglob == mxhalf or iglob == 3.*mxhalf: # stripetanh = 0.0 # flipping harris sheet stripe else: if not (conf.periodicx): stripetanh = tanh((iglob - mxhalf) / delta) else: stripetanh = tanh(Lx * sin(2.0 * pi * (iglob - mxhalf) / Lx) / delta / 2.0 / pi) if conf.trigger: # plasma bulk velocity modulation factor; # NOTE: true velocity v/c= velstripe*beta # velstripe = tanh((iglob-mxhalf)/pinch_delta)/cosh((iglob-mxhalf)/pinch_delta) velstripe = tanh((iglob - mxhalf) / pinch_delta) # velstripe = tanh((iglob - mxhalf) / pinch_delta) / ( # cosh((jglob - myhalf) / pinch_delta) # * cosh((iglob - mxhalf) / pinch_delta) # ) if conf.sheet_thickness == 0.0: pinch_corr = cosh( (jglob - myhalf) / pinch_delta) * triggerz if iglob != mxhalf + 1: # or iglob == 3.0 * mxhalf + 1: pinch_corr = 1.0 else: pinch_corr = (cosh( (jglob - myhalf) / pinch_delta) * cosh( (iglob - mxhalf) / delta) * triggerz) # by yee.by[l, m, n] = binit * sin(bphi) * stripetanh yee.by[l, m, n] += (binit * cos(bphi) * btheta * cos(bphi) * (1.0 - 1.0 / pinch_corr)) # bz yee.bz[l, m, n] = binit * cos(bphi) * stripetanh yee.bz[l, m, n] += (binit * sin(bphi) * btheta * (1.0 - 1.0 / pinch_corr)) # ey yee.ey[l, m, n] = (-beta) * velstripe * yee.bz[l, m, n] # ez yee.ez[l, m, n] = (+beta) * velstripe * yee.by[l, m, n] # drive to trigger reconnection in the middle of the box; # the coefficient should be the desired ExB speed yee.ez[l, m, n] += (conf.trigger_field * yee.by[l, m, n] / pinch_corr) # trigger point if conf.sheet_thickness == 0.0: if jglob == myhalf: if iglob == mxhalf + 1 or iglob == 3.0 * mxhalf + 1: yee.ez[l, m, n] += conf.trigger_field else: yee.by[l, m, n] = binit * sin(bphi) * stripetanh yee.by[l, m, n] += binit * cos(bphi) * btheta yee.bz[l, m, n] = binit * cos(bphi) * stripetanh yee.bz[l, m, n] += binit * sin(bphi) * btheta yee.ey[l, m, n] = (-beta) * yee.bz[l, m, n] yee.ez[l, m, n] = (+beta) * yee.by[l, m, n] yee.ex[l, m, n] = 0.0 # add external non-evolving guide field yee.bz[l, m, n] += binit * sqrt(conf.sigma_ext) # one zell thin current sheet to balance the flip # if iglob == mxhalf or iglob == 3.*mxhalf: # yee.ez[l, m, n] += binit # if iglob == mxhalf+1 or iglob == 3.*mxhalf+1: # yee.ez[l, m, n] += binit if False: # hot current sheet # beta_drift = sqrt(sigma) beta_drift = 0.5 if not (conf.periodicx): num_plasma = 1.0 / (cosh( (iglob - mxhalf) / delta))**2.0 else: # num_plasma = 1.0/(cosh(dstripe*lstripe*sin(2.*pi*(iglob-mxhalf)/lstripe)))**2.*stripecosh num_plasma = ( 1.0 / cosh(Lx * sin(2.0 * pi * (iglob - mxhalf) / Lx) / delta / 2.0 / pi)**2.0) gamma_drift = sqrt(1.0 / (1.0 - beta_drift**2.0)) if conf.periodicx: gamma_drift = gamma_drift * np.sign( cos(2.0 * pi * (iglob - mxhalf) / Lx)) beta_drift = sqrt(1.0 - 1.0 / gamma_drift**2 ) * np.sign(gamma_drift) yee.ez[l, m, n] += beta_drift * num_plasma * binit # copy values to boundary cells # FIXME # try: # for n in range(conf.NzMesh): # for m in range(conf.NyMesh): # for l in range(conf.NxMesh): # c.ex_ref[l,m,n] = yee.ex[l,m,n] # c.ey_ref[l,m,n] = yee.ey[l,m,n] # c.ez_ref[l,m,n] = yee.ez[l,m,n] # c.bx_ref[l,m,n] = yee.bx[l,m,n] # c.by_ref[l,m,n] = yee.by[l,m,n] # c.bz_ref[l,m,n] = yee.bz[l,m,n] # except: # #print("cell ({},{}) is not boundary cell".format(ii,jj)) # pass return
def insert_em_3D_wave_packet(grid, conf): from numpy import arctan2, sin, cos, sqrt b0 = 1.0 # bperp = 1.0 # Lx = conf.NxMesh*conf.Nx # beta = 0.1 # modes = 1. # kx = 2.0*np.pi*modes/Lx # middle of the box x0 = conf.Nx * conf.NxMesh * 0.5 y0 = conf.Ny * conf.NyMesh * 0.5 z1 = 0.0 # conf.Ny*conf.NyMesh*0.25 z2 = conf.Ny * conf.NyMesh * 0.75 print("x0 {} {} {}".format(x0, y0, z1)) # position of the centers as Stagger objects pkg_loc1 = pytools.Stagger(x0, y0, z1) pkg_loc2 = pytools.Stagger(x0, y0, z2) zeta = 1.0 # perturbation amplitude ell = 10.0 # perturbation length for cid in grid.get_tile_ids(): tile = grid.get_tile(cid) yee = tile.get_yee(0) if conf.twoD: ii, jj = tile.index kk = 0 elif conf.threeD: ii, jj, kk = tile.index # insert values into Yee lattices; includes halos from -3 to n+3 for n in range(conf.NzMesh): for m in range(conf.NyMesh): for l in range(conf.NxMesh): # get global coordinates iglob, jglob, kglob = pytools.ind2loc((ii, jj, kk), (l, m, n), conf) loc = pytools.Stagger(iglob, jglob, kglob) # distance from the center of the packets d1 = pkg_loc1 - loc d2 = pkg_loc2 - loc # add stationary guide field yee.bz[l, m, n] = b0 # amplitude for the perturbations # # gauss = zeta * ell * np.exp(-r1 / ell ** 2) # bphi = (2.0 * b0 * w / ell ** 2) * gauss # bphi = {} # theta = {} bpkg1 = {} bpkg2 = {} # build exact initial amplitude for different staggered grid locations for st in [ "rh", "bx", "by", "bz", "ex", "ey", "ez", #'jx', 'jy', 'jz', ]: # spherical distance r1 = d1.at(st).x**2 + d1.at(st).y**2 + d1.at(st).z**2 r2 = d2.at(st).x**2 + d2.at(st).y**2 + d2.at(st).z**2 gauss_profile1 = zeta * ell * np.exp(-r1 / ell**2) gauss_profile2 = zeta * ell * np.exp(-r2 / ell**2) bpkg1[st] = (2 * b0 / ell**2) * gauss_profile1 bpkg2[st] = (2 * b0 / ell**2) * gauss_profile2 # add fields (staggered) yee.bx[l, m, n] = -bpkg1["bx"] * d1.at("bx").y yee.by[l, m, n] = +bpkg1["by"] * d1.at("by").x yee.ex[l, m, n] = -bpkg1["ex"] * d1.at("ex").x yee.ey[l, m, n] = -bpkg1["ey"] * d1.at("ey").y # non staggered #st = 'rh' #yee.bx[l, m, n] = -bpkg1[st] * d1.at(st).y #yee.by[l, m, n] = +bpkg1[st] * d1.at(st).x #yee.ex[l, m, n] = -bpkg1[st] * d1.at(st).x #yee.ey[l, m, n] = -bpkg1[st] * d1.at(st).y return
def insert_em_waves(grid, conf): # into radians # btheta = conf.btheta / 180.0 * np.pi # bphi = conf.bphi / 180.0 * np.pi # beta = conf.beta # beta = 0.1 bpar = 1.0 bperp = 1.0 Lx = conf.NxMesh * conf.Nx beta = 0.1 modes = 1.0 kx = 2.0 * np.pi * modes / Lx for cid in grid.get_tile_ids(): tile = grid.get_tile(cid) yee = tile.get_yee(0) if conf.twoD: ii, jj = tile.index kk = 0 elif conf.threeD: ii, jj, kk = tile.index # insert values into Yee lattices; includes halos from -3 to n+3 for n in range(conf.NzMesh): for m in range(conf.NyMesh): for l in range(conf.NxMesh): # get global coordinates iglob, jglob, kglob = pytools.ind2loc((ii, jj, kk), (l, m, n), conf) # r = np.sqrt(iglob ** 2 + jglob ** 2 + kglob ** 2) if True: # 1D Alfven wave packet yee.bx[l, m, n] = 0.0 # bpar if 0 <= iglob <= 0.5 * Lx: # yee.bz[l, m, n] = bperp*np.sin(kx*iglob) # yee.ey[l, m, n] = bperp*np.sin(kx*iglob) yee.by[l, m, n] = bperp * np.sin(kx * iglob) yee.ez[l, m, n] = bperp * np.sin(kx * iglob) # fast mode wave packet if False: if 0 <= iglob <= 0.5 * Lx: yee.by[l, m, n] = bperp * np.sin(kx * iglob) # yee.ez[l, m, n] = bperp*np.sin(kx*iglob) if False: # 1D Alfven wave packet collisions yee.bx[l, m, n] = bpar if 0 <= iglob < 0.5 * Lx: yee.bz[l, m, n] = bperp * np.sin(kx * iglob) yee.ey[l, m, n] = bperp * np.sin(kx * iglob) if 0.5 * Lx <= iglob < Lx: yee.bz[l, m, n] = bperp * np.sin(kx * iglob) yee.ey[l, m, n] = -bperp * np.sin(kx * iglob) return