def test_gradientJ(shape, kernel, space_order): """ This test ensure that the Jacobian computed with devito satisfies the Taylor expansion property: .. math:: F(m0 + h dm) = F(m0) + \O(h) \\ F(m0 + h dm) = F(m0) + J dm + \O(h^2) \\ with F the Forward modelling operator. :param dimensions: size of the domain in all dimensions in number of grid points :param time_order: order of the time discretization scheme :param space_order: order of the spacial discretization scheme :return: assertion that the Taylor properties are satisfied """ spacing = tuple(15. for _ in shape) wave = setup(shape=shape, spacing=spacing, dtype=np.float64, kernel=kernel, space_order=space_order, tn=1000., nbpml=10 + space_order / 2) m0 = smooth10(wave.model.m.data, wave.model.shape_domain) dm = np.float64(wave.model.m.data - m0) linrec = Receiver(name='rec', grid=wave.model.grid, ntime=wave.receiver.nt, coordinates=wave.receiver.coordinates.data) # Compute receiver data and full wavefield for the smooth velocity rec, u0, _ = wave.forward(m=m0, save=False) # Gradient: J dm Jdm, _, _, _ = wave.born(dm, rec=linrec, m=m0) # FWI Gradient test H = [0.5, 0.25, .125, 0.0625, 0.0312, 0.015625, 0.0078125] error1 = np.zeros(7) error2 = np.zeros(7) for i in range(0, 7): # Add the perturbation to the model mloc = m0 + H[i] * dm # Data for the new model d = wave.forward(m=mloc)[0] # First order error F(m0 + hdm) - F(m0) error1[i] = np.linalg.norm(d.data - rec.data, 1) # Second order term F(m0 + hdm) - F(m0) - J dm error2[i] = np.linalg.norm(d.data - rec.data - H[i] * Jdm.data, 1) # Test slope of the tests p1 = np.polyfit(np.log10(H), np.log10(error1), 1) p2 = np.polyfit(np.log10(H), np.log10(error2), 1) info('1st order error, Phi(m0+dm)-Phi(m0) with slope: %s compared to 1' % (p1[0])) info( '2nd order error, Phi(m0+dm)-Phi(m0) - <J(m0)^T \delta d, dm>with slope:' ' %s comapred to 2' % (p2[0])) assert np.isclose(p1[0], 1.0, rtol=0.1) assert np.isclose(p2[0], 2.0, rtol=0.1)
def test_gradientJ(dimensions, time_order, space_order): """ This test ensure that the Jacobian computed with devito satisfies the Taylor expansion property: .. math:: F(m0 + h dm) = F(m0) + \O(h) \\ F(m0 + h dm) = F(m0) + J dm + \O(h^2) \\ with F the Forward modelling operator. :param dimensions: size of the domain in all dimensions in number of grid points :param time_order: order of the time discretization scheme :param space_order: order of the spacial discretization scheme :return: assertion that the Taylor properties are satisfied """ wave = setup(dimensions=dimensions, time_order=time_order, space_order=space_order, tn=1000., nbpml=10+space_order/2) m0 = smooth10(wave.model.m.data, wave.model.shape_domain) dm = np.float32(wave.model.m.data - m0) linrec = Receiver(name='rec', ntime=wave.receiver.nt, coordinates=wave.receiver.coordinates.data) # Compute receiver data and full wavefield for the smooth velocity rec, u0, _ = wave.forward(m=m0, save=False) # Gradient: J dm Jdm, _, _, _ = wave.born(dm, rec=linrec, m=m0) # FWI Gradient test H = [0.5, 0.25, .125, 0.0625, 0.0312, 0.015625, 0.0078125] error1 = np.zeros(7) error2 = np.zeros(7) for i in range(0, 7): # Add the perturbation to the model mloc = m0 + H[i] * dm # Data for the new model d = wave.forward(m=mloc)[0] # First order error F(m0 + hdm) - F(m0) error1[i] = np.linalg.norm(d.data - rec.data, 1) # Second order term F(m0 + hdm) - F(m0) - J dm error2[i] = np.linalg.norm(d.data - rec.data - H[i] * Jdm.data, 1) # print(F0, .5*linalg.norm(d - rec)**2, error1[i], H[i] *G, error2[i]) # print('For h = ', H[i], '\nFirst order errors is : ', error1[i], # '\nSecond order errors is ', error2[i]) hh = np.zeros(7) for i in range(0, 7): hh[i] = H[i] * H[i] # Test slope of the tests p1 = np.polyfit(np.log10(H), np.log10(error1), 1) p2 = np.polyfit(np.log10(H), np.log10(error2), 1) print(p1) print(p2) assert np.isclose(p1[0], 1.0, rtol=0.1) assert np.isclose(p2[0], 2.0, rtol=0.1)
def test_gradient_checkpointing(self, shape, kernel, space_order): """ This test ensures that the FWI gradient computed with devito satisfies the Taylor expansion property: .. math:: \Phi(m0 + h dm) = \Phi(m0) + \O(h) \\ \Phi(m0 + h dm) = \Phi(m0) + h \nabla \Phi(m0) + \O(h^2) \\ \Phi(m0) = .5* || F(m0 + h dm) - D ||_2^2 where .. math:: \nabla \Phi(m0) = <J^T \delta d, dm> \\ \delta d = F(m0+ h dm) - D \\ with F the Forward modelling operator. :param dimensions: size of the domain in all dimensions in number of grid points :param time_order: order of the time discretization scheme :param space_order: order of the spacial discretization scheme :return: assertion that the Taylor properties are satisfied """ spacing = tuple(10. for _ in shape) wave = setup(shape=shape, spacing=spacing, dtype=np.float64, kernel=kernel, space_order=space_order, nbpml=40) m0 = Function(name='m0', grid=wave.model.m.grid, space_order=space_order) m0.data[:] = smooth10(wave.model.m.data, wave.model.m.shape_domain) # Compute receiver data for the true velocity rec, u, _ = wave.forward() # Compute receiver data and full wavefield for the smooth velocity rec0, u0, _ = wave.forward(m=m0, save=True) # Gradient: <J^T \delta d, dm> residual = Receiver(name='rec', grid=wave.model.grid, data=rec0.data - rec.data, time_range=rec.time_range, coordinates=rec0.coordinates.data) gradient, _ = wave.gradient(residual, u0, m=m0, checkpointing=True) gradient2, _ = wave.gradient(residual, u0, m=m0, checkpointing=False) assert np.allclose(gradient.data, gradient2.data)
def test_gradientFWI(self, shape, kernel, space_order, checkpointing): """ This test ensures that the FWI gradient computed with devito satisfies the Taylor expansion property: .. math:: \Phi(m0 + h dm) = \Phi(m0) + \O(h) \\ \Phi(m0 + h dm) = \Phi(m0) + h \nabla \Phi(m0) + \O(h^2) \\ \Phi(m0) = .5* || F(m0 + h dm) - D ||_2^2 where .. math:: \nabla \Phi(m0) = <J^T \delta d, dm> \\ \delta d = F(m0+ h dm) - D \\ with F the Forward modelling operator. :param dimensions: size of the domain in all dimensions in number of grid points :param time_order: order of the time discretization scheme :param space_order: order of the spacial discretization scheme :return: assertion that the Taylor properties are satisfied """ spacing = tuple(10. for _ in shape) wave = setup(shape=shape, spacing=spacing, dtype=np.float64, kernel=kernel, space_order=space_order, nbpml=40) m0 = Function(name='m0', grid=wave.model.m.grid, space_order=space_order) m0.data[:] = smooth10(wave.model.m.data, wave.model.m.shape_domain) dm = np.float32(wave.model.m.data - m0.data) # Compute receiver data for the true velocity rec, u, _ = wave.forward() # Compute receiver data and full wavefield for the smooth velocity rec0, u0, _ = wave.forward(m=m0, save=True) # Objective function value F0 = .5 * linalg.norm(rec0.data - rec.data)**2 # Gradient: <J^T \delta d, dm> residual = Receiver(name='rec', grid=wave.model.grid, data=rec0.data - rec.data, time_range=rec.time_range, coordinates=rec0.coordinates.data) gradient, _ = wave.gradient(residual, u0, m=m0, checkpointing=checkpointing) G = np.dot(gradient.data.reshape(-1), dm.reshape(-1)) # FWI Gradient test H = [0.5, 0.25, .125, 0.0625, 0.0312, 0.015625, 0.0078125] error1 = np.zeros(7) error2 = np.zeros(7) for i in range(0, 7): # Add the perturbation to the model def initializer(data): data[:] = m0.data + H[i] * dm mloc = Function(name='mloc', grid=wave.model.m.grid, space_order=space_order, initializer=initializer) # Data for the new model d = wave.forward(m=mloc)[0] # First order error Phi(m0+dm) - Phi(m0) error1[i] = np.absolute(.5 * linalg.norm(d.data - rec.data)**2 - F0) # Second order term r Phi(m0+dm) - Phi(m0) - <J(m0)^T \delta d, dm> error2[i] = np.absolute(.5 * linalg.norm(d.data - rec.data)**2 - F0 - H[i] * G) # Test slope of the tests p1 = np.polyfit(np.log10(H), np.log10(error1), 1) p2 = np.polyfit(np.log10(H), np.log10(error2), 1) info('1st order error, Phi(m0+dm)-Phi(m0): %s' % (p1)) info('2nd order error, Phi(m0+dm)-Phi(m0) - <J(m0)^T \delta d, dm>: %s' % (p2)) assert np.isclose(p1[0], 1.0, rtol=0.1) assert np.isclose(p2[0], 2.0, rtol=0.1)
def test_gradientFWI(dimensions, time_order, space_order): """ This test ensure that the FWI gradient computed with devito satisfies the Taylor expansion property: .. math:: \Phi(m0 + h dm) = \Phi(m0) + \O(h) \\ \Phi(m0 + h dm) = \Phi(m0) + h \nabla \Phi(m0) + \O(h^2) \\ \Phi(m0) = .5* || F(m0 + h dm) - D ||_2^2 where .. math:: \nabla \Phi(m0) = <J^T \delta d, dm> \\ \delta d = F(m0+ h dm) - D \\ with F the Forward modelling operator. :param dimensions: size of the domain in all dimensions in number of grid points :param time_order: order of the time discretization scheme :param space_order: order of the spacial discretization scheme :return: assertion that the Taylor properties are satisfied """ wave = setup(dimensions=dimensions, time_order=time_order, space_order=space_order, nbpml=10+space_order/2) m0 = smooth10(wave.model.m.data, wave.model.shape_domain) dm = np.float32(wave.model.m.data - m0) # Compute receiver data for the true velocity rec, u, _ = wave.forward() # Compute receiver data and full wavefield for the smooth velocity rec0, u0, _ = wave.forward(m=m0, save=True) # Objective function value F0 = .5*linalg.norm(rec0.data - rec.data)**2 # Gradient: <J^T \delta d, dm> residual = Receiver(name='rec', data=rec0.data - rec.data, coordinates=rec0.coordinates.data) gradient, _ = wave.gradient(residual, u0, m=m0) G = np.dot(gradient.data.reshape(-1), dm.reshape(-1)) # FWI Gradient test H = [0.5, 0.25, .125, 0.0625, 0.0312, 0.015625, 0.0078125] error1 = np.zeros(7) error2 = np.zeros(7) for i in range(0, 7): # Add the perturbation to the model mloc = m0 + H[i] * dm # Data for the new model d = wave.forward(m=mloc)[0] # First order error Phi(m0+dm) - Phi(m0) error1[i] = np.absolute(.5*linalg.norm(d.data - rec.data)**2 - F0) # Second order term r Phi(m0+dm) - Phi(m0) - <J(m0)^T \delta d, dm> error2[i] = np.absolute(.5*linalg.norm(d.data - rec.data)**2 - F0 - H[i] * G) # print(F0, .5*linalg.norm(d - rec)**2, error1[i], H[i] *G, error2[i]) # print('For h = ', H[i], '\nFirst order errors is : ', error1[i], # '\nSecond order errors is ', error2[i]) hh = np.zeros(7) for i in range(0, 7): hh[i] = H[i] * H[i] # Test slope of the tests p1 = np.polyfit(np.log10(H), np.log10(error1), 1) p2 = np.polyfit(np.log10(H), np.log10(error2), 1) print(p1) print(p2) assert np.isclose(p1[0], 1.0, rtol=0.1) assert np.isclose(p2[0], 2.0, rtol=0.1)