def gen_kernel(self): self.kernel_matrices = [] if self.cell_type == 'prism': for i in range(self.ns): xp = self.orig_data[self.orig_data['i_survey']==i]['x'].values yp = self.orig_data[self.orig_data['i_survey']==i]['y'].values zp = self.orig_data[self.orig_data['i_survey']==i]['z'].values kernel0 = np.zeros((len(xp),self.ny*self.nx)) for j,cell in enumerate(self.mesh): kernel0[:,j] = prism.gz(xp,yp,zp,[cell]) self.kernel_matrices.append(np.array(kernel0)) elif self.cell_type == 'tesseroid': for i in range(self.ns): xp = self.orig_data[self.orig_data['i_survey']==i]['lon'].values yp = self.orig_data[self.orig_data['i_survey']==i]['lat'].values zp = self.orig_data[self.orig_data['i_survey']==i]['z'].values kernel0 = np.zeros((len(xp),self.ny*self.nx)) for j,cell in enumerate(self.mesh): kernel0[:,j] = tesseroid.gz(xp,yp,zp,[cell]) self.kernel_matrices.append(np.array(kernel0)) else: raise ValueError('cell_type must be \'prism\' or \'tesseroid\'!!') self.kernel_op = AbicLSQOperatorMS(self.kernel_matrices, ns=self.ns, nzyx=(self.nz,self.ny,self.nx), smooth_components=self._smooth_components, weights=self._weights) self._gtg_exist = False
def migrate(x, y, z, gz, zmin, zmax, meshshape, power=0.5, scale=1): """ 3D potential field migration (Zhdanov et al., 2011). Actually uses the formula of Fedi and Pilkington (2012), which are comprehensible. .. note:: Only works on **gravity** data for now. .. note:: The data **do not** need to be leveled or on a regular grid. .. note:: The coordinate system adopted is x->North, y->East, and z->Down Parameters: * x, y : 1D-arrays The x and y coordinates of the grid points * z : float or 1D-array The z coordinate of the grid points * gz : 1D-array The gravity anomaly data at the grid points * zmin, zmax : float The top and bottom, respectively, of the region where the physical property distribution is calculated * meshshape : tuple = (nz, ny, nx) Number of prisms in the output mesh in the x, y, and z directions, respectively * power : float The power law used for the depth weighting. This controls what depth the bulk of the solution will be. * scale : float A scale factor for the depth weights. Simply changes the scale of the physical property values. Returns: * mesh : :class:`geoist.mesher.PrismMesh` The estimated physical property distribution set in a prism mesh (for easy 3D plotting) """ nlayers, ny, nx = meshshape mesh = _makemesh(x, y, (ny, nx), zmin, zmax, nlayers) # This way, if z is not an array, it is now z = z * numpy.ones_like(x) dx, dy, dz = mesh.dims # Synthetic tests show that its not good to offset the weights with the # data z coordinate. No idea why depths = mesh.get_zs()[:-1] + 0.5 * dz weights = numpy.abs(depths)**power / (2 * G * numpy.sqrt(numpy.pi)) density = [] for l in range(nlayers): sensibility_T = numpy.array( [pot_prism.gz(x, y, z, [p], dens=1) for p in mesh.get_layer(l)]) density.extend(scale * weights[l] * numpy.dot(sensibility_T, gz)) mesh.addprop('density', numpy.array(density)) return mesh
def gen_grav(shape = (100, 100)): dx = 6000/8. dy = 6000/8. dz = 1900/8. model = [geometry.Prism(-1000, 1000, -1000, 1000, 100, 2000, {'density': 1000}), geometry.Prism(-4000, -3000, -4000, -3000, 100, 2000, {'density': -900}), geometry.Prism(2000, 4000, 3000, 4000, 100, 2000, {'density': 1300})] prism1 = geometry.Prism(-3000+3*dx, -3000+4*dx, -3000+7*dy, -3000+8*dy, 100+4*dz, 100+5*dz, {'density': 2000}) prism2 = geometry.Prism(-3000+2*dx, -3000+3*dx, -3000+2*dy, -3000+3*dy, 100+4*dz, 100+5*dz, {'density': 2000}) model = [prism1,prism2] nzyx = [8,8,8] source_volume = [-3000, 3000, -3000, 3000, 100, 2000] xp, yp, zp = gridder.regular((-5000, 5000, -5000, 5000), shape, z=0) field0 = prism.gz(xp, yp, zp, model) fieldfreq = pftrans.gzfreq(xp, yp, zp, shape, model) #field1 = giutils.contaminate(field0, 0.05, percent = True) return field0, fieldfreq, xp, yp, zp
def jacobian(self, p): """ Build the Jacobian (sensitivity) matrix. The matrix will contain the length of the path takes by the ray inside each cell of the mesh. Parameters: * p : 1d-array An estimate of the parameter vector or ``None``. Returns: * jac : 2d-array (sparse CSR matrix from ``scipy.sparse``) The Jacobian """ srcs = self.srcs xp, yp, zp = srcs kernel = [] for i, layer in enumerate(self.mesh.layers()): for j, p in enumerate(layer): x1 = self.mesh.get_layer(i)[j].x1 x2 = self.mesh.get_layer(i)[j].x2 y1 = self.mesh.get_layer(i)[j].y1 y2 = self.mesh.get_layer(i)[j].y2 z1 = self.mesh.get_layer(i)[j].z1 z2 = self.mesh.get_layer(i)[j].z2 #den = self.mesh.get_layer(i)[j].props model = [ geometry.Prism(x1, x2, y1, y2, z1, z2, {'density': 1000}) ] field = prism.gz(xp, yp, zp, model) kernel.append(field) #print(self.ndata, self.nparams) print(np.array(kernel).shape) return np.transpose(np.array(kernel))
def gen_grav(shape=(100, 100)): model = [ geometry.Prism(-1000, 1000, -1000, 1000, 100, 2000, {'density': 1000}), geometry.Prism(-4000, -3000, -4000, -3000, 100, 2000, {'density': -900}), geometry.Prism(2000, 4000, 3000, 4000, 100, 2000, {'density': 1300}) ] xp, yp, zp = gridder.regular((-5000, 5000, -5000, 5000), shape, z=0) field0 = prism.gz(xp, yp, zp, model) #prism.potential(xp, yp, zp, model) #field1 = giutils.contaminate(field0, 0.05, percent = True) fieldfreq = gzfreq(xp, yp, zp, shape, model) # fields = [prism.gx(xp, yp, zp, model), # prism.gy(xp, yp, zp, model), # prism.gz(xp, yp, zp, model), # prism.gxx(xp, yp, zp, model), # prism.gxy(xp, yp, zp, model), # prism.gxz(xp, yp, zp, model), # prism.gyy(xp, yp, zp, model), # prism.gyz(xp, yp, zp, model), # prism.gzz(xp, yp, zp, model)] return field0, fieldfreq, xp, yp, zp
from geoist.inversion import geometry from geoist.pfm import prism from geoist.vis import giplt model = [ geometry.Prism(-4000, -3000, -4000, -3000, 0, 2000, {'density': 1000}), geometry.Prism(-1000, 1000, -1000, 1000, 0, 2000, {'density': -900}), geometry.Prism(2000, 4000, 3000, 4000, 0, 2000, {'density': 1300}) ] shape = (100, 100) xp, yp, zp = gridder.regular((-5000, 5000, -5000, 5000), shape, z=-150) fields = [ prism.potential(xp, yp, zp, model), prism.gx(xp, yp, zp, model), prism.gy(xp, yp, zp, model), prism.gz(xp, yp, zp, model), prism.gxx(xp, yp, zp, model), prism.gxy(xp, yp, zp, model), prism.gxz(xp, yp, zp, model), prism.gyy(xp, yp, zp, model), prism.gyz(xp, yp, zp, model), prism.gzz(xp, yp, zp, model) ] titles = [ 'potential', 'gx', 'gy', 'gz', 'gxx', 'gxy', 'gxz', 'gyy', 'gyz', 'gzz' ] plt.figure(figsize=(8, 9)) plt.subplots_adjust(left=0.03, right=0.95, bottom=0.05, top=0.92, hspace=0.3) plt.suptitle("Potential fields produced by a 3 prism model") for i, field in enumerate(fields): plt.subplot(4, 3, i + 3)
kernel=[] narea = (-28750, 28750,-48750, 48750) #NS, EW nshape = (30, 40) #NS, EW depthz = [] xp, yp, zp = gridder.regular(narea, nshape, z=-1) for i, layer in enumerate(mesh.layers()): for j, p in enumerate(layer): x1 = mesh.get_layer(i)[j].x1 x2 = mesh.get_layer(i)[j].x2 y1 = mesh.get_layer(i)[j].y1 y2 = mesh.get_layer(i)[j].y2 z1 = mesh.get_layer(i)[j].z1 z2 = mesh.get_layer(i)[j].z2 den = mesh.get_layer(i)[j].props model=[geometry.Prism(x1, x2, y1, y2, z1, z2, {'density': 1000.})] field = prism.gz(xp, yp, zp, model) kernel.append(field) depthz.append((z1+z2)/2.0) kk=np.array(kernel) kk=np.transpose(kernel) #kernel matrix for inversion, 500 cells * 400 points field0=np.mat(kk)*np.transpose(np.mat(density.ravel())) field = giutils.contaminate(np.array(field0).ravel(), 0.05, percent = True) #零均值 print(field.mean()) #field = field + 300. # field.mean() #画图 plt.figure(figsize=(16, 8)) plt.subplot(1, 2, 1)
""" GravMag: Calculating the derivatives of the gravity anomaly using FFT """ import matplotlib.pyplot as plt from geoist import gridder from geoist.inversion import geometry from geoist.pfm import prism, pftrans, giutils from geoist.vis import giplt model = [geometry.Prism(-1000, 1000, -1000, 1000, 0, 2000, {'density': 100})] area = (-5000, 5000, -5000, 5000) shape = (51, 51) z0 = -500 xp, yp, zp = gridder.regular(area, shape, z=z0) gz = giutils.contaminate(prism.gz(xp, yp, zp, model), 0.001) # Need to convert gz to SI units so that the result can be converted to Eotvos gxz = giutils.si2eotvos(pftrans.derivx(xp, yp, giutils.mgal2si(gz), shape)) gyz = giutils.si2eotvos(pftrans.derivy(xp, yp, giutils.mgal2si(gz), shape)) gzz = giutils.si2eotvos(pftrans.derivz(xp, yp, giutils.mgal2si(gz), shape)) gxz_true = prism.gxz(xp, yp, zp, model) gyz_true = prism.gyz(xp, yp, zp, model) gzz_true = prism.gzz(xp, yp, zp, model) plt.figure() plt.title("Original gravity anomaly") plt.axis('scaled') giplt.contourf(xp, yp, gz, shape, 15) plt.colorbar(shrink=0.7) giplt.m2km()
def calc_kernel(i): return prism.gz(self.xp[0:1], self.yp[0:1], self.zp[0:1], [self.mesh[i]])
print('rhs recover misfit: ', np.linalg.norm(rhs - small_model.rhs) / np.linalg.norm(small_model.rhs)) # 方程右端项的检查。 # save density model to vtk, comment out this section if gridToVTK not installed. # nz,ny,nx = nzyx # arr = small_model.solution.real.copy() # xs = np.zeros((nz+1,ny+1,nx+1)) + np.array(small_model.mesh.get_xs()).reshape(1,1,-1) # ys = np.zeros((nz+1,ny+1,nx+1)) + np.array(small_model.mesh.get_ys()).reshape(1,-1,1) # zs = np.zeros((nz+1,ny+1,nx+1)) + np.array(small_model.mesh.get_zs()).reshape(-1,1,1) # gridToVTK(str(work_dir/"results"),xs,ys,zs,cellData={"recover":arr.reshape(nz,ny,nx), # "orig":model_density}) # field0 = prism.gz(small_model.xp, small_model.yp, small_model.zp, small_model.mesh) shape = (nobsyx[0], nobsyx[1]) # plot field fig = plt.figure(figsize=(16, 8)) # original field axes = fig.subplots(2, 2) # plt.axis('scaled') ca = axes[0][0] plt.sca(ca) levels = giplt.contourf(small_model.yp * 0.001, small_model.xp * 0.001, field0, shape, 15) cb = plt.colorbar() giplt.contour(small_model.yp * 0.001, small_model.xp * 0.001, field0,
# local imports from geoist import gridder from geoist.inversion import geometry from geoist.pfm import prism, pftrans, giutils from geoist.vis import giplt model = [ geometry.Prism(-3000, -2000, -3000, -2000, 500, 2000, {'density': 1000}), geometry.Prism(-1000, 1000, -1000, 1000, 0, 2000, {'density': -800}), geometry.Prism(1000, 3000, 2000, 3000, 0, 1000, {'density': 900}) ] area = (-5000, 5000, -5000, 5000) shape = (50, 50) z0 = -100 x, y, z = gridder.regular(area, shape, z=z0) gz = giutils.contaminate(prism.gz(x, y, z, model), 0.5, seed=0) height = 1000 # How much higher to go gzcontf = pftrans.upcontinue(x, y, gz, shape, height) # Compute the true value at the new height for comparison gztrue = prism.gz(x, y, z - height, model) args = dict(shape=shape, levels=20, cmap=plt.cm.RdBu_r) fig, axes = plt.subplots(1, 3, figsize=(12, 3.5)) axes = axes.ravel() plt.sca(axes[0]) plt.title("Original") plt.axis('scaled') giplt.contourf(x, y, gz, **args) plt.colorbar(pad=0).set_label('mGal')