def trivialwavefront(c, N = 50): slowness = lambda x: np.ones(len(x)) /c gradslowness = lambda x: np.zeros_like(x) x0 = np.vstack((np.linspace(0,1,N), np.zeros(N))).T p0 = np.vstack((np.zeros(N), np.ones(N))).T wfs, idxs = prw.wavefront(x0, p0, slowness, gradslowness, 0.05, 1.0/c, 1) plotwavefront(wfs, idxs)
def bubblematerial(c=1, N=20, dt=0.05, gridpoints=100, plotoutput=True): """ Calculate first arrival times for a wave travelling through NicolasBubble using a wavefront method that is then interpolated onto a grid Args: c: baseline wave speed N: number of points to put on initial wavefront dt: timestep (the wavefront implementation uses forward Euler) gridpoints: number of points to resolve on the grid plotoutput: whether to display output Returns: A 2D array containing the first arrival times at the points on the grid """ bounds = [[0, 1], [0, 1]] # The x-axis and y-axis bounds for the domain npoints = [gridpoints, gridpoints] # The number of points to (eventually) resolve in the grid speed = NicolasBubble() if plotoutput: pom.output2dfn(bounds, speed, npoints, show=False) # plot the speed function slowness = lambda x: 1 / speed(x) gradslowness = prw.gradient(slowness, 1e-6) # A very crude numerical gradient # These two lines would initialise a plane wave entering the domain # x0 = np.vstack((np.linspace(0,1,N), np.zeros(N))).T # p0 = np.vstack((np.zeros(N), np.ones(N))).T # These three lines initialise a source angles = np.linspace(-1e-2, math.pi + 1e-2, N) p0 = np.vstack((np.cos(angles), np.sin(angles))).T x0 = np.array([0.5, 0]) + dt * p0 # Perform the wavefront tracking wfs, idxs = prw.wavefront(x0, p0, slowness, gradslowness, dt, 1.25 / c, 0.1) if plotoutput: erw.plotwavefront(wfs, idxs, bounds) # plot the wavefronts # Use SciPy's interpolation (which doesn't work well when there are multiple arrival times) # phasefn = interpolatephase(wfs, dt) # pom.output2dfn(bounds, phasefn, npoints, show=False, type='contour') # Home-brew interpolation: sp = pug.StructuredPoints(np.array(bounds).T, npoints) # Define the points onto which we're going to interpolate initialbox = [[0.4, 0], [0.6, 0.1]] # The vertices of a box that contain (some of) the first wave front pointinfo = prw.StructuredPointInfo( sp, sp.getPoints(initialbox)[0] ) # Obtain the indices of the points that are in the initial box h = np.max((sp.upper - sp.lower) / sp.npoints) # The (maximum) grid spacing _, phases = prw.nodesToDirsAndPhases( wfs, idxs, pointinfo, lookback=int(math.ceil(h / (c * dt))) ) # perform the interpolation firstphase = ( np.array([p[0] if len(p) > 0 else -1 for p in phases]) * dt ) # We only care about the first phase found per point # pom.image(firstphase, (M+1,M+1), np.array(bounds)) if plotoutput: pom.contour(pointinfo.points, firstphase, npoints) return firstphase.reshape(npoints)
def linearmaterial(): N = 50 speed = lambda x: 1 + x[:,0] slowness = lambda x: 1 / speed(x) gradslowness = prw.gradient(slowness, 1E-6) x0 = np.vstack((np.linspace(0,1,N), np.zeros(N))).T p0 = np.vstack((np.zeros(N), np.ones(N))).T wfs, idxs = prw.wavefront(x0, p0, slowness, gradslowness, 0.05, 1.5, 1) plotwavefront(wfs, idxs)
def bubblematerial(c = 1, N = 20): # slowness, gradslowness = bubble(c) slowness, gradslowness = hump(c) x0 = np.vstack((np.linspace(0,1,N), np.zeros(N))).T p0 = np.vstack((np.zeros(N), np.ones(N))).T wfs, idxs = prw.wavefront(x0, p0, slowness, gradslowness, 0.1, 1.2/c, 0.1) mp.subplot(1,2,1) plotwavefront(wfs, idxs) mesh = ptum.regularsquaremesh(12, "BDY") etob = prb.getetob(wfs, idxs, mesh, "BDY") mp.subplot(1,2,2) pom.showmesh(mesh) pom.showdirections(mesh, etob,scale=20)
def testRaytraceMesh(self): c = 0.5 for (Nmesh, Nrt) in [(10,10), (20,4), (4, 20)]: mesh = ptum.regularsquaremesh(Nmesh, "BDY") x0 = np.vstack((np.linspace(-0.2,1.2,Nrt), np.ones(Nrt)*(-0.2))).transpose() p0 = np.vstack((np.zeros(Nrt), np.ones(Nrt))).transpose() slowness = lambda x: np.ones(len(x))/c gradslowness = lambda x: np.zeros_like(x) wfs, fidxs = prw.wavefront(x0, p0, slowness, gradslowness, 1/(c * Nrt), 1.4 / c, 1/(c * Nrt)) phases = prw.nodesToPhases(wfs, fidxs, mesh, ["BDY"]) self.assertEqual(len(phases), (Nmesh+1)**2) for vp in phases: self.assertGreaterEqual(len(vp), 1) for p in vp: np.testing.assert_array_almost_equal(p, [0,1/c])
pdeg = 2 c = 1 N = 20 slow = w.GaussianBubble(c) gradslow = prw.gradient(slow, 1E-6) #speed = Recip(slow) speed = lambda p: 1.0/slow(p) #slow, gradslow = w.hump(c,0.2,0.1,0.3) #entityton = {6:1} x0 = np.vstack((np.linspace(0,1,N),np.zeros(N))).T p0 = np.vstack((np.zeros(N),np.ones(N))).T wavefronts, forwardidxs = prw.wavefront(x0, p0, slow, gradslow, 0.1, 1.6/c, 0.1) # Original basis: pw = pcbv.PlaneWaveVariableN(pcb.uniformdirs(2,npw)) # Polynomials only: poly = pcbr.ReferenceBasisRule(pcbr.Dubiner(pdeg)) prodpw = pcb.ProductBasisRule(pw, poly) # Product basis: #basisrule = pcb.ProductBasisRule(pcb.planeWaveBases(2,k,npw), pcbr.ReferenceBasisRule(pcbr.Dubiner(1))) #basisrule=pcb.ProductBasisRule(pw,pcbr.ReferenceBasisRule(pcbr.Dubiner(0))) #basisrule = pcbred.SVDBasisReduceRule(puq.trianglequadrature(quadpoints), basisrule)