def test_Kroneker_Derivative(par): """Use Kronecker operator to apply the Derivative operator over one axis and compare with FirstDerivative(... dir=axis) """ Dop = FirstDerivative(par["ny"], sampling=1, edge=True, dtype="float32") D2op = FirstDerivative( par["ny"] * par["nx"], dims=(par["ny"], par["nx"]), dir=0, sampling=1, edge=True, dtype="float32", ) Kop = Kronecker(Dop, Identity(par["nx"], dtype=par["dtype"]), dtype=par["dtype"]) x = np.zeros((par["ny"], par["nx"])) + par["imag"] * np.zeros( (par["ny"], par["nx"])) x[par["ny"] // 2, par["nx"] // 2] = 1 y = D2op * x.ravel() yk = Kop * x.ravel() assert_array_equal(y, yk)
def test_SplitBregman(par): """Invert denoise problem with SplitBregman """ np.random.seed(42) nx = 3 * par[ 'nx'] # need enough samples for TV regularization to be effective Iop = Identity(nx) Dop = FirstDerivative(nx, edge=True) x = np.zeros(nx) x[:nx // 2] = 10 x[nx // 2:3 * nx // 4] = -5 n = np.random.normal(0, 1, nx) y = x + n mu = 0.01 lamda = 0.2 niter_end = 100 niter_in = 3 x0 = np.ones(nx) xinv, niter = SplitBregman(Iop, [Dop], y, niter_end, niter_in, mu=mu, epsRL1s=[lamda], tol=1e-4, tau=1, x0=x0 if par['x0'] else None, restart=False, show=False, **dict(iter_lim=5, damp=1e-3)) assert (np.linalg.norm(x - xinv) / np.linalg.norm(x)) < 1e-1
def test_CausalIntegration2d(par): """Dot-test and inversion for CausalIntegration operator for 2d signals""" dt = 0.2 * par["dt"] # need lower frequency in sinusoids for stability t = np.arange(par["nt"]) * dt x = np.outer(np.sin(t), np.ones( par["nx"])) + par["imag"] * np.outer(np.sin(t), np.ones(par["nx"])) for kind, rf in itertools.product(("full", "half", "trapezoidal"), (False, True)): Cop = CausalIntegration( par["nt"] * par["nx"], dims=(par["nt"], par["nx"]), sampling=dt, dir=0, kind=kind, halfcurrent=False, removefirst=rf, dtype=par["dtype"], ) rf1 = 1 if rf else 0 print(Cop.shape, (par["nt"] - rf1) * par["nx"], par["nt"] * par["nx"]) assert dottest( Cop, (par["nt"] - rf1) * par["nx"], par["nt"] * par["nx"], complexflag=0 if par["imag"] == 0 else 3, ) # test analytical integration and derivative inversion only for # cases where a zero c is required if kind != "full" and not rf: # numerical integration y = Cop * x.ravel() y = y.reshape(par["nt"], par["nx"]) # analytical integration yana = (np.outer(-np.cos(t), np.ones(par["nx"])) + np.cos(t[0]) + par["imag"] * (np.outer(-np.cos(t), np.ones(par["nx"])) + np.cos(t[0]))) yana = yana.reshape(par["nt"], par["nx"]) assert_array_almost_equal(y, yana, decimal=2) # numerical derivative Dop = FirstDerivative( par["nt"] * par["nx"], dims=(par["nt"], par["nx"]), dir=0, sampling=dt, dtype=par["dtype"], ) xder = Dop * y.ravel() xder = xder.reshape(par["nt"], par["nx"]) # derivative by inversion xinv = Cop / y.ravel() xinv = xinv.reshape(par["nt"], par["nx"]) assert_array_almost_equal(x[:-1], xder[:-1], decimal=2) assert_array_almost_equal(x, xinv, decimal=2)
def test_Kroneker_Derivative(par): """Use Kronecker operator to apply the Derivative operator over one axis and compare with FirstDerivative(... dir=axis) """ Dop = FirstDerivative(par['ny'], sampling=1, edge=True, dtype='float32') D2op = FirstDerivative(par['ny'] * par['nx'], dims=(par['ny'], par['nx']), dir=0, sampling=1, edge=True, dtype='float32') Kop = Kronecker(Dop, Identity(par['nx'], dtype=par['dtype']), dtype=par['dtype']) x = np.zeros((par['ny'], par['nx'])) + \ par['imag']*np.zeros((par['ny'], par['nx'])) x[par['ny'] // 2, par['nx'] // 2] = 1 y = D2op * x.flatten() yk = Kop * x.flatten() assert_array_equal(y, yk)
def test_CausalIntegration2d(par): """Dot-test and inversion for CausalIntegration operator for 2d signals """ dt = 0.2 * par['dt'] # need lower frequency in sinusoids for stability t = np.arange(par['nt']) * dt x = np.outer(np.sin(t), np.ones(par['nx'])) + \ par['imag']*np.outer(np.sin(t), np.ones(par['nx'])) Cop = CausalIntegration(par['nt'] * par['nx'], dims=(par['nt'], par['nx']), sampling=dt, dir=0, halfcurrent=True, dtype=par['dtype']) assert dottest(Cop, par['nt'] * par['nx'], par['nt'] * par['nx'], complexflag=0 if par['imag'] == 0 else 3) # numerical integration y = Cop * x.flatten() y = y.reshape(par['nt'], par['nx']) # analytical integration yana = np.outer(-np.cos(t), np.ones(par['nx'])) + np.cos(t[0]) + \ par['imag']*(np.outer(-np.cos(t), np.ones(par['nx'])) + np.cos(t[0])) yana = yana.reshape(par['nt'], par['nx']) assert_array_almost_equal(y, yana, decimal=2) # numerical derivative Dop = FirstDerivative(par['nt'] * par['nx'], dims=(par['nt'], par['nx']), dir=0, sampling=dt, dtype=par['dtype']) xder = Dop * y.flatten() xder = xder.reshape(par['nt'], par['nx']) # derivative by inversion xinv = Cop / y.flatten() xinv = xinv.reshape(par['nt'], par['nx']) assert_array_almost_equal(x[:-1], xder[:-1], decimal=2) assert_array_almost_equal(x, xinv, decimal=2)
def test_SecondDirectionalDerivative_verticalderivative(par): """Compare vertical derivative for SecondDirectionalDerivative operator and SecondDerivative """ Fop = \ FirstDerivative(par['ny'] * par['nx'], (par['ny'], par['nx']), dir=0, edge=par['edge'], dtype='float32') F2op = Fop.H * Fop F2dop = \ SecondDirectionalDerivative((par['ny'], par['nx']), v=np.array([1, 0]), edge=par['edge'], dtype='float32') x = np.random.normal(0., 1., (par['ny'], par['nx'])) assert_array_equal(-F2op * x.ravel(), F2dop * x.ravel())
def test_CausalIntegration1d(par): """Dot-test and inversion for CausalIntegration operator for 1d signals""" t = np.arange(par["nt"]) * par["dt"] x = t + par["imag"] * t for kind, rf in itertools.product(("full", "half", "trapezoidal"), (False, True)): Cop = CausalIntegration( par["nt"], sampling=par["dt"], kind=kind, halfcurrent=False, removefirst=rf, dtype=par["dtype"], ) rf1 = 1 if rf else 0 assert dottest(Cop, par["nt"] - rf1, par["nt"], complexflag=0 if par["imag"] == 0 else 3) # test analytical integration and derivative inversion only for # cases where a zero c is required if kind != "full" and not rf: # numerical integration y = Cop * x # analytical integration yana = (t**2 / 2.0 - t[0]**2 / 2.0 + par["imag"] * (t**2 / 2.0 - t[0]**2 / 2.0)) assert_array_almost_equal(y, yana[rf1:], decimal=4) # numerical derivative Dop = FirstDerivative(par["nt"] - rf1, sampling=par["dt"], dtype=par["dtype"]) xder = Dop * y.ravel() # derivative by inversion xinv = Cop / y assert_array_almost_equal(x[:-1], xder[:-1], decimal=4) assert_array_almost_equal(x, xinv, decimal=4)
def test_SecondDirectionalDerivative_verticalderivative(par): """Compare vertical derivative for SecondDirectionalDerivative operator and SecondDerivative """ Fop = FirstDerivative( par["ny"] * par["nx"], (par["ny"], par["nx"]), dir=0, edge=par["edge"], dtype="float32", ) F2op = Fop.H * Fop F2dop = SecondDirectionalDerivative((par["ny"], par["nx"]), v=np.array([1, 0]), edge=par["edge"], dtype="float32") x = np.random.normal(0.0, 1.0, (par["ny"], par["nx"])) assert_array_equal(-F2op * x.ravel(), F2dop * x.ravel())
def test_CausalIntegration1d(par): """Dot-test and inversion for CausalIntegration operator for 1d signals """ t = np.arange(par['nt']) * par['dt'] x = t + par['imag'] * t Cop = CausalIntegration(par['nt'], sampling=par['dt'], halfcurrent=False, dtype=par['dtype']) assert dottest(Cop, par['nt'], par['nt'], complexflag=0 if par['imag'] == 0 else 3) Cop = CausalIntegration(par['nt'], sampling=par['dt'], halfcurrent=True, dtype=par['dtype']) assert dottest(Cop, par['nt'], par['nt'], complexflag=0 if par['imag'] == 0 else 3) # numerical integration y = Cop * x # analytical integration yana = t ** 2 / 2. - t[0] ** 2 / 2.\ + par['imag'] * (t ** 2 / 2. - t[0] ** 2 / 2.) + y[0] assert_array_almost_equal(y, yana, decimal=4) # numerical derivative Dop = FirstDerivative(par['nt'], sampling=par['dt'], dtype=par['dtype']) xder = Dop * y.flatten() # derivative by inversion xinv = Cop / y assert_array_almost_equal(x[:-1], xder[:-1], decimal=4) assert_array_almost_equal(x, xinv, decimal=4)
def test_FirstDerivative_forwaback(par): """Dot-test for FirstDerivative operator (forward and backward stencils). Note that the analytical expression cannot be validated in this case """ for kind in ('forward', 'backward'): # 1d D1op = FirstDerivative(par['nx'], sampling=par['dx'], edge=par['edge'], kind=kind, dtype='float32') assert dottest(D1op, par['nx'], par['nx'], tol=1e-3) # 2d - derivative on 1st direction D1op = FirstDerivative(par['ny']*par['nx'], dims=(par['ny'], par['nx']), dir=0, sampling=par['dy'], edge=par['edge'], kind=kind, dtype='float32') assert dottest(D1op, par['ny']*par['nx'], par['ny']*par['nx'], tol=1e-3) # 2d - derivative on 2nd direction D1op = FirstDerivative(par['ny'] * par['nx'], dims=(par['ny'], par['nx']), dir=1, sampling=par['dx'], edge=par['edge'], kind=kind, dtype='float32') assert dottest(D1op, par['ny'] * par['nx'], par['ny'] * par['nx'], tol=1e-3) # 3d - derivative on 1st direction D1op = FirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=0, sampling=par['dz'], edge=par['edge'], kind=kind, dtype='float32') assert dottest(D1op, par['nz'] * par['ny'] * par['nx'], par['nz'] * par['ny'] * par['nx'], tol=1e-3) # 3d - derivative on 2nd direction D1op = FirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=1, sampling=par['dy'], edge=par['edge'], kind=kind, dtype='float32') assert dottest(D1op, par['nz']*par['ny']*par['nx'], par['nz']*par['ny']*par['nx'], tol=1e-3) # 3d - derivative on 3rd direction D1op = FirstDerivative(par['nz']*par['ny']*par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=2, sampling=par['dx'], edge=par['edge'], kind=kind, dtype='float32') assert dottest(D1op, par['nz']*par['ny']*par['nx'], par['nz']*par['ny']*par['nx'], tol=1e-3)
def test_FirstDerivative(par): """Dot-test and comparison with Pylops for FirstDerivative operator """ np.random.seed(10) # 1d dD1op = dFirstDerivative(par['nx'], sampling=par['dx'], compute=(True, True), dtype='float32') D1op = FirstDerivative(par['nx'], sampling=par['dx'], edge=False, dtype='float32') assert dottest(dD1op, par['nx'], par['nx'], chunks=(par['nx'], par['nx']), tol=1e-3) x = (par['dx'] * np.arange(par['nx']))**2 x = da.from_array(x, chunks=par['nx'] // 2 + 1) dy = dD1op * x y = D1op * x.compute() assert_array_almost_equal(y[1:-1], dy[1:-1], decimal=1) # 2d - derivative on 1st direction dD1op = dFirstDerivative(par['ny'] * par['nx'], dims=(par['ny'], par['nx']), dir=0, sampling=par['dy'], compute=(True, True), dtype='float32') D1op = FirstDerivative(par['ny'] * par['nx'], dims=(par['ny'], par['nx']), dir=0, sampling=par['dy'], edge=False, dtype='float32') assert dottest(dD1op, par['ny'] * par['nx'], par['ny'] * par['nx'], chunks=(par['ny'] * par['nx'], par['ny'] * par['nx']), tol=1e-3) x = np.outer((par['dy'] * np.arange(par['ny']))**2, np.ones(par['nx'])) x = da.from_array(x, chunks=(par['ny'] // 2 + 1, par['nx'] // 2 + 1)) dy = dD1op * x.ravel() y = D1op * x.compute().ravel() assert_array_almost_equal(y.reshape(par['ny'], par['nx'])[1:-1, 1:-1], dy.reshape(par['ny'], par['nx'])[1:-1, 1:-1], decimal=1) # 2d - derivative on 2nd direction dD1op = dFirstDerivative(par['ny'] * par['nx'], dims=(par['ny'], par['nx']), dir=1, sampling=par['dx'], compute=(True, True), dtype='float32') D1op = FirstDerivative(par['ny'] * par['nx'], dims=(par['ny'], par['nx']), dir=1, sampling=par['dx'], edge=False, dtype='float32') assert dottest(dD1op, par['ny'] * par['nx'], par['ny'] * par['nx'], chunks=(par['ny'] * par['nx'], par['ny'] * par['nx']), tol=1e-3) x = np.outer((par['dy'] * np.arange(par['ny']))**2, np.ones(par['nx'])) x = da.from_array(x, chunks=(par['ny'] // 2 + 1, par['nx'] // 2 + 1)) dy = dD1op * x.ravel() y = D1op * x.compute().ravel() assert_array_almost_equal(y.reshape(par['ny'], par['nx'])[1:-1, 1:-1], dy.reshape(par['ny'], par['nx'])[1:-1, 1:-1], decimal=1) # 3d - derivative on 1st direction dD1op = dFirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=0, sampling=par['dz'], compute=(True, True), dtype='float32') D1op = FirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=0, sampling=par['dz'], edge=False, dtype='float32') assert dottest(dD1op, par['nz'] * par['ny'] * par['nx'], par['nz'] * par['ny'] * par['nx'], chunks=((par['nz'] // 2 + 1) * (par['ny'] // 2 + 1) * (par['nx'] // 2 + 1), (par['nz'] // 2 + 1) * (par['ny'] // 2 + 1) * (par['nx'] // 2 + 1)), tol=1e-3) x = np.outer((par['dz'] * np.arange(par['nz']))**2, np.ones( (par['ny'], par['nx']))).reshape(par['nz'], par['ny'], par['nx']) x = da.from_array(x, chunks=(par['nz'] // 2 + 1, par['ny'] // 2 + 1, par['nx'] // 2 + 1)) dy = dD1op * x.ravel() y = D1op * x.compute().ravel() assert_array_almost_equal(y.reshape(par['nz'], par['ny'], par['nx'])[1:-1, 1:-1], dy.reshape(par['nz'], par['ny'], par['nx'])[1:-1, 1:-1], decimal=1) # 3d - derivative on 2nd direction dD1op = dFirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=1, sampling=par['dz'], compute=(True, True), dtype='float32') D1op = FirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=1, sampling=par['dy'], edge=False, dtype='float32') assert dottest(dD1op, par['nz'] * par['ny'] * par['nx'], par['nz'] * par['ny'] * par['nx'], chunks=((par['nz'] // 2 + 1) * (par['ny'] // 2 + 1) * (par['nx'] // 2 + 1), (par['nz'] // 2 + 1) * (par['ny'] // 2 + 1) * (par['nx'] // 2 + 1)), tol=1e-3) x = np.outer((par['dz'] * np.arange(par['nz']))**2, np.ones( (par['ny'], par['nx']))).reshape(par['nz'], par['ny'], par['nx']) x = da.from_array(x, chunks=(par['nz'] // 2 + 1, par['ny'] // 2 + 1, par['nx'] // 2 + 1)) dy = dD1op * x.ravel() y = D1op * x.compute().ravel() assert_array_almost_equal(y.reshape(par['nz'], par['ny'], par['nx'])[1:-1, 1:-1], dy.reshape(par['nz'], par['ny'], par['nx'])[1:-1, 1:-1], decimal=1)
def test_FirstDerivative(par): """Dot-test and forward for FirstDerivative operator """ # 1d gD1op = gFirstDerivative(par['nx'], sampling=par['dx'], dtype=torch.float32) assert dottest(gD1op, par['nx'], par['nx'], tol=1e-3) x = torch.from_numpy( (par['dx'] * np.arange(par['nx'], dtype='float32'))**2) D1op = FirstDerivative(par['nx'], sampling=par['dx'], dtype='float32') assert_array_equal((gD1op * x)[1:-1], (D1op * x.cpu().numpy())[1:-1]) # 2d - derivative on 1st direction gD1op = gFirstDerivative(par['ny'] * par['nx'], dims=(par['ny'], par['nx']), dir=0, sampling=par['dy'], dtype=torch.float32) assert dottest(gD1op, par['ny'] * par['nx'], par['ny'] * par['nx'], tol=1e-3) x = torch.from_numpy( (np.outer((par['dy'] * np.arange(par['ny']))**2, np.ones(par['nx']))).astype(dtype='float32')) D1op = FirstDerivative(par['ny'] * par['nx'], dims=(par['ny'], par['nx']), dir=0, sampling=par['dy'], dtype='float32') gy = (gD1op * x.view(-1)).reshape(par['ny'], par['nx']).cpu().numpy() y = (D1op * x.view(-1).cpu().numpy()).reshape(par['ny'], par['nx']) assert_array_equal(gy[1:-1], y[1:-1]) # 2d - derivative on 2nd direction gD1op = gFirstDerivative(par['ny'] * par['nx'], dims=(par['ny'], par['nx']), dir=1, sampling=par['dy'], dtype=torch.float32) assert dottest(gD1op, par['ny'] * par['nx'], par['ny'] * par['nx'], tol=1e-3) x = torch.from_numpy( (np.outer((par['dy'] * np.arange(par['ny']))**2, np.ones(par['nx']))).astype(dtype='float32')) D1op = FirstDerivative(par['ny'] * par['nx'], dims=(par['ny'], par['nx']), dir=1, sampling=par['dy'], dtype='float32') gy = (gD1op * x.view(-1)).reshape(par['ny'], par['nx']).cpu().numpy() y = (D1op * x.view(-1).cpu().numpy()).reshape(par['ny'], par['nx']) assert_array_equal(gy[:, 1:-1], y[:, 1:-1]) # 3d - derivative on 1st direction gD1op = gFirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=0, sampling=par['dz'], dtype=torch.float32) assert dottest(gD1op, par['nz'] * par['ny'] * par['nx'], par['nz'] * par['ny'] * par['nx'], tol=1e-3) x = torch.from_numpy( (np.outer((par['dz'] * np.arange(par['nz']))**2, np.ones((par['ny'], par['nx']))).astype(dtype='float32'))) D1op = FirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=0, sampling=par['dz'], dtype='float32') gy = (gD1op * x.view(-1)).reshape(par['nz'], par['ny'], par['nx']).cpu().numpy() y = (D1op * x.view(-1).cpu().numpy()).reshape(par['nz'], par['ny'], par['nx']) assert_array_almost_equal(gy[1:-1], y[1:-1], decimal=5) # 3d - derivative on 2nd direction gD1op = gFirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=1, sampling=par['dy'], dtype=torch.float32) assert dottest(gD1op, par['nz'] * par['ny'] * par['nx'], par['nz'] * par['ny'] * par['nx'], tol=1e-3) x = torch.from_numpy((np.outer( (par['dz'] * np.arange(par['nz']))**2, np.ones( (par['ny'], par['nx']))).reshape(par['nz'], par['ny'], par['nx'])).astype(dtype='float32')) D1op = FirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=1, sampling=par['dy'], dtype='float32') gy = (gD1op * x.view(-1)).reshape(par['nz'], par['ny'], par['nx']).cpu().numpy() y = (D1op * x.view(-1).cpu().numpy()).reshape(par['nz'], par['ny'], par['nx']) assert_array_almost_equal(gy[1:-1], y[1:-1], decimal=5) # 3d - derivative on 3rd direction gD1op = gFirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=2, sampling=par['dx'], dtype=torch.float32) assert dottest(gD1op, par['nz'] * par['ny'] * par['nx'], par['nz'] * par['ny'] * par['nx'], tol=1e-3) x = torch.from_numpy((np.outer( (par['dz'] * np.arange(par['nz']))**2, np.ones( (par['ny'], par['nx']))).reshape(par['nz'], par['ny'], par['nx'])).astype(dtype='float32')) D1op = FirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=2, sampling=par['dx'], dtype='float32') gy = (gD1op * x.view(-1)).reshape(par['nz'], par['ny'], par['nx']).cpu().numpy() y = (D1op * x.view(-1).cpu().numpy()).reshape(par['nz'], par['ny'], par['nx']) assert_array_almost_equal(gy[1:-1], y[1:-1], decimal=5)
def test_FirstDerivative(par): """Dot-test and forward for FirstDerivative operator """ # 1d D1op = FirstDerivative(par['nx'], sampling=par['dx'], edge=par['edge'], dtype='float32') assert dottest(D1op, par['nx'], par['nx'], tol=1e-3) x = (par['dx'] * np.arange(par['nx']))**2 yana = 2 * par['dx'] * np.arange(par['nx']) y = D1op * x assert_array_almost_equal(y[1:-1], yana[1:-1], decimal=1) # 2d - derivative on 1st direction D1op = FirstDerivative(par['ny'] * par['nx'], dims=(par['ny'], par['nx']), dir=0, sampling=par['dy'], edge=par['edge'], dtype='float32') assert dottest(D1op, par['ny'] * par['nx'], par['ny'] * par['nx'], tol=1e-3) x = np.outer((par['dy'] * np.arange(par['ny']))**2, np.ones(par['nx'])) yana = np.outer(2 * par['dy'] * np.arange(par['ny']), np.ones(par['nx'])) y = D1op * x.flatten() y = y.reshape(par['ny'], par['nx']) assert_array_almost_equal(y[1:-1], yana[1:-1], decimal=1) # 2d - derivative on 2nd direction D1op = FirstDerivative(par['ny'] * par['nx'], dims=(par['ny'], par['nx']), dir=1, sampling=par['dx'], edge=par['edge'], dtype='float32') assert dottest(D1op, par['ny'] * par['nx'], par['ny'] * par['nx'], tol=1e-3) x = np.outer((par['dy'] * np.arange(par['ny']))**2, np.ones(par['nx'])) yana = np.zeros((par['ny'], par['nx'])) y = D1op * x.flatten() y = y.reshape(par['ny'], par['nx']) assert_array_almost_equal(y[1:-1], yana[1:-1], decimal=1) # 3d - derivative on 1st direction D1op = FirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=0, sampling=par['dz'], edge=par['edge'], dtype='float32') assert dottest(D1op, par['nz'] * par['ny'] * par['nx'], par['nz'] * par['ny'] * par['nx'], tol=1e-3) x = np.outer((par['dz'] * np.arange(par['nz']))**2, np.ones( (par['ny'], par['nx']))).reshape(par['nz'], par['ny'], par['nx']) yana = np.outer(2 * par['dz'] * np.arange(par['nz']), np.ones((par['ny'], par['nx']))).reshape(par['nz'], par['ny'], par['nx']) y = D1op * x.flatten() y = y.reshape(par['nz'], par['ny'], par['nx']) assert_array_almost_equal(y[1:-1], yana[1:-1], decimal=1) # 3d - derivative on 2nd direction D1op = FirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=1, sampling=par['dy'], edge=par['edge'], dtype='float32') assert dottest(D1op, par['nz'] * par['ny'] * par['nx'], par['nz'] * par['ny'] * par['nx'], tol=1e-3) x = np.outer((par['dz'] * np.arange(par['nz']))**2, np.ones( (par['ny'], par['nx']))).reshape(par['nz'], par['ny'], par['nx']) yana = np.zeros((par['nz'], par['ny'], par['nx'])) y = D1op * x.flatten() y = y.reshape(par['nz'], par['ny'], par['nx']) assert_array_almost_equal(y[1:-1], yana[1:-1], decimal=1) # 3d - derivative on 3rd direction D1op = FirstDerivative(par['nz'] * par['ny'] * par['nx'], dims=(par['nz'], par['ny'], par['nx']), dir=2, sampling=par['dx'], edge=par['edge'], dtype='float32') assert dottest(D1op, par['nz'] * par['ny'] * par['nx'], par['nz'] * par['ny'] * par['nx'], tol=1e-3) yana = np.zeros((par['nz'], par['ny'], par['nx'])) y = D1op * x.flatten() y = y.reshape(par['nz'], par['ny'], par['nx']) assert_array_almost_equal(y[1:-1], yana[1:-1], decimal=1)
def Gradient(dims, sampling=1, edge=False, dtype='float64', kind='centered'): r"""Gradient. Apply gradient operator to a multi-dimensional array (at least 2 dimensions are required). Parameters ---------- dims : :obj:`tuple` Number of samples for each dimension. sampling : :obj:`tuple`, optional Sampling steps for each direction. edge : :obj:`bool`, optional Use reduced order derivative at edges (``True``) or ignore them (``False``). dtype : :obj:`str`, optional Type of elements in input array. kind : :obj:`str`, optional Derivative kind (``forward``, ``centered``, or ``backward``). Returns ------- l2op : :obj:`pylops.LinearOperator` Gradient linear operator Notes ----- The Gradient operator applies a first-order derivative to each dimension of a multi-dimensional array in forward mode. For simplicity, given a three dimensional array, the Gradient in forward mode using a centered stencil can be expressed as: .. math:: \mathbf{g}_{i, j, k} = (f_{i+1, j, k} - f_{i-1, j, k}) / d_1 \mathbf{i_1} + (f_{i, j+1, k} - f_{i, j-1, k}) / d_2 \mathbf{i_2} + (f_{i, j, k+1} - f_{i, j, k-1}) / d_3 \mathbf{i_3} which is discretized as follows: .. math:: \mathbf{g} = \begin{bmatrix} \mathbf{df_1} \\ \mathbf{df_2} \\ \mathbf{df_3} \end{bmatrix} In adjoint mode, the adjoints of the first derivatives along different axes are instead summed together. """ ndims = len(dims) if isinstance(sampling, (int, float)): sampling = [sampling] * ndims gop = VStack([FirstDerivative(np.prod(dims), dims=dims, dir=idir, sampling=sampling[idir], edge=edge, kind=kind, dtype=dtype) for idir in range(ndims)]) return gop
def test_FirstDerivative_centered(par): """Dot-test and forward for FirstDerivative operator (centered stencil)""" # 1d D1op = FirstDerivative(par["nx"], sampling=par["dx"], edge=par["edge"], dtype="float32") assert dottest(D1op, par["nx"], par["nx"], tol=1e-3) x = (par["dx"] * np.arange(par["nx"]))**2 yana = 2 * par["dx"] * np.arange(par["nx"]) y = D1op * x assert_array_almost_equal(y[1:-1], yana[1:-1], decimal=1) # 2d - derivative on 1st direction D1op = FirstDerivative( par["ny"] * par["nx"], dims=(par["ny"], par["nx"]), dir=0, sampling=par["dy"], edge=par["edge"], dtype="float32", ) assert dottest(D1op, par["ny"] * par["nx"], par["ny"] * par["nx"], tol=1e-3) x = np.outer((par["dy"] * np.arange(par["ny"]))**2, np.ones(par["nx"])) yana = np.outer(2 * par["dy"] * np.arange(par["ny"]), np.ones(par["nx"])) y = D1op * x.ravel() y = y.reshape(par["ny"], par["nx"]) assert_array_almost_equal(y[1:-1], yana[1:-1], decimal=1) # 2d - derivative on 2nd direction D1op = FirstDerivative( par["ny"] * par["nx"], dims=(par["ny"], par["nx"]), dir=1, sampling=par["dx"], edge=par["edge"], dtype="float32", ) assert dottest(D1op, par["ny"] * par["nx"], par["ny"] * par["nx"], tol=1e-3) x = np.outer((par["dy"] * np.arange(par["ny"]))**2, np.ones(par["nx"])) yana = np.zeros((par["ny"], par["nx"])) y = D1op * x.ravel() y = y.reshape(par["ny"], par["nx"]) assert_array_almost_equal(y[1:-1], yana[1:-1], decimal=1) # 3d - derivative on 1st direction D1op = FirstDerivative( par["nz"] * par["ny"] * par["nx"], dims=(par["nz"], par["ny"], par["nx"]), dir=0, sampling=par["dz"], edge=par["edge"], dtype="float32", ) assert dottest( D1op, par["nz"] * par["ny"] * par["nx"], par["nz"] * par["ny"] * par["nx"], tol=1e-3, ) x = np.outer((par["dz"] * np.arange(par["nz"]))**2, np.ones( (par["ny"], par["nx"]))).reshape(par["nz"], par["ny"], par["nx"]) yana = np.outer(2 * par["dz"] * np.arange(par["nz"]), np.ones((par["ny"], par["nx"]))).reshape(par["nz"], par["ny"], par["nx"]) y = D1op * x.ravel() y = y.reshape(par["nz"], par["ny"], par["nx"]) assert_array_almost_equal(y[1:-1], yana[1:-1], decimal=1) # 3d - derivative on 2nd direction D1op = FirstDerivative( par["nz"] * par["ny"] * par["nx"], dims=(par["nz"], par["ny"], par["nx"]), dir=1, sampling=par["dy"], edge=par["edge"], dtype="float32", ) assert dottest( D1op, par["nz"] * par["ny"] * par["nx"], par["nz"] * par["ny"] * par["nx"], tol=1e-3, ) x = np.outer((par["dz"] * np.arange(par["nz"]))**2, np.ones( (par["ny"], par["nx"]))).reshape(par["nz"], par["ny"], par["nx"]) yana = np.zeros((par["nz"], par["ny"], par["nx"])) y = D1op * x.ravel() y = y.reshape(par["nz"], par["ny"], par["nx"]) assert_array_almost_equal(y[1:-1], yana[1:-1], decimal=1) # 3d - derivative on 3rd direction D1op = FirstDerivative( par["nz"] * par["ny"] * par["nx"], dims=(par["nz"], par["ny"], par["nx"]), dir=2, sampling=par["dx"], edge=par["edge"], dtype="float32", ) assert dottest( D1op, par["nz"] * par["ny"] * par["nx"], par["nz"] * par["ny"] * par["nx"], tol=1e-3, ) yana = np.zeros((par["nz"], par["ny"], par["nx"])) y = D1op * x.ravel() y = y.reshape(par["nz"], par["ny"], par["nx"]) assert_array_almost_equal(y[1:-1], yana[1:-1], decimal=1)
def test_FirstDerivative_forwaback(par): """Dot-test for FirstDerivative operator (forward and backward stencils). Note that the analytical expression cannot be validated in this case """ for kind in ("forward", "backward"): # 1d D1op = FirstDerivative(par["nx"], sampling=par["dx"], edge=par["edge"], kind=kind, dtype="float32") assert dottest(D1op, par["nx"], par["nx"], tol=1e-3) # 2d - derivative on 1st direction D1op = FirstDerivative( par["ny"] * par["nx"], dims=(par["ny"], par["nx"]), dir=0, sampling=par["dy"], edge=par["edge"], kind=kind, dtype="float32", ) assert dottest(D1op, par["ny"] * par["nx"], par["ny"] * par["nx"], tol=1e-3) # 2d - derivative on 2nd direction D1op = FirstDerivative( par["ny"] * par["nx"], dims=(par["ny"], par["nx"]), dir=1, sampling=par["dx"], edge=par["edge"], kind=kind, dtype="float32", ) assert dottest(D1op, par["ny"] * par["nx"], par["ny"] * par["nx"], tol=1e-3) # 3d - derivative on 1st direction D1op = FirstDerivative( par["nz"] * par["ny"] * par["nx"], dims=(par["nz"], par["ny"], par["nx"]), dir=0, sampling=par["dz"], edge=par["edge"], kind=kind, dtype="float32", ) assert dottest( D1op, par["nz"] * par["ny"] * par["nx"], par["nz"] * par["ny"] * par["nx"], tol=1e-3, ) # 3d - derivative on 2nd direction D1op = FirstDerivative( par["nz"] * par["ny"] * par["nx"], dims=(par["nz"], par["ny"], par["nx"]), dir=1, sampling=par["dy"], edge=par["edge"], kind=kind, dtype="float32", ) assert dottest( D1op, par["nz"] * par["ny"] * par["nx"], par["nz"] * par["ny"] * par["nx"], tol=1e-3, ) # 3d - derivative on 3rd direction D1op = FirstDerivative( par["nz"] * par["ny"] * par["nx"], dims=(par["nz"], par["ny"], par["nx"]), dir=2, sampling=par["dx"], edge=par["edge"], kind=kind, dtype="float32", ) assert dottest( D1op, par["nz"] * par["ny"] * par["nx"], par["nz"] * par["ny"] * par["nx"], tol=1e-3, )