def read_class_nqvar_red(datadir='./data', pfile='qvar.dat', proc=0, verbose=False): dims = pc.read_dim(datadir, proc) qdims = pc.read_qdim(datadir) nqpar = read_qpar(datadir=datadir, pfile=pfile, proc=proc) if (verbose): #print npar_loc,' particles on processor: ',proc # Python 2 print(nqpar + 'massive particles on processor: ' + proc) mvars = pdims.mqaux + pdims.mqvar ltot = nqpar * mvars if (dims.precision == 'S'): REAL = '<f4' else: REAL = '<f8' array_shape = np.dtype([('header', '<i4'), ('nqpar', '<i4'), ('footer', '<i4'), ('header2', '<i4'), ('ipar', '<i4', nqpar), ('footer2', '<i4'), ('header3', '<i4'), ('fq', REAL, ltot), ('footer3', '<i4'), ('header4', '<i4'), ('t', REAL), ('x', REAL, dims.mx), ('y', REAL, dims.my), ('z', REAL, dims.mz), ('dx', REAL), ('dy', REAL), ('dz', REAL), ('footer4', '<i4')]) p_data = np.fromfile(datadir + '/proc' + str(proc) + '/' + pfile, dtype=array_shape) partpars = np.array(p_data['fq'].reshape(mvars, npar_loc)) ipar = np.squeeze(p_data['ipar'].reshape(p_data['ipar'].size)) return ipar, partpars
def loadData(field, extension): global data # check if data has already been loaded if (field + extension in data.loaded) == False: data.slices[field + extension], data.t = pc.read_slices( datadir='data', field=field, extension=extension, proc=-1) data.dim[field + extension] = pc.read_dim() # system dimensions data.param[field + extension] = pc.read_param( quiet=True) # system parameters data.loaded.add(field + extension)
def read_class_nqvar(datadir='data', pfile='', proc=0, verbose=False): dims = pc.read_dim(datadir, proc) if (dims.precision == 'S'): REAL = '<f4' else: REAL = '<f8' qdims = pc.read_qdim(datadir) nqpars = qdims.nqpar mqvars = qdims.mqvar ltot = nqpars * mqvars if (verbose): print(nqpars + 'massqvarve particles on processor: ' + proc) # MR modified array_shape array_shape = np.dtype([('header', '<i4'), ('ipar', '<i4'), ('footer', '<i4'), ('header2', '<i4'), ('fq', REAL, ltot), ('footer2', '<i4'), ('header3', '<i4'), ('t', REAL), ('footer3', '<i4')]) p_data = np.fromfile(datadir + '/proc0/' + pfile, dtype=array_shape) ipar = np.squeeze(p_data[0]['ipar'].reshape(p_data[0]['ipar'].size)) partpars = np.array(p_data[0]['fq'].reshape(mqvars, nqpars)) t = p_data[0]['t'] return ipar, partpars, t
def pc2npz(ivar=-1, datadir="data", files="all", quiet=True, trimall=True): """Convert pencil outputs to npz files. Pencil files can be extremely large, making it difficult to transfer files from a remote location to your local machine. This function helps mitigate that issue by reading these large files and converting them into npz files that are much easier to transfer. Inputs: ivar (int) -- The specific VAR and PVAR file you would like to read. Defaults to -1 (i.e., read var.dat, pvar.dat) datadir (str) -- Path to the data directory. Defaults to "data". quiet (bool) -- Suppress much of the print statements when reading the files. Defaults to True trimall (bool) -- Trim the ghost zones from the f array. Defaults to True. Returns: None """ datadir2 = datadir + "/" if ivar < 0: varfile = "var.dat" pvarfile = "pvar.dat" ts_file = "ts.npz" dim_file = "dim.npz" grid_file = "grid.npz" ff_file = "ff.npz" fp_file = "fp.npz" else: varfile = "VAR" + str(ivar) pvarfile = "PVAR" + str(ivar) ts_file = "ts{}.npz".format(ivar) dim_file = "dim{}.npz".format(ivar) grid_file = "grid{}.npz".format(ivar) ff_file = "ff{}.npz".format(ivar) fp_file = "fp{}.npz".format(ivar) if "ts" in files or "all" in files: print("Reading time series") print(" ") ts = ReadTimeSeries(datadir=datadir) print(" ") ts_vars = vars(ts) print("Saving time series as {}".format(ts_file)) np.savez(ts_file, **ts_vars) print("...") print("...") if "dim" in files or "all" in files: print("Reading dim files") print(" ") dim = read_dim(datadir=datadir2) print(" ") dim_vars = vars(dim) print("Saving dim files as {}".format(dim_file)) np.savez(dim_file, **dim_vars) print("...") print("...") if "grid" in files or "all" in files: print("Reading grid files") print(" ") grid = read_grid(datadir=datadir2, quiet=quiet) print(" ") grid_vars = vars(grid) print("Saving grid files as {}".format(grid_file)) np.savez(grid_file, **grid_vars) print("...") print("...") print("Finished...") if "ff" in files or "all" in files: print("Reading {} (this might take a while) ...".format(varfile)) print(" ") var = read_var(datadir=datadir, trimall=trimall, quiet=quiet, varfile=varfile) print(" ") var_vars = vars(var) print("Saving var files as {}".format(ff_file)) np.savez(ff_file, **var_vars) print("...") print("...") if "fp" in files or "all" in files: print("Reading {} (this might take a while) ...".format(pvarfile)) print(" ") pvar = read_pvar(datadir=datadir, varfile=pvarfile) print(" ") pvar_vars = vars(pvar) print("Saving pvar files as {}".format(fp_file)) np.savez(fp_file, **pvar_vars) print("...") print("...")
def read_class_npvar_red(datadir='./data', pfile='pvar.dat', proc=0, verbose=False, reduce_to=-1, set_reduce=-1): dims = pc.read_dim(datadir,proc) pdims = pc.read_pdim(datadir) npar_loc = read_npar_loc(datadir=datadir,pfile=pfile,proc=proc) # # the Next bit calculates how many particles are written for all but # the last processor. The last processor is assigned a number of particles # to write so that the required number of particles is obtained # if (reduce_to > 0): if (set_reduce <= 0): reductionfactor = float(reduce_to)/float(pdims.npar) npar_red = int(round(npar_loc*reductionfactor)) else: npar_red = set_reduce if (verbose): #print 'reducing '+str(npar_loc)+' to '+str(npar_red)+ ' on proc'+str(proc) print('reducing {} to {} on proc {}'.format( npar_loc, npar_red, proc)) written_parts=npar_red else: written_parts=set_reduce if (verbose): #print npar_loc,' particles on processor: ',proc # Python 2 print(str(npar_loc)+' particles on processor: '+str(proc)) mvars = pdims.mpaux+pdims.mpvar ltot = npar_loc*mvars if (dims.precision == 'S'): REAL = '<f4' else: REAL = '<f8' array_shape= np.dtype([('header','<i4'), ('npar_loc','<i4'), ('footer','<i4'), ('header2','<i4'), ('ipar','<i4',npar_loc), ('footer2','<i4'), ('header3','<i4'), ('fp',REAL,ltot), ('footer3','<i4'), ('header4','<i4'), ('t',REAL), ('x',REAL,dims.mx), ('y',REAL,dims.my), ('z',REAL,dims.mz), ('dx',REAL), ('dy',REAL), ('dz',REAL), ('footer4','<i4')]) p_data = np.fromfile(datadir+'/proc'+str(proc)+'/'+pfile,dtype=array_shape) partpars = np.array(p_data['fp'].reshape(mvars,npar_loc)) if (reduce_to>0): particle_list = map(lambda x: int(x),np.linspace(0.0,npar_loc,num=npar_red,endpoint=False)) red_parts = partpars[:,particle_list] red_shape = np.dtype([('header','<i4'), ('npar_loc','<i4'), ('footer','<i4'), ('header2','<i4'), ('ipar','<i4',(npar_red),), ('footer2','<i4'), ('header3','<i4'), ('fp',REAL,npar_red*mvars), ('footer3','<i4'), ('header4','<i4'), ('t',REAL), ('x',REAL,(dims.mx,)), ('y',REAL,(dims.my,)), ('z',REAL,(dims.mz,)), ('dx',REAL), ('dy',REAL), ('dz',REAL), ('footer4','<i4')]) p_red =np.array([(4, npar_red, 4, (npar_red*4), (np.squeeze(p_data['ipar'][0,:npar_red])), (npar_red*4), (npar_red*mvars*8), (np.squeeze(np.ravel(red_parts))), (npar_red*mvars*8), (p_data['header4'][0]), (p_data['t']), (p_data['x']), (p_data['y']), (p_data['z']), (p_data['dx']), (p_data['dy']), (p_data['dz']), p_data['footer4'][0]) ],dtype=red_shape) p_red.tofile(datadir+'/proc'+str(proc)+'/'+str(reduce_to)+'_'+pfile) ipar = np.squeeze(p_data['ipar'].reshape(p_data['ipar'].size)) return ipar, partpars, written_parts
def calc_tensors(datatopdir, lskip_zeros=False, datadir='data/', rank=0, size=1, comm=None, proc=[0], l_mpi=True, iuxmxy=0, irhomxy=7, iTTmxy=6, first_alpha=9, l_correction=False, t_correction=0., fskip=2, mskip=1, trange=(0, None), tindex=(0, None, 1), yindex=[]): nt = None alltmp = 100000 dim = pc.read_dim() gc.garbage if len(yindex) == 0: iy = np.arange(dim.ny) else: iy = yindex os.chdir(datatopdir) # return to working directory av = [] if l_mpi: from mpi4py import MPI if proc.size < dim.nprocz: print('rank {}: proc.size {} < dim.nprocz {}'.format( rank, proc.size, dim.nprocz)) yproc = proc[0] / dim.nprocz aav, time = pc.read_zaver(datadir, trange=trange, tindex=tindex, proc=yproc) tmp = time.size else: print('rank {}: proc.size {} >= dim.nprocz {}'.format( rank, proc.size, dim.nprocz)) for iproc in range(0, proc.size, dim.nprocz): if iproc == 0: aav, time = pc.read_zaver(datadir, trange=trange, tindex=tindex, proc=proc[iproc] / dim.nprocz) tmp = time.size else: aav, time = pc.read_zaver(datadir, proc=proc[iproc] / dim.nprocz) tmp = min(time.size, tmp) else: av, time = pc.read_zaver(datadir, trange=trange, tindex=tindex) gc.garbage if l_mpi: print('rank {}: tmp {}'.format(rank, tmp)) if rank != 0: comm.send(tmp, dest=0, tag=rank) else: for irank in range(1, size): tmp = comm.recv(source=irank, tag=irank) alltmp = min(alltmp, tmp) nt = comm.bcast(alltmp, root=0) print('rank {}: nt {}'.format(rank, nt)) if proc.size < dim.nprocz: yndx = iy - yproc * (dim.nygrid / dim.nprocy) print('rank {}: yndx[0] {}'.format(rank, yndx[0])) av = aav[:nt, :, yndx, :] else: av = aav[:nt] for iproc in range(dim.nprocz, proc.size, dim.nprocz): aav, time = pc.read_zaver(datadir, tindex=(0, nt, 1), proc=proc[iproc] / dim.nprocz) av = np.concatenate((av, aav), axis=2) aav = [] print('rank {}: loaded av'.format(rank)) #where testfield calculated under old incorrect spec apply correction gc.garbage if l_correction: itcorr = np.where(time < t_correction)[0] av[itcorr, first_alpha + 2] *= -dim.nprocz / (dim.nprocz - 2.) for j in range(0, 3): av[itcorr, first_alpha + 5 + j] *= -dim.nprocz / (dim.nprocz - 2.) av[itcorr, first_alpha + 11] *= -dim.nprocz / (dim.nprocz - 2.) for j in range(0, 3): av[itcorr, first_alpha + 14 + j] *= -dim.nprocz / (dim.nprocz - 2.) av[itcorr, first_alpha + 20] *= -dim.nprocz / (dim.nprocz - 2.) for j in range(0, 3): av[itcorr, first_alpha + 23 + j] *= -dim.nprocz / (dim.nprocz - 2.) #factor by which to rescale code time to years trescale = 0.62 / 2.7e-6 / (365. * 86400.) #0.007281508 time *= trescale grid = pc.read_grid(datadir, trim=True, quiet=True) r, theta = np.meshgrid(grid.x, grid.y[iy]) gc.garbage #exclude zeros and next point if resetting of test fields is used #trim reset data and neighbours as required fskip after zeros and mskip before zeros. if lskip_zeros: if l_mpi: if rank == 0: izer0 = np.where(av[:, 9, av.shape[2] / 2, av.shape[3] / 2] == 0)[0] for ii in range(1, fskip): izer1 = np.where(av[:, 9, av.shape[2] / 2, av.shape[3] / 2] == 0)[0] + ii izer0 = np.append(izer0, izer1) for ii in range(1, mskip): izer1 = np.where(av[:, 9, av.shape[2] / 2, av.shape[3] / 2] == 0)[0] - ii izer0 = np.append(izer0, izer1) if izer0.size > 0: imask = np.delete(np.where(time), [izer0]) else: imask = np.where(time)[0] else: imask = None imask = comm.bcast(imask, root=0) else: izer0 = np.where(av[:, 9, av.shape[2] / 2, av.shape[3] / 2] == 0)[0] for ii in range(1, fskip): izer1 = np.where(av[:, 9, av.shape[2] / 2, av.shape[3] / 2] == 0)[0] + ii izer0 = np.append(izer0, izer1) for ii in range(1, mskip): izer1 = np.where(av[:, 9, av.shape[2] / 2, av.shape[3] / 2] == 0)[0] - ii izer0 = np.append(izer0, izer1) if izer0.size > 0: imask = np.delete(np.where(time), [izer0]) else: imask = np.where(time)[0] else: imask = np.arange(time.size) #if lskip_zeros: # izer0=np.where(av[:,first_alpha,av.shape[2]/2,av.shape[3]/2]==0)[0] # izer1=np.where(av[:,first_alpha,av.shape[2]/2,av.shape[3]/2]==0)[0]+1 # if izer0.size>0: # imask=np.delete(np.where(time[:nt]),[izer0,izer1]) # else: # imask=np.where(time[:nt])[0] #else: # imask=np.arange(time[:nt].size) if rank == 0: print('rank {}: calculating alp'.format(rank)) alp = np.zeros([3, 3, imask.size, av.shape[2], av.shape[3]]) eta = np.zeros([3, 3, 3, imask.size, av.shape[2], av.shape[3]]) urmst = np.zeros([3, 3, av.shape[2], av.shape[3]]) etat0 = np.zeros([3, 3, 3, av.shape[2], av.shape[3]]) #eta0 = np.zeros([3,3,3,imask.size,av.shape[2],av.shape[3]]) Hp = np.zeros([av.shape[2], av.shape[3]]) #compute rms velocity normalisation if rank == 0: print('rank {}: calculating urms'.format(rank)) urms = np.sqrt( np.mean(av[imask, iuxmxy + 3, :, :] - av[imask, iuxmxy + 0, :, :]**2 + av[imask, iuxmxy + 4, :, :] - av[imask, iuxmxy + 1, :, :]**2 + av[imask, iuxmxy + 5, :, :] - av[imask, iuxmxy + 2, :, :]**2, axis=0)) #compute turbulent diffusion normalisation cv, gm, alp_MLT = 0.6, 5. / 3, 5. / 3 pp = np.mean(av[imask, iTTmxy, :, :] * av[imask, irhomxy, :, :] * cv * (gm - 1), axis=0) if rank == 0: print('rank {}: completed pressure'.format(rank)) for i in range(0, av.shape[2]): Hp[i, :] = -1. / np.gradient(np.log(pp[i, :]), grid.dx) grid, pp = [], [] for i in range(0, 3): for j in range(0, 3): alp[i, j, :, :, :] = av[imask, first_alpha + 3 * j + i, :, :] urmst[i, j, :, :] = urms / 3. for k in range(0, 3): etat0[i, j, k, :, :] = urms * alp_MLT * Hp / 3. #for i in range(0,imask.size): # eta0[i,:,:,:,:,:] = etat0 if rank == 0: print('rank {}: calculating eta'.format(rank)) for j in range(0, 3): for k in range(0, 3): # Sign difference with Schrinner + r correction eta[j, k, 1, :, :, :] = -av[imask, first_alpha + 18 + 3 * k + j, :, :] * r eta[j, k, 0, :, :, :] = -av[imask, first_alpha + 9 + 3 * k + j, :, :] nnt, ny, nx = imask.size, av.shape[2], av.shape[3] av = [] irr, ith, iph = 0, 1, 2 # Create output tensors if rank == 0: print('rank {}: setting alp'.format(rank)) alpha = np.zeros([3, 3, nnt, ny, nx]) beta = np.zeros([3, 3, nnt, ny, nx]) gamma = np.zeros([3, nnt, ny, nx]) delta = np.zeros([3, nnt, ny, nx]) kappa = np.zeros([3, 3, 3, nnt, ny, nx]) # Alpha tensor if rank == 0: print('rank {}: calculating alpha'.format(rank)) alpha[irr, irr, :, :, :] = (alp[irr, irr, :, :, :] - eta[irr, ith, ith, :, :, :] / r) alpha[irr, ith, :, :, :] = 0.5 * ( alp[irr, ith, :, :, :] + eta[irr, irr, ith, :, :, :] / r + alp[ith, irr, :, :, :] - eta[ith, ith, ith, :, :, :] / r) alpha[irr, iph, :, :, :] = 0.5 * (alp[iph, irr, :, :, :] + alp[irr, iph, :, :, :] - eta[iph, ith, ith, :, :, :] / r) alpha[ith, irr, :, :, :] = alpha[irr, ith, :, :, :] alpha[ith, ith, :, :, :] = (alp[ith, ith, :, :, :] + eta[ith, irr, ith, :, :, :] / r) alpha[ith, iph, :, :, :] = 0.5 * (alp[iph, ith, :, :, :] + alp[ith, iph, :, :, :] + eta[iph, irr, ith, :, :, :] / r) alpha[iph, irr, :, :, :] = alpha[irr, iph, :, :, :] alpha[iph, ith, :, :, :] = alpha[ith, iph, :, :, :] alpha[iph, iph, :, :, :] = alp[iph, iph, :, :, :] # Gamma vector gamma[irr, :, :, :] = -0.5 * (alp[ith, iph, :, :, :] - alp[iph, ith, :, :, :] - eta[iph, irr, ith, :, :, :] / r) gamma[ith, :, :, :] = -0.5 * (alp[iph, irr, :, :, :] - alp[irr, iph, :, :, :] - eta[iph, ith, ith, :, :, :] / r) gamma[iph, :, :, :] = -0.5 * ( alp[irr, ith, :, :, :] - alp[ith, irr, :, :, :] + eta[irr, irr, ith, :, :, :] / r + eta[ith, ith, ith, :, :, :] / r) if rank == 0: print('rank {}: calculating beta'.format(rank)) alp = [] # Beta tensor beta[irr, irr, :, :, :] = -0.5 * eta[irr, iph, ith, :, :, :] beta[irr, ith, :, :, :] = 0.25 * (eta[irr, iph, irr, :, :, :] - eta[ith, iph, ith, :, :, :]) beta[irr, iph, :, :, :] = 0.25 * (eta[irr, irr, ith, :, :, :] - eta[iph, iph, ith, :, :, :] - eta[irr, ith, irr, :, :, :]) beta[ith, ith, :, :, :] = 0.5 * eta[ith, iph, irr, :, :, :] beta[ith, iph, :, :, :] = 0.25 * (eta[ith, irr, ith, :, :, :] + eta[iph, iph, irr, :, :, :] - eta[ith, ith, irr, :, :, :]) beta[iph, iph, :, :, :] = 0.5 * (eta[iph, irr, ith, :, :, :] - eta[iph, ith, irr, :, :, :]) beta[ith, irr, :, :, :] = beta[irr, ith, :, :, :] beta[iph, irr, :, :, :] = beta[irr, iph, :, :, :] beta[iph, ith, :, :, :] = beta[ith, iph, :, :, :] # Delta vector delta[irr, :, :, :] = 0.25 * (eta[ith, ith, irr, :, :, :] - eta[ith, irr, ith, :, :, :] + eta[iph, iph, irr, :, :, :]) delta[ith, :, :, :] = 0.25 * (eta[irr, irr, ith, :, :, :] - eta[irr, ith, irr, :, :, :] + eta[iph, iph, ith, :, :, :]) delta[iph, :, :, :] = -0.25 * (eta[irr, iph, irr, :, :, :] + eta[ith, iph, ith, :, :, :]) # Kappa tensor if rank == 0: print('rank {}: calculating kappa'.format(rank)) for i in range(0, 3): kappa[i, irr, irr, :, :, :] = -eta[i, irr, irr, :, :, :] kappa[i, irr, ith, :, :, :] = -0.5 * (eta[i, ith, irr, :, :, :] + eta[i, irr, ith, :, :, :]) kappa[i, irr, iph, :, :, :] = -0.5 * eta[i, iph, irr, :, :, :] kappa[i, ith, irr, :, :, :] = kappa[i, irr, ith, :, :, :] kappa[i, ith, ith, :, :, :] = -eta[i, ith, ith, :, :, :] kappa[i, ith, iph, :, :, :] = -0.5 * eta[i, iph, ith, :, :, :] kappa[i, iph, irr, :, :, :] = kappa[i, irr, iph, :, :, :] kappa[i, iph, ith, :, :, :] = kappa[i, ith, iph, :, :, :] #for it in range(0,nnt): # kappa[i,iph,iph,it,:,:]= 1e-9*etat0[i,0,0,:,:] eta = [] return alpha, beta, gamma, delta, kappa,\ time[imask], urmst, etat0
def read_fixed_points(datadir='data/', fileName='fixed_points.dat', hm=1): """ Reads the fixed points files. call signature:: fixed = read_fixed_points(datadir = 'data/', fileName = 'fixed_points.dat', hm = 1) Reads from the fixed points files. Returns the fixed points positions. Keyword arguments: *datadir*: Data directory. *fileName*: Name of the fixed points file. *hm*: Header multiplication factor in case Fortran's binary data writes extra large header. For most cases hm = 1 is sufficient. For the cluster in St Andrews use hm = 2. """ # read the cpu structure dim = pc.read_dim(datadir=datadir) if (dim.nprocz > 1): print("error: number of cores in z-direction > 1") data = [] # read the data fixed_file = open(datadir + fileName, 'rb') tmp = fixed_file.read(4 * hm) data = pc.fixed_struct() eof = 0 # length of longest array of fixed points fixedMax = 0 if tmp == '': eof = 1 while (eof == 0): data.t.append( struct.unpack("<" + str(hm + 1) + "f", fixed_file.read(4 * (hm + 1)))[0]) n_fixed = int( struct.unpack("<" + str(2 * hm + 1) + "f", fixed_file.read(4 * (2 * hm + 1)))[1 + int(hm / 2)]) x = list(np.zeros(n_fixed)) y = list(np.zeros(n_fixed)) q = list(np.zeros(n_fixed)) for j in range(n_fixed): x[j] = struct.unpack("<" + str(hm + 1) + "f", fixed_file.read(4 * (hm + 1)))[-1] y[j] = struct.unpack("<f", fixed_file.read(4))[0] q[j] = struct.unpack("<" + str(hm + 1) + "f", fixed_file.read(4 * (hm + 1)))[0] data.x.append(x) data.y.append(y) data.q.append(q) data.fidx.append(n_fixed) tmp = fixed_file.read(4 * hm) if tmp == '': eof = 1 if fixedMax < len(x): fixedMax = len(x) fixed_file.close() # add NaN to fill up the times with smaller number of fixed points fixed = pc.fixed_struct() for i in range(len(data.t)): annex = list(np.zeros(fixedMax - len(data.x[i])) + np.nan) fixed.t.append(data.t[i]) fixed.x.append(data.x[i] + annex) fixed.y.append(data.y[i] + annex) fixed.q.append(data.q[i] + annex) fixed.fidx.append(data.fidx[i]) fixed.t = np.array(fixed.t) fixed.x = np.array(fixed.x) fixed.y = np.array(fixed.y) fixed.q = np.array(fixed.q) fixed.fidx = np.array(fixed.fidx) return fixed
def fixed_points(datadir='data/', fileName='fixed_points_post.dat', varfile='VAR0', ti=-1, tf=-1, traceField='bb', hMin=2e-3, hMax=2e4, lMax=500, tol=1e-2, interpolation='weighted', trace_sub=1, integration='simple', nproc=1): """ Find the fixed points. call signature:: fixed = fixed_points(datadir = 'data/', fileName = 'fixed_points_post.dat', varfile = 'VAR0', ti = -1, tf = -1, traceField = 'bb', hMin = 2e-3, hMax = 2e4, lMax = 500, tol = 1e-2, interpolation = 'weighted', trace_sub = 1, integration = 'simple', nproc = 1) Finds the fixed points. Returns the fixed points positions. Keyword arguments: *datadir*: Data directory. *fileName*: Name of the fixed points file. *varfile*: Varfile to be read. *ti*: Initial VAR file index for tracer time sequences. Overrides 'varfile'. *tf*: Final VAR file index for tracer time sequences. Overrides 'varfile'. *traceField*: Vector field used for the streamline tracing. *hMin*: Minimum step length for and underflow to occur. *hMax*: Parameter for the initial step length. *lMax*: Maximum length of the streamline. Integration will stop if l >= lMax. *tol*: Tolerance for each integration step. Reduces the step length if error >= tol. *interpolation*: Interpolation of the vector field. 'mean': takes the mean of the adjacent grid point. 'weighted': weights the adjacent grid points according to their distance. *trace_sub*: Number of sub-grid cells for the seeds for the initial mapping. *intQ*: Quantities to be integrated along the streamlines. *integration*: Integration method. 'simple': low order method. 'RK6': Runge-Kutta 6th order. *nproc*: Number of cores for multi core computation. """ class data_struct: def __init__(self): self.t = [] self.fidx = [] # number of fixed points at this time self.x = [] self.y = [] self.q = [] # Computes rotation along one edge. def edge(vv, p, sx, sy, diff1, diff2, phiMin, rec, hMin=hMin, hMax=hMax, lMax=lMax, tol=tol, interpolation=interpolation, integration=integration): dtot = m.atan2(diff1[0] * diff2[1] - diff2[0] * diff1[1], diff1[0] * diff2[0] + diff1[1] * diff2[1]) if ((abs(dtot) > phiMin) and (rec < 4)): xm = 0.5 * (sx[0] + sx[1]) ym = 0.5 * (sy[0] + sy[1]) # trace intermediate field line s = pc.stream(vv, p, hMin=hMin, hMax=hMax, lMax=lMax, tol=tol, interpolation=interpolation, integration=integration, xx=np.array([xm, ym, p.Oz])) tracer = np.concatenate( (s.tracers[0, 0:2], s.tracers[s.sl - 1, :], np.reshape(s.l, (1)))) # discard any streamline which does not converge or hits the boundary if ((tracer[5] >= lMax) or (tracer[4] < p.Oz + p.Lz - p.dz)): dtot = 0. else: diffm = np.array( [tracer[2] - tracer[0], tracer[3] - tracer[1]]) if (sum(diffm**2) != 0): diffm = diffm / np.sqrt(sum(diffm**2)) dtot = edge(vv, p, [sx[0], xm], [sy[0], ym], diff1, diffm, phiMin, rec+1, hMin = hMin, hMax = hMax, lMax = lMax, tol = tol, interpolation = interpolation, integration = integration)+ \ edge(vv, p, [xm, sx[1]], [ym, sy[1]], diffm, diff2, phiMin, rec+1, hMin = hMin, hMax = hMax, lMax = lMax, tol = tol, interpolation = interpolation, integration = integration) return dtot # Finds the Poincare index of this grid cell. def pIndex(vv, p, sx, sy, diff, phiMin, hMin=hMin, hMax=hMax, lMax=lMax, tol=tol, interpolation=interpolation, integration=integration): poincare = 0 poincare += edge(vv, p, [sx[0], sx[1]], [sy[0], sy[0]], diff[0, :], diff[1, :], phiMin, 0, hMin=hMin, hMax=hMax, lMax=lMax, tol=tol, interpolation=interpolation, integration=integration) poincare += edge(vv, p, [sx[1], sx[1]], [sy[0], sy[1]], diff[1, :], diff[2, :], phiMin, 0, hMin=hMin, hMax=hMax, lMax=lMax, tol=tol, interpolation=interpolation, integration=integration) poincare += edge(vv, p, [sx[1], sx[0]], [sy[1], sy[1]], diff[2, :], diff[3, :], phiMin, 0, hMin=hMin, hMax=hMax, lMax=lMax, tol=tol, interpolation=interpolation, integration=integration) poincare += edge(vv, p, [sx[0], sx[0]], [sy[1], sy[0]], diff[3, :], diff[0, :], phiMin, 0, hMin=hMin, hMax=hMax, lMax=lMax, tol=tol, interpolation=interpolation, integration=integration) return poincare # fixed point finder for a subset of the domain def subFixed(queue, ix0, iy0, vv, p, tracers, iproc, hMin=2e-3, hMax=2e4, lMax=500, tol=1e-2, interpolation='weighted', integration='simple'): diff = np.zeros((4, 2)) phiMin = np.pi / 8. x = [] y = [] q = [] fidx = 0 for ix in ix0: for iy in iy0: # compute Poincare index around this cell (!= 0 for potential fixed point) diff[0, :] = tracers[iy, ix, 0, 2:4] - tracers[iy, ix, 0, 0:2] diff[1, :] = tracers[iy, ix + 1, 0, 2:4] - tracers[iy, ix + 1, 0, 0:2] diff[2, :] = tracers[iy + 1, ix + 1, 0, 2:4] - tracers[iy + 1, ix + 1, 0, 0:2] diff[3, :] = tracers[iy + 1, ix, 0, 2:4] - tracers[iy + 1, ix, 0, 0:2] if (sum(np.sum(diff**2, axis=1) != 0) == True): diff = np.swapaxes( np.swapaxes(diff, 0, 1) / np.sqrt(np.sum(diff**2, axis=1)), 0, 1) poincare = pIndex(vv, p, tracers[iy, ix:ix + 2, 0, 0], tracers[iy:iy + 2, ix, 0, 1], diff, phiMin, hMin=hMin, hMax=hMax, lMax=lMax, tol=tol, interpolation=interpolation, integration=integration) if (abs(poincare) > 5 ): # use 5 instead of 2pi to account for rounding errors # subsample to get starting point for iteration nt = 4 xmin = tracers[iy, ix, 0, 0] ymin = tracers[iy, ix, 0, 1] xmax = tracers[iy, ix + 1, 0, 0] ymax = tracers[iy + 1, ix, 0, 1] xx = np.zeros((nt**2, 3)) tracersSub = np.zeros((nt**2, 5)) i1 = 0 for j1 in range(nt): for k1 in range(nt): xx[i1, 0] = xmin + j1 / (nt - 1.) * (xmax - xmin) xx[i1, 1] = ymin + k1 / (nt - 1.) * (ymax - ymin) xx[i1, 2] = p.Oz i1 += 1 for it1 in range(nt**2): s = pc.stream(vv, p, hMin=hMin, hMax=hMax, lMax=lMax, tol=tol, interpolation=interpolation, integration=integration, xx=xx[it1, :]) tracersSub[it1, 0:2] = xx[it1, 0:2] tracersSub[it1, 2:] = s.tracers[s.sl - 1, :] min2 = 1e6 minx = xmin miny = ymin i1 = 0 for j1 in range(nt): for k1 in range(nt): diff2 = (tracersSub[i1, 2] - tracersSub[i1, 0] )**2 + (tracersSub[i1, 3] - tracersSub[i1, 1])**2 if (diff2 < min2): min2 = diff2 minx = xmin + j1 / (nt - 1.) * (xmax - xmin) miny = ymin + k1 / (nt - 1.) * (ymax - ymin) it1 += 1 # get fixed point from this starting position using Newton's method #TODO: dl = np.min( var.dx, var.dy ) / 100. # step-size for calculating the Jacobian by finite differences it = 0 # tracers used to find the fixed point tracersNull = np.zeros((5, 4)) point = np.array([minx, miny]) while True: # trace field lines at original point and for Jacobian: # (second order seems to be enough) xx = np.zeros((5, 3)) xx[0, :] = np.array([point[0], point[1], p.Oz]) xx[1, :] = np.array([point[0] - dl, point[1], p.Oz]) xx[2, :] = np.array([point[0] + dl, point[1], p.Oz]) xx[3, :] = np.array([point[0], point[1] - dl, p.Oz]) xx[4, :] = np.array([point[0], point[1] + dl, p.Oz]) for it1 in range(5): s = pc.stream(vv, p, hMin=hMin, hMax=hMax, lMax=lMax, tol=tol, interpolation=interpolation, integration=integration, xx=xx[it1, :]) tracersNull[it1, :2] = xx[it1, :2] tracersNull[it1, 2:] = s.tracers[s.sl - 1, 0:2] # check function convergence ff = np.zeros(2) ff[0] = tracersNull[0, 2] - tracersNull[0, 0] ff[1] = tracersNull[0, 3] - tracersNull[0, 1] #TODO: if (sum(abs(ff)) <= 1e-4): fixedPoint = np.array([point[0], point[1]]) break # compute the Jacobian fjac = np.zeros((2, 2)) fjac[0, 0] = ( (tracersNull[2, 2] - tracersNull[2, 0]) - (tracersNull[1, 2] - tracersNull[1, 0])) / 2. / dl fjac[0, 1] = ( (tracersNull[4, 2] - tracersNull[4, 0]) - (tracersNull[3, 2] - tracersNull[3, 0])) / 2. / dl fjac[1, 0] = ( (tracersNull[2, 3] - tracersNull[2, 1]) - (tracersNull[1, 3] - tracersNull[1, 1])) / 2. / dl fjac[1, 1] = ( (tracersNull[4, 3] - tracersNull[4, 1]) - (tracersNull[3, 3] - tracersNull[3, 1])) / 2. / dl # invert the Jacobian fjin = np.zeros((2, 2)) det = fjac[0, 0] * fjac[1, 1] - fjac[0, 1] * fjac[1, 0] #TODO: if (abs(det) < dl): fixedPoint = point break fjin[0, 0] = fjac[1, 1] fjin[1, 1] = fjac[0, 0] fjin[0, 1] = -fjac[0, 1] fjin[1, 0] = -fjac[1, 0] fjin = fjin / det dpoint = np.zeros(2) dpoint[0] = -fjin[0, 0] * ff[0] - fjin[0, 1] * ff[1] dpoint[1] = -fjin[1, 0] * ff[0] - fjin[1, 1] * ff[1] point += dpoint # check root convergence #TODO: if (sum(abs(dpoint)) < 1e-4): fixedPoint = point break if (it > 20): fixedPoint = point print("warning: Newton did not converged") break it += 1 # check if fixed point lies inside the cell if ((fixedPoint[0] < tracers[iy, ix, 0, 0]) or (fixedPoint[0] > tracers[iy, ix + 1, 0, 0]) or (fixedPoint[1] < tracers[iy, ix, 0, 1]) or (fixedPoint[1] > tracers[iy + 1, ix, 0, 1])): print("warning: fixed point lies outside the cell") else: x.append(fixedPoint[0]) y.append(fixedPoint[1]) #q.append() fidx += 1 queue.put((x, y, q, fidx, iproc)) # multi core setup if (np.isscalar(nproc) == False) or (nproc % 1 != 0): print("error: invalid processor number") return -1 queue = mp.Queue() proc = [] # make sure to read the var files with the correct magic if (traceField == 'bb'): magic = 'bb' if (traceField == 'jj'): magic = 'jj' if (traceField == 'vort'): magic = 'vort' # read the cpu structure dim = pc.read_dim(datadir=datadir) if (dim.nprocz > 1): print("error: number of cores in z-direction > 1") var = pc.read_var(varfile=varfile, datadir=datadir, magic=magic, quiet=True, trimall=True) grid = pc.read_grid(datadir=datadir, quiet=True, trim=True) vv = getattr(var, traceField) # initialize the parameters p = pc.pClass() p.dx = var.dx p.dy = var.dy p.dz = var.dz p.Ox = var.x[0] p.Oy = var.y[0] p.Oz = var.z[0] p.Lx = grid.Lx p.Ly = grid.Ly p.Lz = grid.Lz p.nx = dim.nx p.ny = dim.ny p.nz = dim.nz # create the initial mapping tracers, mapping, t = pc.tracers(traceField='bb', hMin=hMin, hMax=hMax, lMax=lMax, tol=tol, interpolation=interpolation, trace_sub=trace_sub, varfile=varfile, integration=integration, datadir=datadir, destination='', nproc=nproc) # find fixed points fixed = pc.fixed_struct() xyq = [] # list of return values from subFixed ix0 = range(0, p.nx * trace_sub - 1) # set of grid indices for the cores iy0 = range(0, p.ny * trace_sub - 1) # set of grid indices for the cores subFixedLambda = lambda queue, ix0, iy0, vv, p, tracers, iproc: \ subFixed(queue, ix0, iy0, vv, p, tracers, iproc, hMin = hMin, hMax = hMax, lMax = lMax, tol = tol, interpolation = interpolation, integration = integration) for iproc in range(nproc): proc.append( mp.Process(target=subFixedLambda, args=(queue, ix0[iproc::nproc], iy0, vv, p, tracers, iproc))) for iproc in range(nproc): proc[iproc].start() for iproc in range(nproc): xyq.append(queue.get()) for iproc in range(nproc): proc[iproc].join() # put together return values from subFixed fixed.fidx = 0 fixed.t = var.t for iproc in range(nproc): fixed.x.append(xyq[xyq[iproc][4]][0]) fixed.y.append(xyq[xyq[iproc][4]][1]) fixed.q.append(xyq[xyq[iproc][4]][2]) fixed.fidx += xyq[xyq[iproc][4]][3] fixed.t = np.array(fixed.t) fixed.x = np.array(fixed.x) fixed.y = np.array(fixed.y) fixed.q = np.array(fixed.q) fixed.fidx = np.array(fixed.fidx) return fixed