美文网首页
17_Geoist三维重力反演_4

17_Geoist三维重力反演_4

作者: 地学小哥 | 来源:发表于2020-04-25 23:43 被阅读0次

内容摘要:书接上文,说了半天还没有开始写一个完整的反演例子。这次我们以一个最简单的例子,来讨论一下如何通过反演得到一个三维密度结构。

1、问题定义

我们从一个最简单的最小构造模型入手。下式中右端第二项是正则部分(mnorm),第一项为观测数据部分(dnorm)。

\phi =||Gm-d||^2 + \lambda ||m||^2

上式中\lambda为正则化因子,可以通过L-Curve算法找到一个最佳值,平衡mnorm和dnorm之间的关系。G为核函数,在反演之前可以得到,d是重力异常,m是要反演获得的密度结构。

问题简单来说:已知G,d,求m,优化\lambda,最小化\phi

2、程序实现

这样一个最简单的反演如何实现呢?核心代码如下所示:

print('starting inversion')
from geoist.inversion.regularization import Damping
from geoist.inversion.hyper_param import LCurve
from geoist.pfm import inv3d
datamisfit = inv3d.Density3D(np.array(field.T).ravel(), [xp, yp, zp], mesh)
regul = Damping(datamisfit.nparams)
regul_params = [10**i for i in range(-10, 5, 1)]
density3d = LCurve(datamisfit, regul, regul_params)
_ = density3d.fit()
print(density3d.regul_param_)
density3d.plot_lcurve()

上面代码重点看Density3D这个类,创建后实例对象为datamisfit,这部分可以理解为dnorm,Damping是一个生成最小构造正则项的类,实例化后的对象为regul。然后,指定一个要搜索的正则参数列表regul_params,最后,调用LCurve类,生成一个density3d对象。

运行density3d对象的fit接口,开始反演。LCurve支持多线程,当模型较大的时候可以多线程运行,njobs参数对应开的线程数量。

density3d = LCurve(datamisfit, regul, regul_params, njobs=4)

本例子最佳的\lambda值为0.01,曲线如图1所示。

图1 LCurve曲线

\lambda=0.01反演得到的结果,导出后,用Meshtools3D画图如下:

图2 反演模型
真实模型如图3所示。
图3 真实模型

如果要显示一下残差和反演异常,代码如下:

predicted = density3d[0].predicted()
residuals = density3d[0].residuals()

如图4所示,这个理想的无噪声异常,残差很小了(图4右)。


图4 模型正演结果和残差

一句话总结:今天简单介绍了一下最简单情况下的重力正则化反演,没有深度加权,光滑等更复杂的正则项。别急,后面我们一点点深入讨论。

附完整代码:

import matplotlib.pyplot as plt
import numpy as np
from geoist import gridder
from geoist.inversion import geometry
from geoist.pfm import prism
from geoist.inversion.mesh import PrismMesh
from geoist.vis import giplt
meshfile = r"d:\msh.txt"
densfile = r"d:\den.txt"
area = (-20000, 20000, -40000, 40000, 4000, 32000) #ny nx nz
shape = (10, 20, 5) #nz nx ny
mesh = PrismMesh(area, shape)
density=np.zeros(shape)
density[3:8,9:12,1:4]=1.0 # z x y
mesh.addprop('density', density.ravel())
mesh.dump(meshfile, densfile, 'density') #输出网格到磁盘,MeshTools3D可视化
#生成核矩阵
kernel=[] 
narea = (-28750, 28750,-48750, 48750)
nshape = (30, 40)
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)       
kk=np.array(kernel)        
kk=np.transpose(kernel)  #kernel matrix for inversion, 500 cells * 400 points
field=np.mat(kk)*np.transpose(np.mat(density.ravel()))
#画图
plt.figure()
plt.title('gz')
plt.axis('scaled')
levels = giplt.contourf(yp * 0.001, xp * 0.001, field, nshape, 15)
cb = plt.colorbar()
giplt.contour(yp * 0.001, xp * 0.001, field, nshape,
                levels, clabel=False, linewidth=0.1)
plt.show()
###反演
print('starting inversion')
from geoist.inversion.regularization import Damping
from geoist.inversion.hyper_param import LCurve
from geoist.pfm import inv3d
datamisfit = inv3d.Density3D(np.array(field.T).ravel(), [xp, yp, zp], mesh)
regul = Damping(datamisfit.nparams)
regul_params = [10**i for i in range(-10, 5, 1)]
density3d = LCurve(datamisfit, regul, regul_params)
_ = density3d.fit()
print(density3d.regul_param_)
density3d.plot_lcurve()

predicted = density3d[0].predicted()
residuals = density3d[0].residuals()
plt.figure(figsize=(16, 8))
plt.subplot(1, 2, 1)
plt.axis('scaled')
plt.title('inversed gravity anomlay (mGal)')
levels = giplt.contourf(yp * 0.001, xp * 0.001, predicted, nshape, 15)
cb = plt.colorbar(orientation='horizontal')
giplt.contour(yp * 0.001, xp * 0.001, predicted, nshape,
                levels, clabel=False, linewidth=0.1)

plt.subplot(1, 2, 2)
plt.axis('scaled')
plt.title('residual (mGal)')
levels = giplt.contourf(yp * 0.001, xp * 0.001, residuals, nshape, 15)
cb = plt.colorbar(orientation='horizontal')
giplt.contour(yp * 0.001, xp * 0.001, residuals, nshape,
                levels, clabel=False, linewidth=0.1)

print('res mean={:.4f}; std={:.4f}'.format(residuals.mean(), residuals.std()))

densinv = r"d:\deninv.txt"
values = np.fromiter(density3d.estimate_, dtype=np.float)
reordered = np.ravel(np.reshape(values, mesh.shape), order='F')
np.savetxt(densinv, 1000.*reordered, fmt='%.8f')    

normfile = r"d:\norms.txt"
with open(normfile, 'w') as f:
    for i in range(len(density3d.dnorm)):
        f.write('{} {} {}\n'.format(density3d.mnorm[i], density3d.dnorm[i]
                                    ,regul_params[i]))

相关文章

  • 17_Geoist三维重力反演_4

    内容摘要:书接上文,说了半天还没有开始写一个完整的反演例子。这次我们以一个最简单的例子,来讨论一下如何通过反演得到...

  • 番外篇3_Geoist之欧拉反褶积

    内容摘要:用在勘探重力学领域和位场研究中广泛采用的反演和解释方法,即位场数据的三维欧拉反褶积方法,来研究重力场变化...

  • 18_Geoist三维重力反演_5

    内容摘要:书接上文,我们实现了一个最简单的重力反演程序构建。Geoist的反演框架不但适合于重磁位场反演,也可以作...

  • 14_Geoist三维重力反演_1

    内容摘要:重力位场正反演技术在地球物理资料解释和研究中,具有重要的应用与研究价值。但相关地球物理研究中常用的工具软...

  • 20_Geoist三维重力反演_7

    内容摘要:书接上文,在实际的反演问题中,观测的重力异常都是包含噪声污染的。这种含噪声的数据会不会影响反演结果呢?还...

  • 21_Geoist三维重力反演_8

    内容摘要:书接上文,今天是最后一讲,小哥准备和大家再讨论一下上下界约束的反演方法。因为,在反演开始之前,我们对目标...

  • 15_Geoist三维重力反演_2

    内容摘要:书接上文,了解了反演的目的意义后,我们开始重力反演的第一个例子,并介绍Geoist中inv3d接口的使用...

  • 16_Geoist三维重力反演_3

    内容摘要:书接上文,Geoist本身这套程序因为没有GUI界面,全部的操作都要代码实现,这样做的优点是可以了解更多...

  • 19_Geoist三维重力反演_6

    内容摘要:书接上文,我们还是回到重力反演这个问题上来。通过正则项获得一个反演结果后,细心的朋友会发现还有一些问题,...

  • FM2:30-6三维对称性

    三维中的对称性总计七类,230种。 三斜 三个初基矢,长度不同,夹角不同,没有转动和反射对称,但是有反演对称 三角...

网友评论

      本文标题:17_Geoist三维重力反演_4

      本文链接:https://www.haomeiwen.com/subject/utbjuhtx.html