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
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
def tracers(traceField = 'bb', hMin = 2e-3, hMax = 2e4, lMax = 500, tol = 1e-2, interpolation = 'weighted', trace_sub = 1, intQ = [''], varfile = 'VAR0', ti = -1, tf = -1, integration = 'simple', datadir = 'data/', destination = 'tracers.dat', nproc = 1): """ Trace streamlines from the VAR files and integrate quantity 'intQ' along them. call signature:: tracers(field = 'bb', hMin = 2e-3, hMax = 2e2, lMax = 500, tol = 2e-3, interpolation = 'weighted', trace_sub = 1, intQ = '', varfile = 'VAR0', ti = -1, tf = -1, datadir = 'data', destination = 'tracers.dat', nproc = 1) Trace streamlines of the vectofield 'field' from z = z0 to z = z1 and integrate quantities 'intQ' along the lines. Creates a 2d mapping as in 'streamlines.f90'. Keyword arguments: *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. *intQ*: Quantities to be integrated along the streamlines. *varfile*: Varfile to be read. *integration*: Integration method. 'simple': low order method. 'RK6': Runge-Kutta 6th order. *ti*: Initial VAR file index for tracer time sequences. Overrides 'varfile'. *tf*: Final VAR file index for tracer time sequences. Overrides 'varfile'. *datadir*: Directory where the data is stored. *destination*: Destination file. *nproc*: Number of cores for multi core computation. """ # returns the tracers for the specified starting locations def subTracers(q, vv, p, tracers0, iproc, hMin = 2e-3, hMax = 2e4, lMax = 500, tol = 1e-2, interpolation = 'weighted', integration = 'simple', intQ = ['']): tracers = tracers0 mapping = np.zeros((tracers.shape[0], tracers.shape[1], 3)) for ix in range(tracers.shape[0]): for iy in range(tracers.shape[1]): xx = tracers[ix, iy, 2:5].copy() s = pc.stream(vv, p, interpolation = interpolation, integration = integration, hMin = hMin, hMax = hMax, lMax = lMax, tol = tol, xx = xx) tracers[ix, iy, 2:5] = s.tracers[s.sl-1] tracers[ix, iy, 5] = s.l if (any(intQ == 'curlyA')): for l in range(s.sl-1): aaInt = pc.vecInt((s.tracers[l+1] + s.tracers[l])/2, aa, p, interpolation) tracers[ix, iy, 6] += np.dot(aaInt, (s.tracers[l+1] - s.tracers[l])) # create the color mapping if (tracers[ix, iy, 4] > grid.z[-2]): if (tracers[ix, iy, 0] - tracers[ix, iy, 2]) > 0: if (tracers[ix, iy, 1] - tracers[ix, iy, 3]) > 0: mapping[ix, iy, :] = [0,1,0] else: mapping[ix, iy, :] = [1,1,0] else: if (tracers[ix, iy, 1] - tracers[ix, iy, 3]) > 0: mapping[ix, iy, :] = [0,0,1] else: mapping[ix, iy, :] = [1,0,0] else: mapping[ix, iy, :] = [1,1,1] q.put((tracers, mapping, iproc)) # multi core setup if (np.isscalar(nproc) == False) or (nproc%1 != 0): print("error: invalid processor number") return -1 queue = mp.Queue() # read the data # 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' # convert intQ string into list if (isinstance(intQ, list) == False): intQ = [intQ] intQ = np.array(intQ) grid = pc.read_grid(datadir = datadir, trim = True, quiet = True) dim = pc.read_dim(datadir = datadir) tol2 = tol**2 # check if user wants a tracer time series if ((ti%1 == 0) and (tf%1 == 0) and (ti >= 0) and (tf >= ti)): series = True n_times = tf-ti+1 else: series = False n_times = 1 tracers = np.zeros([int(trace_sub*dim.nx), int(trace_sub*dim.ny), n_times, 6+len(intQ)]) mapping = np.zeros([int(trace_sub*dim.nx), int(trace_sub*dim.ny), n_times, 3]) t = np.zeros(n_times) for tIdx in range(n_times): if series: varfile = 'VAR' + str(tIdx) # read the data var = pc.read_var(varfile = varfile, datadir = datadir, magic = magic, quiet = True, trimall = True) grid = pc.read_grid(datadir = datadir, quiet = True, trim = True) t[tIdx] = var.t # extract the requested vector traceField vv = getattr(var, traceField) if (any(intQ == 'curlyA')): aa = var.aa # 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 # initialize the tracers for ix in range(int(trace_sub*dim.nx)): for iy in range(int(trace_sub*dim.ny)): tracers[ix, iy, tIdx, 0] = grid.x[0] + int(grid.dx/trace_sub)*ix tracers[ix, iy, tIdx, 2] = tracers[ix, iy, tIdx, 0] tracers[ix, iy, tIdx, 1] = grid.y[0] + int(grid.dy/trace_sub)*iy tracers[ix, iy, tIdx, 3] = tracers[ix, iy, tIdx, 1] tracers[ix, iy, tIdx, 4] = grid.z[0] # declare vectors xMid = np.zeros(3) xSingle = np.zeros(3) xHalf = np.zeros(3) xDouble = np.zeros(3) tmp = [] subTracersLambda = lambda queue, vv, p, tracers, iproc: \ subTracers(queue, vv, p, tracers, iproc, hMin = hMin, hMax = hMax, lMax = lMax, tol = tol, interpolation = interpolation, integration = integration, intQ = intQ) proc = [] for iproc in range(nproc): proc.append(mp.Process(target = subTracersLambda, args = (queue, vv, p, tracers[iproc::nproc,:,tIdx,:], iproc))) for iproc in range(nproc): proc[iproc].start() for iproc in range(nproc): tmp.append(queue.get()) for iproc in range(nproc): proc[iproc].join() for iproc in range(nproc): tracers[tmp[iproc][2]::nproc,:,tIdx,:], mapping[tmp[iproc][2]::nproc,:,tIdx,:] = (tmp[iproc][0], tmp[iproc][1]) for iproc in range(nproc): proc[iproc].terminate() tracers = np.copy(tracers.swapaxes(0, 3), order = 'C') if (destination != ''): f = open(datadir + destination, 'wb') f.write(np.array(trace_sub, dtype = 'float32')) # write tracers into file for tIdx in range(n_times): f.write(t[tIdx].astype('float32')) f.write(tracers[:,:,tIdx,:].astype('float32')) f.close() tracers = tracers.swapaxes(0, 3) tracers = tracers.swapaxes(0, 1) mapping = mapping.swapaxes(0, 1) return tracers, mapping, t
def tracers(traceField='bb', hMin=2e-3, hMax=2e4, lMax=500, tol=1e-2, interpolation='weighted', trace_sub=1, intQ=[''], varfile='VAR0', ti=-1, tf=-1, integration='simple', datadir='data/', destination='tracers.dat', nproc=1): """ Trace streamlines from the VAR files and integrate quantity 'intQ' along them. call signature:: tracers(field = 'bb', hMin = 2e-3, hMax = 2e2, lMax = 500, tol = 2e-3, interpolation = 'weighted', trace_sub = 1, intQ = '', varfile = 'VAR0', ti = -1, tf = -1, datadir = 'data', destination = 'tracers.dat', nproc = 1) Trace streamlines of the vectofield 'field' from z = z0 to z = z1 and integrate quantities 'intQ' along the lines. Creates a 2d mapping as in 'streamlines.f90'. Keyword arguments: *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. *intQ*: Quantities to be integrated along the streamlines. *varfile*: Varfile to be read. *integration*: Integration method. 'simple': low order method. 'RK6': Runge-Kutta 6th order. *ti*: Initial VAR file index for tracer time sequences. Overrides 'varfile'. *tf*: Final VAR file index for tracer time sequences. Overrides 'varfile'. *datadir*: Directory where the data is stored. *destination*: Destination file. *nproc*: Number of cores for multi core computation. """ # returns the tracers for the specified starting locations def subTracers(q, vv, p, tracers0, iproc, hMin=2e-3, hMax=2e4, lMax=500, tol=1e-2, interpolation='weighted', integration='simple', intQ=['']): tracers = tracers0 mapping = np.zeros((tracers.shape[0], tracers.shape[1], 3)) for ix in range(tracers.shape[0]): for iy in range(tracers.shape[1]): xx = tracers[ix, iy, 2:5].copy() s = pc.stream(vv, p, interpolation=interpolation, integration=integration, hMin=hMin, hMax=hMax, lMax=lMax, tol=tol, xx=xx) tracers[ix, iy, 2:5] = s.tracers[s.sl - 1] tracers[ix, iy, 5] = s.l if (any(intQ == 'curlyA')): for l in range(s.sl - 1): aaInt = pc.vecInt( (s.tracers[l + 1] + s.tracers[l]) / 2, aa, p, interpolation) tracers[ix, iy, 6] += np.dot(aaInt, (s.tracers[l + 1] - s.tracers[l])) # create the color mapping if (tracers[ix, iy, 4] > grid.z[-2]): if (tracers[ix, iy, 0] - tracers[ix, iy, 2]) > 0: if (tracers[ix, iy, 1] - tracers[ix, iy, 3]) > 0: mapping[ix, iy, :] = [0, 1, 0] else: mapping[ix, iy, :] = [1, 1, 0] else: if (tracers[ix, iy, 1] - tracers[ix, iy, 3]) > 0: mapping[ix, iy, :] = [0, 0, 1] else: mapping[ix, iy, :] = [1, 0, 0] else: mapping[ix, iy, :] = [1, 1, 1] q.put((tracers, mapping, iproc)) # multi core setup if (np.isscalar(nproc) == False) or (nproc % 1 != 0): print("error: invalid processor number") return -1 queue = mp.Queue() # read the data # 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' # convert intQ string into list if (isinstance(intQ, list) == False): intQ = [intQ] intQ = np.array(intQ) grid = pc.read_grid(datadir=datadir, trim=True, quiet=True) dim = pc.read_dim(datadir=datadir) tol2 = tol**2 # check if user wants a tracer time series if ((ti % 1 == 0) and (tf % 1 == 0) and (ti >= 0) and (tf >= ti)): series = True n_times = tf - ti + 1 else: series = False n_times = 1 tracers = np.zeros([ int(trace_sub * dim.nx), int(trace_sub * dim.ny), n_times, 6 + len(intQ) ]) mapping = np.zeros( [int(trace_sub * dim.nx), int(trace_sub * dim.ny), n_times, 3]) t = np.zeros(n_times) for tIdx in range(n_times): if series: varfile = 'VAR' + str(tIdx) # read the data var = pc.read_var(varfile=varfile, datadir=datadir, magic=magic, quiet=True, trimall=True) grid = pc.read_grid(datadir=datadir, quiet=True, trim=True) t[tIdx] = var.t # extract the requested vector traceField vv = getattr(var, traceField) if (any(intQ == 'curlyA')): aa = var.aa # 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 # initialize the tracers for ix in range(int(trace_sub * dim.nx)): for iy in range(int(trace_sub * dim.ny)): tracers[ix, iy, tIdx, 0] = grid.x[0] + int(grid.dx / trace_sub) * ix tracers[ix, iy, tIdx, 2] = tracers[ix, iy, tIdx, 0] tracers[ix, iy, tIdx, 1] = grid.y[0] + int(grid.dy / trace_sub) * iy tracers[ix, iy, tIdx, 3] = tracers[ix, iy, tIdx, 1] tracers[ix, iy, tIdx, 4] = grid.z[0] # declare vectors xMid = np.zeros(3) xSingle = np.zeros(3) xHalf = np.zeros(3) xDouble = np.zeros(3) tmp = [] subTracersLambda = lambda queue, vv, p, tracers, iproc: \ subTracers(queue, vv, p, tracers, iproc, hMin = hMin, hMax = hMax, lMax = lMax, tol = tol, interpolation = interpolation, integration = integration, intQ = intQ) proc = [] for iproc in range(nproc): proc.append( mp.Process(target=subTracersLambda, args=(queue, vv, p, tracers[iproc::nproc, :, tIdx, :], iproc))) for iproc in range(nproc): proc[iproc].start() for iproc in range(nproc): tmp.append(queue.get()) for iproc in range(nproc): proc[iproc].join() for iproc in range(nproc): tracers[tmp[iproc][2]::nproc, :, tIdx, :], mapping[tmp[iproc][2]::nproc, :, tIdx, :] = (tmp[iproc][0], tmp[iproc][1]) for iproc in range(nproc): proc[iproc].terminate() tracers = np.copy(tracers.swapaxes(0, 3), order='C') if (destination != ''): f = open(datadir + destination, 'wb') f.write(np.array(trace_sub, dtype='float32')) # write tracers into file for tIdx in range(n_times): f.write(t[tIdx].astype('float32')) f.write(tracers[:, :, tIdx, :].astype('float32')) f.close() tracers = tracers.swapaxes(0, 3) tracers = tracers.swapaxes(0, 1) mapping = mapping.swapaxes(0, 1) return tracers, mapping, t