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): 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 yee.by[l, m, n] = 0.0 yee.bz[l, m, n] = conf.binit yee.ex[l, m, n] = 0.0 yee.ey[l, m, n] = 0.0 yee.ez[l, m, n] = 0.0 return
# timer.verbose = 1 # 0 normal; 1 - debug mode # -------------------------------------------------- # sync e and b fields # mpi e grid.send_data(1) grid.recv_data(1) grid.wait_data(1) # mpi b grid.send_data(2) grid.recv_data(2) grid.wait_data(2) for tile in pytools.tiles_all(grid): tile.update_boundaries(grid) ################################################## # simulation time step loop sys.stdout.flush() # simulation loop time = lap * (conf.cfl / conf.c_omp) for lap in range(lap, conf.Nt + 1): # -------------------------------------------------- # push B half t1 = timer.start_comp("push_half_b1") for tile in pytools.tiles_all(grid):
def test_problematic_prtcls(self): # test pic loop behavior when particle is located in wrong container conf = Conf() conf.twoD = False conf.threeD = True conf.Nx = 2 conf.Ny = 2 conf.Nz = 2 conf.NxMesh = 3 conf.NyMesh = 3 conf.NzMesh = 3 conf.Nt = 3 conf.update_bbox() grid = pycorgi.threeD.Grid(conf.Nx, conf.Ny, conf.Nz) grid.set_grid_lims(conf.xmin, conf.xmax, conf.ymin, conf.ymax, conf.zmin, conf.zmax) pytools.pic.load_tiles(grid, conf) insert_em(grid, conf, zero_field) print("============================================================") #-------------------------------------------------- cid = grid.id(0, 0, 0) c = grid.get_tile(cid) #get cell ptr container = c.get_container(0) #ispcs container.set_keygen_state(0, 0) #number, rank u0 = [0.0, 0.0, 0.0] # problematic prtcl set 1 (at minimum boundary) #x0 = [0.0, 1.0, 1.0] #container.add_particle(x0, u0, 1.0) #x0 = [1.0, 0.0, 1.0] #container.add_particle(x0, u0, 1.0) #x0 = [1.0, 1.0, 0.0] #container.add_particle(x0, u0, 1.0) # problematic prtcl set 2 (at maximum boundary) #x0 = [3.0, 1.0, 1.0] #container.add_particle(x0, u0, 1.0) #x0 = [1.0, 3.0, 1.0] #container.add_particle(x0, u0, 1.0) #x0 = [1.0, 1.0, 3.0] #container.add_particle(x0, u0, 1.0) # problematic prtcl set 3 (completely outside) #x0 = [3.1, 1.0, 1.0] #container.add_particle(x0, u0, 1.0) #x0 = [1.0, 3.1, 1.0] #container.add_particle(x0, u0, 1.0) #x0 = [1.0, 1.0, 3.1] #container.add_particle(x0, u0, 1.0) #x0 = [-0.1, 1.0, 1.0] #container.add_particle(x0, u0, 1.0) #x0 = [1.0, -0.1, 1.0] #container.add_particle(x0, u0, 1.0) #x0 = [1.0, 1.0, -0.1] #container.add_particle(x0, u0, 1.0) # last tile cid = grid.id(1, 1, 1) c = grid.get_tile(cid) #get cell ptr container = c.get_container(0) #ispcs container.set_keygen_state(0, 0) #number, rank x0 = [6.0, 5.0, 5.0] container.add_particle(x0, u0, 1.0) x0 = [0.0, 5.0, 5.0] container.add_particle(x0, u0, 1.0) #-------------------------------------------------- pusher = pyrunko.pic.threeD.BorisPusher() fldprop = pyrunko.fields.threeD.FDTD2() fintp = pyrunko.pic.threeD.LinearInterpolator() currint = pyrunko.pic.threeD.ZigZag() flt = pyrunko.fields.threeD.Binomial2(conf.NxMesh, conf.NyMesh, conf.NzMesh) lap = 0 for lap in range(lap, conf.Nt): # -------------------------------------------------- # push B half for tile in pytools.tiles_all(grid): fldprop.push_half_b(tile) # -------------------------------------------------- # comm B grid.send_data(2) grid.recv_data(2) grid.wait_data(2) # -------------------------------------------------- # update boundaries for tile in pytools.tiles_all(grid): tile.update_boundaries(grid) ################################################## # move particles (only locals tiles) # -------------------------------------------------- # interpolate fields for tile in pytools.tiles_local(grid): fintp.solve(tile) #print('successful interp') # -------------------------------------------------- # push particles in x and u #for tile in pytools.tiles_local(grid): # pusher.solve(tile) ################################################## # advance B half # -------------------------------------------------- # push B half for tile in pytools.tiles_all(grid): fldprop.push_half_b(tile) # -------------------------------------------------- # comm B grid.send_data(1) grid.recv_data(1) grid.wait_data(1) # -------------------------------------------------- # update boundaries for tile in pytools.tiles_all(grid): tile.update_boundaries(grid) ################################################## # advance E # -------------------------------------------------- # push E for tile in pytools.tiles_all(grid): fldprop.push_e(tile) # -------------------------------------------------- # current calculation; charge conserving current deposition for tile in pytools.tiles_local(grid): currint.solve(tile) #print('successful currint') # -------------------------------------------------- # clear virtual current arrays for boundary addition after mpi for tile in pytools.tiles_virtual(grid): tile.clear_current() # -------------------------------------------------- # mpi send currents grid.send_data(0) grid.recv_data(0) grid.wait_data(0) # -------------------------------------------------- # exchange currents for tile in pytools.tiles_all(grid): tile.exchange_currents(grid) ################################################## # particle communication (only local/boundary tiles) # -------------------------------------------------- # local particle exchange (independent) for tile in pytools.tiles_local(grid): tile.check_outgoing_particles() # -------------------------------------------------- # global mpi exchange (independent) for tile in pytools.tiles_boundary(grid): tile.pack_outgoing_particles() # -------------------------------------------------- # MPI global particle exchange # transfer primary and extra data grid.send_data(3) grid.recv_data(3) grid.wait_data(3) # orig just after send3 grid.send_data(4) grid.recv_data(4) grid.wait_data(4) # -------------------------------------------------- # global unpacking (independent) for tile in pytools.tiles_virtual(grid): tile.unpack_incoming_particles() tile.check_outgoing_particles() # -------------------------------------------------- # transfer local + global for tile in pytools.tiles_local(grid): tile.get_incoming_particles(grid) # -------------------------------------------------- # delete local transferred particles for tile in pytools.tiles_local(grid): tile.delete_transferred_particles() # -------------------------------------------------- # delete all virtual particles (because new prtcls will come) for tile in pytools.tiles_virtual(grid): tile.delete_all_particles() # -------------------------------------------------- # add current to E for tile in pytools.tiles_all(grid): tile.deposit_current() # comm E grid.send_data(1) grid.recv_data(1) grid.wait_data(1) # -------------------------------------------------- # comm B grid.send_data(2) grid.recv_data(2) grid.wait_data(2) # -------------------------------------------------- # update boundaries for tile in pytools.tiles_all(grid): tile.update_boundaries(grid) # -------------------------------------------------- ip = 0 prtcls = {} for tile in pytools.tiles_all(grid): container = tile.get_container(0) #ispcs xp = container.loc(0) yp = container.loc(1) zp = container.loc(2) for i in range(len(xp)): prtcls[ip] = (xp[i], yp[i], zp[i], tile.cid) ip += 1
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