mirror of
https://github.com/wassname/simpeg.git
synced 2026-06-28 20:56:57 +08:00
495 lines
12 KiB
Python
495 lines
12 KiB
Python
from SimPEG import Maps, Survey, Utils, np, sp
|
|
from scipy.constants import mu_0
|
|
import re
|
|
|
|
class BaseMagSurvey(Survey.BaseSurvey):
|
|
"""Base Magnetics Survey"""
|
|
|
|
rxLoc = None #: receiver locations
|
|
rxType = None #: receiver type
|
|
|
|
def __init__(self, **kwargs):
|
|
Survey.BaseSurvey.__init__(self, **kwargs)
|
|
|
|
|
|
def setBackgroundField(self, Inc, Dec, Btot):
|
|
|
|
Bx = Btot*np.cos(Inc/180.*np.pi)*np.sin(Dec/180.*np.pi)
|
|
By = Btot*np.cos(Inc/180.*np.pi)*np.cos(Dec/180.*np.pi)
|
|
Bz = -Btot*np.sin(Inc/180.*np.pi)
|
|
|
|
self.B0 = np.r_[Bx,By,Bz]
|
|
|
|
@property
|
|
def Qfx(self):
|
|
if getattr(self, '_Qfx', None) is None:
|
|
self._Qfx = self.prob.mesh.getInterpolationMat(self.rxLoc,'Fx')
|
|
return self._Qfx
|
|
|
|
@property
|
|
def Qfy(self):
|
|
if getattr(self, '_Qfy', None) is None:
|
|
self._Qfy = self.prob.mesh.getInterpolationMat(self.rxLoc,'Fy')
|
|
return self._Qfy
|
|
|
|
@property
|
|
def Qfz(self):
|
|
if getattr(self, '_Qfz', None) is None:
|
|
self._Qfz = self.prob.mesh.getInterpolationMat(self.rxLoc,'Fz')
|
|
return self._Qfz
|
|
|
|
def projectFields(self, u):
|
|
"""
|
|
This function projects the fields onto the data space.
|
|
|
|
Especially, here for we use total magnetic intensity (TMI) data,
|
|
which is common in practice.
|
|
|
|
First we project our B on to data location
|
|
|
|
.. math::
|
|
|
|
\mathbf{B}_{rec} = \mathbf{P} \mathbf{B}
|
|
|
|
then we take the dot product between B and b_0
|
|
|
|
.. math ::
|
|
|
|
\\text{TMI} = \\vec{B}_s \cdot \hat{B}_0
|
|
|
|
"""
|
|
#TODO: There can be some different tyes of data like |B| or B
|
|
|
|
bfx = self.Qfx*u['B']
|
|
bfy = self.Qfy*u['B']
|
|
bfz = self.Qfz*u['B']
|
|
|
|
# Generate unit vector
|
|
B0 = self.prob.survey.B0
|
|
Bot = np.sqrt(B0[0]**2+B0[1]**2+B0[2]**2)
|
|
box = B0[0]/Bot
|
|
boy = B0[1]/Bot
|
|
boz = B0[2]/Bot
|
|
|
|
# return bfx*box + bfx*boy + bfx*boz
|
|
return bfx*box + bfy*boy + bfz*boz
|
|
|
|
|
|
@Utils.count
|
|
def projectFieldsDeriv(self, B):
|
|
"""
|
|
This function projects the fields onto the data space.
|
|
|
|
.. math::
|
|
|
|
\\frac{\partial d_\\text{pred}}{\partial \mathbf{B}} = \mathbf{P}
|
|
|
|
Especially, this function is for TMI data type
|
|
|
|
"""
|
|
# Generate unit vector
|
|
B0 = self.prob.survey.B0
|
|
Bot = np.sqrt(B0[0]**2+B0[1]**2+B0[2]**2)
|
|
box = B0[0]/Bot
|
|
boy = B0[1]/Bot
|
|
boz = B0[2]/Bot
|
|
|
|
return self.Qfx*box+self.Qfy*boy+self.Qfz*boz
|
|
|
|
|
|
def projectFieldsAsVector(self, B):
|
|
|
|
bfx = self.Qfx*B
|
|
bfy = self.Qfy*B
|
|
bfz = self.Qfz*B
|
|
|
|
return np.r_[bfx, bfy, bfz]
|
|
|
|
class MagSurveyBx(object):
|
|
"""docstring for MagSurveyBx"""
|
|
def __init__(self, **kwargs):
|
|
Survey.BaseData.__init__(self, **kwargs)
|
|
|
|
def projectFields(self, B):
|
|
bfx = self.Qfx*B
|
|
return bfx
|
|
|
|
|
|
class BaseMagMap(Maps.IdentityMap):
|
|
"""BaseMagMap"""
|
|
|
|
def __init__(self, mesh, **kwargs):
|
|
Maps.IdentityMap.__init__(self, mesh)
|
|
|
|
def _transform(self, m):
|
|
|
|
return mu_0*(1 + m)
|
|
|
|
def deriv(self, m):
|
|
|
|
return mu_0*sp.identity(self.nP)
|
|
|
|
class WeightMap(Maps.IdentityMap):
|
|
"""Weighted Map for distributed parameters"""
|
|
|
|
def __init__(self, nP, weight, **kwargs):
|
|
Maps.IdentityMap.__init__(self, nP)
|
|
self.mesh = None
|
|
self.weight = weight
|
|
|
|
def _transform(self, m):
|
|
return m*self.weight
|
|
|
|
def deriv(self, m):
|
|
return Utils.sdiag(self.weight)
|
|
|
|
|
|
|
|
|
|
def readUBCmagObs(obs_file):
|
|
|
|
"""
|
|
Read and write UBC mag file format
|
|
|
|
INPUT:
|
|
:param fileName, path to the UBC obs mag file
|
|
|
|
OUTPUT:
|
|
:param dobs, observation in (x y z [data] [wd])
|
|
:param B, primary field information (BI, BD, B0)
|
|
:param M, magnetization orentiaton (MI, MD)
|
|
|
|
"""
|
|
|
|
fid = open(obs_file,'r')
|
|
|
|
# First line has the inclination,declination and amplitude of B0
|
|
line = fid.readline()
|
|
B = np.array(line.split(),dtype=float)
|
|
|
|
# Second line has the magnetization orientation and a flag
|
|
line = fid.readline()
|
|
M = np.array(line.split(),dtype=float)
|
|
|
|
# Third 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)
|
|
|
|
dobs = np.zeros((ndat,len(temp)), dtype=float)
|
|
|
|
|
|
for ii in range(ndat):
|
|
|
|
dobs[ii,:] = np.array(line.split(),dtype=float)
|
|
line = fid.readline()
|
|
|
|
return B, M, dobs
|
|
|
|
def read_MAGfwr_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
|
|
modfile
|
|
magfile
|
|
topofile
|
|
# All files should be in the working directory, otherwise the path must
|
|
# be specified.
|
|
|
|
Created on Jul 17, 2013
|
|
|
|
@author: dominiquef
|
|
"""
|
|
|
|
|
|
fid = open(input_file,'r')
|
|
|
|
line = fid.readline()
|
|
l_input = line.split('!')
|
|
mshfile = l_input[0].rstrip()
|
|
|
|
line = fid.readline()
|
|
l_input = line.split('!')
|
|
obsfile = l_input[0].rstrip()
|
|
|
|
line = fid.readline()
|
|
l_input = line.split('!')
|
|
modfile = l_input[0].rstrip()
|
|
|
|
line = fid.readline()
|
|
l_input = line.split('!')
|
|
if l_input=='null':
|
|
magfile = []
|
|
|
|
else:
|
|
magfile = l_input[0].rstrip()
|
|
|
|
|
|
line = fid.readline()
|
|
l_input = line.split('!')
|
|
if l_input=='null':
|
|
topofile = []
|
|
|
|
else:
|
|
topofile = l_input[0].rstrip()
|
|
|
|
return mshfile, obsfile, modfile, magfile, topofile
|
|
|
|
def read_MAGinv_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
|
|
mag 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 6
|
|
line = fid.readline()
|
|
l_input = re.split('[!\s]',line)
|
|
if l_input=='DEFAULT':
|
|
magfile = []
|
|
|
|
else:
|
|
magfile = l_input[0].rstrip()
|
|
|
|
# Line 7
|
|
line = fid.readline()
|
|
l_input = re.split('[!\s]',line)
|
|
if l_input=='DEFAULT':
|
|
wgtfile = []
|
|
|
|
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, magfile, wgtfile, chi, alphas, bounds, lpnorms
|
|
|
|
def read_GOCAD_ts(tsfile):
|
|
"""Read GOCAD triangulated surface (*.ts) file
|
|
INPUT:
|
|
tsfile: Triangulated surface
|
|
|
|
OUTPUT:
|
|
vrts : Array of vertices in XYZ coordinates [n x 3]
|
|
trgl : Array of index for triangles [m x 3]. The order of the vertices
|
|
is important and describes the normal
|
|
n = cross( (P2 - P1 ) , (P3 - P1) )
|
|
|
|
|
|
Created on Jan 13th, 2016
|
|
|
|
Author: @fourndo
|
|
"""
|
|
|
|
|
|
fid = open(tsfile,'r')
|
|
line = fid.readline()
|
|
|
|
# Skip all the lines until the vertices
|
|
while re.match('TFACE',line)==None:
|
|
line = fid.readline()
|
|
|
|
line = fid.readline()
|
|
vrtx = []
|
|
|
|
# Run down all the vertices and save in array
|
|
while re.match('VRTX',line):
|
|
l_input = re.split('[\s*]',line)
|
|
temp = np.array(l_input[2:5])
|
|
vrtx.append(temp.astype(np.float))
|
|
|
|
# Read next line
|
|
line = fid.readline()
|
|
|
|
vrtx = np.asarray(vrtx)
|
|
|
|
# Skip lines to the triangles
|
|
while re.match('TRGL',line)==None:
|
|
line = fid.readline()
|
|
|
|
# Run down the list of triangles
|
|
trgl = []
|
|
|
|
# Run down all the vertices and save in array
|
|
while re.match('TRGL',line):
|
|
l_input = re.split('[\s*]',line)
|
|
temp = np.array(l_input[1:4])
|
|
trgl.append(temp.astype(np.int))
|
|
|
|
# Read next line
|
|
line = fid.readline()
|
|
|
|
trgl = np.asarray(trgl)
|
|
|
|
return vrtx, trgl
|
|
|
|
def gocad2vtk(gcFile,mesh,bcflag,inflag):
|
|
""""
|
|
Function to read gocad polystructure file and output indexes of mesh with in the structure.
|
|
|
|
"""
|
|
import vtk, vtk.util.numpy_support as npsup
|
|
|
|
print "Reading GOCAD ts file..."
|
|
vrtx, trgl = read_GOCAD_ts(gcFile)
|
|
# Adjust the index
|
|
trgl = trgl - 1
|
|
|
|
# Make vtk pts
|
|
ptsvtk = vtk.vtkPoints()
|
|
ptsvtk.SetData(npsup.numpy_to_vtk(vrtx,deep=1))
|
|
|
|
# Make the polygon connection
|
|
polys = vtk.vtkCellArray()
|
|
for face in trgl:
|
|
poly = vtk.vtkPolygon()
|
|
poly.GetPointIds().SetNumberOfIds(len(face))
|
|
for nrv, vert in enumerate(face):
|
|
poly.GetPointIds().SetId(nrv,vert)
|
|
polys.InsertNextCell(poly)
|
|
|
|
# Make the polydata, structure of connections and vrtx
|
|
polyData = vtk.vtkPolyData()
|
|
polyData.SetPoints(ptsvtk)
|
|
polyData.SetPolys(polys)
|
|
|
|
# Make implicit func
|
|
ImpDistFunc = vtk.vtkImplicitPolyDataDistance()
|
|
ImpDistFunc.SetInput(polyData)
|
|
|
|
# Convert the mesh
|
|
vtkMesh = vtk.vtkRectilinearGrid()
|
|
vtkMesh.SetDimensions(mesh.nNx,mesh.nNy,mesh.nNz)
|
|
vtkMesh.SetXCoordinates(npsup.numpy_to_vtk(mesh.vectorNx,deep=1))
|
|
vtkMesh.SetYCoordinates(npsup.numpy_to_vtk(mesh.vectorNy,deep=1))
|
|
vtkMesh.SetZCoordinates(npsup.numpy_to_vtk(mesh.vectorNz,deep=1))
|
|
# Add indexes
|
|
vtkInd = npsup.numpy_to_vtk(np.arange(mesh.nC),deep=1)
|
|
vtkInd.SetName('Index')
|
|
vtkMesh.GetCellData().AddArray(vtkInd)
|
|
|
|
extractImpDistRectGridFilt = vtk.vtkExtractGeometry() # Object constructor
|
|
extractImpDistRectGridFilt.SetImplicitFunction(ImpDistFunc) #
|
|
extractImpDistRectGridFilt.SetInputData(vtkMesh)
|
|
|
|
if bcflag is True:
|
|
extractImpDistRectGridFilt.ExtractBoundaryCellsOn()
|
|
|
|
else:
|
|
extractImpDistRectGridFilt.ExtractBoundaryCellsOff()
|
|
|
|
if inflag is True:
|
|
extractImpDistRectGridFilt.ExtractInsideOn()
|
|
|
|
else:
|
|
extractImpDistRectGridFilt.ExtractInsideOff()
|
|
|
|
print "Extracting indices from grid..."
|
|
# Executing the pipe
|
|
extractImpDistRectGridFilt.Update()
|
|
|
|
# Get index inside
|
|
insideGrid = extractImpDistRectGridFilt.GetOutput()
|
|
insideGrid = npsup.vtk_to_numpy(insideGrid.GetCellData().GetArray('Index'))
|
|
|
|
|
|
# Return the indexes inside
|
|
return insideGrid |