mirror of
https://github.com/wassname/simpeg.git
synced 2026-06-28 11:37:51 +08:00
577 lines
14 KiB
Python
577 lines
14 KiB
Python
from SimPEG import *
|
|
import BaseGrav as GRAV
|
|
import re
|
|
|
|
|
|
class GravityIntegral(Problem.BaseProblem):
|
|
|
|
# surveyPair = Survey.LinearSurvey
|
|
forwardOnly = False #: Determine if the forward matrix is stored (defaut:yes)
|
|
actInd = None #: Active cell indices provided
|
|
rtype = 'z'
|
|
|
|
def __init__(self, mesh, mapping=None, **kwargs):
|
|
Problem.BaseProblem.__init__(self, mesh, mapping=mapping, **kwargs)
|
|
|
|
def fwr_op(self):
|
|
# Add forward function
|
|
# kappa = self.curModel.kappa TODO
|
|
rho = self.mapping*self.curModel
|
|
|
|
if self.forwardOnly:
|
|
|
|
if getattr(self, 'actInd', None) is not None:
|
|
|
|
if self.actInd.dtype=='bool':
|
|
inds = np.asarray([inds for inds, elem in enumerate(self.actInd, 1) if elem], dtype = int) - 1
|
|
else:
|
|
inds = self.actInd
|
|
|
|
else:
|
|
|
|
inds = np.asarray(range(self.mesh.nC))
|
|
|
|
nC = len(inds)
|
|
|
|
# Create active cell projector
|
|
P = sp.csr_matrix(
|
|
(np.ones(nC), (inds, range(nC))),
|
|
shape=(self.mesh.nC, nC)
|
|
)
|
|
|
|
# Create vectors of nodal location (lower and upper corners for each cell)
|
|
xn = self.mesh.vectorNx
|
|
yn = self.mesh.vectorNy
|
|
zn = self.mesh.vectorNz
|
|
|
|
yn2, xn2, zn2 = np.meshgrid(yn[1:], xn[1:], zn[1:])
|
|
yn1, xn1, zn1 = np.meshgrid(yn[0:-1], xn[0:-1], zn[0:-1])
|
|
|
|
Yn = P.T*np.c_[mkvc(yn1), mkvc(yn2)]
|
|
Xn = P.T*np.c_[mkvc(xn1), mkvc(xn2)]
|
|
Zn = P.T*np.c_[mkvc(zn1), mkvc(zn2)]
|
|
|
|
rxLoc = self.survey.srcField.rxList[0].locs
|
|
ndata = rxLoc.shape[0]
|
|
|
|
|
|
# Pre-allocate space and create magnetization matrix if required
|
|
# Pre-allocate space
|
|
if self.rtype == 'z':
|
|
|
|
fwr_d = np.zeros(self.survey.nRx)
|
|
|
|
elif self.rtype == 'xyz':
|
|
|
|
fwr_d = np.zeros(3*self.survey.nRx)
|
|
|
|
else:
|
|
|
|
print """Flag must be either 'z' | 'xyz', please revised"""
|
|
return
|
|
|
|
|
|
# Add counter to dsiplay progress. Good for large problems
|
|
count = -1;
|
|
for ii in range(ndata):
|
|
|
|
|
|
tx, ty, tz = get_T_mat(Xn, Yn, Zn, rxLoc[ii, :])
|
|
|
|
|
|
if self.rtype =='z':
|
|
fwr_d[ii] =tz.dot(rho)
|
|
|
|
elif self.rtype =='xyz':
|
|
fwr_d[ii] = tx.dot(rho)
|
|
fwr_d[ii+ndata] = ty.dot(rho)
|
|
fwr_d[ii+2*ndata] = tz.dot(rho)
|
|
|
|
|
|
# Display progress
|
|
count = progress(ii,count,ndata)
|
|
|
|
print "Done 100% ...forward operator completed!!\n"
|
|
|
|
return fwr_d
|
|
|
|
else:
|
|
return self.G.dot(rho)
|
|
|
|
def fields(self, m):
|
|
self.curModel = m
|
|
|
|
fields = self.fwr_op()
|
|
|
|
return fields
|
|
|
|
# return self.G.dot(self.mapping*(m))
|
|
|
|
def Jvec(self, m, v, f=None):
|
|
dmudm = self.mapping.deriv(m)
|
|
return self.G.dot(dmudm*v)
|
|
|
|
def Jtvec(self, m, v, f=None):
|
|
dmudm = self.mapping.deriv(m)
|
|
return dmudm.T * (self.G.T.dot(v))
|
|
|
|
@property
|
|
def G(self):
|
|
if not self.ispaired:
|
|
raise Exception('Need to pair!')
|
|
|
|
if getattr(self, '_G', None) is None:
|
|
self._G = self.Intrgl_Fwr_Op( 'z' )
|
|
|
|
return self._G
|
|
|
|
def Intrgl_Fwr_Op(self, flag):
|
|
|
|
"""
|
|
|
|
Gravity forward operator in integral form
|
|
|
|
flag = 'z' | 'xyz'
|
|
|
|
Return
|
|
_G = Linear forward modeling operation
|
|
|
|
Created on March, 15th 2016
|
|
|
|
@author: dominiquef
|
|
|
|
"""
|
|
# Find non-zero cells
|
|
# inds = np.nonzero(actv)[0]
|
|
if getattr(self, 'actInd', None) is not None:
|
|
|
|
if self.actInd.dtype=='bool':
|
|
inds = np.asarray([inds for inds, elem in enumerate(self.actInd, 1) if elem], dtype = int) - 1
|
|
else:
|
|
inds = self.actInd
|
|
|
|
else:
|
|
|
|
inds = np.asarray(range(self.mesh.nC))
|
|
|
|
nC = len(inds)
|
|
|
|
# Create active cell projector
|
|
P = sp.csr_matrix(
|
|
(np.ones(nC), (inds, range(nC))),
|
|
shape=(self.mesh.nC, nC)
|
|
)
|
|
|
|
# Create vectors of nodal location (lower and upper corners for each cell)
|
|
xn = self.mesh.vectorNx
|
|
yn = self.mesh.vectorNy
|
|
zn = self.mesh.vectorNz
|
|
|
|
yn2, xn2, zn2 = np.meshgrid(yn[1:], xn[1:], zn[1:])
|
|
yn1, xn1, zn1 = np.meshgrid(yn[0:-1], xn[0:-1], zn[0:-1])
|
|
|
|
Yn = P.T*np.c_[mkvc(yn1), mkvc(yn2)]
|
|
Xn = P.T*np.c_[mkvc(xn1), mkvc(xn2)]
|
|
Zn = P.T*np.c_[mkvc(zn1), mkvc(zn2)]
|
|
|
|
rxLoc = self.survey.srcField.rxList[0].locs
|
|
ndata = rxLoc.shape[0]
|
|
|
|
# Pre-allocate space and create magnetization matrix if required
|
|
# Pre-allocate space
|
|
if flag == 'z':
|
|
|
|
G = np.zeros((ndata, nC))
|
|
|
|
elif flag == 'xyz':
|
|
|
|
G = np.zeros((int(3*ndata), nC))
|
|
|
|
else:
|
|
|
|
print """Flag must be either 'z' | 'xyz', please revised"""
|
|
return
|
|
|
|
|
|
# Loop through all observations and create forward operator (ndata-by-nC)
|
|
print "Begin calculation of forward operator: " + flag
|
|
|
|
# Add counter to dsiplay progress. Good for large problems
|
|
count = -1;
|
|
for ii in range(ndata):
|
|
|
|
if flag=='z':
|
|
tt = get_T_mat(Xn, Yn, Zn, rxLoc[ii, :])
|
|
G[ii, :] = tt
|
|
|
|
elif flag == 'xyz':
|
|
print "Sorry 3-component not implemented yet"
|
|
|
|
# Display progress
|
|
count = progress(ii, count, ndata)
|
|
|
|
print "Done 100% ...forward operator completed!!\n"
|
|
|
|
return G
|
|
|
|
|
|
def get_T_mat(Xn, Yn, Zn, rxLoc):
|
|
"""
|
|
Load in the active nodes of a tensor mesh and computes the gravity tensor
|
|
for a given observation location rxLoc[obsx, obsy, obsz]
|
|
|
|
INPUT:
|
|
Xn, Yn, Zn: Node location matrix for the lower and upper most corners of
|
|
all cells in the mesh shape[nC,2]
|
|
M
|
|
OUTPUT:
|
|
Tx = [Txx Txy Txz]
|
|
Ty = [Tyx Tyy Tyz]
|
|
Tz = [Tzx Tzy Tzz]
|
|
|
|
where each elements have dimension 1-by-nC.
|
|
Only the upper half 5 elements have to be computed since symetric.
|
|
Currently done as for-loops but will eventually be changed to vector
|
|
indexing, once the topography has been figured out.
|
|
|
|
"""
|
|
NewtG=6.6738e-3
|
|
eps = 1e-10 # add a small value to the locations to avoid /0
|
|
|
|
nC = Xn.shape[0]
|
|
|
|
# Pre-allocate space for 1D array
|
|
tx = np.zeros((1,nC))
|
|
ty = np.zeros((1,nC))
|
|
tz = np.zeros((1,nC))
|
|
|
|
dz = rxLoc[2] - Zn + eps
|
|
|
|
dy = Yn - rxLoc[1] + eps
|
|
|
|
dx = Xn - rxLoc[0] + eps
|
|
|
|
# Compute contribution from each corners
|
|
for aa in range(2):
|
|
for bb in range(2):
|
|
for cc in range(2):
|
|
|
|
r = (
|
|
dx[:, aa] ** 2 +
|
|
dy[:, bb] ** 2 +
|
|
dz[:, cc] ** 2
|
|
) ** (0.50)
|
|
|
|
tx = tx - NewtG * (-1) ** aa * (-1) ** bb * (-1) ** cc * (
|
|
dy[:, bb] * np.log(dz[:, cc] + r) +
|
|
dz[:, cc] * np.log(dy[:, bb] + r) -
|
|
dx[:, aa] * np.arctan(dy[:, bb] * dz[:, cc] / (dx[:, aa] * r)))
|
|
|
|
ty = ty - NewtG * (-1) ** aa * (-1) ** bb * (-1) ** cc * (
|
|
dx[:, aa] * np.log(dz[:, cc] + r) +
|
|
dz[:, cc] * np.log(dx[:, aa] + r) -
|
|
dy[:, bb] * np.arctan(dx[:, aa] * dz[:, cc] / (dy[:, bb] * r)))
|
|
|
|
tz = tz - NewtG * (-1) ** aa * (-1) ** bb * (-1) ** cc * (
|
|
dx[:, aa] * np.log(dy[:, bb] + r) +
|
|
dy[:, bb] * np.log(dx[:, aa] + r) -
|
|
dz[:, cc] * np.arctan(dx[:, aa] * dy[:, bb] / (dz[:, cc] * r)))
|
|
|
|
return tx,ty,tz
|
|
|
|
|
|
def progress(iter, prog, final):
|
|
"""
|
|
progress(iter,prog,final)
|
|
|
|
Function measuring the progress of a process and print to screen the %.
|
|
Useful to estimate the remaining runtime of a large problem.
|
|
|
|
Created on Dec, 20th 2015
|
|
|
|
@author: dominiquef
|
|
"""
|
|
arg = np.floor(float(iter)/float(final)*10.)
|
|
|
|
if arg > prog:
|
|
|
|
strg = "Done " + str(arg*10) + " %"
|
|
print strg
|
|
prog = arg
|
|
|
|
return prog
|
|
|
|
|
|
def writeUBCobs(filename, survey, d):
|
|
"""
|
|
writeUBCobs(filename,survey,d)
|
|
|
|
Function writing an observation file in UBC-GRAV3D format.
|
|
|
|
INPUT
|
|
filename : Name of out file including directory
|
|
survey
|
|
flag : dobs | dpred
|
|
|
|
OUTPUT
|
|
Obsfile
|
|
|
|
"""
|
|
|
|
rxLoc = survey.srcField.rxList[0].locs
|
|
|
|
wd = survey.std
|
|
|
|
data = np.c_[rxLoc, d, wd]
|
|
|
|
with file(filename, 'w') as fid:
|
|
fid.write('%i\n' % len(d))
|
|
np.savetxt(fid, data, fmt='%e', delimiter=' ', newline='\n')
|
|
|
|
print "Observation file saved to: " + filename
|
|
|
|
|
|
def getActiveTopo(mesh, topo, flag):
|
|
"""
|
|
getActiveTopo(mesh,topo)
|
|
|
|
Function creates an active cell model from topography
|
|
|
|
INPUT
|
|
mesh : Mesh in SimPEG format
|
|
topo : Scatter points defining topography [x,y,z]
|
|
|
|
OUTPUT
|
|
actv : Active cell model
|
|
|
|
"""
|
|
import scipy.interpolate as interpolation
|
|
|
|
if flag == 'N':
|
|
Zn = np.zeros((mesh.nNx, mesh.nNy))
|
|
# wght = np.zeros((mesh.nNx,mesh.nNy))
|
|
cx = mesh.vectorNx
|
|
cy = mesh.vectorNy
|
|
|
|
F = interpolation.NearestNDInterpolator(topo[:, 0:2], topo[:, 2])
|
|
[Y, X] = np.meshgrid(cy, cx)
|
|
|
|
Zn = F(X, Y)
|
|
|
|
actv = np.zeros((mesh.nCx, mesh.nCy, mesh.nCz))
|
|
|
|
if flag == 'N':
|
|
Nz = mesh.vectorNz[1:]
|
|
|
|
for jj in range(mesh.nCy):
|
|
|
|
for ii in range(mesh.nCx):
|
|
|
|
temp = [kk for kk in range(len(Nz)) if np.all(Zn[ii:(ii+2), jj:(jj+2)] > Nz[kk]) ]
|
|
actv[ii, jj, temp] = 1
|
|
|
|
actv = mkvc(actv == 1)
|
|
|
|
inds = np.asarray([inds for inds, elem in enumerate(actv, 1) if elem], dtype = int) - 1
|
|
|
|
return inds
|
|
|
|
def plot_obs_2D(survey,varstr, fig = None):
|
|
""" Function plot_obs(rxLoc,d,wd)
|
|
Generate a 2d interpolated plot from scatter points of data
|
|
|
|
INPUT
|
|
rxLoc : Observation locations [x,y,z]
|
|
d : Data vector
|
|
wd : Uncertainty vector
|
|
|
|
OUTPUT
|
|
figure()
|
|
|
|
Created on Dec, 27th 2015
|
|
|
|
@author: dominiquef
|
|
|
|
"""
|
|
|
|
from scipy.interpolate import griddata
|
|
import pylab as plt
|
|
|
|
rxLoc = survey.srcField.rxList[0].locs
|
|
d = survey.dobs
|
|
wd = survey.std
|
|
|
|
# Create grid of points
|
|
x = np.linspace(rxLoc[:,0].min(), rxLoc[:,0].max(), 100)
|
|
y = np.linspace(rxLoc[:,1].min(), rxLoc[:,1].max(), 100)
|
|
|
|
X, Y = np.meshgrid(x,y)
|
|
|
|
# Interpolate
|
|
d_grid = griddata(rxLoc[:,0:2],d,(X,Y), method ='linear')
|
|
|
|
# Plot result
|
|
if fig is None:
|
|
fig = plt.figure()
|
|
|
|
ax = plt.subplot()
|
|
plt.imshow(d_grid, extent=[x.min(), x.max(), y.min(), y.max()],origin = 'lower', cmap='plasma')
|
|
plt.colorbar(fraction=0.02)
|
|
plt.contour(X,Y, d_grid,10)
|
|
plt.scatter(rxLoc[:,0],rxLoc[:,1], c=d, s=20)
|
|
plt.title(varstr)
|
|
plt.gca().set_aspect('equal', adjustable='box')
|
|
|
|
def readUBCgravObs(obs_file):
|
|
|
|
"""
|
|
Read UBC grav file format
|
|
|
|
INPUT:
|
|
:param fileName, path to the UBC obs grav file
|
|
|
|
OUTPUT:
|
|
:param survey
|
|
|
|
"""
|
|
|
|
fid = open(obs_file,'r')
|
|
|
|
# First line has the number of rows
|
|
line = fid.readline()
|
|
ndat = np.array(line.split(),dtype=int)
|
|
|
|
# Pre-allocate space for obsx, obsy, obsz, data, uncert
|
|
line = fid.readline()
|
|
temp = np.array(line.split(),dtype=float)
|
|
|
|
d = np.zeros(ndat, dtype=float)
|
|
wd = np.zeros(ndat, dtype=float)
|
|
locXYZ = np.zeros( (ndat,3), dtype=float)
|
|
|
|
for ii in range(ndat):
|
|
|
|
temp = np.array(line.split(),dtype=float)
|
|
locXYZ[ii,:] = temp[:3]
|
|
d[ii] = temp[3]
|
|
wd[ii] = temp[4]
|
|
line = fid.readline()
|
|
|
|
rxLoc = GRAV.RxObs(locXYZ)
|
|
srcField = GRAV.SrcField([rxLoc])
|
|
survey = GRAV.LinearSurvey(srcField)
|
|
survey.dobs = d
|
|
survey.std = wd
|
|
return survey
|
|
|
|
|
|
def read_GRAVinv_inp(input_file):
|
|
"""Read input files for forward modeling MAG data with integral form
|
|
INPUT:
|
|
input_file: File name containing the forward parameter
|
|
|
|
OUTPUT:
|
|
mshfile
|
|
obsfile
|
|
topofile
|
|
start model
|
|
ref model
|
|
weightfile
|
|
chi_target
|
|
as, ax ,ay, az
|
|
upper, lower bounds
|
|
lp, lqx, lqy, lqz
|
|
|
|
# All files should be in the working directory, otherwise the path must
|
|
# be specified.
|
|
|
|
Created on Dec 21th, 2015
|
|
|
|
@author: dominiquef
|
|
"""
|
|
|
|
|
|
fid = open(input_file,'r')
|
|
|
|
# Line 1
|
|
line = fid.readline()
|
|
l_input = line.split('!')
|
|
mshfile = l_input[0].rstrip()
|
|
|
|
# Line 2
|
|
line = fid.readline()
|
|
l_input = line.split('!')
|
|
obsfile = l_input[0].rstrip()
|
|
|
|
# Line 3
|
|
line = fid.readline()
|
|
l_input = re.split('[!\s]',line)
|
|
if l_input=='null':
|
|
topofile = []
|
|
|
|
else:
|
|
topofile = l_input[0].rstrip()
|
|
|
|
|
|
# Line 4
|
|
line = fid.readline()
|
|
l_input = re.split('[!\s]',line)
|
|
if l_input[0]=='VALUE':
|
|
mstart = float(l_input[1])
|
|
|
|
else:
|
|
mstart = l_input[0].rstrip()
|
|
|
|
# Line 5
|
|
line = fid.readline()
|
|
l_input = re.split('[!\s]',line)
|
|
if l_input[0]=='VALUE':
|
|
mref = float(l_input[1])
|
|
|
|
else:
|
|
mref = l_input[0].rstrip()
|
|
|
|
|
|
# Line 7
|
|
line = fid.readline()
|
|
l_input = re.split('[!\s]',line)
|
|
if l_input[0]=='DEFAULT':
|
|
wgtfile = None
|
|
|
|
else:
|
|
wgtfile = l_input[0].rstrip()
|
|
|
|
# Line 8
|
|
line = fid.readline()
|
|
l_input = re.split('[!\s]',line)
|
|
chi = float(l_input[0])
|
|
|
|
# Line 9
|
|
line = fid.readline()
|
|
l_input = re.split('[!\s]',line)
|
|
val = np.array(l_input[0:4])
|
|
alphas = val.astype(np.float)
|
|
|
|
# Line 10
|
|
line = fid.readline()
|
|
l_input = re.split('[!\s]',line)
|
|
if l_input[0]=='VALUE':
|
|
val = np.array(l_input[1:3])
|
|
bounds = val.astype(np.float)
|
|
|
|
else:
|
|
bounds = l_input[0].rstrip()
|
|
|
|
# Line 11
|
|
line = fid.readline()
|
|
l_input = re.split('[!\s]',line)
|
|
if l_input[0]=='VALUE':
|
|
val = np.array(l_input[1:6])
|
|
lpnorms = val.astype(np.float)
|
|
|
|
else:
|
|
lpnorms = l_input[0].rstrip()
|
|
|
|
return mshfile, obsfile, topofile, mstart, mref, wgtfile, chi, alphas, bounds, lpnorms
|
|
|