def __init__(self, intQ = ['Jp'], dataDir = 'data', streamFileInit = 'streamInit.vtk', streamFile = 'stream.vtk', dumpFile = 'save.vtk', mapFile = 'map.vtk', interpolation = 'weighted', s0 = [], s = []): """ Compute the integrated quantities. If the streamline objects are not passed, read them. Make sure 'streamFile' and 'dumpFile' are from the same time or you will get unexpected results. call signature: intStreamintQ = ['Jp'], dataDir = 'data', streamFileInit = 'streamInit.vtk', streamFile = 'stream.vtk', dumpFile = 'save.vtk', mapFile = 'map.vtk', interpolation = 'weighted', s0 = [], s = []) Keyword arguments: *intQ*: Quantity to be integrated along the streamlines. Options: 'Jp', 'JB', 'lam', 'lamS', 'deltaLam', 'epsilon', 'epsilonS', 'l', 'twist', 'mu' *dataDir*: Data directory. *streamFileInit*: Read the initial streamline at t = 0 from this file. *streamFile*: Read the streamline at t from this file. *dumpFile: File containing the physical values. *mapFile*: Store the mapping here. *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. *s0*: The streamlines object for t = 0. If not passed obtain it from 'streamFileInit'. *s*: The streamlines object at t. If not passed obtain it from 'streamFile'. """ if (s0 == []): s0 = gm.readStream(dataDir = dataDir, streamFile = streamFileInit) if (s == []): s = gm.readStream(dataDir = dataDir, streamFile = streamFile) data = gm.readDump(dataDir = dataDir, fileName = dumpFile) p = s.p self.x0 = s.x0 self.y0 = s.y0 self.tracers0 = s.tracers[:,:,:,0] self.p = p self.sub = s.sub self.hMin = s.hMin self.hMax = s.hMax self.lMax = s.lMax self.tol = s.tol self.iterMax = s.iterMax # vtk object containing the grid points = vtk.vtkPoints() xx = s.tracers[:,:,:,0] xx = xx[:,:,:,np.newaxis] for i in range(len(s.x0)): for j in range(len(s.y0)): points.InsertNextPoint(xx[:,j,i,0]) grid = vtk.vtkStructuredGrid() grid.SetDimensions([len(s.y0),len(s.x0),1]) grid.SetPoints(points) # make intQ iterable even if it contains only one element if (isinstance(intQ, str)): intQ = [intQ] intQ = np.array(intQ) # check if we need to J needJ = np.any(np.array(['Jp', 'JB', 'lam', 'lamS', 'deltaLam', 'epsilon', 'epsilonS', 'twist', 'mu']) == intQ.reshape((intQ.shape[0],1))) # check if we need B needB = np.any(np.array(['JB', 'lam', 'lamS', 'deltaLam', 'epsilon', 'epsilonS', 'twist', 'mu']) == intQ.reshape((intQ.shape[0],1))) # check if we need the length dl needDl = np.any(np.array(['JB', 'lam', 'lamS', 'deltaLam', 'epsilon', 'epsilonS', 'l', 'twist', 'mu']) == intQ.reshape((intQ.shape[0],1))) # check if the data has the necessarry attributes if (needJ and not(hasattr(data, 'jfield'))): print("Error: missing attribute 'jfield' in data.") return -1 if (needJ and not(hasattr(data, 'bfield'))): print("Error: missing attribute 'bfield' in data.") return -1 # add integrated quantities to intQ (because we can) addQ = set([]) if needJ: addQ = addQ.union(set(['Jp', 'JB', 'lam', 'lamS', 'deltaLam', 'epsilon', 'epsilonS', 'twist', 'mu'])) if needB: addQ = addQ.union(set(['JB', 'lam', 'lamS', 'deltaLam', 'epsilon', 'epsilonS', 'twist', 'mu'])) if needDl: addQ = addQ.union(set(['JB', 'lam', 'lamS', 'deltaLam', 'epsilon', 'epsilonS', 'l', 'twist', 'mu'])) intQ = np.array(list(addQ)) # create arrays for the vtk i/o arrays = {} for q in intQ: arr = vtk.vtkFloatArray() arr.SetName(q) arr.SetNumberOfComponents(1) arr.SetNumberOfTuples(grid.GetNumberOfPoints()) arrays[q] = arr # initialize all arrays print(s.tracers.shape[1:3]) if needJ: Jp = np.zeros(s.tracers.shape[1:3]) if (needJ and needB): JB = np.zeros(s.tracers.shape[1:3]) lam = np.zeros(s.tracers.shape[1:3]) lamS = np.zeros(s.tracers.shape[1:3]) deltaLam = np.zeros(s.tracers.shape[1:3]) epsilon = np.zeros(s.tracers.shape[1:3]) epsilonS = np.zeros(s.tracers.shape[1:3]) twist = np.zeros(s.tracers.shape[1:3]) mu = np.zeros(s.tracers.shape[1:3]) Jn = np.zeros(3) # normalized current if needDl: l2d = np.zeros(s.tracers.shape[1:3]) for i in range(len(s.x0)): for j in range(len(s.y0)): xx1 = s.tracers[:,i,j,0] if needJ: JJ1 = gm.vecInt(s0.tracers[:,i,j,0], data.jfield, p, interpolation = interpolation) if needB: BB1 = gm.vecInt(s0.tracers[:,i,j,0], data.bfield, p, interpolation = interpolation) lamTmp = np.zeros(s.sl[i,j]) lamTmp[0] = np.dot(JJ1, BB1)/np.dot(BB1, BB1) epsilonTmp = np.zeros(s.sl[i,j]) epsilonTmp[0] = np.linalg.norm(np.cross(JJ1, BB1))/np.dot(BB1, BB1) if needDl: l = 0 ll = np.zeros(s.sl[i,j]) ll[0] = l for k in range(1, s.sl[i,j]): xx2 = s.tracers[:,i,j,k] if needJ: JJ2 = gm.vecInt(s0.tracers[:,i,j,k], data.jfield, p, interpolation = interpolation) if needB: BB2 = gm.vecInt(s0.tracers[:,i,j,k], data.bfield, p, interpolation = interpolation) if needDl: dl = np.linalg.norm(xx2-xx1) l += dl ll[k-1] = l # integrate the quantities if needJ: Jp[i,j] += np.dot((JJ2+JJ1), (xx2-xx1)) # division by 2 done later if (needJ and needB): JB[i,j] += np.dot((JJ2+JJ1), (BB2+BB1))*dl # division by 4 done later #lamTmp[k-1] = np.dot((JJ2+JJ1), (BB2+BB1))/np.dot((BB2+BB1), (BB2+BB1)) lamTmp[k] = np.dot(JJ2, BB2)/np.dot(BB2, BB2) lam[i,j] += (lamTmp[k]+lamTmp[k-1])*dl/2 deltaLam[i,j] += (np.dot(JJ2,BB2)/np.dot(BB2,BB2) - np.dot(JJ1,BB1)/np.dot(BB1,BB1))/dl #epsilonTmp[k-1] = np.linalg.norm(np.cross((JJ2+JJ1), (BB2+BB1)))/np.dot((BB2+BB1), (BB2+BB1)) epsilonTmp[k] = np.linalg.norm(np.cross(JJ2, BB2))/np.dot(BB2, BB2) epsilon[i,j] += epsilonTmp[k]*dl #twist[i,j] += np.dot((JJ2+JJ1), (BB2+BB1))/(np.linalg.norm(JJ2+JJ1)*np.linalg.norm(BB2+BB1))*dl # take the norm such that for small vectors errors are small Jtmp = (JJ2+JJ1) Jn[0] = np.sign(Jtmp[0])/np.sqrt(1 + (Jtmp[1]/Jtmp[0])**2 + (Jtmp[2]/Jtmp[0])**2) Jn[1] = np.sign(Jtmp[1])/np.sqrt(1 + (Jtmp[2]/Jtmp[1])**2 + (Jtmp[0]/Jtmp[1])**2) Jn[2] = np.sign(Jtmp[2])/np.sqrt(1 + (Jtmp[0]/Jtmp[2])**2 + (Jtmp[1]/Jtmp[2])**2) Jn = Jn/np.linalg.norm(Jn) twist[i,j] += np.dot(Jn, (BB2+BB1))/np.linalg.norm(BB2+BB1)*dl xx1 = xx2 if needJ: JJ1 = JJ2 if needB: BB1 = BB2 if needJ: Jp[i,j] = Jp[i,j]/2 arrays['Jp'].SetValue(i+j*len(s.x0), Jp[i,j]) if (needJ and needB): JB = JB/4 lam[i,j] = lam[i,j]/l dLamTmp = abs((lamTmp[1:] - lamTmp[:-1]) / (ll[1:] - ll[:-1])) dLamTmp[np.isnan(dLamTmp)] = 0 lamS[i,j] = np.max(dLamTmp) epsilon[i,j] = epsilon[i,j]/l epsilonTmp = (epsilonTmp[1:] - epsilonTmp[:-1]) / (ll[1:] - ll[:-1]) epsilonTmp[np.isnan(epsilonTmp)] = 0 epsilonS[i,j] = np.max(abs(epsilonTmp)) twist[i,j] = twist[i,j]/l if (ll.shape[0] > 1): idx = np.where(dLamTmp == lamS[i,j])[0][0] mu[i,j] = lamS[i,j]*2*(ll[idx+1] - ll[idx])/(lamTmp[idx+1] + lamTmp[idx]) else: mu[i,j] = lamS[i,j]*2*ll[0]/lamTmp[0] arrays['JB'].SetValue(i+j*len(s.x0), JB[i,j]) arrays['lam'].SetValue(i+j*len(s.x0), lam[i,j]) arrays['lamS'].SetValue(i+j*len(s.x0), lamS[i,j]) arrays['deltaLam'].SetValue(i+j*len(s.x0), deltaLam[i,j]) arrays['epsilon'].SetValue(i+j*len(s.x0), epsilon[i,j]) arrays['epsilonS'].SetValue(i+j*len(s.x0), epsilonS[i,j]) arrays['twist'].SetValue(i+j*len(s.x0), twist[i,j]) arrays['mu'].SetValue(i+j*len(s.x0), mu[i,j]) if needDl: l2d[i,j] = l arrays['l'].SetValue(i+j*len(s.x0), l2d[i,j]) if needJ: self.Jp = Jp if (needJ and needB): self.JB = JB self.lam = lam self.lamS = lamS self.deltaLam = deltaLam self.epsilon = epsilon self.epsilonS = epsilonS self.twist = twist self.mu = mu if needDl: self.l = l2d # add results to the vtk array for q in intQ: grid.GetPointData().AddArray(arrays[q]) fieldData = vtk.vtkFieldData() # save parameter x0, y0 field = VN.numpy_to_vtk(self.x0) field.SetName('x0') fieldData.AddArray(field) field = VN.numpy_to_vtk(self.y0) field.SetName('y0') fieldData.AddArray(field) # streamline parameters tmp = range(10) tmp[0] = np.array([s.sub], dtype = 'int32'); field = VN.numpy_to_vtk(tmp[0]); field.SetName('sub'); fieldData.AddArray(field) tmp[1] = np.array([s.hMin], dtype = 'float32'); field = VN.numpy_to_vtk(tmp[1]); field.SetName('hMin'); fieldData.AddArray(field) tmp[2] = np.array([s.hMax], dtype = 'float32'); field = VN.numpy_to_vtk(tmp[2]); field.SetName('hMax'); fieldData.AddArray(field) tmp[3] = np.array([s.lMax], dtype = 'float32'); field = VN.numpy_to_vtk(tmp[3]); field.SetName('lMax'); fieldData.AddArray(field) tmp[4] = np.array([s.tol], dtype = 'float32'); field = VN.numpy_to_vtk(tmp[4]); field.SetName('tol'); fieldData.AddArray(field) tmp[5] = np.array([s.iterMax], dtype = 'int32'); field = VN.numpy_to_vtk(tmp[5]); field.SetName('iterMax'); fieldData.AddArray(field) # fields containing simulation parameters stored in paramFile dic = dir(p) params = range(len(dic)) i = 0 for attr in dic: if( attr[0] != '_'): params[i] = getattr(p, attr) params[i] = np.array([params[i]], dtype = type(params[i])) field = VN.numpy_to_vtk(params[i]) field.SetName(attr) fieldData.AddArray(field) i += 1 grid.SetFieldData(fieldData) # write into vtk file writer = vtk.vtkStructuredGridWriter() writer.SetFileName(dataDir + '/' + mapFile) writer.SetInput(grid) writer.SetFileTypeToBinary() writer.Write()
def __init__(self, dataDir='data', streamFileInit='streamInit.vtk', streamFile='stream.vtk', dumpFile='save.vtk', interpolation='weighted', s=[]): """ Maps the streamlines from X to x. call signature: mapStream(dataDir = 'data', streamFileInit = 'streamInit.vtk', streamFile = 'stream.vtk', dumpFile = 'save.vtk', interpolation = 'weighted') Keyword arguments: *dataDir*: Data directory. *streamFileInit*: Read the initial streamline in this file. *streamFile*: Store the streamline in this file. *dumpFile*: Use this file for the mapping x(X,t). *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. *s*: The streamlines object for t = 0. If not passed obtain it from 'streamFileInit'. """ # read the stream lines at t = 0 if (s == []): s = gm.readStream(dataDir=dataDir, streamFile=streamFileInit) #s = gm.readStream(dataDir = dataDir, streamFile = streamFileInit) # convert x0 and y0 into array in case of scalars try: len(s.x0) except: s.x0 = np.array([s.x0]) s.y0 = np.array([s.y0]) # read the current state data = gm.readDump(dataDir=dataDir, fileName=dumpFile) p = data.p xx = data.grid # mapped tracers tracersNew = np.zeros(s.tracers.shape, dtype=s.tracers.dtype) # interpolate x(X,t) at S to get x(S,t), where S is the initial streamline for i in range(len(s.x0)): for j in range(len(s.y0)): for sl in range(s.sl[i, j]): tracersNew[:, i, j, sl] = vecInt(s.tracers[:, i, j, sl], xx, p, interpolation) self.x0 = s.x0 self.y0 = s.y0 self.sl = s.sl self.tracers = tracersNew self.p = p #self.tracers = s.tracers self.sub = s.sub self.hMin = s.hMin self.hMax = s.hMax self.lMax = s.lMax self.tol = s.tol self.iterMax = s.iterMax # save into vtk file if (streamFile != []): writer = vtk.vtkPolyDataWriter() writer.SetFileName(dataDir + '/' + streamFile) polyData = vtk.vtkPolyData() fieldData = vtk.vtkFieldData() # fields containing initial x and y values field = VN.numpy_to_vtk(self.x0) field.SetName('x0') fieldData.AddArray(field) field = VN.numpy_to_vtk(self.y0) field.SetName('y0') fieldData.AddArray(field) # field containing length of stream lines for later decomposition field = VN.numpy_to_vtk(self.sl) field.SetName('sl') fieldData.AddArray(field) # streamline parameters tmp = range(10) tmp[0] = np.array([s.sub], dtype='int32') field = VN.numpy_to_vtk(tmp[0]) field.SetName('sub') fieldData.AddArray(field) tmp[1] = np.array([s.hMin], dtype='float32') field = VN.numpy_to_vtk(tmp[1]) field.SetName('hMin') fieldData.AddArray(field) tmp[2] = np.array([s.hMax], dtype='float32') field = VN.numpy_to_vtk(tmp[2]) field.SetName('hMax') fieldData.AddArray(field) tmp[3] = np.array([s.lMax], dtype='float32') field = VN.numpy_to_vtk(tmp[3]) field.SetName('lMax') fieldData.AddArray(field) tmp[4] = np.array([s.tol], dtype='float32') field = VN.numpy_to_vtk(tmp[4]) field.SetName('tol') fieldData.AddArray(field) tmp[5] = np.array([s.iterMax], dtype='int32') field = VN.numpy_to_vtk(tmp[5]) field.SetName('iterMax') fieldData.AddArray(field) # fields containing simulation parameters stored in paramFile dic = dir(p) params = range(len(dic)) i = 0 for attr in dic: if (attr[0] != '_'): params[i] = getattr(p, attr) params[i] = np.array([params[i]], dtype=type(params[i])) field = VN.numpy_to_vtk(params[i]) field.SetName(attr) fieldData.AddArray(field) i += 1 # all stremlines as continuous array of points points = vtk.vtkPoints() for i in range(len(s.x0)): for j in range(len(s.y0)): for k in range(self.sl[i, j]): points.InsertNextPoint(self.tracers[:, i, j, k]) polyData.SetPoints(points) polyData.SetFieldData(fieldData) writer.SetInput(polyData) writer.SetFileTypeToBinary() writer.Write()
def __init__(self, dataDir='data', poincareInit='poincareInit.vtk', poincare='poincare.vtk', dumpFile='save.vtk', interpolation='weighted', po=[]): """ Maps the streamlines from X to x. call signature: mapPoincare(dataDir = 'data', poincareInit = 'poincareInit.vtk', poincareFile = 'poincare.vtk', dumpFile = 'save.vtk', interpolation = 'weighted', po = []) Keyword arguments: *dataDir*: Data directory. *poincareInit*: Read the initial Poincare maps from this file. *poincareFile*: Store the Poincare map in this file. *dumpFile*: Use this file for the mapping x(X,t). *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. *po*: The Poincare object for t = 0. If not passed obtain it from 'poincareInit'. """ # read the Poincare map at t = 0 if (po == []): po = gm.readPoincare(dataDir=dataDir, poincare=poincareInit) # read the current state data = gm.readDump(dataDir=dataDir, fileName=dumpFile) p = data.p xx = data.grid # mapped tracers tracersNew = np.zeros(po.tracers.shape, dtype=po.tracers.dtype) # mapped Poincare map xNew = np.zeros(po.x.shape) yNew = np.zeros(po.y.shape) # interpolate x(X,t) at S to get x(S,t), where S is the initial streamline for j in range(po.x.shape[1]): for sl in range(po.sl[j]): tracersNew[:, j, sl] = gm.vecInt(po.tracers[:, j, sl], xx, p, interpolation) for i in range(po.x.shape[0]): if (i == 0): #xyz = np.array([po.x[i,j], po.y[i,j], p.Oz-p.dz]) xyz = np.array([po.x[i, j], po.y[i, j], p.Oz]) else: #xyz = np.array([po.x[i,j], po.y[i,j], p.Oz+p.Lz+p.dz]) xyz = np.array([po.x[i, j], po.y[i, j], p.Oz + p.Lz]) tmp = gm.vecInt(xyz, xx, p, interpolation) xNew[i, j] = tmp[0] yNew[i, j] = tmp[1] self.x = xNew self.y = yNew self.sl = po.sl self.tracers = tracersNew self.p = p self.hMin = po.hMin self.hMax = po.hMax self.lMax = po.lMax self.tol = po.tol self.iterMax = po.iterMax self.nIter = po.nIter self.nSeeds = po.nSeeds # save into vtk file if (poincare != []): writer = vtk.vtkPolyDataWriter() writer.SetFileName(dataDir + '/' + poincare) polyData = vtk.vtkPolyData() fieldData = vtk.vtkFieldData() # fields containing x and y values field = VN.numpy_to_vtk(self.x) field.SetName('x') fieldData.AddArray(field) field = VN.numpy_to_vtk(self.y) field.SetName('y') fieldData.AddArray(field) # field containing length of stream lines for later decomposition field = VN.numpy_to_vtk(self.sl) field.SetName('sl') fieldData.AddArray(field) # streamline parameters tmp = range(10) tmp[0] = np.array([po.hMin], dtype='float32') field = VN.numpy_to_vtk(tmp[0]) field.SetName('hMin') fieldData.AddArray(field) tmp[1] = np.array([po.hMax], dtype='float32') field = VN.numpy_to_vtk(tmp[1]) field.SetName('hMax') fieldData.AddArray(field) tmp[2] = np.array([po.lMax], dtype='float32') field = VN.numpy_to_vtk(tmp[2]) field.SetName('lMax') fieldData.AddArray(field) tmp[3] = np.array([po.tol], dtype='float32') field = VN.numpy_to_vtk(tmp[3]) field.SetName('tol') fieldData.AddArray(field) tmp[4] = np.array([po.iterMax], dtype='int32') field = VN.numpy_to_vtk(tmp[4]) field.SetName('iterMax') fieldData.AddArray(field) tmp[5] = np.array([po.tol], dtype='int32') field = VN.numpy_to_vtk(tmp[5]) field.SetName('nSeeds') fieldData.AddArray(field) tmp[6] = np.array([po.tol], dtype='int32') field = VN.numpy_to_vtk(tmp[6]) field.SetName('nIter') fieldData.AddArray(field) # fields containing simulation parameters stored in paramFile dic = dir(p) params = range(len(dic)) i = 0 for attr in dic: if (attr[0] != '_'): params[i] = getattr(p, attr) params[i] = np.array([params[i]], dtype=type(params[i])) field = VN.numpy_to_vtk(params[i]) field.SetName(attr) fieldData.AddArray(field) i += 1 # all streamlines as continuous array of points points = vtk.vtkPoints() for q in range(self.x.shape[1]): for l in range(self.sl[q]): points.InsertNextPoint(self.tracers[:, q, l]) polyData.SetPoints(points) polyData.SetFieldData(fieldData) writer.SetInput(polyData) writer.SetFileTypeToBinary() writer.Write()
def __init__(self, dataDir='data', B0File='B0.vtk', streamFileInit='streamInit.vtk', paramFile='save.vtk', interpolation='weighted', integration='simple', sub=1, hMin=2e-3, hMax=2e4, lMax=500, tol=1e-2, iterMax=1e3, x0=[], y0=[]): """ Creates, saves and returns the initial streamline map. call signature: streamInit(dataDir = 'data', B0File = 'B0.vtk', streamFileInit = 'streamInit.vtk', paramFile = 'save.vtk', interpolation = 'weighted', integration = 'simple', sub = 1, hMin = 2e-3, hMax = 2e2, lMax = 500, tol = 2e-3, iterMax = 1e3, x0 = [], y0 = []) Trace magnetic streamlines for t = 0 and store the positions in a file. Keyword arguments: *dataDir*: Data directory. *B0File*: Name of the file storing B(X,0) = B0. *streamFileInit*: Store the streamline in this file. If it is empty [] don't write. *paramFile*: Dump file from where to read the simulation parameters. *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. *integration*: Integration method. 'simple': low order method. 'RK6': Runge-Kutta 6th order. *sub*: Subsampling of the streamlines. *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. *iterMax*: Maximum number of iterations. *x0*: Initial seed in x-direction. *y0*: Initial seed in y-direction. """ data = gm.readB0(dataDir=dataDir, fileName=B0File) B0 = data.bfield p = gm.readParams(dataDir=dataDir, fileName=paramFile) self.p = p self.p.t = 0 # streamline parameters self.sub = sub self.hMin = hMin self.hMax = hMax self.lMax = lMax self.tol = tol self.iterMax = iterMax # create initial seeds if (x0 == []): x0 = np.float32( np.linspace(p.Ox - p.dx, p.Ox + p.Lx + p.dx, np.round(1 + (2 * p.dx + p.Lx) / p.dx * sub))) if (y0 == []): y0 = np.float32( np.linspace(p.Oy - p.dy, p.Oy + p.Ly + p.dy, np.round(1 + (2 * p.dy + p.Ly) / p.dy * sub))) self.x0 = x0 self.y0 = y0 try: len(x0) except: x0 = np.array([x0]) y0 = np.array([y0]) self.tracers = np.zeros([3, len(x0), len(y0), iterMax], dtype='float32') # tentative streamline length self.sl = np.zeros([len(x0), len(y0)], dtype='int32') tol2 = tol**2 # declare vectors xMid = np.zeros(3) xSingle = np.zeros(3) xHalf = np.zeros(3) xDouble = np.zeros(3) # initialize the coefficient for the 6th order adaptive time step RK a = np.zeros(6) b = np.zeros((6, 5)) c = np.zeros(6) cs = np.zeros(6) k = np.zeros((6, 3)) a[1] = 0.2 a[2] = 0.3 a[3] = 0.6 a[4] = 1 a[5] = 0.875 b[1, 0] = 0.2 b[2, 0] = 3 / 40. b[2, 1] = 9 / 40. b[3, 0] = 0.3 b[3, 1] = -0.9 b[3, 2] = 1.2 b[4, 0] = -11 / 54. b[4, 1] = 2.5 b[4, 2] = -70 / 27. b[4, 3] = 35 / 27. b[5, 0] = 1631 / 55296. b[5, 1] = 175 / 512. b[5, 2] = 575 / 13824. b[5, 3] = 44275 / 110592. b[5, 4] = 253 / 4096. c[0] = 37 / 378. c[2] = 250 / 621. c[3] = 125 / 594. c[5] = 512 / 1771. cs[0] = 2825 / 27648. cs[2] = 18575 / 48384. cs[3] = 13525 / 55296. cs[4] = 277 / 14336. cs[5] = 0.25 # do the streamline tracing r = 0 for u in x0: s = 0 for v in y0: # initialize the streamline xx = np.array([u, v, p.Oz]) self.tracers[:, r, s, 0] = xx dh = np.sqrt(hMax * hMin) # initial step size sl = 0 l = 0 outside = False if (integration == 'simple'): while ((l < lMax) and (xx[2] < p.Oz + p.Lz) and (sl < iterMax - 1) and (not (np.isnan(xx[0]))) and (outside == False)): # (a) single step (midpoint method) xMid = xx + 0.5 * dh * gm.vecInt( xx, B0, p, interpolation) xSingle = xx + dh * gm.vecInt(xMid, B0, p, interpolation) # (b) two steps with half stepsize xMid = xx + 0.25 * dh * gm.vecInt( xx, B0, p, interpolation) xHalf = xx + 0.5 * dh * gm.vecInt( xMid, B0, p, interpolation) xMid = xHalf + 0.25 * dh * gm.vecInt( xHalf, B0, p, interpolation) xDouble = xHalf + 0.5 * dh * gm.vecInt( xMid, B0, p, interpolation) # (c) check error (difference between methods) dist2 = np.sum((xSingle - xDouble)**2) if (dist2 > tol2): dh = 0.5 * dh if (abs(dh) < hMin): print("Error: stepsize underflow") break else: l += np.sqrt(np.sum((xx - xDouble)**2)) xx = xDouble.copy() if (abs(dh) < hMin): dh = 2 * dh sl += 1 self.tracers[:, r, s, sl] = xx.copy() if ((dh > hMax) or (np.isnan(dh))): dh = hMax # check if this point lies outside the domain if ((xx[0] < p.Ox - p.dx) or (xx[0] > p.Ox + p.Lx + p.dx) or (xx[1] < p.Oy - p.dy) or (xx[1] > p.Oy + p.Ly + p.dy) or (xx[2] < p.Oz) or (xx[2] > p.Oz + p.Lz)): outside = True if (integration == 'RK6'): while ((l < lMax) and (xx[2] < p.Oz + p.Lz) and (sl < iterMax) and (not (np.isnan(xx[0]))) and (outside == False)): k[0, :] = dh * gm.vecInt(xx, B0, p, interpolation) k[1, :] = dh * gm.vecInt(xx + b[1, 0] * k[0, :], B0, p, interpolation) k[2, :] = dh * gm.vecInt( xx + b[2, 0] * k[0, :] + b[2, 1] * k[1, :], B0, p, interpolation) k[3, :] = dh * gm.vecInt( xx + b[3, 0] * k[0, :] + b[3, 1] * k[1, :] + b[3, 2] * k[2, :], B0, p, interpolation) k[4, :] = dh * gm.vecInt( xx + b[4, 0] * k[0, :] + b[4, 1] * k[1, :] + b[4, 2] * k[2, :] + b[4, 3] * k[3, :], B0, p, interpolation) k[5, :] = dh * gm.vecInt( xx + b[5, 0] * k[0, :] + b[5, 1] * k[1, :] + b[5, 2] * k[2, :] + b[5, 3] * k[3, :] + b[5, 4] * k[4, :], B0, p, interpolation) xNew = xx + c[0] * k[0, :] + c[1] * k[1, :] + c[2] * k[ 2, :] + c[3] * k[3, :] + c[4] * k[4, :] + c[5] * k[ 5, :] xNewS = xx + cs[0] * k[0, :] + cs[1] * k[ 1, :] + cs[2] * k[2, :] + cs[3] * k[ 3, :] + cs[4] * k[4, :] + cs[5] * k[5, :] delta2 = np.dot((xNew - xNewS), (xNew - xNewS)) delta = np.sqrt(delta2) if (delta2 > tol2): dh = dh * (0.9 * abs(tol / delta))**0.2 if (abs(dh) < hMin): print("Error: step size underflow") break else: l += np.sqrt(np.sum((xx - xNew)**2)) xx = xNew if (abs(dh) < hMin): dh = 2 * dh sl += 1 self.tracers[:, r, s, sl] = xx if ((dh > hMax) or (np.isnan(dh))): dh = hMax # check if this point lies outside the domain if ((xx[0] < p.Ox - p.dx) or (xx[0] > p.Ox + p.Lx + p.dx) or (xx[1] < p.Oy - p.dy) or (xx[1] > p.Oy + p.Ly + p.dy) or (xx[2] < p.Oz) or (xx[2] > p.Oz + p.Lz)): outside = True if ((dh > hMax) or (delta == 0) or (np.isnan(dh))): dh = hMax self.sl[r, s] = sl + 1 s += 1 r += 1 # save into vtk file if (streamFileInit != []): writer = vtk.vtkPolyDataWriter() writer.SetFileName(dataDir + '/' + streamFileInit) polyData = vtk.vtkPolyData() fieldData = vtk.vtkFieldData() # fields containing initial x and y values field = VN.numpy_to_vtk(self.x0) field.SetName('x0') fieldData.AddArray(field) field = VN.numpy_to_vtk(self.y0) field.SetName('y0') fieldData.AddArray(field) # field containing length of stream lines for later decomposition field = VN.numpy_to_vtk(self.sl) field.SetName('sl') fieldData.AddArray(field) # streamline parameters tmp = range(10) tmp[0] = np.array([sub], dtype='int32') field = VN.numpy_to_vtk(tmp[0]) field.SetName('sub') fieldData.AddArray(field) tmp[1] = np.array([hMin], dtype='float32') field = VN.numpy_to_vtk(tmp[1]) field.SetName('hMin') fieldData.AddArray(field) tmp[2] = np.array([hMax], dtype='float32') field = VN.numpy_to_vtk(tmp[2]) field.SetName('hMax') fieldData.AddArray(field) tmp[3] = np.array([lMax], dtype='float32') field = VN.numpy_to_vtk(tmp[3]) field.SetName('lMax') fieldData.AddArray(field) tmp[4] = np.array([tol], dtype='float32') field = VN.numpy_to_vtk(tmp[4]) field.SetName('tol') fieldData.AddArray(field) tmp[5] = np.array([iterMax], dtype='int32') field = VN.numpy_to_vtk(tmp[5]) field.SetName('iterMax') fieldData.AddArray(field) # fields containing simulation parameters stored in paramFile dic = dir(p) params = range(len(dic)) i = 0 for attr in dic: if (attr[0] != '_'): params[i] = getattr(p, attr) params[i] = np.array([params[i]], dtype=type(params[i])) field = VN.numpy_to_vtk(params[i]) field.SetName(attr) fieldData.AddArray(field) i += 1 # all streamlines as continuous array of points points = vtk.vtkPoints() for r in range(len(x0)): for s in range(len(y0)): for sl in range(self.sl[r, s]): points.InsertNextPoint(self.tracers[:, r, s, sl]) polyData.SetPoints(points) polyData.SetFieldData(fieldData) writer.SetInput(polyData) writer.SetFileTypeToBinary() writer.Write()
def __init__(self, dataDir='data', B0File='B0.vtk', poincare='poincareInit.vtk', paramFile='save.vtk', dumpFile=[], interpolation='weighted', integration='simple', hMin=2e-3, hMax=2e2, lMax=500, tol=2e-3, iterMax=1e3, x0=[], y0=[], nSeeds=10, nIter=10): """ Creates, saves and returns the initial streamline map for a few lines and the Poincare map. call signature: streamInit(dataDir = 'data', B0File = 'B0.vtk', poincare = 'poincareInit.vtk', paramFile = 'save.vtk', dumpFile = [], interpolation = 'weighted', integration = 'simple', sub = 1, hMin = 2e-3, hMax = 2e2, lMax = 500, tol = 2e-3, iterMax = 1e3, x0 = [], y0 = []) Trace magnetic streamlines for t = 0 and store the positions in a file. Keyword arguments: *dataDir*: Data directory. *B0File*: Name of the file storing B(X,0) = B0. *poincare*: Store the Poincare map in this file. *paramFile*: Dump file from where to read the simulation parameters. *dumpFile*: If not empty map the streamlines from B0.vtk to the time of dumpFile. *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. *integration*: Integration method. 'simple': low order method. 'RK6': Runge-Kutta 6th order. *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. *iterMax*: Maximum number of iterations. *x0*: Initial seed in x-direction. *y0*: Initial seed in y-direction. *nSeeds*: Number of initial seeds. *nIter*: Number of times the streamlines go through the domain. """ p = gm.readParams(dataDir=dataDir, fileName=paramFile) if (len(x0) != len(y0)): print("error: length of x0 != length of y0.") return -1 if ((len(x0) == 0) and (len(y0) == 0)): x0 = np.random.random(nSeeds) * p.Lx + p.Ox y0 = np.random.random(nSeeds) * p.Ly + p.Oy else: nSeeds = len(x0) x = np.zeros((nIter + 1, nSeeds)) y = np.zeros((nIter + 1, nSeeds)) x[0, :] = x0 y[0, :] = y0 streams = range(nSeeds) tracers = range(nSeeds) sl = np.zeros(nSeeds, dtype='int32') for q in range(len(x0)): tracers[q] = [] for i in range(nIter): # stream the lines until they hit the upper boundary s = gm.streamInit(dataDir=dataDir, B0File=B0File, streamFileInit=[], paramFile=paramFile, interpolation=interpolation, integration=integration, hMin=hMin, hMax=hMax, lMax=lMax, tol=tol, iterMax=iterMax, x0=x[i, q], y0=y[i, q]) # in case the initial time is not 0, map the streamline accordingly if (dumpFile != []): s = gm.mapStream(dataDir=dataDir, streamFileInit='streamInit.vtk', streamFile=[], dumpFile=dumpFile, interpolation=interpolation, s=s) # interpolate the final values for points hitting through the boundary l = (p.Oz + p.Lz - s.tracers[2, 0, 0, s.sl - 2]) / ( s.tracers[2, 0, 0, s.sl - 1] - s.tracers[2, 0, 0, s.sl - 2]) x[i + 1, q] = (s.tracers[0, 0, 0, s.sl - 1] - s.tracers[0, 0, 0, s.sl - 2]) * l + s.tracers[0, 0, 0, s.sl - 2] y[i + 1, q] = (s.tracers[1, 0, 0, s.sl - 1] - s.tracers[1, 0, 0, s.sl - 2]) * l + s.tracers[1, 0, 0, s.sl - 2] # add the tracers to the existing ones tracers[q].extend( list(np.swapaxes(s.tracers[:, 0, 0, :s.sl], 0, 1))) sl[q] += s.sl p = s.p self.p = p self.x = x self.y = y self.sl = sl maxLen = sl.max() self.tracers = np.zeros((3, nSeeds, maxLen)) for q in range(len(x0)): self.tracers[:, q, :sl[q]] = np.swapaxes(np.array(tracers[q]), 0, 1) # streamline parameters self.hMin = hMin self.hMax = hMax self.lMax = lMax self.tol = tol self.iterMax = iterMax self.nSeeds = nSeeds self.nIter = nIter # safe in vtk file if (poincare != []): writer = vtk.vtkPolyDataWriter() writer.SetFileName(dataDir + '/' + poincare) polyData = vtk.vtkPolyData() fieldData = vtk.vtkFieldData() # fields containing x and y values field = VN.numpy_to_vtk(self.x) field.SetName('x') fieldData.AddArray(field) field = VN.numpy_to_vtk(self.y) field.SetName('y') fieldData.AddArray(field) # field containing length of stream lines for later decomposition field = VN.numpy_to_vtk(self.sl) field.SetName('sl') fieldData.AddArray(field) # streamline parameters tmp = range(10) tmp[0] = np.array([s.hMin], dtype='float32') field = VN.numpy_to_vtk(tmp[0]) field.SetName('hMin') fieldData.AddArray(field) tmp[1] = np.array([s.hMax], dtype='float32') field = VN.numpy_to_vtk(tmp[1]) field.SetName('hMax') fieldData.AddArray(field) tmp[2] = np.array([s.lMax], dtype='float32') field = VN.numpy_to_vtk(tmp[2]) field.SetName('lMax') fieldData.AddArray(field) tmp[3] = np.array([s.tol], dtype='float32') field = VN.numpy_to_vtk(tmp[3]) field.SetName('tol') fieldData.AddArray(field) tmp[4] = np.array([s.iterMax], dtype='int32') field = VN.numpy_to_vtk(tmp[4]) field.SetName('iterMax') fieldData.AddArray(field) tmp[5] = np.array([nSeeds], dtype='int32') field = VN.numpy_to_vtk(tmp[5]) field.SetName('nSeeds') fieldData.AddArray(field) tmp[6] = np.array([nIter], dtype='int32') field = VN.numpy_to_vtk(tmp[6]) field.SetName('nIter') fieldData.AddArray(field) # fields containing simulation parameters stored in paramFile dic = dir(p) params = range(len(dic)) i = 0 for attr in dic: if (attr[0] != '_'): params[i] = getattr(p, attr) params[i] = np.array([params[i]], dtype=type(params[i])) field = VN.numpy_to_vtk(params[i]) field.SetName(attr) fieldData.AddArray(field) i += 1 # all streamlines as continuous array of points points = vtk.vtkPoints() for q in range(len(x0)): for l in range(self.sl[q]): points.InsertNextPoint(self.tracers[:, q, l]) polyData.SetPoints(points) polyData.SetFieldData(fieldData) writer.SetInput(polyData) writer.SetFileTypeToBinary() writer.Write()