Files

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