mirror of
https://github.com/wassname/simpeg.git
synced 2026-09-13 13:03:14 +08:00
Compare commits
126
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21d817d9a2 | ||
|
|
f20fcb4504 | ||
|
|
0179631fe3 | ||
|
|
c4c97ae054 | ||
|
|
e8bd78f63d | ||
|
|
8803956d83 | ||
|
|
c488dabf9a | ||
|
|
69ec374415 | ||
|
|
224105364d | ||
|
|
a7f89131b4 | ||
|
|
6e12bdc57a | ||
|
|
354e57f24e | ||
|
|
ddb11096c8 | ||
|
|
fa6033c438 | ||
|
|
bd63e67161 | ||
|
|
d350dc258d | ||
|
|
350818d802 | ||
|
|
4df6f340d3 | ||
|
|
9b2eec0ea3 | ||
|
|
ace9cad016 | ||
|
|
38aef03f9d | ||
|
|
ef602eaab1 | ||
|
|
0610289fdf | ||
|
|
d14cd444ac | ||
|
|
92e2fd67de | ||
|
|
6a064c5f96 | ||
|
|
f944f9b76b | ||
|
|
dcd4fbf973 | ||
|
|
edc2c5feb6 | ||
|
|
1936a04683 | ||
|
|
fcc2b8b22a | ||
|
|
eeee594f09 | ||
|
|
a48224ed8b | ||
|
|
0bb001973c | ||
|
|
0e16645b67 | ||
|
|
8cac166fba | ||
|
|
73001abfc5 | ||
|
|
a9362bd38e | ||
|
|
64b94861a0 | ||
|
|
8775364d8f | ||
|
|
5ec6e79a39 | ||
|
|
2c09be9fc1 | ||
|
|
cd5339322e | ||
|
|
28005dde45 | ||
|
|
8739ba0f20 | ||
|
|
119bc801c7 | ||
|
|
35bac38c8b | ||
|
|
05e3b02b3a | ||
|
|
bd318f0092 | ||
|
|
2a351be971 | ||
|
|
3e4f47711c | ||
|
|
e305600de5 | ||
|
|
d13c540be0 | ||
|
|
822f6d333d | ||
|
|
6000034826 | ||
|
|
16c6cc8d74 | ||
|
|
636d178fbf | ||
|
|
0575490f56 | ||
|
|
ae9ca6cec9 | ||
|
|
f799733a9d | ||
|
|
2bd5829b42 | ||
|
|
8b94cd4dfe | ||
|
|
09f3f7b55b | ||
|
|
15d59a5b50 | ||
|
|
e646211e7d | ||
|
|
ba977206ea | ||
|
|
fb1ff4e867 | ||
|
|
a31319b46e | ||
|
|
d8aec96080 | ||
|
|
aad596a8cc | ||
|
|
8d6bd65923 | ||
|
|
df620b42bd | ||
|
|
31d418bed8 | ||
|
|
7a6f4e0780 | ||
|
|
2ee158e5d7 | ||
|
|
8f73b2e7be | ||
|
|
16d62a6d0a | ||
|
|
5d9d746932 | ||
|
|
df3d32cb35 | ||
|
|
b531c162a2 | ||
|
|
c7883673bf | ||
|
|
9c220ef37c | ||
|
|
b6438688d8 | ||
|
|
824ce64c7e | ||
|
|
7aa5599211 | ||
|
|
fbec011983 | ||
|
|
5fb8cdb88c | ||
|
|
b765699d2f | ||
|
|
fdc081970e | ||
|
|
f92ff1301d | ||
|
|
d302a59b2c | ||
|
|
ef467efce0 | ||
|
|
d226186c8e | ||
|
|
38b4079f0b | ||
|
|
9d4e2488f3 | ||
|
|
838035adae | ||
|
|
ef4513bcd4 | ||
|
|
4fefccc97d | ||
|
|
1946e1f69e | ||
|
|
33c9059e4e | ||
|
|
d9b3c038c4 | ||
|
|
2f8b8a36bf | ||
|
|
5e5c7ba0fb | ||
|
|
6c33455d15 | ||
|
|
7000699e38 | ||
|
|
63bf8b9e4d | ||
|
|
e3af1fd94e | ||
|
|
4e871a43a9 | ||
|
|
b5f4d8e999 | ||
|
|
e4a3e0a16d | ||
|
|
1c2fecf3a2 | ||
|
|
c10777a245 | ||
|
|
05a85018de | ||
|
|
8aa23c31de | ||
|
|
a9c9ce6bc8 | ||
|
|
6286e48830 | ||
|
|
4cf5d49524 | ||
|
|
88ef74ac38 | ||
|
|
3a506b9051 | ||
|
|
fa6bcd3ffa | ||
|
|
47895ef270 | ||
|
|
429d8b1191 | ||
|
|
774d612c18 | ||
|
|
433457f649 | ||
|
|
3eeb5dbd3c | ||
|
|
df78f7b33a |
@@ -25,6 +25,10 @@ SimPEG
|
||||
:target: https://coveralls.io/r/simpeg/simpeg?branch=master
|
||||
:alt: Coverage status
|
||||
|
||||
.. image:: http://img.shields.io/badge/GITTER-JOIN_CHAT-brightgreen.svg?style=flat-square
|
||||
:alt: gitter chat room at https://gitter.im/simpeg/simpeg
|
||||
:target: https://gitter.im/simpeg/simpeg
|
||||
|
||||
Simulation and Parameter Estimation in Geophysics - A python package for simulation and gradient based parameter estimation in the context of geophysical applications.
|
||||
|
||||
The vision is to create a package for finite volume simulation with applications to geophysical imaging and subsurface flow. To enable the understanding of the many different components, this package has the following features:
|
||||
|
||||
+163
-57
@@ -169,7 +169,7 @@ def readUBC_DC2DModel(fileName):
|
||||
|
||||
return model
|
||||
|
||||
def plot_pseudoSection(DCsurvey, axs, stype):
|
||||
def plot_pseudoSection(DCsurvey, axs, stype='dpdp', dtype="appc", clim=None):
|
||||
"""
|
||||
Read list of 2D tx-rx location and plot a speudo-section of apparent
|
||||
resistivity.
|
||||
@@ -179,7 +179,7 @@ def plot_pseudoSection(DCsurvey, axs, stype):
|
||||
Input:
|
||||
:param d2D, z0
|
||||
:switch stype -> Either 'pdp' (pole-dipole) | 'dpdp' (dipole-dipole)
|
||||
|
||||
:switch dtype=-> Either 'appr' (app. res) | 'appc' (app. con) | 'volt' (potential)
|
||||
Output:
|
||||
:figure scatter plot overlayed on image
|
||||
|
||||
@@ -221,20 +221,43 @@ def plot_pseudoSection(DCsurvey, axs, stype):
|
||||
Cmid = (Tx[0][0] + Tx[1][0])/2
|
||||
Pmid = (Rx[0][:,0] + Rx[1][:,0])/2
|
||||
|
||||
# Compute pant leg of apparent rho
|
||||
if stype == 'pdp':
|
||||
leg = data * 2*np.pi * MA * ( MA + MN ) / MN
|
||||
# Change output for dtype
|
||||
if dtype == 'volt':
|
||||
|
||||
leg = np.log10(abs(1/leg))
|
||||
rho = np.hstack([rho,data])
|
||||
|
||||
elif stype == 'dpdp':
|
||||
leg = data * 2*np.pi / ( 1/MA - 1/MB - 1/NB + 1/NA )
|
||||
else:
|
||||
|
||||
# Compute pant leg of apparent rho
|
||||
if stype == 'pdp':
|
||||
|
||||
leg = data * 2*np.pi * MA * ( MA + MN ) / MN
|
||||
|
||||
elif stype == 'dpdp':
|
||||
|
||||
leg = data * 2*np.pi / ( 1/MA - 1/MB - 1/NB + 1/NA )
|
||||
|
||||
else:
|
||||
print """dtype must be 'pdp'(pole-dipole) | 'dpdp' (dipole-dipole) """
|
||||
break
|
||||
|
||||
|
||||
if dtype == 'appc':
|
||||
|
||||
leg = np.log10(abs(1./leg))
|
||||
rho = np.hstack([rho,leg])
|
||||
|
||||
elif dtype == 'appr':
|
||||
|
||||
leg = np.log10(abs(leg))
|
||||
rho = np.hstack([rho,leg])
|
||||
|
||||
else:
|
||||
print """dtype must be 'appr' | 'appc' | 'volt' """
|
||||
break
|
||||
|
||||
midx = np.hstack([midx, ( Cmid + Pmid )/2 ])
|
||||
midz = np.hstack([midz, -np.abs(Cmid-Pmid)/2 + z0 ])
|
||||
rho = np.hstack([rho,leg])
|
||||
|
||||
midz = np.hstack([midz, -np.abs(Cmid-Pmid)/2 + (Tx[0][2] + Tx[1][2])/2 ])
|
||||
|
||||
ax = axs
|
||||
|
||||
@@ -242,26 +265,38 @@ def plot_pseudoSection(DCsurvey, axs, stype):
|
||||
grid_x, grid_z = np.mgrid[np.min(midx):np.max(midx), np.min(midz):np.max(midz)]
|
||||
grid_rho = griddata(np.c_[midx,midz], rho.T, (grid_x, grid_z), method='linear')
|
||||
|
||||
if clim == None:
|
||||
vmin, vmax = rho.min(), rho.max()
|
||||
else:
|
||||
vmin, vmax = clim[0], clim[1]
|
||||
|
||||
plt.imshow(grid_rho.T, extent = (np.min(midx),np.max(midx),np.min(midz),np.max(midz)), origin='lower', alpha=0.8, vmin = np.min(rho), vmax = np.max(rho))
|
||||
cbar = plt.colorbar(format = '%.2f',fraction=0.04,orientation="horizontal")
|
||||
grid_rho = np.ma.masked_where(np.isnan(grid_rho), grid_rho)
|
||||
ph = plt.pcolormesh(grid_x[:,0],grid_z[0,:],grid_rho.T, clim=(vmin, vmax))
|
||||
cbar = plt.colorbar(format="$10^{%.1f}$",fraction=0.04,orientation="horizontal")
|
||||
|
||||
cmin,cmax = cbar.get_clim()
|
||||
ticks = np.linspace(cmin,cmax,3)
|
||||
cbar.set_ticks(ticks)
|
||||
cbar.ax.tick_params(labelsize=10)
|
||||
|
||||
if dtype == 'appc':
|
||||
cbar.set_label("App.Cond",size=12)
|
||||
elif dtype == 'appr':
|
||||
cbar.set_label("App.Res.",size=12)
|
||||
elif dtype == 'volt':
|
||||
cbar.set_label("Potential (V)",size=12)
|
||||
|
||||
# Plot apparent resistivity
|
||||
plt.scatter(midx,midz,s=50,c=rho.T)
|
||||
ax.scatter(midx,midz,s=10,c=rho.T, vmin =vmin, vmax = vmax, clim=(vmin, vmax))
|
||||
|
||||
ax.set_xticklabels([])
|
||||
#ax.set_xticklabels([])
|
||||
#ax.set_yticklabels([])
|
||||
|
||||
ax.set_ylabel('Z')
|
||||
ax.yaxis.tick_right()
|
||||
ax.yaxis.set_label_position('right')
|
||||
plt.gca().set_aspect('equal', adjustable='box')
|
||||
|
||||
|
||||
return ax
|
||||
|
||||
return ph
|
||||
|
||||
def gen_DCIPsurvey(endl, mesh, stype, a, b, n):
|
||||
"""
|
||||
@@ -361,16 +396,6 @@ def gen_DCIPsurvey(endl, mesh, stype, a, b, n):
|
||||
srcClass = DC.SrcDipole([rxClass], M[ii,:],M[ii,:])
|
||||
SrcList.append(srcClass)
|
||||
|
||||
#==============================================================================
|
||||
# elif re.match(stype,'dpdp'):
|
||||
#
|
||||
# for ii in range(0, int(nstn)-2):
|
||||
#
|
||||
# indx = np.min([ii+n+1,nstn])
|
||||
# Tx.append(np.c_[M[ii,:],N[ii,:]])
|
||||
# Rx.append(np.c_[M[ii+2:indx,:],N[ii+2:indx,:]])
|
||||
#==============================================================================
|
||||
|
||||
elif stype == 'gradient':
|
||||
|
||||
# Gradient survey only requires Tx at end of line and creates a square
|
||||
@@ -513,22 +538,22 @@ def writeUBC_DCobs(fileName, DCsurvey, dtype, stype):
|
||||
|
||||
fid.close()
|
||||
|
||||
def convertObs_DC3D_to_2D(DCsurvey,lineID):
|
||||
def convertObs_DC3D_to_2D(DCsurvey,lineID, flag = 'local'):
|
||||
"""
|
||||
Read DC survey and data and change
|
||||
coordinate system to distance along line assuming
|
||||
all data is acquired along line.
|
||||
First transmitter pole is assumed to be at the origin
|
||||
Read DC survey and projects the coordinate system
|
||||
according to the flag = 'Xloc' | 'Yloc' | 'local' (default)
|
||||
In the 'local' system, station coordinates are referenced
|
||||
to distance from the first srcLoc[0].loc[0]
|
||||
|
||||
Assumes flat topo for now...
|
||||
The Z value is preserved, but Y coordinates zeroed.
|
||||
|
||||
Input:
|
||||
:param Tx, Rx
|
||||
:param survey3D
|
||||
|
||||
Output:
|
||||
:figure Tx2d, Rx2d
|
||||
:figure survey2D
|
||||
|
||||
Edited Feb 17th, 2016
|
||||
Edited April 6th, 2016
|
||||
|
||||
@author: dominiquef
|
||||
|
||||
@@ -570,25 +595,39 @@ def convertObs_DC3D_to_2D(DCsurvey,lineID):
|
||||
Rx = DCsurvey.srcList[indx[ii]].rxList[0].locs
|
||||
nrx = Rx[0].shape[0]
|
||||
|
||||
# Find A electrode along line
|
||||
vec, r = r_unit(x0,Tx[ii][0,0:2])
|
||||
A = stn_id(vecTx,vec,r)
|
||||
if flag == 'local':
|
||||
# Find A electrode along line
|
||||
vec, r = r_unit(x0,Tx[ii][0,0:2])
|
||||
A = stn_id(vecTx,vec,r)
|
||||
|
||||
# Find B electrode along line
|
||||
vec, r = r_unit(x0,Tx[ii][1,0:2])
|
||||
B = stn_id(vecTx,vec,r)
|
||||
# Find B electrode along line
|
||||
vec, r = r_unit(x0,Tx[ii][1,0:2])
|
||||
B = stn_id(vecTx,vec,r)
|
||||
|
||||
M = np.zeros(nrx)
|
||||
N = np.zeros(nrx)
|
||||
for kk in range(nrx):
|
||||
M = np.zeros(nrx)
|
||||
N = np.zeros(nrx)
|
||||
for kk in range(nrx):
|
||||
|
||||
# Find all M electrodes along line
|
||||
vec, r = r_unit(x0,Rx[0][kk,0:2])
|
||||
M[kk] = stn_id(vecTx,vec,r)
|
||||
# Find all M electrodes along line
|
||||
vec, r = r_unit(x0,Rx[0][kk,0:2])
|
||||
M[kk] = stn_id(vecTx,vec,r)
|
||||
|
||||
# Find all N electrodes along line
|
||||
vec, r = r_unit(x0,Rx[1][kk,0:2])
|
||||
N[kk] = stn_id(vecTx,vec,r)
|
||||
# Find all N electrodes along line
|
||||
vec, r = r_unit(x0,Rx[1][kk,0:2])
|
||||
N[kk] = stn_id(vecTx,vec,r)
|
||||
elif flag == 'Yloc':
|
||||
""" Flip the XY axis locs"""
|
||||
A = Tx[ii][0,1]
|
||||
B = Tx[ii][1,1]
|
||||
M = Rx[0][:,1]
|
||||
N = Rx[1][:,1]
|
||||
|
||||
elif flag == 'Xloc':
|
||||
""" Copy the rx-tx locs"""
|
||||
A = Tx[ii][0,0]
|
||||
B = Tx[ii][1,0]
|
||||
M = Rx[0][:,0]
|
||||
N = Rx[1][:,0]
|
||||
|
||||
Rx = DC.RxDipole(np.c_[M,np.zeros(nrx),Rx[0][:,2]],np.c_[N,np.zeros(nrx),Rx[1][:,2]])
|
||||
|
||||
@@ -604,16 +643,16 @@ def convertObs_DC3D_to_2D(DCsurvey,lineID):
|
||||
|
||||
def readUBC_DC3Dobs(fileName):
|
||||
"""
|
||||
Read UBC GIF DCIP 3D observation file and generate arrays for tx-rx location
|
||||
Read UBC GIF DCIP 3D observation file and generate survey
|
||||
|
||||
Input:
|
||||
:param fileName, path to the UBC GIF 3D obs file
|
||||
|
||||
Output:
|
||||
:param rx, tx, d, wd
|
||||
:param DCIPsurvey
|
||||
:return
|
||||
|
||||
Created on Mon December 7th, 2015
|
||||
Created on Mon April 6th, 2015
|
||||
|
||||
@author: dominiquef
|
||||
|
||||
@@ -688,6 +727,7 @@ def readUBC_DC3Dobs(fileName):
|
||||
|
||||
def readUBC_DC2Dobs(fileName):
|
||||
"""
|
||||
------- NEEDS TO BE UPDATED ------
|
||||
Read UBC GIF 2D observation file and generate arrays for tx-rx location
|
||||
|
||||
Input:
|
||||
@@ -735,6 +775,73 @@ def readUBC_DC2Dobs(fileName):
|
||||
|
||||
return tx, rx, d, wd
|
||||
|
||||
def readUBC_DC2Dpre(fileName):
|
||||
"""
|
||||
Read UBC GIF DCIP 2D observation file and generate arrays for tx-rx location
|
||||
|
||||
Input:
|
||||
:param fileName, path to the UBC GIF 3D obs file
|
||||
|
||||
Output:
|
||||
DCsurvey
|
||||
:return
|
||||
|
||||
Created on Mon March 9th, 2016 << Doug's 70th Birthday !! >>
|
||||
|
||||
@author: dominiquef
|
||||
|
||||
"""
|
||||
|
||||
# Load file
|
||||
obsfile = np.genfromtxt(fileName,delimiter=' \n',dtype=np.str,comments='!')
|
||||
|
||||
# Pre-allocate
|
||||
srcLists = []
|
||||
Rx = []
|
||||
d = []
|
||||
zflag = True # Flag for z value provided
|
||||
|
||||
for ii in range(obsfile.shape[0]):
|
||||
|
||||
if not obsfile[ii]:
|
||||
continue
|
||||
|
||||
# First line is transmitter with number of receivers
|
||||
|
||||
|
||||
temp = (np.fromstring(obsfile[ii], dtype=float,sep=' ').T)
|
||||
|
||||
|
||||
# Check if z value is provided, if False -> nan
|
||||
if len(temp)==5:
|
||||
tx = np.r_[temp[0],np.nan,np.nan,temp[1],np.nan,np.nan]
|
||||
zflag = False
|
||||
|
||||
else:
|
||||
tx = np.r_[temp[0],np.nan,temp[1],temp[2],np.nan,temp[3]]
|
||||
|
||||
|
||||
if zflag:
|
||||
rx = np.c_[temp[4],np.nan,temp[5],temp[6],np.nan,temp[7]]
|
||||
|
||||
|
||||
else:
|
||||
rx = np.c_[temp[2],np.nan,np.nan,temp[3],np.nan,np.nan]
|
||||
# Check if there is data with the location
|
||||
|
||||
d.append(temp[-1])
|
||||
|
||||
|
||||
Rx = DC.RxDipole(rx[:,:3],rx[:,3:])
|
||||
srcLists.append( DC.SrcDipole( [Rx], tx[:3],tx[3:]) )
|
||||
|
||||
# Create survey class
|
||||
survey = DC.SurveyDC(srcLists)
|
||||
|
||||
survey.dobs = np.asarray(d)
|
||||
|
||||
return {'DCsurvey':survey}
|
||||
|
||||
def readUBC_DC2DMesh(fileName):
|
||||
"""
|
||||
Read UBC GIF 2DTensor mesh and generate 2D Tensor mesh in simpeg
|
||||
@@ -928,7 +1035,6 @@ def getSrc_locs(DCsurvey):
|
||||
|
||||
srcMat = np.zeros((DCsurvey.nSrc,2,3))
|
||||
for ii in range(DCsurvey.nSrc):
|
||||
print np.asarray(DCsurvey.srcList[ii].loc).shape
|
||||
srcMat[ii,:,:] = np.asarray(DCsurvey.srcList[ii].loc)
|
||||
|
||||
return srcMat
|
||||
|
||||
+125
-35
@@ -216,7 +216,7 @@ class SaveOutputDictEveryIteration(_SaveEveryIteration):
|
||||
# Save the data.
|
||||
ms = self.reg.Ws * ( self.reg.mapping * (self.invProb.curModel - self.reg.mref) )
|
||||
phi_ms = 0.5*ms.dot(ms)
|
||||
if self.reg.smoothModel == True:
|
||||
if self.reg.mrefInSmooth == True:
|
||||
mref = self.reg.mref
|
||||
else:
|
||||
mref = 0
|
||||
@@ -237,40 +237,41 @@ class SaveOutputDictEveryIteration(_SaveEveryIteration):
|
||||
# Save the file as a npz
|
||||
np.savez('{:03d}-{:s}'.format(self.opt.iter,self.fileName), iter=self.opt.iter, beta=self.invProb.beta, phi_d=self.invProb.phi_d, phi_m=self.invProb.phi_m, phi_ms=phi_ms, phi_mx=phi_mx, phi_my=phi_my, phi_mz=phi_mz,f=self.opt.f, m=self.invProb.curModel,dpred=self.invProb.dpred)
|
||||
|
||||
class SaveOutputDictEveryIteration(_SaveEveryIteration):
|
||||
"""SaveOutputDictEveryIteration
|
||||
A directive that saves some relevant information from the inversion run to a numpy .npz dictionary file (see numpy.savez function for further info).
|
||||
"""
|
||||
|
||||
def initialize(self):
|
||||
print "SimPEG.SaveOutputDictEveryIteration will save your inversion progress as dictionary: '%s-###.npz'"%self.fileName
|
||||
|
||||
def endIter(self):
|
||||
# Save the data.
|
||||
ms = self.reg.Ws * ( self.reg.mapping * (self.invProb.curModel - self.reg.mref) )
|
||||
phi_ms = 0.5*ms.dot(ms)
|
||||
if self.reg.smoothModel == True:
|
||||
mref = self.reg.mref
|
||||
else:
|
||||
mref = 0
|
||||
mx = self.reg.Wx * ( self.reg.mapping * (self.invProb.curModel - mref) )
|
||||
phi_mx = 0.5 * mx.dot(mx)
|
||||
if self.prob.mesh.dim==2:
|
||||
my = self.reg.Wy * ( self.reg.mapping * (self.invProb.curModel - mref) )
|
||||
phi_my = 0.5 * my.dot(my)
|
||||
else:
|
||||
phi_my = 'NaN'
|
||||
if self.prob.mesh.dim==3 and 'CYL' not in self.prob.mesh._meshType:
|
||||
mz = self.reg.Wz * ( self.reg.mapping * (self.invProb.curModel - mref) )
|
||||
phi_mz = 0.5 * mz.dot(mz)
|
||||
else:
|
||||
phi_mz = 'NaN'
|
||||
|
||||
|
||||
# Save the file as a npz
|
||||
np.savez('{:s}-{:03d}'.format(self.fileName,self.opt.iter), iter=self.opt.iter, beta=self.invProb.beta, phi_d=self.invProb.phi_d, phi_m=self.invProb.phi_m, phi_ms=phi_ms, phi_mx=phi_mx, phi_my=phi_my, phi_mz=phi_mz,f=self.opt.f, m=self.invProb.curModel,dpred=self.invProb.dpred)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# class SaveOutputDictEveryIteration(_SaveEveryIteration):
|
||||
# """SaveOutputDictEveryIteration
|
||||
# A directive that saves some relevant information from the inversion run to a numpy .npz dictionary file (see numpy.savez function for further info).
|
||||
# """
|
||||
#
|
||||
# def initialize(self):
|
||||
# print "SimPEG.SaveOutputDictEveryIteration will save your inversion progress as dictionary: '%s-###.npz'"%self.fileName
|
||||
#
|
||||
# def endIter(self):
|
||||
# # Save the data.
|
||||
# ms = self.reg.Ws * ( self.reg.mapping * (self.invProb.curModel - self.reg.mref) )
|
||||
# phi_ms = 0.5*ms.dot(ms)
|
||||
# if self.reg.mrefInSmooth == True:
|
||||
# mref = self.reg.mref
|
||||
# else:
|
||||
# mref = 0
|
||||
# mx = self.reg.Wx * ( self.reg.mapping * (self.invProb.curModel - mref) )
|
||||
# phi_mx = 0.5 * mx.dot(mx)
|
||||
# if self.prob.mesh.dim==2:
|
||||
# my = self.reg.Wy * ( self.reg.mapping * (self.invProb.curModel - mref) )
|
||||
# phi_my = 0.5 * my.dot(my)
|
||||
# else:
|
||||
# phi_my = 'NaN'
|
||||
# if self.prob.mesh.dim==3 and 'CYL' not in self.prob.mesh._meshType:
|
||||
# mz = self.reg.Wz * ( self.reg.mapping * (self.invProb.curModel - mref) )
|
||||
# phi_mz = 0.5 * mz.dot(mz)
|
||||
# else:
|
||||
# phi_mz = 'NaN'
|
||||
#
|
||||
#
|
||||
# # Save the file as a npz
|
||||
# np.savez('{:s}-{:03d}'.format(self.fileName,self.opt.iter), iter=self.opt.iter, beta=self.invProb.beta, phi_d=self.invProb.phi_d, phi_m=self.invProb.phi_m, phi_ms=phi_ms, phi_mx=phi_mx, phi_my=phi_my, phi_mz=phi_mz,f=self.opt.f, m=self.invProb.curModel,dpred=self.invProb.dpred)
|
||||
#
|
||||
#==============================================================================
|
||||
|
||||
# class UpdateReferenceModel(Parameter):
|
||||
|
||||
@@ -283,3 +284,92 @@ class SaveOutputDictEveryIteration(_SaveEveryIteration):
|
||||
# mref = self.mref0
|
||||
# self.m_prev = self.invProb.m_current
|
||||
# return mref
|
||||
|
||||
class Update_IRLS(InversionDirective):
|
||||
|
||||
eps_min = None
|
||||
factor = None
|
||||
gamma = None
|
||||
phi_m_last = None
|
||||
phi_d_last = None
|
||||
|
||||
def initialize(self):
|
||||
|
||||
# Scale the regularization for changes in norm
|
||||
if getattr(self, 'phi_m_last', None) is not None:
|
||||
|
||||
self.reg.curModel = self.invProb.curModel
|
||||
self.reg.gamma = 1.
|
||||
phim_new = self.reg.eval(self.invProb.curModel)
|
||||
self.gamma = self.phi_m_last / phim_new
|
||||
|
||||
self.reg.curModel = self.invProb.curModel
|
||||
self.reg.gamma = self.gamma
|
||||
|
||||
if getattr(self, 'phi_d_last', None) is None:
|
||||
self.phi_d_last = self.invProb.phi_d
|
||||
|
||||
def endIter(self):
|
||||
# Cool the threshold parameter
|
||||
if getattr(self, 'factor', None) is not None:
|
||||
eps = self.reg.eps / self.factor
|
||||
|
||||
if getattr(self, 'eps_min', None) is not None:
|
||||
self.reg.eps = np.max([self.eps_min,eps])
|
||||
else:
|
||||
self.reg.eps = eps
|
||||
|
||||
# Get phi_m at the end of current iteration
|
||||
self.phi_m_last = self.invProb.phi_m_last
|
||||
|
||||
# Update the model used for the IRLS weights
|
||||
self.reg.curModel = self.invProb.curModel
|
||||
|
||||
# Temporarely set gamma to 1.
|
||||
self.reg.gamma = 1.
|
||||
|
||||
# Compute change in model objective function and update scaling
|
||||
phim_new = self.reg.eval(self.invProb.curModel)
|
||||
|
||||
self.reg.gamma = self.phi_m_last / phim_new
|
||||
|
||||
self.invProb.beta = self.invProb.beta * self.survey.nD*0.5 / self.invProb.phi_d
|
||||
|
||||
class Update_lin_PreCond(InversionDirective):
|
||||
|
||||
|
||||
def endIter(self):
|
||||
# Cool the threshold parameter
|
||||
|
||||
if getattr(self.opt, 'approxHinv', None) is not None:
|
||||
# Update the pre-conditioner
|
||||
diagA = np.sum(self.prob.G**2.,axis=0) + self.invProb.beta*(self.reg.W.T*self.reg.W).diagonal() * (self.reg.mapping * np.ones(self.reg.curModel.size))**2.
|
||||
PC = Utils.sdiag(diagA**-1.)
|
||||
self.opt.approxHinv = PC
|
||||
print 'Updated pre-cond'
|
||||
|
||||
class Update_Wj(InversionDirective):
|
||||
"""
|
||||
Create approx-sensitivity base weighting using the probing method
|
||||
"""
|
||||
k = None # Number of probing cycles
|
||||
itr = None # Iteration number to update Wj, or always update if None
|
||||
|
||||
def endIter(self):
|
||||
|
||||
if self.itr is None or self.itr == self.opt.iter:
|
||||
|
||||
m = self.invProb.curModel
|
||||
if self.k is None:
|
||||
self.k = int(self.survey.nD/10)
|
||||
|
||||
def JtJv(v):
|
||||
|
||||
Jv = self.prob.Jvec(m, v)
|
||||
|
||||
return self.prob.Jtvec(m,Jv)
|
||||
|
||||
JtJdiag = Utils.diagEst(JtJv,len(m),k=self.k)
|
||||
JtJdiag = JtJdiag / max(JtJdiag)
|
||||
|
||||
self.reg.wght = JtJdiag
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
import numpy as np
|
||||
from scipy.constants import mu_0, pi
|
||||
from scipy import special
|
||||
|
||||
def DCAnalyticHalf(txloc, rxlocs, sigma, flag="wholespace"):
|
||||
"""
|
||||
Analytic solution for electric potential from a postive pole
|
||||
|
||||
Input variables:
|
||||
|
||||
txloc = a xyz location of A (+) electrode (np.r_[xa, ya, za])
|
||||
|
||||
rxlocs = [M, N]
|
||||
M: xyz locations of M (+) electrode (np.c_[xmlocs, ymlocs, zmlocs])
|
||||
N: xyz locations of N (-) electrode (np.c_[xnlocs, ynlocs, znlocs])
|
||||
|
||||
sigma = conductivity (either float or complex)
|
||||
flag = "wholsespace" or "halfspace"
|
||||
|
||||
"""
|
||||
M = rxlocs[0]
|
||||
N = rxlocs[1]
|
||||
|
||||
rM = np.sqrt( (M[:,0]-txloc[0])**2 + (M[:,1]-txloc[1])**2 + (M[:,2]-txloc[1])**2 )
|
||||
rN = np.sqrt( (N[:,0]-txloc[0])**2 + (N[:,1]-txloc[1])**2 + (N[:,2]-txloc[1])**2 )
|
||||
|
||||
phiM = 1./(4*np.pi*rM*sigma)
|
||||
phiN = 1./(4*np.pi*rN*sigma)
|
||||
phi = phiM - phiN
|
||||
|
||||
if flag == "halfspace":
|
||||
phi *= 2
|
||||
|
||||
return phi
|
||||
|
||||
deg2rad = lambda deg: deg/180.*np.pi
|
||||
rad2deg = lambda rad: rad*180./np.pi
|
||||
|
||||
def DCAnalyticSphere(txloc, rxloc, xc, radius, sigma, sigma1, \
|
||||
flag = "sec", order=12, halfspace=False):
|
||||
# def DCSpherePointCurrent(txloc, rxloc, xc, radius, rho, rho1, \
|
||||
# flag = "sec", order=12):
|
||||
"""
|
||||
|
||||
Parameters:
|
||||
|
||||
txloc (array) : current electrode location (x,y,z)
|
||||
xc (float) : x center of depressed sphere
|
||||
rxloc (array) : electrode locations
|
||||
(Nx3 array, # of electrodes)
|
||||
radius (float): radius of the sphere (m)
|
||||
rho (float) : resistivity of the background (ohm-m)
|
||||
rho1 (float) : resistivity of the sphere
|
||||
flag (string) : "sec", "total", "prim"
|
||||
(default="sec")
|
||||
"sec": secondary potential only due to sphere
|
||||
"prim": primary potential from the point source
|
||||
"total": "sec"+"prim"
|
||||
order (float) : maximum order of Legendre polynomial
|
||||
(default=12)
|
||||
|
||||
Written by Seogi Kang (skang@eos.ubc.ca)
|
||||
Ph.D. Candidate of University of British Columbia, Canada
|
||||
|
||||
"""
|
||||
|
||||
Pleg = []
|
||||
# Compute Legendre Polynomial
|
||||
for i in range(order):
|
||||
Pleg.append(special.legendre(i, monic=0))
|
||||
|
||||
|
||||
rho = 1./sigma
|
||||
rho1 = 1./sigma1
|
||||
|
||||
# Center of the sphere should be aligned in txloc in y-direction
|
||||
yc = txloc[1]
|
||||
xyz = np.c_[rxloc[:,0]-xc, rxloc[:,1]-yc, rxloc[:,2]]
|
||||
r = np.sqrt( (xyz**2).sum(axis=1) )
|
||||
|
||||
x0 = abs(txloc[0]-xc)
|
||||
|
||||
costheta = xyz[:,0]/r * (txloc[0]-xc)/x0
|
||||
phi = np.zeros_like(r)
|
||||
R = (r**2+x0**2.-2.*r*x0*costheta)**0.5
|
||||
# primary potential in a whole space
|
||||
prim = rho*1./(4*np.pi*R)
|
||||
|
||||
if flag =="prim":
|
||||
return prim
|
||||
|
||||
sphind = r < radius
|
||||
out = np.zeros_like(r)
|
||||
for n in range(order):
|
||||
An, Bn = AnBnfun(n, radius, x0, rho, rho1)
|
||||
dumout = An*r[~sphind]**(-n-1.)*Pleg[n](costheta[~sphind])
|
||||
out[~sphind] += dumout
|
||||
dumin = Bn*r[sphind]**(n)*Pleg[n](costheta[sphind])
|
||||
out[sphind] += dumin
|
||||
|
||||
out[~sphind] += prim[~sphind]
|
||||
|
||||
if halfspace:
|
||||
scale = 2
|
||||
else:
|
||||
scale = 1
|
||||
|
||||
if flag == "sec":
|
||||
return scale*(out-prim)
|
||||
elif flag == "total":
|
||||
return scale*out
|
||||
|
||||
def AnBnfun(n, radius, x0, rho, rho1, I=1.):
|
||||
const = I*rho/(4*np.pi)
|
||||
bunmo = n*rho + (n+1)*rho1
|
||||
An = const * radius**(2*n+1) / x0 ** (n+1.) * n * \
|
||||
(rho1-rho) / bunmo
|
||||
Bn = const * 1. / x0 ** (n+1.) * (2*n+1) * (rho1) / bunmo
|
||||
return An, Bn
|
||||
@@ -1,3 +1,4 @@
|
||||
from TDEM import hzAnalyticDipoleT
|
||||
from FDEM import hzAnalyticDipoleF
|
||||
from FDEMcasing import *
|
||||
from DC import DCAnalyticHalf, DCAnalyticSphere
|
||||
|
||||
+17
-7
@@ -1,13 +1,14 @@
|
||||
from SimPEG import Survey, Problem, Utils, Models, Maps, PropMaps, np, sp, Solver as SimpegSolver
|
||||
from scipy.constants import mu_0
|
||||
|
||||
|
||||
class EMPropMap(Maps.PropMap):
|
||||
"""
|
||||
Property Map for EM Problems. The electrical conductivity (\\(\\sigma\\)) is the default inversion property, and the default value of the magnetic permeability is that of free space (\\(\\mu = 4\\pi\\times 10^{-7} \\) H/m)
|
||||
"""
|
||||
|
||||
sigma = Maps.Property("Electrical Conductivity", defaultInvProp = True, propertyLink=('rho',Maps.ReciprocalMap))
|
||||
mu = Maps.Property("Magnetic Permeability", defaultVal = mu_0, propertyLink=('mui',Maps.ReciprocalMap))
|
||||
mu = Maps.Property("Inverse Magnetic Permeability", defaultVal = mu_0, propertyLink=('mui',Maps.ReciprocalMap))
|
||||
|
||||
rho = Maps.Property("Electrical Resistivity", propertyLink=('sigma', Maps.ReciprocalMap))
|
||||
mui = Maps.Property("Inverse Magnetic Permeability", defaultVal = 1./mu_0, propertyLink=('mu', Maps.ReciprocalMap))
|
||||
@@ -70,6 +71,12 @@ class BaseEMProblem(Problem.BaseProblem):
|
||||
self._Mf = self.mesh.getFaceInnerProduct()
|
||||
return self._Mf
|
||||
|
||||
@property
|
||||
def Vol(self):
|
||||
if getattr(self, '_Vol', None) is None:
|
||||
self._Vol = Utils.sdiag(self.mesh.vol)
|
||||
return self._Vol
|
||||
|
||||
|
||||
# ----- Magnetic Permeability ----- #
|
||||
@property
|
||||
@@ -127,7 +134,6 @@ class BaseEMProblem(Problem.BaseProblem):
|
||||
"""
|
||||
return self.mesh.getEdgeInnerProductDeriv(self.curModel.sigma)(u) * self.curModel.sigmaDeriv
|
||||
|
||||
|
||||
@property
|
||||
def MeSigmaI(self):
|
||||
"""
|
||||
@@ -150,7 +156,6 @@ class BaseEMProblem(Problem.BaseProblem):
|
||||
return dMeSigmaI_dI * ( dMe_dsig * ( dsig_dm))
|
||||
# return self.mesh.getEdgeInnerProductDeriv(self.curModel.sigma, invMat=True)(u)
|
||||
|
||||
|
||||
@property
|
||||
def MfRho(self):
|
||||
"""
|
||||
@@ -183,7 +188,12 @@ class BaseEMProblem(Problem.BaseProblem):
|
||||
"""
|
||||
Derivative of :code:`MfRhoI` with respect to the model.
|
||||
"""
|
||||
return self.mesh.getFaceInnerProductDeriv(self.curModel.rho, invMat=True)(u) * self.curModel.rhoDeriv
|
||||
|
||||
dMfRhoI_dI = -self.MfRhoI**2
|
||||
dMf_drho = self.mesh.getFaceInnerProductDeriv(self.curModel.rho)(u)
|
||||
return dMfRhoI_dI * ( dMf_drho * (-Utils.sdiag(self.curModel.rho**2) * self.curModel.sigmaDeriv) )
|
||||
|
||||
# return self.mesh.getFaceInnerProductDeriv(self.curModel.rho, invMat=True)(u) * self.curModel.rhoDeriv
|
||||
|
||||
class BaseEMSurvey(Survey.BaseSurvey):
|
||||
|
||||
@@ -192,7 +202,7 @@ class BaseEMSurvey(Survey.BaseSurvey):
|
||||
self.srcList = srcList
|
||||
Survey.BaseSurvey.__init__(self, **kwargs)
|
||||
|
||||
def eval(self, u):
|
||||
def eval(self, f):
|
||||
"""
|
||||
Project fields to receiver locations
|
||||
:param Fields u: fields object
|
||||
@@ -202,8 +212,8 @@ class BaseEMSurvey(Survey.BaseSurvey):
|
||||
data = Survey.Data(self)
|
||||
for src in self.srcList:
|
||||
for rx in src.rxList:
|
||||
data[src, rx] = rx.eval(src, self.mesh, u)
|
||||
data[src, rx] = rx.eval(src, self.mesh, f)
|
||||
return data
|
||||
|
||||
def evalDeriv(self, u):
|
||||
def evalDeriv(self, f):
|
||||
raise Exception('Use Receivers to project fields deriv.')
|
||||
|
||||
+17
-57
@@ -8,29 +8,29 @@ from SimPEG.EM.Utils import omega
|
||||
|
||||
class BaseFDEMProblem(BaseEMProblem):
|
||||
"""
|
||||
We start by looking at Maxwell's equations in the electric
|
||||
field \\\(\\\mathbf{e}\\\) and the magnetic flux
|
||||
density \\\(\\\mathbf{b}\\\)
|
||||
We start by looking at Maxwell's equations in the electric
|
||||
field \\\(\\\mathbf{e}\\\) and the magnetic flux
|
||||
density \\\(\\\mathbf{b}\\\)
|
||||
|
||||
.. math ::
|
||||
.. math ::
|
||||
|
||||
\mathbf{C} \mathbf{e} + i \omega \mathbf{b} = \mathbf{s_m} \\\\
|
||||
{\mathbf{C}^{\\top} \mathbf{M_{\mu^{-1}}^f} \mathbf{b} - \mathbf{M_{\sigma}^e} \mathbf{e} = \mathbf{s_e}}
|
||||
\mathbf{C} \mathbf{e} + i \omega \mathbf{b} = \mathbf{s_m} \\\\
|
||||
{\mathbf{C}^{\\top} \mathbf{M_{\mu^{-1}}^f} \mathbf{b} - \mathbf{M_{\sigma}^e} \mathbf{e} = \mathbf{s_e}}
|
||||
|
||||
if using the E-B formulation (:code:`Problem_e`
|
||||
or :code:`Problem_b`). Note that in this case, :math:`\mathbf{s_e}` is an integrated quantity.
|
||||
if using the E-B formulation (:code:`Problem_e`
|
||||
or :code:`Problem_b`). Note that in this case, :math:`\mathbf{s_e}` is an integrated quantity.
|
||||
|
||||
If we write Maxwell's equations in terms of
|
||||
\\\(\\\mathbf{h}\\\) and current density \\\(\\\mathbf{j}\\\)
|
||||
If we write Maxwell's equations in terms of
|
||||
\\\(\\\mathbf{h}\\\) and current density \\\(\\\mathbf{j}\\\)
|
||||
|
||||
.. math ::
|
||||
.. math ::
|
||||
|
||||
\mathbf{C}^{\\top} \mathbf{M_{\\rho}^f} \mathbf{j} + i \omega \mathbf{M_{\mu}^e} \mathbf{h} = \mathbf{s_m} \\\\
|
||||
\mathbf{C} \mathbf{h} - \mathbf{j} = \mathbf{s_e}
|
||||
\mathbf{C}^{\\top} \mathbf{M_{\\rho}^f} \mathbf{j} + i \omega \mathbf{M_{\mu}^e} \mathbf{h} = \mathbf{s_m} \\\\
|
||||
\mathbf{C} \mathbf{h} - \mathbf{j} = \mathbf{s_e}
|
||||
|
||||
if using the H-J formulation (:code:`Problem_j` or :code:`Problem_h`). Note that here, :math:`\mathbf{s_m}` is an integrated quantity.
|
||||
if using the H-J formulation (:code:`Problem_j` or :code:`Problem_h`). Note that here, :math:`\mathbf{s_m}` is an integrated quantity.
|
||||
|
||||
The problem performs the elimination so that we are solving the system for \\\(\\\mathbf{e},\\\mathbf{b},\\\mathbf{j} \\\) or \\\(\\\mathbf{h}\\\)
|
||||
The problem performs the elimination so that we are solving the system for \\\(\\\mathbf{e},\\\mathbf{b},\\\mathbf{j} \\\) or \\\(\\\mathbf{h}\\\)
|
||||
"""
|
||||
|
||||
surveyPair = SurveyFDEM
|
||||
@@ -167,6 +167,7 @@ class BaseFDEMProblem(BaseEMProblem):
|
||||
|
||||
for i, src in enumerate(Srcs):
|
||||
smi, sei = src.eval(self)
|
||||
#Why are you adding?
|
||||
s_m[:,i] = s_m[:,i] + smi
|
||||
s_e[:,i] = s_e[:,i] + sei
|
||||
|
||||
@@ -204,17 +205,6 @@ class Problem_e(BaseFDEMProblem):
|
||||
def __init__(self, mesh, **kwargs):
|
||||
BaseFDEMProblem.__init__(self, mesh, **kwargs)
|
||||
|
||||
def _GLoc(self, fieldType):
|
||||
if fieldType == 'e':
|
||||
return 'E'
|
||||
elif fieldType == 'b':
|
||||
return 'F'
|
||||
elif (fieldType == 'h') or (fieldType == 'j'):
|
||||
return 'CCV'
|
||||
else:
|
||||
raise Exception('Field type must be e, b, h, j')
|
||||
|
||||
|
||||
def getA(self, freq):
|
||||
"""
|
||||
System matrix
|
||||
@@ -294,6 +284,7 @@ class Problem_e(BaseFDEMProblem):
|
||||
if adjoint:
|
||||
dRHS = MfMui * (C * v)
|
||||
return s_mDeriv(dRHS) - 1j * omega(freq) * s_eDeriv(v)
|
||||
|
||||
else:
|
||||
return C.T * (MfMui * s_mDeriv(v)) -1j * omega(freq) * s_eDeriv(v)
|
||||
|
||||
@@ -325,16 +316,6 @@ class Problem_b(BaseFDEMProblem):
|
||||
def __init__(self, mesh, **kwargs):
|
||||
BaseFDEMProblem.__init__(self, mesh, **kwargs)
|
||||
|
||||
def _GLoc(self, fieldType):
|
||||
if fieldType == 'e':
|
||||
return 'E'
|
||||
elif fieldType == 'b':
|
||||
return 'F'
|
||||
elif (fieldType == 'h') or (fieldType == 'j'):
|
||||
return'CCV'
|
||||
else:
|
||||
raise Exception('Field type must be e, b, h, j')
|
||||
|
||||
def getA(self, freq):
|
||||
"""
|
||||
System matrix
|
||||
@@ -483,16 +464,6 @@ class Problem_j(BaseFDEMProblem):
|
||||
def __init__(self, mesh, **kwargs):
|
||||
BaseFDEMProblem.__init__(self, mesh, **kwargs)
|
||||
|
||||
def _GLoc(self, fieldType):
|
||||
if fieldType == 'h':
|
||||
return 'E'
|
||||
elif fieldType == 'j':
|
||||
return 'F'
|
||||
elif (fieldType == 'e') or (fieldType == 'b'):
|
||||
return 'CCV'
|
||||
else:
|
||||
raise Exception('Field type must be e, b, h, j')
|
||||
|
||||
def getA(self, freq):
|
||||
"""
|
||||
System matrix
|
||||
@@ -631,17 +602,6 @@ class Problem_h(BaseFDEMProblem):
|
||||
def __init__(self, mesh, **kwargs):
|
||||
BaseFDEMProblem.__init__(self, mesh, **kwargs)
|
||||
|
||||
def _GLoc(self, fieldType):
|
||||
if fieldType == 'h':
|
||||
return 'E'
|
||||
elif fieldType == 'j':
|
||||
return 'F'
|
||||
elif (fieldType == 'e') or (fieldType == 'b'):
|
||||
return 'CCV'
|
||||
else:
|
||||
raise Exception('Field type must be e, b, h, j')
|
||||
|
||||
|
||||
def getA(self, freq):
|
||||
"""
|
||||
System matrix
|
||||
|
||||
@@ -181,7 +181,7 @@ class Fields_e(Fields):
|
||||
}
|
||||
|
||||
def __init__(self, mesh, survey, **kwargs):
|
||||
Fields.__init__(self,mesh,survey,**kwargs)
|
||||
Fields.__init__(self, mesh, survey, **kwargs)
|
||||
|
||||
def startup(self):
|
||||
self.prob = self.survey.prob
|
||||
@@ -193,6 +193,16 @@ class Fields_e(Fields):
|
||||
self._MeSigmaDeriv = self.survey.prob.MeSigmaDeriv
|
||||
self._MfMui = self.survey.prob.MfMui
|
||||
|
||||
def _GLoc(self, fieldType):
|
||||
if fieldType == 'e':
|
||||
return 'E'
|
||||
elif fieldType == 'b':
|
||||
return 'F'
|
||||
elif (fieldType == 'h') or (fieldType == 'j'):
|
||||
return 'CCV'
|
||||
else:
|
||||
raise Exception('Field type must be e, b, h, j')
|
||||
|
||||
|
||||
def _ePrimary(self, eSolution, srcList):
|
||||
"""
|
||||
@@ -455,6 +465,17 @@ class Fields_b(Fields):
|
||||
self._nC = self.survey.prob.mesh.nC
|
||||
|
||||
|
||||
|
||||
def _GLoc(self,fieldType):
|
||||
if fieldType == 'e':
|
||||
return 'E'
|
||||
elif fieldType == 'b':
|
||||
return 'F'
|
||||
elif (fieldType == 'h') or (fieldType == 'j'):
|
||||
return'CCV'
|
||||
else:
|
||||
raise Exception('Field type must be e, b, h, j')
|
||||
|
||||
def _bPrimary(self, bSolution, srcList):
|
||||
"""
|
||||
Primary magnetic flux density from source
|
||||
@@ -708,6 +729,16 @@ class Fields_j(Fields):
|
||||
self._aveE2CCV = self.survey.prob.mesh.aveE2CCV
|
||||
self._nC = self.survey.prob.mesh.nC
|
||||
|
||||
def _GLoc(self,fieldType):
|
||||
if fieldType == 'h':
|
||||
return 'E'
|
||||
elif fieldType == 'j':
|
||||
return 'F'
|
||||
elif (fieldType == 'e') or (fieldType == 'b'):
|
||||
return 'CCV'
|
||||
else:
|
||||
raise Exception('Field type must be e, b, h, j')
|
||||
|
||||
def _jPrimary(self, jSolution, srcList):
|
||||
"""
|
||||
Primary current density from source
|
||||
@@ -993,6 +1024,16 @@ class Fields_h(Fields):
|
||||
self._aveE2CCV = self.survey.prob.mesh.aveE2CCV
|
||||
self._nC = self.survey.prob.mesh.nC
|
||||
|
||||
def _GLoc(self,fieldType):
|
||||
if fieldType == 'h':
|
||||
return 'E'
|
||||
elif fieldType == 'j':
|
||||
return 'F'
|
||||
elif (fieldType == 'e') or (fieldType == 'b'):
|
||||
return 'CCV'
|
||||
else:
|
||||
raise Exception('Field type must be e, b, h, j')
|
||||
|
||||
def _hPrimary(self, hSolution, srcList):
|
||||
"""
|
||||
Primary magnetic field from source
|
||||
|
||||
+17
-242
@@ -9,14 +9,11 @@ class BaseSrc(Survey.BaseSrc):
|
||||
"""
|
||||
|
||||
freq = None
|
||||
integrate = False
|
||||
|
||||
def __init__(self, rxList, **kwargs):
|
||||
Survey.BaseSrc.__init__(self, rxList, **kwargs)
|
||||
# rxPair = RxFDEM
|
||||
integrate = True
|
||||
|
||||
def eval(self, prob):
|
||||
"""
|
||||
Evaluate the source terms.
|
||||
- :math:`s_m` : magnetic source term
|
||||
- :math:`s_e` : electric source term
|
||||
|
||||
@@ -105,7 +102,7 @@ class BaseSrc(Survey.BaseSrc):
|
||||
"""
|
||||
return Zero()
|
||||
|
||||
def s_mDeriv(self, prob, v, adjoint=False):
|
||||
def s_mDeriv(self, prob, v, adjoint = False):
|
||||
"""
|
||||
Derivative of magnetic source term with respect to the inversion model
|
||||
|
||||
@@ -118,7 +115,7 @@ class BaseSrc(Survey.BaseSrc):
|
||||
|
||||
return Zero()
|
||||
|
||||
def s_eDeriv(self, prob, v, adjoint=False):
|
||||
def s_eDeriv(self, prob, v, adjoint = False):
|
||||
"""
|
||||
Derivative of electric source term with respect to the inversion model
|
||||
|
||||
@@ -138,12 +135,13 @@ class RawVec_e(BaseSrc):
|
||||
:param list rxList: receiver list
|
||||
:param float freq: frequency
|
||||
:param numpy.array s_e: electric source term
|
||||
:param bool integrate: Integrate the source term (multiply by Me) [False]
|
||||
:param bool integrate: Integrate the source term (multiply by Me) [True]
|
||||
"""
|
||||
|
||||
def __init__(self, rxList, freq, s_e):
|
||||
def __init__(self, rxList, freq, s_e, integrate=True): #, ePrimary=None, bPrimary=None, hPrimary=None, jPrimary=None):
|
||||
self._s_e = np.array(s_e, dtype=complex)
|
||||
self.freq = float(freq)
|
||||
self.integrate = integrate
|
||||
|
||||
BaseSrc.__init__(self, rxList)
|
||||
|
||||
@@ -167,12 +165,13 @@ class RawVec_m(BaseSrc):
|
||||
:param float freq: frequency
|
||||
:param rxList: receiver list
|
||||
:param numpy.array s_m: magnetic source term
|
||||
:param bool integrate: Integrate the source term (multiply by Me) [False]
|
||||
:param bool integrate: Integrate the source term (multiply by Me) [True]
|
||||
"""
|
||||
|
||||
def __init__(self, rxList, freq, s_m, integrate=True): #ePrimary=Zero(), bPrimary=Zero(), hPrimary=Zero(), jPrimary=Zero()):
|
||||
self._s_m = np.array(s_m, dtype=complex)
|
||||
self.freq = float(freq)
|
||||
self.integrate = integrate
|
||||
|
||||
BaseSrc.__init__(self, rxList)
|
||||
|
||||
@@ -197,13 +196,14 @@ class RawVec(BaseSrc):
|
||||
:param float freq: frequency
|
||||
:param numpy.array s_m: magnetic source term
|
||||
:param numpy.array s_e: electric source term
|
||||
:param bool integrate: Integrate the source term (multiply by Me) [False]
|
||||
:param bool integrate: Integrate the source term (multiply by Me) [True]
|
||||
"""
|
||||
def __init__(self, rxList, freq, s_m, s_e, **kwargs):
|
||||
def __init__(self, rxList, freq, s_m, s_e, integrate=True):
|
||||
self._s_m = np.array(s_m, dtype=complex)
|
||||
self._s_e = np.array(s_e, dtype=complex)
|
||||
self.freq = float(freq)
|
||||
BaseSrc.__init__(self, rxList, **kwargs)
|
||||
self.integrate = integrate
|
||||
BaseSrc.__init__(self, rxList)
|
||||
|
||||
def s_m(self, prob):
|
||||
"""
|
||||
@@ -277,13 +277,14 @@ class MagDipole(BaseSrc):
|
||||
:param float mu: background magnetic permeability
|
||||
"""
|
||||
|
||||
def __init__(self, rxList, freq, loc, orientation='Z', moment=1., mu=mu_0, **kwargs):
|
||||
def __init__(self, rxList, freq, loc, orientation='Z', moment=1., mu=mu_0):
|
||||
self.freq = float(freq)
|
||||
self.loc = loc
|
||||
self.orientation = orientation
|
||||
assert orientation in ['X','Y','Z'], "Orientation (right now) doesn't actually do anything! The methods in SrcUtils should take care of this..."
|
||||
self.moment = moment
|
||||
self.mu = mu
|
||||
self.integrate = False
|
||||
BaseSrc.__init__(self, rxList)
|
||||
|
||||
def bPrimary(self, prob):
|
||||
@@ -541,10 +542,10 @@ class CircularLoop(BaseSrc):
|
||||
if not prob.mesh.isSymmetric:
|
||||
# TODO ?
|
||||
raise NotImplementedError('Non-symmetric cyl mesh not implemented yet!')
|
||||
a = MagneticLoopVectorPotential(self.loc, gridY, 'y', moment=self.radius, mu=self.mu)
|
||||
a = MagneticDipoleVectorPotential(self.loc, gridY, 'y', moment=self.radius, mu=self.mu)
|
||||
|
||||
else:
|
||||
srcfct = MagneticLoopVectorPotential
|
||||
srcfct = MagneticDipoleVectorPotential
|
||||
ax = srcfct(self.loc, gridX, 'x', self.radius, mu=self.mu)
|
||||
ay = srcfct(self.loc, gridY, 'y', self.radius, mu=self.mu)
|
||||
az = srcfct(self.loc, gridZ, 'z', self.radius, mu=self.mu)
|
||||
@@ -603,231 +604,5 @@ class CircularLoop(BaseSrc):
|
||||
return -C.T * (MMui_s * self.bPrimary(prob))
|
||||
|
||||
|
||||
class PrimSec(BaseSrc):
|
||||
"""
|
||||
Primary-Secondary source in the physical properties. A primary problem is
|
||||
first solved, and the fields from this problem are used to construct a
|
||||
source term for the secondary problem. Either a mesh and
|
||||
fields need to be provided or a prob and a survey.
|
||||
|
||||
For the EB formulation, we start the derivation from Maxwell's equations:
|
||||
|
||||
.. math::
|
||||
\\nabla \\times \\vec{E} + i \omega \\vec{B} = \\vec{s_m} \\\\
|
||||
\\nabla \\times \\mu^{-1} \\vec{B} - \sigma \\vec{E} = \\vec{s_e}
|
||||
|
||||
we consider the physical properties, fields, and fluxes to be composed of
|
||||
two parts, a primary and a secondary:
|
||||
|
||||
- :math:`\sigma = \sigma_p + \sigma_s`
|
||||
- :math:`\mu^{-1} = \mu^{-1}_p + \mu^{-1}_s`
|
||||
- :math:`\\vec{E} = \\vec{E_p} + \\vec{E_s}`
|
||||
- :math:`\\vec{B} = \\vec{B_p} + \\vec{B_s}`
|
||||
|
||||
and choose our primary such that
|
||||
|
||||
.. math::
|
||||
\\nabla \\times \\vec{E}_p + i \omega \\vec{B}_p = \\vec{s_m} \\\\
|
||||
\\nabla \\times \\mu^{-1}_p \\vec{B}_p - \sigma_p \\vec{E}_p = \\vec{s_e}_p
|
||||
|
||||
so the secondary problem is then
|
||||
|
||||
.. math::
|
||||
\\nabla \\times \\vec{E}_s + i \omega \\vec{B}_s = 0 \\\\
|
||||
\\nabla \\times \\mu^{-1} \\vec{B}_s - \sigma \\vec{E}_s = - \\nabla \\times \\mu^{-1}_s \\vec{B}_p + \sigma_s \\vec{E}_p
|
||||
|
||||
|
||||
If instead, HJ formulation is considered, then we start off with
|
||||
|
||||
.. math::
|
||||
\\nabla \\times \\rho \\vec{J} + i \omega \\mu \\vec{H} = \\vec{s_m} \\\\
|
||||
\\nabla \\times \\vec{H} - \\vec{J} = \\vec{s_e}
|
||||
|
||||
and we define the primary secondary problem in terms of
|
||||
|
||||
- :math:`\\rho = \\rho_p + \\rho_s`
|
||||
- :math:`\mu = \mu_p + \mu_s`
|
||||
- :math:`\\vec{J} = \\vec{J_p} + \\vec{J_s}`
|
||||
- :math:`\\vec{H} = \\vec{H_p} + \\vec{H_s}`
|
||||
|
||||
with the primary being defined by
|
||||
|
||||
.. math::
|
||||
\\nabla \\times \\rho_p \\vec{J}_p + i \omega \\mu_p \\vec{H}_p = \\vec{s_m} \\\\
|
||||
\\nabla \\times \\vec{H}_p - \\vec{J}_p = \\vec{s_e}
|
||||
|
||||
so the secondary problem is given by
|
||||
|
||||
.. math::
|
||||
\\nabla \\times \\rho \\vec{J}_s + i \omega \\mu \\vec{H} = - \\nabla \\times \\rho_s \\vec{J}_p - i \omega \\mu_s \\vec{H}_p \\
|
||||
\\nabla \\times \\vec{H}_p - \\vec{J}_p = 0
|
||||
|
||||
Note: if different meshes are employed for the primary and secondary
|
||||
problems, then we need to interpolate the fields from the primary mesh to
|
||||
the secondary mesh. We do this by always interpolating the field and
|
||||
computing a flux if need be in order to ensure that fluxes remain
|
||||
numerically divergence free.
|
||||
|
||||
:param list rxList: Receiver list
|
||||
:param float freq: frequency
|
||||
:param numpy.array m: primary model
|
||||
:param Problem prob: primary problem
|
||||
:param Survey survey: primary survey
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, rxList, freq, m, prob, survey):
|
||||
self.freq = float(freq)
|
||||
self.m = m
|
||||
self.prob = prob
|
||||
self.survey = survey
|
||||
self.fields = None
|
||||
|
||||
if self.survey.ispaired:
|
||||
if self.survey.prob is not self.prob:
|
||||
raise Exception('The survey object is already paired to a problem. Use survey.unpair()')
|
||||
else:
|
||||
self.prob.pair(self.survey)
|
||||
|
||||
self.mesh = self.prob.mesh
|
||||
self.prob.curModel = self.m
|
||||
|
||||
BaseSrc.__init__(self, rxList)
|
||||
|
||||
def MeSigma(self, prob):
|
||||
if getattr(self, '_MeSigma', None) is None:
|
||||
sigmaprimary = self.prob.curModel.sigma
|
||||
if self.mesh != prob.mesh:
|
||||
P = self.mesh.getInterpolationMatMesh2Mesh(prob.mesh, locType='CC')
|
||||
sigmaprimary = P * sigmaprimary
|
||||
self._MeSigma = prob.mesh.getEdgeInnerProduct(sigmaprimary)
|
||||
return self._MeSigma
|
||||
|
||||
def MfMui(self, prob):
|
||||
if getattr(self, '_MfMui', None) is None:
|
||||
muiprimary = self.prob.curModel.mui
|
||||
if self.mesh != prob.mesh and not isinstance(muiprimary,float): # if different meshes and mu is a vector --> need to interpolate
|
||||
P = self.mesh.getInterpolationMatMesh2Mesh(prob.mesh, locType='CC')
|
||||
muiprimary = P * muiprimary
|
||||
self._MfMui = prob.mesh.getFaceInnerProduct(muiprimary)
|
||||
return self._MfMui
|
||||
|
||||
def MfRho(self, prob):
|
||||
if getattr(self, '_MfRho', None) is None:
|
||||
rhoprimary = self.prob.curModel.rho
|
||||
if self.mesh != prob.mesh:
|
||||
P = self.mesh.getInterpolationMatMesh2Mesh(prob.mesh, locType='CC')
|
||||
rhoprimary = P * rhoprimary
|
||||
self._MfRho = prob.mesh.getFaceInnerProduct(rhoprimary)
|
||||
return self._MfRho
|
||||
|
||||
def MeMu(self, prob):
|
||||
if getattr(self, '_MeMu', None) is None:
|
||||
muprimary = self.prob.curModel.mu
|
||||
if self.mesh != prob.mesh and not isinstance(muiprimary,float): # if different meshes and mu is a vector --> need to interpolate
|
||||
P = self.mesh.getInterpolationMatMesh2Mesh(prob.mesh, locType='CC')
|
||||
muprimary = P * muprimary
|
||||
self._MeMu = prob.mesh.getEdgeInnerProduct(muprimary)
|
||||
return self._MeMu
|
||||
|
||||
# note if you switch from one formulation to another, but are using the same mesh, this will break
|
||||
def ePrimary(self,prob):
|
||||
if getattr(self, '_ePrimary', None) is None:
|
||||
if self.fields is None:
|
||||
self.fields = self.prob.fields(self.m)
|
||||
|
||||
ePrimary = self.fields[:,'e']
|
||||
|
||||
if self.mesh != prob.mesh:
|
||||
if self.prob._formulation == 'HJ':
|
||||
P = self.mesh.getInterpolationMatMesh2Mesh(prob.mesh, locType=prob._GLoc('e'), locTypeFrom='CCV')
|
||||
else:
|
||||
P = self.mesh.getInterpolationMatMesh2Mesh(prob.mesh, locType=prob._GLoc('e'))
|
||||
ePrimary = Utils.mkvc(P * ePrimary)
|
||||
self._ePrimary = Utils.mkvc(ePrimary)
|
||||
|
||||
return self._ePrimary
|
||||
|
||||
# note if you switch from one formulation to another, but are using the same mesh, this will break
|
||||
def bPrimary(self, prob):
|
||||
if getattr(self, '_bPrimary', None) is None:
|
||||
if self.fields is None:
|
||||
self.fields = self.prob.fields(self.m)
|
||||
|
||||
if self.mesh == prob.mesh:
|
||||
bPrimary = self.fields[:,'b']
|
||||
else:
|
||||
bPrimary = prob.mesh.edgeCurl * self.ePrimary(prob)
|
||||
|
||||
self._bPrimary = Utils.mkvc(bPrimary)
|
||||
|
||||
return self._bPrimary
|
||||
|
||||
# note if you switch from one formulation to another, but are using the same mesh, this will break
|
||||
def hPrimary(self, prob):
|
||||
if getattr(self, '_hPrimary', None) is None:
|
||||
if self.fields is None:
|
||||
self.fields = self.prob.fields(self.m)
|
||||
|
||||
hPrimary = self.fields[:,'h']
|
||||
|
||||
if self.mesh != prob.mesh:
|
||||
if self.prob._formulation == 'EB':
|
||||
P = self.mesh.getInterpolationMatMesh2Mesh(prob.mesh, locType=prob._GLoc('h'), locTypeFrom='CCV')
|
||||
else:
|
||||
P = self.mesh.getInterpolationMatMesh2Mesh(prob.mesh, locType=prob._GLoc('h'))
|
||||
print P.shape, hPrimary.shape, prob._GLoc('h')
|
||||
hPrimary = Utils.mkvc(P * hPrimary)
|
||||
self._hPrimary = Utils.mkvc(hPrimary)
|
||||
|
||||
return self._hPrimary
|
||||
|
||||
# note if you switch from one formulation to another, but are using the same mesh, this will break
|
||||
def jPrimary(self, prob):
|
||||
if getattr(self, '_jPrimary', None) is None:
|
||||
if self.fields is None:
|
||||
self.fields = self.prob.fields(self.m)
|
||||
|
||||
if self.mesh == prob.mesh:
|
||||
jPrimary = self.fields[:,'j']
|
||||
else:
|
||||
jPrimary = prob.mesh.edgeCurl * self.hPrimary(prob)
|
||||
|
||||
self._jPrimary = Utils.mkvc(jPrimary)
|
||||
|
||||
return self._jPrimary
|
||||
|
||||
def s_e(self,prob):
|
||||
if prob._formulation == 'EB':
|
||||
# - \\nabla \\times \\mu^{-1}_s \\vec{B}_p + \sigma_s \\vec{E}_p
|
||||
s_e = -prob.mesh.edgeCurl.T * ((prob.MfMui - self.MfMui(prob)) * self.bPrimary(prob)) + (prob.MeSigma - self.MeSigma(prob)) * self.ePrimary(prob)
|
||||
return Utils.mkvc(s_e)
|
||||
else:
|
||||
return Zero()
|
||||
|
||||
def s_eDeriv(self, prob, v, adjoint=False):
|
||||
if prob._formulation == 'EB':
|
||||
if adjoint is True:
|
||||
return prob.MeSigmaDeriv(self.ePrimary(prob)).T * v
|
||||
return prob.MeSigmaDeriv(self.ePrimary(prob)) * v
|
||||
else:
|
||||
return Zero()
|
||||
|
||||
def s_m(self,prob):
|
||||
if prob._formulation == 'HJ':
|
||||
# - \\nabla \\times \\rho_s \\vec{J}_p - i \omega \\mu_s \\vec{H}_p
|
||||
s_m = - prob.mesh.edgeCurl.T * (prob.MfRho - self.MfRho(prob)) * self.jPrimary(prob) - 1j * omega(self.freq) * ((prob.MeMu - self.MeMu(prob)) * self.hPrimary(prob))
|
||||
return s_m
|
||||
else:
|
||||
return Zero()
|
||||
|
||||
def s_mDeriv(self, prob, v, adjoint=False):
|
||||
if prob._formulation == 'HJ':
|
||||
if adjoint is True:
|
||||
return - prob.MfRhoDeriv(self.jPrimary(prob)).T * (prob.mesh.edgeCurl * v)
|
||||
return - prob.mesh.edgeCurl.T * (prob.MfRhoDeriv(self.jPrimary(prob)) * v)
|
||||
else:
|
||||
return Zero()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -63,9 +63,9 @@ class Rx(SimPEG.Survey.BaseRx):
|
||||
"""Component projection (real/imag)"""
|
||||
return self.knownRxTypes[self.rxType][2]
|
||||
|
||||
def projGLoc(self, u):
|
||||
def projGLoc(self, f):
|
||||
"""Grid Location projection (e.g. Ex Fy ...)"""
|
||||
return u.prob._GLoc(self.rxType[0]) + self.knownRxTypes[self.rxType][1]
|
||||
return f._GLoc(self.rxType[0]) + self.knownRxTypes[self.rxType][1]
|
||||
|
||||
def eval(self, src, mesh, f):
|
||||
"""
|
||||
@@ -77,6 +77,8 @@ class Rx(SimPEG.Survey.BaseRx):
|
||||
:rtype: numpy.ndarray
|
||||
:return: fields projected to recievers
|
||||
"""
|
||||
# projGLoc = u._GLoc(self.knownRxTypes[self.rxType][0])
|
||||
# projGLoc += self.knownRxTypes[self.rxType][1]
|
||||
|
||||
P = self.getP(mesh, self.projGLoc(f))
|
||||
f_part_complex = f[src, self.projField]
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
import numpy as np
|
||||
|
||||
def getxBCyBC_CC(mesh, alpha, beta, gamma):
|
||||
# def getxBCyBC(mesh, alpha, beta, gamma):
|
||||
"""
|
||||
This is a subfunction generating mixed-boundary condition:
|
||||
|
||||
.. math::
|
||||
|
||||
\nabla \cdot \vec{j} = -\nabla \cdot \vec{j}_s = q
|
||||
|
||||
\rho \vec{j} = -\nabla \phi \phi
|
||||
|
||||
\alpha \phi + \beta \frac{\partial \phi}{\partial r} = \gamma \ at \ r = \partial \Omega
|
||||
|
||||
xBC = f_1(\alpha, \beta, \gamma)
|
||||
yBC = f(\alpha, \beta, \gamma)
|
||||
|
||||
Computes xBC and yBC for cell-centered discretizations
|
||||
"""
|
||||
if mesh.dim == 1: #1D
|
||||
if (len(alpha) != 2 or len(beta) != 2 or len(gamma) != 2):
|
||||
raise Exception("Lenght of list, alpha should be 2")
|
||||
fCCxm,fCCxp = mesh.cellBoundaryInd
|
||||
nBC = fCCxm.sum()+fCCxp.sum()
|
||||
h_xm, h_xp = mesh.gridCC[fCCxm], mesh.gridCC[fCCxp]
|
||||
|
||||
alpha_xm, beta_xm, gamma_xm = alpha[0], beta[0], gamma[0]
|
||||
alpha_xp, beta_xp, gamma_xp = alpha[1], beta[1], gamma[1]
|
||||
|
||||
# h_xm, h_xp = mesh.gridCC[fCCxm], mesh.gridCC[fCCxp]
|
||||
h_xm, h_xp = mesh.hx[0], mesh.hx[-1]
|
||||
|
||||
a_xm = gamma_xm/(0.5*alpha_xm-beta_xm/h_xm)
|
||||
b_xm = (0.5*alpha_xm+beta_xm/h_xm)/(0.5*alpha_xm-beta_xm/h_xm)
|
||||
a_xp = gamma_xp/(0.5*alpha_xp-beta_xp/h_xp)
|
||||
b_xp = (0.5*alpha_xp+beta_xp/h_xp)/(0.5*alpha_xp-beta_xp/h_xp)
|
||||
|
||||
xBC_xm = 0.5*a_xm
|
||||
xBC_xp = 0.5*a_xp/b_xp
|
||||
yBC_xm = 0.5*(1.-b_xm)
|
||||
yBC_xp = 0.5*(1.-1./b_xp)
|
||||
|
||||
xBC = np.r_[xBC_xm, xBC_xp]
|
||||
yBC = np.r_[yBC_xm, yBC_xp]
|
||||
|
||||
elif mesh.dim == 2: #2D
|
||||
if (len(alpha) != 4 or len(beta) != 4 or len(gamma) != 4):
|
||||
raise Exception("Lenght of list, alpha should be 4")
|
||||
|
||||
fxm,fxp,fym,fyp = mesh.faceBoundaryInd
|
||||
nBC = fxm.sum()+fxp.sum()+fxm.sum()+fxp.sum()
|
||||
|
||||
alpha_xm, beta_xm, gamma_xm = alpha[0], beta[0], gamma[0]
|
||||
alpha_xp, beta_xp, gamma_xp = alpha[1], beta[1], gamma[1]
|
||||
alpha_ym, beta_ym, gamma_ym = alpha[2], beta[2], gamma[2]
|
||||
alpha_yp, beta_yp, gamma_yp = alpha[3], beta[3], gamma[3]
|
||||
|
||||
# h_xm, h_xp = mesh.gridCC[fCCxm,0], mesh.gridCC[fCCxp,0]
|
||||
# h_ym, h_yp = mesh.gridCC[fCCym,1], mesh.gridCC[fCCyp,1]
|
||||
|
||||
h_xm, h_xp = mesh.hx[0]*np.ones_like(alpha_xm), mesh.hx[-1]*np.ones_like(alpha_xp)
|
||||
h_ym, h_yp = mesh.hy[0]*np.ones_like(alpha_ym), mesh.hy[-1]*np.ones_like(alpha_yp)
|
||||
|
||||
a_xm = gamma_xm/(0.5*alpha_xm-beta_xm/h_xm)
|
||||
b_xm = (0.5*alpha_xm+beta_xm/h_xm)/(0.5*alpha_xm-beta_xm/h_xm)
|
||||
a_xp = gamma_xp/(0.5*alpha_xp-beta_xp/h_xp)
|
||||
b_xp = (0.5*alpha_xp+beta_xp/h_xp)/(0.5*alpha_xp-beta_xp/h_xp)
|
||||
|
||||
a_ym = gamma_ym/(0.5*alpha_ym-beta_ym/h_ym)
|
||||
b_ym = (0.5*alpha_ym+beta_ym/h_ym)/(0.5*alpha_ym-beta_ym/h_ym)
|
||||
a_yp = gamma_yp/(0.5*alpha_yp-beta_yp/h_yp)
|
||||
b_yp = (0.5*alpha_yp+beta_yp/h_yp)/(0.5*alpha_yp-beta_yp/h_yp)
|
||||
|
||||
xBC_xm = 0.5*a_xm
|
||||
xBC_xp = 0.5*a_xp/b_xp
|
||||
yBC_xm = 0.5*(1.-b_xm)
|
||||
yBC_xp = 0.5*(1.-1./b_xp)
|
||||
xBC_ym = 0.5*a_ym
|
||||
xBC_yp = 0.5*a_yp/b_yp
|
||||
yBC_ym = 0.5*(1.-b_ym)
|
||||
yBC_yp = 0.5*(1.-1./b_yp)
|
||||
|
||||
sortindsfx = np.argsort(np.r_[np.arange(mesh.nFx)[fxm], np.arange(mesh.nFx)[fxp]])
|
||||
sortindsfy = np.argsort(np.r_[np.arange(mesh.nFy)[fym], np.arange(mesh.nFy)[fyp]])
|
||||
|
||||
xBC_x = np.r_[xBC_xm, xBC_xp][sortindsfx]
|
||||
xBC_y = np.r_[xBC_ym, xBC_yp][sortindsfy]
|
||||
yBC_x = np.r_[yBC_xm, yBC_xp][sortindsfx]
|
||||
yBC_y = np.r_[yBC_ym, yBC_yp][sortindsfy]
|
||||
|
||||
xBC = np.r_[xBC_x, xBC_y]
|
||||
yBC = np.r_[yBC_x, yBC_y]
|
||||
|
||||
elif mesh.dim == 3: #3D
|
||||
if (len(alpha) != 6 or len(beta) != 6 or len(gamma) != 6):
|
||||
raise Exception("Lenght of list, alpha should be 6")
|
||||
# fCCxm,fCCxp,fCCym,fCCyp,fCCzm,fCCzp = mesh.cellBoundaryInd
|
||||
fxm,fxp,fym,fyp,fzm,fzp = mesh.faceBoundaryInd
|
||||
nBC = fxm.sum()+fxp.sum()+fxm.sum()+fxp.sum()
|
||||
|
||||
alpha_xm, beta_xm, gamma_xm = alpha[0], beta[0], gamma[0]
|
||||
alpha_xp, beta_xp, gamma_xp = alpha[1], beta[1], gamma[1]
|
||||
alpha_ym, beta_ym, gamma_ym = alpha[2], beta[2], gamma[2]
|
||||
alpha_yp, beta_yp, gamma_yp = alpha[3], beta[3], gamma[3]
|
||||
alpha_zm, beta_zm, gamma_zm = alpha[4], beta[4], gamma[4]
|
||||
alpha_zp, beta_zp, gamma_zp = alpha[5], beta[5], gamma[5]
|
||||
|
||||
# h_xm, h_xp = mesh.gridCC[fCCxm,0], mesh.gridCC[fCCxp,0]
|
||||
# h_ym, h_yp = mesh.gridCC[fCCym,1], mesh.gridCC[fCCyp,1]
|
||||
# h_zm, h_zp = mesh.gridCC[fCCzm,2], mesh.gridCC[fCCzp,2]
|
||||
|
||||
h_xm, h_xp = mesh.hx[0]*np.ones_like(alpha_xm), mesh.hx[-1]*np.ones_like(alpha_xp)
|
||||
h_ym, h_yp = mesh.hy[0]*np.ones_like(alpha_ym), mesh.hy[-1]*np.ones_like(alpha_yp)
|
||||
h_zm, h_zp = mesh.hz[0]*np.ones_like(alpha_zm), mesh.hz[-1]*np.ones_like(alpha_zp)
|
||||
|
||||
a_xm = gamma_xm/(0.5*alpha_xm-beta_xm/h_xm)
|
||||
b_xm = (0.5*alpha_xm+beta_xm/h_xm)/(0.5*alpha_xm-beta_xm/h_xm)
|
||||
a_xp = gamma_xp/(0.5*alpha_xp-beta_xp/h_xp)
|
||||
b_xp = (0.5*alpha_xp+beta_xp/h_xp)/(0.5*alpha_xp-beta_xp/h_xp)
|
||||
|
||||
a_ym = gamma_ym/(0.5*alpha_ym-beta_ym/h_ym)
|
||||
b_ym = (0.5*alpha_ym+beta_ym/h_ym)/(0.5*alpha_ym-beta_ym/h_ym)
|
||||
a_yp = gamma_yp/(0.5*alpha_yp-beta_yp/h_yp)
|
||||
b_yp = (0.5*alpha_yp+beta_yp/h_yp)/(0.5*alpha_yp-beta_yp/h_yp)
|
||||
|
||||
a_zm = gamma_zm/(0.5*alpha_zm-beta_zm/h_zm)
|
||||
b_zm = (0.5*alpha_zm+beta_zm/h_zm)/(0.5*alpha_zm-beta_zm/h_zm)
|
||||
a_zp = gamma_zp/(0.5*alpha_zp-beta_zp/h_zp)
|
||||
b_zp = (0.5*alpha_zp+beta_zp/h_zp)/(0.5*alpha_zp-beta_zp/h_zp)
|
||||
|
||||
xBC_xm = 0.5*a_xm
|
||||
xBC_xp = 0.5*a_xp/b_xp
|
||||
yBC_xm = 0.5*(1.-b_xm)
|
||||
yBC_xp = 0.5*(1.-1./b_xp)
|
||||
xBC_ym = 0.5*a_ym
|
||||
xBC_yp = 0.5*a_yp/b_yp
|
||||
yBC_ym = 0.5*(1.-b_ym)
|
||||
yBC_yp = 0.5*(1.-1./b_yp)
|
||||
xBC_zm = 0.5*a_zm
|
||||
xBC_zp = 0.5*a_zp/b_zp
|
||||
yBC_zm = 0.5*(1.-b_zm)
|
||||
yBC_zp = 0.5*(1.-1./b_zp)
|
||||
|
||||
sortindsfx = np.argsort(np.r_[np.arange(mesh.nFx)[fxm], np.arange(mesh.nFx)[fxp]])
|
||||
sortindsfy = np.argsort(np.r_[np.arange(mesh.nFy)[fym], np.arange(mesh.nFy)[fyp]])
|
||||
sortindsfz = np.argsort(np.r_[np.arange(mesh.nFz)[fzm], np.arange(mesh.nFz)[fzp]])
|
||||
|
||||
xBC_x = np.r_[xBC_xm, xBC_xp][sortindsfx]
|
||||
xBC_y = np.r_[xBC_ym, xBC_yp][sortindsfy]
|
||||
xBC_z = np.r_[xBC_zm, xBC_zp][sortindsfz]
|
||||
|
||||
yBC_x = np.r_[yBC_xm, yBC_xp][sortindsfx]
|
||||
yBC_y = np.r_[yBC_ym, yBC_yp][sortindsfy]
|
||||
yBC_z = np.r_[yBC_zm, yBC_zp][sortindsfz]
|
||||
|
||||
xBC = np.r_[xBC_x, xBC_y, xBC_z]
|
||||
yBC = np.r_[yBC_x, yBC_y, yBC_z]
|
||||
|
||||
return xBC, yBC
|
||||
@@ -0,0 +1,148 @@
|
||||
import SimPEG
|
||||
from SimPEG.Utils import Identity, Zero
|
||||
import numpy as np
|
||||
from scipy.constants import epsilon_0
|
||||
|
||||
class Fields(SimPEG.Problem.Fields):
|
||||
knownFields = {}
|
||||
dtype = float
|
||||
|
||||
def _phiDeriv(self, src, du_dm_v, v, adjoint=False):
|
||||
if getattr(self, '_phiDeriv_u', None) is None or getattr(self, '_phiDeriv_m', None) is None:
|
||||
raise NotImplementedError ('Getting phiDerivs from %s is not implemented' %self.knownFields.keys()[0])
|
||||
|
||||
if adjoint:
|
||||
return self._phiDeriv_u(src, v, adjoint=adjoint), self._phiDeriv_m(src, v, adjoint=adjoint)
|
||||
|
||||
return np.array(self._phiDeriv_u(src, du_dm_v, adjoint) + self._phiDeriv_m(src, v, adjoint), dtype = float)
|
||||
|
||||
def _eDeriv(self, src, du_dm_v, v, adjoint=False):
|
||||
if getattr(self, '_eDeriv_u', None) is None or getattr(self, '_eDeriv_m', None) is None:
|
||||
raise NotImplementedError ('Getting eDerivs from %s is not implemented' %self.knownFields.keys()[0])
|
||||
|
||||
if adjoint:
|
||||
return self._eDeriv_u(src, v, adjoint), self._eDeriv_m(src, v, adjoint)
|
||||
return np.array(self._eDeriv_u(src, du_dm_v, adjoint) + self._eDeriv_m(src, v, adjoint), dtype = float)
|
||||
|
||||
def _jDeriv(self, src, du_dm_v, v, adjoint=False):
|
||||
if getattr(self, '_jDeriv_u', None) is None or getattr(self, '_jDeriv_m', None) is None:
|
||||
raise NotImplementedError ('Getting jDerivs from %s is not implemented' %self.knownFields.keys()[0])
|
||||
|
||||
if adjoint:
|
||||
return self._jDeriv_u(src, v, adjoint), self._jDeriv_m(src, v, adjoint)
|
||||
return np.array(self._jDeriv_u(src, du_dm_v, adjoint) + self._jDeriv_m(src, v, adjoint), dtype = float)
|
||||
|
||||
|
||||
class Fields_CC(Fields):
|
||||
knownFields = {'phiSolution':'CC'}
|
||||
aliasFields = {
|
||||
'phi': ['phiSolution','CC','_phi'],
|
||||
'j' : ['phiSolution','F','_j'],
|
||||
'e' : ['phiSolution','F','_e'],
|
||||
'charge' : ['phiSolution','CC','_charge'],
|
||||
}
|
||||
# primary - secondary
|
||||
# CC variables
|
||||
|
||||
def __init__(self, mesh, survey, **kwargs):
|
||||
Fields.__init__(self, mesh, survey, **kwargs)
|
||||
mesh.setCellGradBC("neumann")
|
||||
cellGrad = mesh.cellGrad
|
||||
def startup(self):
|
||||
self.prob = self.survey.prob
|
||||
|
||||
def _GLoc(self, fieldType):
|
||||
if fieldType == 'phi':
|
||||
return 'CC'
|
||||
elif fieldType == 'e' or fieldType == 'j':
|
||||
return 'F'
|
||||
else:
|
||||
raise Exception('Field type must be phi, e, j')
|
||||
|
||||
def _phi(self, phiSolution, srcList):
|
||||
return phiSolution
|
||||
|
||||
def _phiDeriv_u(self, src, v, adjoint = False):
|
||||
return Identity()*v
|
||||
|
||||
def _phiDeriv_m(self, src, v, adjoint = False):
|
||||
return Zero()
|
||||
|
||||
def _j(self, phiSolution, srcList):
|
||||
"""
|
||||
.. math::
|
||||
\mathbf{j} = \mathbf{M}^{f \ -1}_{\rho} \mathbf{G} \phi
|
||||
"""
|
||||
return self.prob.MfRhoI*self.prob.Grad*phiSolution
|
||||
|
||||
def _e(self, phiSolution, srcList):
|
||||
"""
|
||||
In HJ formulation e is not well-defined!!
|
||||
.. math::
|
||||
\vec{e} = -\nabla \phi
|
||||
"""
|
||||
return -self.mesh.cellGrad*phiSolution
|
||||
|
||||
def _charge(self, phiSolution, srcList):
|
||||
"""
|
||||
.. math::
|
||||
\int \nabla \codt \vec{e} = \int \frac{\rho_v }{\epsillon_0}
|
||||
"""
|
||||
return epsilon_0*self.prob.Vol*(self.mesh.faceDiv*self._e(phiSolution, srcList))
|
||||
|
||||
class Fields_N(Fields):
|
||||
knownFields = {'phiSolution':'N'}
|
||||
aliasFields = {
|
||||
'phi': ['phiSolution','N','_phi'],
|
||||
'j' : ['phiSolution','E','_j'],
|
||||
'e' : ['phiSolution','E','_e'],
|
||||
'charge' : ['phiSolution','N','_charge'],
|
||||
}
|
||||
# primary - secondary
|
||||
# N variables
|
||||
|
||||
def __init__(self, mesh, survey, **kwargs):
|
||||
Fields.__init__(self, mesh, survey, **kwargs)
|
||||
|
||||
def startup(self):
|
||||
self.prob = self.survey.prob
|
||||
|
||||
def _GLoc(self, fieldType):
|
||||
if fieldType == 'phi':
|
||||
return 'N'
|
||||
elif fieldType == 'e' or fieldType == 'j':
|
||||
return 'E'
|
||||
else:
|
||||
raise Exception('Field type must be phi, e, j')
|
||||
|
||||
def _phi(self, phiSolution, srcList):
|
||||
return phiSolution
|
||||
|
||||
def _phiDeriv_u(self, src, v, adjoint = False):
|
||||
return Identity()*v
|
||||
|
||||
def _phiDeriv_m(self, src, v, adjoint = False):
|
||||
return Zero()
|
||||
|
||||
def _j(self, phiSolution, srcList):
|
||||
"""
|
||||
In EB formulation j is not well-defined!!
|
||||
.. math::
|
||||
\mathbf{j} = - \mathbf{M}^{e}_{\sigma} \mathbf{G} \phi
|
||||
"""
|
||||
return self.prob.MeSigma * self._e(phiSolution, srcList)
|
||||
|
||||
def _e(self, phiSolution, srcList):
|
||||
"""
|
||||
In HJ formulation e is not well-defined!!
|
||||
.. math::
|
||||
\vec{e} = -\nabla \phi
|
||||
"""
|
||||
return -self.mesh.nodalGrad * phiSolution
|
||||
|
||||
def _charge(self, phiSolution, srcList):
|
||||
"""
|
||||
.. math::
|
||||
\int \nabla \codt \vec{e} = \int \frac{\rho_v }{\epsillon_0}
|
||||
"""
|
||||
return - epsilon_0*(self.mesh.nodalGrad.T*self.mesh.getEdgeInnerProduct()*self._e(phiSolution, srcList))
|
||||
@@ -0,0 +1,146 @@
|
||||
import SimPEG
|
||||
from SimPEG.Utils import Identity, Zero
|
||||
import numpy as np
|
||||
|
||||
class Fields_ky(SimPEG.Problem.TimeFields):
|
||||
|
||||
"""
|
||||
|
||||
Fancy Field Storage for a 2.5D code.
|
||||
|
||||
u[:,'phi', kyInd] = phi
|
||||
print u[src0,'phi']
|
||||
|
||||
Only one field type is stored for
|
||||
each problem, the rest are computed. The fields obejct acts like an array and is indexed by
|
||||
.. code-block:: python
|
||||
f = problem.fields(m)
|
||||
e = f[srcList,'e']
|
||||
j = f[srcList,'j']
|
||||
|
||||
If accessing all sources for a given field, use the :code:`:`
|
||||
.. code-block:: python
|
||||
f = problem.fields(m)
|
||||
phi = f[:,'phi']
|
||||
e = f[:,'e']
|
||||
b = f[:,'b']
|
||||
The array returned will be size (nE or nF, nSrcs :math:`\\times` nFrequencies)
|
||||
"""
|
||||
|
||||
knownFields = {}
|
||||
dtype = float
|
||||
|
||||
def _phiDeriv(self,kyInd, src, du_dm_v, v, adjoint=False):
|
||||
if getattr(self, '_phiDeriv_u', None) is None or getattr(self, '_phiDeriv_m', None) is None:
|
||||
raise NotImplementedError ('Getting phiDerivs from %s is not implemented' %self.knownFields.keys()[0])
|
||||
|
||||
if adjoint:
|
||||
return self._phiDeriv_u(kyInd, src, v, adjoint=adjoint), self._phiDeriv_m(kyInd, src, v, adjoint=adjoint)
|
||||
|
||||
return np.array(self._phiDeriv_u(kyInd, src, du_dm_v, adjoint) + self._phiDeriv_m(kyInd, src, v, adjoint), dtype = float)
|
||||
|
||||
def _eDeriv(self,kyInd, src, du_dm_v, v, adjoint=False):
|
||||
if getattr(self, '_eDeriv_u', None) is None or getattr(self, '_eDeriv_m', None) is None:
|
||||
raise NotImplementedError ('Getting eDerivs from %s is not implemented' %self.knownFields.keys()[0])
|
||||
|
||||
if adjoint:
|
||||
return self._eDeriv_u(kyInd, src, v, adjoint), self._eDeriv_m(kyInd, src, v, adjoint)
|
||||
return np.array(self._eDeriv_u(kyInd, src, du_dm_v, adjoint) + self._eDeriv_m(kyInd, src, v, adjoint), dtype = float)
|
||||
|
||||
def _jDeriv(self,kyInd, src, du_dm_v, v, adjoint=False):
|
||||
if getattr(self, '_jDeriv_u', None) is None or getattr(self, '_jDeriv_m', None) is None:
|
||||
raise NotImplementedError ('Getting jDerivs from %s is not implemented' %self.knownFields.keys()[0])
|
||||
|
||||
if adjoint:
|
||||
return self._jDeriv_u(kyInd, src, v, adjoint), self._jDeriv_m(kyInd, src, v, adjoint)
|
||||
return np.array(self._jDeriv_u(kyInd, src, du_dm_v, adjoint) + self._jDeriv_m(kyInd, src, v, adjoint), dtype = float)
|
||||
|
||||
|
||||
# def _eDeriv(self, tInd, src, dun_dm_v, v, adjoint=False):
|
||||
# if adjoint is True:
|
||||
# return self._eDeriv_u(tInd, src, v, adjoint), self._eDeriv_m(tInd, src, v, adjoint)
|
||||
# return self._eDeriv_u(tInd, src, dun_dm_v) + self._eDeriv_m(tInd, src, v)
|
||||
|
||||
# def _bDeriv(self, tInd, src, dun_dm_v, v, adjoint=False):
|
||||
# if adjoint is True:
|
||||
# return self._bDeriv_u(tInd, src, v, adjoint), self._bDeriv_m(tInd, src, v, adjoint)
|
||||
# return self._bDeriv_u(tInd, src, dun_dm_v) + self._bDeriv_m(tInd, src, v)
|
||||
|
||||
|
||||
class Fields_ky_CC(Fields_ky):
|
||||
knownFields = {'phiSolution':'CC'}
|
||||
aliasFields = {
|
||||
'phi': ['phiSolution','CC','_phi'],
|
||||
'j' : ['phiSolution','F','_j'],
|
||||
'e' : ['phiSolution','F','_e'],
|
||||
}
|
||||
# primary - secondary
|
||||
# CC variables
|
||||
|
||||
def __init__(self, mesh, survey, **kwargs):
|
||||
Fields_ky.__init__(self, mesh, survey, **kwargs)
|
||||
|
||||
def startup(self):
|
||||
self.prob = self.survey.prob
|
||||
|
||||
def _GLoc(self, fieldType):
|
||||
if fieldType == 'phi':
|
||||
return 'CC'
|
||||
elif fieldType == 'e' or fieldType == 'j':
|
||||
return 'F'
|
||||
else:
|
||||
raise Exception('Field type must be phi, e, j')
|
||||
|
||||
def _phi(self, phiSolution, src, kyInd):
|
||||
return phiSolution
|
||||
|
||||
def _phiDeriv_u(self, kyInd, src, v, adjoint = False):
|
||||
return Identity()*v
|
||||
|
||||
def _phiDeriv_m(self, kyInd, src, v, adjoint = False):
|
||||
return Zero()
|
||||
|
||||
def _j(self, phiSolution, srcList):
|
||||
raise NotImplementedError
|
||||
|
||||
def _e(self, phiSolution, srcList):
|
||||
raise NotImplementedError
|
||||
|
||||
class Fields_ky_N(Fields_ky):
|
||||
knownFields = {'phiSolution':'N'}
|
||||
aliasFields = {
|
||||
'phi': ['phiSolution','N','_phi'],
|
||||
'j' : ['phiSolution','E','_j'],
|
||||
'e' : ['phiSolution','E','_e'],
|
||||
}
|
||||
# primary - secondary
|
||||
# CC variables
|
||||
|
||||
def __init__(self, mesh, survey, **kwargs):
|
||||
Fields_ky.__init__(self, mesh, survey, **kwargs)
|
||||
|
||||
def startup(self):
|
||||
self.prob = self.survey.prob
|
||||
|
||||
def _GLoc(self, fieldType):
|
||||
if fieldType == 'phi':
|
||||
return 'N'
|
||||
elif fieldType == 'e' or fieldType == 'j':
|
||||
return 'E'
|
||||
else:
|
||||
raise Exception('Field type must be phi, e, j')
|
||||
|
||||
def _phi(self, phiSolution, src, kyInd):
|
||||
return phiSolution
|
||||
|
||||
def _phiDeriv_u(self, kyInd, src, v, adjoint = False):
|
||||
return Identity()*v
|
||||
|
||||
def _phiDeriv_m(self, kyInd, src, v, adjoint = False):
|
||||
return Zero()
|
||||
|
||||
def _j(self, phiSolution, srcList):
|
||||
raise NotImplementedError
|
||||
|
||||
def _e(self, phiSolution, srcList):
|
||||
raise NotImplementedError
|
||||
@@ -0,0 +1,307 @@
|
||||
from SimPEG import Problem, Utils
|
||||
from SimPEG.EM.Base import BaseEMProblem
|
||||
from SurveyDC import Survey
|
||||
from FieldsDC import Fields, Fields_CC, Fields_N
|
||||
from SimPEG.Utils import sdiag
|
||||
import numpy as np
|
||||
from SimPEG.Utils import Zero
|
||||
from BoundaryUtils import getxBCyBC_CC
|
||||
|
||||
class BaseDCProblem(BaseEMProblem):
|
||||
|
||||
surveyPair = Survey
|
||||
fieldsPair = Fields
|
||||
Ainv = None
|
||||
|
||||
def fields(self, m):
|
||||
self.curModel = m
|
||||
|
||||
if not self.Ainv == None:
|
||||
self.Ainv.clean()
|
||||
|
||||
f = self.fieldsPair(self.mesh, self.survey)
|
||||
A = self.getA()
|
||||
self.Ainv = self.Solver(A, **self.solverOpts)
|
||||
RHS = self.getRHS()
|
||||
u = self.Ainv * RHS
|
||||
Srcs = self.survey.srcList
|
||||
f[Srcs, self._solutionType] = u
|
||||
return f
|
||||
|
||||
def Jvec(self, m, v, f=None):
|
||||
|
||||
if f is None:
|
||||
f = self.fields(m)
|
||||
|
||||
self.curModel = m
|
||||
|
||||
Jv = self.dataPair(self.survey) #same size as the data
|
||||
|
||||
A = self.getA()
|
||||
|
||||
for src in self.survey.srcList:
|
||||
u_src = f[src, self._solutionType] # solution vector
|
||||
dA_dm_v = self.getADeriv(u_src, v)
|
||||
dRHS_dm_v = self.getRHSDeriv(src, v)
|
||||
du_dm_v = self.Ainv * ( - dA_dm_v + dRHS_dm_v )
|
||||
|
||||
for rx in src.rxList:
|
||||
df_dmFun = getattr(f, '_%sDeriv'%rx.projField, None)
|
||||
df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False)
|
||||
Jv[src, rx] = rx.evalDeriv(src, self.mesh, f, df_dm_v)
|
||||
return Utils.mkvc(Jv)
|
||||
|
||||
def Jtvec(self, m, v, f=None):
|
||||
if f is None:
|
||||
f = self.fields(m)
|
||||
|
||||
self.curModel = m
|
||||
|
||||
# Ensure v is a data object.
|
||||
if not isinstance(v, self.dataPair):
|
||||
v = self.dataPair(self.survey, v)
|
||||
|
||||
Jtv = np.zeros(m.size)
|
||||
AT = self.getA()
|
||||
|
||||
|
||||
for src in self.survey.srcList:
|
||||
u_src = f[src, self._solutionType]
|
||||
for rx in src.rxList:
|
||||
PTv = rx.evalDeriv(src, self.mesh, f, v[src, rx], adjoint=True) # wrt f, need possibility wrt m
|
||||
df_duTFun = getattr(f, '_%sDeriv'%rx.projField, None)
|
||||
df_duT, df_dmT = df_duTFun(src, None, PTv, adjoint=True)
|
||||
|
||||
ATinvdf_duT = self.Ainv * df_duT
|
||||
|
||||
dA_dmT = self.getADeriv(u_src, ATinvdf_duT, adjoint=True)
|
||||
dRHS_dmT = self.getRHSDeriv(src, ATinvdf_duT, adjoint=True)
|
||||
du_dmT = -dA_dmT + dRHS_dmT
|
||||
Jtv += (df_dmT + du_dmT).astype(float)
|
||||
|
||||
return Utils.mkvc(Jtv)
|
||||
|
||||
def getSourceTerm(self):
|
||||
"""
|
||||
takes concept of source and turns it into a matrix
|
||||
"""
|
||||
"""
|
||||
Evaluates the sources, and puts them in matrix form
|
||||
|
||||
:rtype: (numpy.ndarray, numpy.ndarray)
|
||||
:return: q (nC or nN, nSrc)
|
||||
"""
|
||||
|
||||
Srcs = self.survey.srcList
|
||||
|
||||
if self._formulation is 'EB':
|
||||
n = self.mesh.nN
|
||||
# return NotImplementedError
|
||||
|
||||
elif self._formulation is 'HJ':
|
||||
n = self.mesh.nC
|
||||
|
||||
q = np.zeros((n, len(Srcs)))
|
||||
|
||||
for i, src in enumerate(Srcs):
|
||||
q[:,i] = src.eval(self)
|
||||
return q
|
||||
|
||||
class Problem3D_CC(BaseDCProblem):
|
||||
|
||||
_solutionType = 'phiSolution'
|
||||
_formulation = 'HJ' # CC potentials means J is on faces
|
||||
fieldsPair = Fields_CC
|
||||
|
||||
def __init__(self, mesh, **kwargs):
|
||||
BaseDCProblem.__init__(self, mesh, **kwargs)
|
||||
self.setBC()
|
||||
|
||||
def getA(self):
|
||||
"""
|
||||
|
||||
Make the A matrix for the cell centered DC resistivity problem
|
||||
|
||||
A = D MfRhoI D^\\top V
|
||||
|
||||
"""
|
||||
|
||||
D = self.Div
|
||||
G = self.Grad
|
||||
# TODO: this won't work for full anisotropy
|
||||
MfRhoI = self.MfRhoI
|
||||
A = D * MfRhoI * G
|
||||
|
||||
# I think we should deprecate this for DC problem.
|
||||
# if self._makeASymmetric is True:
|
||||
# return V.T * A
|
||||
return A
|
||||
|
||||
def getADeriv(self, u, v, adjoint= False):
|
||||
|
||||
D = self.Div
|
||||
G = self.Grad
|
||||
MfRhoIDeriv = self.MfRhoIDeriv
|
||||
|
||||
if adjoint:
|
||||
# if self._makeASymmetric is True:
|
||||
# v = V * v
|
||||
return(MfRhoIDeriv( G * u ).T) * ( D.T * v)
|
||||
|
||||
# I think we should deprecate this for DC problem.
|
||||
# if self._makeASymmetric is True:
|
||||
# return V.T * ( D * ( MfRhoIDeriv( D.T * ( V * u ) ) * v ) )
|
||||
return D * (MfRhoIDeriv( G * u ) * v)
|
||||
|
||||
def getRHS(self):
|
||||
"""
|
||||
RHS for the DC problem
|
||||
|
||||
q
|
||||
"""
|
||||
|
||||
RHS = self.getSourceTerm()
|
||||
|
||||
# I think we should deprecate this for DC problem.
|
||||
# if self._makeASymmetric is True:
|
||||
# return self.Vol.T * RHS
|
||||
|
||||
return RHS
|
||||
|
||||
def getRHSDeriv(self, src, v, adjoint=False):
|
||||
"""
|
||||
Derivative of the right hand side with respect to the model
|
||||
"""
|
||||
# TODO: add qDeriv for RHS depending on m
|
||||
# qDeriv = src.evalDeriv(self, adjoint=adjoint)
|
||||
# return qDeriv
|
||||
return Zero()
|
||||
|
||||
def setBC(self):
|
||||
if self.mesh.dim==3:
|
||||
fxm,fxp,fym,fyp,fzm,fzp = self.mesh.faceBoundaryInd
|
||||
gBFxm = self.mesh.gridFx[fxm,:]
|
||||
gBFxp = self.mesh.gridFx[fxp,:]
|
||||
gBFym = self.mesh.gridFy[fym,:]
|
||||
gBFyp = self.mesh.gridFy[fyp,:]
|
||||
gBFzm = self.mesh.gridFz[fzm,:]
|
||||
gBFzp = self.mesh.gridFz[fzp,:]
|
||||
|
||||
# Setup Mixed B.C (alpha, beta, gamma)
|
||||
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
|
||||
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
|
||||
temp_zm, temp_zp = np.ones_like(gBFzm[:,2]), np.ones_like(gBFzp[:,2])
|
||||
|
||||
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
|
||||
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
|
||||
alpha_zm, alpha_zp = temp_zm*0., temp_zp*0.
|
||||
|
||||
beta_xm, beta_xp = temp_xm, temp_xp
|
||||
beta_ym, beta_yp = temp_ym, temp_yp
|
||||
beta_zm, beta_zp = temp_zm, temp_zp
|
||||
|
||||
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
|
||||
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
|
||||
gamma_zm, gamma_zp = temp_zm*0., temp_zp*0.
|
||||
|
||||
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp, alpha_zm, alpha_zp]
|
||||
beta = [beta_xm, beta_xp, beta_ym, beta_yp, beta_zm, beta_zp]
|
||||
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp, gamma_zm, gamma_zp]
|
||||
|
||||
elif self.mesh.dim==2:
|
||||
|
||||
fxm,fxp,fym,fyp = self.mesh.faceBoundaryInd
|
||||
gBFxm = self.mesh.gridFx[fxm,:]
|
||||
gBFxp = self.mesh.gridFx[fxp,:]
|
||||
gBFym = self.mesh.gridFy[fym,:]
|
||||
gBFyp = self.mesh.gridFy[fyp,:]
|
||||
|
||||
# Setup Mixed B.C (alpha, beta, gamma)
|
||||
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
|
||||
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
|
||||
|
||||
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
|
||||
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
|
||||
|
||||
beta_xm, beta_xp = temp_xm, temp_xp
|
||||
beta_ym, beta_yp = temp_ym, temp_yp
|
||||
|
||||
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
|
||||
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
|
||||
|
||||
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp]
|
||||
beta = [beta_xm, beta_xp, beta_ym, beta_yp]
|
||||
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp]
|
||||
|
||||
x_BC, y_BC = getxBCyBC_CC(self.mesh, alpha, beta, gamma)
|
||||
V = self.Vol
|
||||
self.Div = V * self.mesh.faceDiv
|
||||
P_BC, B = self.mesh.getBCProjWF_simple()
|
||||
M = B*self.mesh.aveCC2F
|
||||
self.Grad = self.Div.T - P_BC*Utils.sdiag(y_BC)*M
|
||||
|
||||
|
||||
class Problem3D_N(BaseDCProblem):
|
||||
|
||||
_solutionType = 'phiSolution'
|
||||
_formulation = 'EB' # N potentials means B is on faces
|
||||
fieldsPair = Fields_N
|
||||
|
||||
def __init__(self, mesh, **kwargs):
|
||||
BaseDCProblem.__init__(self, mesh, **kwargs)
|
||||
|
||||
def getA(self):
|
||||
"""
|
||||
|
||||
Make the A matrix for the cell centered DC resistivity problem
|
||||
|
||||
A = D MfRhoI D^\\top V
|
||||
|
||||
"""
|
||||
|
||||
# TODO: this won't work for full anisotropy
|
||||
MeSigma = self.MeSigma
|
||||
Grad = self.mesh.nodalGrad
|
||||
A = Grad.T * MeSigma * Grad
|
||||
|
||||
# Handling Null space of A
|
||||
A[0,0] = A[0,0] + 1.
|
||||
|
||||
return A
|
||||
|
||||
def getADeriv(self, u, v, adjoint=False):
|
||||
"""
|
||||
|
||||
Product of the derivative of our system matrix with respect to the model and a vector
|
||||
|
||||
"""
|
||||
MeSigma = self.MeSigma
|
||||
Grad = self.mesh.nodalGrad
|
||||
if not adjoint:
|
||||
return Grad.T*(self.MeSigmaDeriv(Grad*u)*v)
|
||||
elif adjoint:
|
||||
return self.MeSigmaDeriv(Grad*u).T * (Grad*v)
|
||||
|
||||
|
||||
def getRHS(self):
|
||||
"""
|
||||
RHS for the DC problem
|
||||
|
||||
q
|
||||
"""
|
||||
|
||||
RHS = self.getSourceTerm()
|
||||
return RHS
|
||||
|
||||
def getRHSDeriv(self, src, v, adjoint=False):
|
||||
"""
|
||||
Derivative of the right hand side with respect to the model
|
||||
"""
|
||||
# TODO: add qDeriv for RHS depending on m
|
||||
# qDeriv = src.evalDeriv(self, adjoint=adjoint)
|
||||
# return qDeriv
|
||||
return Zero()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,351 @@
|
||||
from SimPEG import Problem, Utils
|
||||
from SimPEG.EM.Base import BaseEMProblem
|
||||
from SurveyDC import Survey, Survey_ky
|
||||
from FieldsDC_2D import Fields_ky, Fields_ky_CC, Fields_ky_N
|
||||
from SimPEG.Utils import sdiag
|
||||
import numpy as np
|
||||
from SimPEG.Utils import Zero
|
||||
from BoundaryUtils import getxBCyBC_CC
|
||||
|
||||
class BaseDCProblem_2D(BaseEMProblem):
|
||||
|
||||
surveyPair = Survey_ky
|
||||
fieldsPair = Fields_ky
|
||||
nky = 15
|
||||
kys = np.logspace(-4, 1, nky)
|
||||
Ainv = [None for i in range(nky)]
|
||||
nT = nky # Only for using TimeFields
|
||||
|
||||
def fields(self, m):
|
||||
self.curModel = m
|
||||
|
||||
if not self.Ainv[0] == None:
|
||||
for i in range(self.nky):
|
||||
self.Ainv[i].clean()
|
||||
|
||||
f = self.fieldsPair(self.mesh, self.survey)
|
||||
Srcs = self.survey.srcList
|
||||
for iky in range(self.nky):
|
||||
ky = self.kys[iky]
|
||||
A = self.getA(ky)
|
||||
self.Ainv[iky] = self.Solver(A, **self.solverOpts)
|
||||
RHS = self.getRHS(ky)
|
||||
u = self.Ainv[iky] * RHS
|
||||
f[Srcs, self._solutionType, iky] = u
|
||||
return f
|
||||
|
||||
def Jvec(self, m, v, f=None):
|
||||
|
||||
if f is None:
|
||||
f = self.fields(m)
|
||||
|
||||
self.curModel = m
|
||||
|
||||
Jv = self.dataPair(self.survey) #same size as the data
|
||||
Jv0 = self.dataPair(self.survey)
|
||||
|
||||
# Assume y=0.
|
||||
# This needs some thoughts to implement in general when src is dipole
|
||||
dky = np.diff(self.kys)
|
||||
dky = np.r_[dky[0], dky]
|
||||
y = 0.
|
||||
|
||||
#TODO: this loop is pretty slow .. (Parellize)
|
||||
for iky in range(self.nky):
|
||||
ky = self.kys[iky]
|
||||
A = self.getA(ky)
|
||||
for src in self.survey.srcList:
|
||||
u_src = f[src, self._solutionType, iky] # solution vector
|
||||
dA_dm_v = self.getADeriv(ky, u_src, v)
|
||||
dRHS_dm_v = self.getRHSDeriv(ky, src, v)
|
||||
du_dm_v = self.Ainv[iky] * ( - dA_dm_v + dRHS_dm_v )
|
||||
for rx in src.rxList:
|
||||
df_dmFun = getattr(f, '_%sDeriv'%rx.projField, None)
|
||||
df_dm_v = df_dmFun(iky, src, du_dm_v, v, adjoint=False)
|
||||
# Trapezoidal intergration
|
||||
Jv1_temp = 1./np.pi*rx.evalDeriv(ky, src, self.mesh, f, df_dm_v)
|
||||
if iky==0:
|
||||
#First assigment
|
||||
Jv[src, rx] = Jv1_temp*dky[iky]*np.cos(ky*y)
|
||||
else:
|
||||
Jv[src, rx] += Jv1_temp*dky[iky] /2.*np.cos(ky*y)
|
||||
Jv[src, rx] += Jv0[src, rx]*dky[iky]/2.*np.cos(ky*y)
|
||||
Jv0[src, rx] = Jv1_temp.copy()
|
||||
return Utils.mkvc(Jv)
|
||||
|
||||
def Jtvec(self, m, v, f=None):
|
||||
if f is None:
|
||||
f = self.fields(m)
|
||||
|
||||
self.curModel = m
|
||||
|
||||
# Ensure v is a data object.
|
||||
if not isinstance(v, self.dataPair):
|
||||
v = self.dataPair(self.survey, v)
|
||||
|
||||
Jtv = np.zeros(m.size, dtype=float)
|
||||
|
||||
# Assume y=0.
|
||||
# This needs some thoughts to implement in general when src is dipole
|
||||
dky = np.diff(self.kys)
|
||||
dky = np.r_[dky[0], dky]
|
||||
y = 0.
|
||||
|
||||
for src in self.survey.srcList:
|
||||
for rx in src.rxList:
|
||||
Jtv_temp1 = np.zeros(m.size, dtype=float)
|
||||
Jtv_temp0 = np.zeros(m.size, dtype=float)
|
||||
#TODO: this loop is pretty slow .. (Parellize)
|
||||
for iky in range(self.nky):
|
||||
u_src = f[src, self._solutionType, iky]
|
||||
ky = self.kys[iky]
|
||||
AT = self.getA(ky)
|
||||
PTv = rx.evalDeriv(ky, src, self.mesh, f, v[src, rx], adjoint=True) # wrt f, need possibility wrt m
|
||||
df_duTFun = getattr(f, '_%sDeriv'%rx.projField, None)
|
||||
df_duT, df_dmT = df_duTFun(iky, src, None, PTv, adjoint=True)
|
||||
|
||||
ATinvdf_duT = self.Ainv[iky] * df_duT
|
||||
|
||||
dA_dmT = self.getADeriv(ky, u_src, ATinvdf_duT, adjoint=True)
|
||||
dRHS_dmT = self.getRHSDeriv(ky, src, ATinvdf_duT, adjoint=True)
|
||||
du_dmT = -dA_dmT + dRHS_dmT
|
||||
Jtv_temp1 = 1./np.pi*(df_dmT + du_dmT).astype(float)
|
||||
# Trapezoidal intergration
|
||||
if iky==0:
|
||||
#First assigment
|
||||
Jtv += Jtv_temp1*dky[iky]*np.cos(ky*y)
|
||||
else:
|
||||
Jtv += Jtv_temp1*dky[iky]/2.*np.cos(ky*y)
|
||||
Jtv += Jtv_temp0*dky[iky]/2.*np.cos(ky*y)
|
||||
Jtv_temp0 = Jtv_temp1.copy()
|
||||
return Utils.mkvc(Jtv)
|
||||
|
||||
def getSourceTerm(self, ky):
|
||||
"""
|
||||
takes concept of source and turns it into a matrix
|
||||
"""
|
||||
"""
|
||||
Evaluates the sources, and puts them in matrix form
|
||||
|
||||
:rtype: (numpy.ndarray, numpy.ndarray)
|
||||
:return: q (nC or nN, nSrc)
|
||||
"""
|
||||
|
||||
Srcs = self.survey.srcList
|
||||
|
||||
if self._formulation is 'EB':
|
||||
n = self.mesh.nN
|
||||
# return NotImplementedError
|
||||
|
||||
elif self._formulation is 'HJ':
|
||||
n = self.mesh.nC
|
||||
|
||||
q = np.zeros((n, len(Srcs)))
|
||||
|
||||
for i, src in enumerate(Srcs):
|
||||
q[:,i] = src.eval(self)
|
||||
return q
|
||||
|
||||
class Problem2D_CC(BaseDCProblem_2D):
|
||||
|
||||
_solutionType = 'phiSolution'
|
||||
_formulation = 'HJ' # CC potentials means J is on faces
|
||||
fieldsPair = Fields_ky_CC
|
||||
|
||||
def __init__(self, mesh, **kwargs):
|
||||
BaseDCProblem_2D.__init__(self, mesh, **kwargs)
|
||||
self.setBC()
|
||||
|
||||
def getA(self, ky):
|
||||
"""
|
||||
|
||||
Make the A matrix for the cell centered DC resistivity problem
|
||||
|
||||
A = D MfRhoI D^\\top V
|
||||
|
||||
"""
|
||||
|
||||
D = self.Div
|
||||
G = self.Grad
|
||||
vol = self.mesh.vol
|
||||
# TODO: this won't work for full anisotropy
|
||||
MfRhoI = self.MfRhoI
|
||||
# Get resistivity rho
|
||||
rho = self.curModel.rho
|
||||
A = D * MfRhoI * G + Utils.sdiag(ky**2*vol/rho)
|
||||
return A
|
||||
|
||||
def getADeriv(self, ky, u, v, adjoint= False):
|
||||
|
||||
D = self.Div
|
||||
G = self.Grad
|
||||
vol = self.mesh.vol
|
||||
MfRhoIDeriv = self.MfRhoIDeriv
|
||||
rho = self.curModel.rho
|
||||
if adjoint:
|
||||
return(MfRhoIDeriv( G * u ).T) * ( D.T * v) + ky**2*Utils.sdiag(u.flatten()*vol*(-1./rho**2))*v
|
||||
return D * ((MfRhoIDeriv( G * u )) * v) + ky**2*Utils.sdiag(u.flatten()*vol*(-1./rho**2))*v
|
||||
|
||||
def getRHS(self, ky):
|
||||
"""
|
||||
RHS for the DC problem
|
||||
|
||||
q
|
||||
"""
|
||||
|
||||
RHS = self.getSourceTerm(ky)
|
||||
return RHS
|
||||
|
||||
def getRHSDeriv(self, ky, src, v, adjoint=False):
|
||||
"""
|
||||
Derivative of the right hand side with respect to the model
|
||||
"""
|
||||
# TODO: add qDeriv for RHS depending on m
|
||||
# qDeriv = src.evalDeriv(self, ky, adjoint=adjoint)
|
||||
# return qDeriv
|
||||
return Zero()
|
||||
|
||||
def setBC(self):
|
||||
if self.mesh.dim==3:
|
||||
fxm,fxp,fym,fyp,fzm,fzp = self.mesh.faceBoundaryInd
|
||||
gBFxm = self.mesh.gridFx[fxm,:]
|
||||
gBFxp = self.mesh.gridFx[fxp,:]
|
||||
gBFym = self.mesh.gridFy[fym,:]
|
||||
gBFyp = self.mesh.gridFy[fyp,:]
|
||||
gBFzm = self.mesh.gridFz[fzm,:]
|
||||
gBFzp = self.mesh.gridFz[fzp,:]
|
||||
|
||||
# Setup Mixed B.C (alpha, beta, gamma)
|
||||
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
|
||||
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
|
||||
temp_zm, temp_zp = np.ones_like(gBFzm[:,2]), np.ones_like(gBFzp[:,2])
|
||||
|
||||
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
|
||||
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
|
||||
alpha_zm, alpha_zp = temp_zm*0., temp_zp*0.
|
||||
|
||||
beta_xm, beta_xp = temp_xm, temp_xp
|
||||
beta_ym, beta_yp = temp_ym, temp_yp
|
||||
beta_zm, beta_zp = temp_zm, temp_zp
|
||||
|
||||
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
|
||||
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
|
||||
gamma_zm, gamma_zp = temp_zm*0., temp_zp*0.
|
||||
|
||||
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp, alpha_zm, alpha_zp]
|
||||
beta = [beta_xm, beta_xp, beta_ym, beta_yp, beta_zm, beta_zp]
|
||||
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp, gamma_zm, gamma_zp]
|
||||
|
||||
elif self.mesh.dim==2:
|
||||
|
||||
fxm,fxp,fym,fyp = self.mesh.faceBoundaryInd
|
||||
gBFxm = self.mesh.gridFx[fxm,:]
|
||||
gBFxp = self.mesh.gridFx[fxp,:]
|
||||
gBFym = self.mesh.gridFy[fym,:]
|
||||
gBFyp = self.mesh.gridFy[fyp,:]
|
||||
|
||||
# Setup Mixed B.C (alpha, beta, gamma)
|
||||
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
|
||||
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
|
||||
|
||||
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
|
||||
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
|
||||
|
||||
beta_xm, beta_xp = temp_xm, temp_xp
|
||||
beta_ym, beta_yp = temp_ym, temp_yp
|
||||
|
||||
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
|
||||
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
|
||||
|
||||
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp]
|
||||
beta = [beta_xm, beta_xp, beta_ym, beta_yp]
|
||||
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp]
|
||||
|
||||
x_BC, y_BC = getxBCyBC_CC(self.mesh, alpha, beta, gamma)
|
||||
V = self.Vol
|
||||
self.Div = V * self.mesh.faceDiv
|
||||
P_BC, B = self.mesh.getBCProjWF_simple()
|
||||
M = B*self.mesh.aveCC2F
|
||||
self.Grad = self.Div.T - P_BC*Utils.sdiag(y_BC)*M
|
||||
|
||||
class Problem2D_N(BaseDCProblem_2D):
|
||||
|
||||
_solutionType = 'phiSolution'
|
||||
_formulation = 'EB' # CC potentials means J is on faces
|
||||
fieldsPair = Fields_ky_N
|
||||
|
||||
def __init__(self, mesh, **kwargs):
|
||||
BaseDCProblem_2D.__init__(self, mesh, **kwargs)
|
||||
# self.setBC()
|
||||
|
||||
@property
|
||||
def MnSigma(self):
|
||||
"""
|
||||
Node inner product matrix for \\(\\sigma\\). Used in the E-B formulation
|
||||
"""
|
||||
# TODO: only works isotropic sigma
|
||||
sigma = self.curModel.sigma
|
||||
vol = self.mesh.vol
|
||||
MnSigma = Utils.sdiag(self.mesh.aveN2CC.T*(Utils.sdiag(vol)*sigma))
|
||||
|
||||
return MnSigma
|
||||
|
||||
def MnSigmaDeriv(self, u):
|
||||
"""
|
||||
Derivative of MnSigma with respect to the model
|
||||
"""
|
||||
sigma = self.curModel.sigma
|
||||
sigmaderiv = self.curModel.sigmaDeriv
|
||||
vol = self.mesh.vol
|
||||
return Utils.sdiag(u)*self.mesh.aveN2CC.T*Utils.sdiag(vol) * self.curModel.sigmaDeriv
|
||||
|
||||
def getA(self, ky):
|
||||
"""
|
||||
|
||||
Make the A matrix for the cell centered DC resistivity problem
|
||||
|
||||
A = D MfRhoI D^\\top V
|
||||
|
||||
"""
|
||||
|
||||
# TODO: this won't work for full anisotropy
|
||||
MeSigma = self.MeSigma
|
||||
MnSigma = self.MnSigma
|
||||
Grad = self.mesh.nodalGrad
|
||||
# Get conductivity sigma
|
||||
sigma = self.curModel.sigma
|
||||
A = Grad.T * MeSigma * Grad + ky**2*MnSigma
|
||||
|
||||
# Handling Null space of A
|
||||
A[0,0] = A[0,0] + 1.
|
||||
return A
|
||||
|
||||
def getADeriv(self, ky, u, v, adjoint= False):
|
||||
|
||||
MeSigma = self.MeSigma
|
||||
Grad = self.mesh.nodalGrad
|
||||
sigma = self.curModel.sigma
|
||||
vol = self.mesh.vol
|
||||
|
||||
if adjoint:
|
||||
return self.MeSigmaDeriv(Grad*u).T * (Grad*v) + ky**2*self.MnSigmaDeriv(u).T*v
|
||||
return Grad.T*(self.MeSigmaDeriv(Grad*u)*v) + ky**2*self.MnSigmaDeriv(u)*v
|
||||
|
||||
def getRHS(self, ky):
|
||||
"""
|
||||
RHS for the DC problem
|
||||
|
||||
q
|
||||
"""
|
||||
|
||||
RHS = self.getSourceTerm(ky)
|
||||
return RHS
|
||||
|
||||
def getRHSDeriv(self, ky, src, v, adjoint=False):
|
||||
"""
|
||||
Derivative of the right hand side with respect to the model
|
||||
"""
|
||||
# TODO: add qDeriv for RHS depending on m
|
||||
# qDeriv = src.evalDeriv(self, ky, adjoint=adjoint)
|
||||
# return qDeriv
|
||||
return Zero()
|
||||
@@ -0,0 +1,129 @@
|
||||
import SimPEG
|
||||
import numpy as np
|
||||
from SimPEG.Utils import Zero, closestPoints
|
||||
|
||||
class BaseRx(SimPEG.Survey.BaseRx):
|
||||
locs = None
|
||||
rxType = None
|
||||
|
||||
knownRxTypes = {
|
||||
'phi':['phi',None],
|
||||
'ex':['e','x'],
|
||||
'ey':['e','y'],
|
||||
'ez':['e','z'],
|
||||
'jx':['j','x'],
|
||||
'jy':['j','y'],
|
||||
'jz':['j','z'],
|
||||
}
|
||||
|
||||
def __init__(self, locs, rxType, **kwargs):
|
||||
SimPEG.Survey.BaseRx.__init__(self, locs, rxType, **kwargs)
|
||||
|
||||
|
||||
@property
|
||||
def projField(self):
|
||||
"""Field Type projection (e.g. e b ...)"""
|
||||
return self.knownRxTypes[self.rxType][0]
|
||||
|
||||
def projGLoc(self, f):
|
||||
"""Grid Location projection (e.g. Ex Fy ...)"""
|
||||
comp = self.knownRxTypes[self.rxType][1]
|
||||
if comp is not None:
|
||||
return f._GLoc(self.rxType) + comp
|
||||
return f._GLoc(self.rxType)
|
||||
|
||||
def eval(self, src, mesh, f):
|
||||
P = self.getP(mesh, self.projGLoc(f))
|
||||
return P*f[src, self.projField]
|
||||
|
||||
def evalDeriv(self, src, mesh, f, v, adjoint=False):
|
||||
P = self.getP(mesh, self.projGLoc(f))
|
||||
if not adjoint:
|
||||
return P*v
|
||||
elif adjoint:
|
||||
return P.T*v
|
||||
|
||||
# DC.Rx.Dipole(locs)
|
||||
class Dipole(BaseRx):
|
||||
|
||||
def __init__(self, locsM, locsN, rxType = 'phi', **kwargs):
|
||||
assert locsM.shape == locsN.shape, 'locsM and locsN need to be the same size'
|
||||
locs = [locsM, locsN]
|
||||
# We may not need this ...
|
||||
BaseRx.__init__(self, locs, rxType)
|
||||
|
||||
@property
|
||||
def nD(self):
|
||||
"""Number of data in the receiver."""
|
||||
return self.locs[0].shape[0]
|
||||
|
||||
# Not sure why ...
|
||||
# return int(self.locs[0].size / 2)
|
||||
|
||||
|
||||
def getP(self, mesh, Gloc):
|
||||
if mesh in self._Ps:
|
||||
return self._Ps[mesh]
|
||||
|
||||
P0 = mesh.getInterpolationMat(self.locs[0], Gloc)
|
||||
P1 = mesh.getInterpolationMat(self.locs[1], Gloc)
|
||||
P = P0 - P1
|
||||
|
||||
if self.storeProjections:
|
||||
self._Ps[mesh] = P
|
||||
|
||||
return P
|
||||
|
||||
|
||||
class Dipole_ky(BaseRx):
|
||||
|
||||
def __init__(self, locsM, locsN, rxType = 'phi', **kwargs):
|
||||
assert locsM.shape == locsN.shape, 'locsM and locsN need to be the same size'
|
||||
locs = [locsM, locsN]
|
||||
# We may not need this ...
|
||||
BaseRx.__init__(self, locs, rxType)
|
||||
|
||||
@property
|
||||
def nD(self):
|
||||
"""Number of data in the receiver."""
|
||||
return self.locs[0].shape[0]
|
||||
|
||||
# Not sure why ...
|
||||
# return int(self.locs[0].size / 2)
|
||||
|
||||
def getP(self, mesh, Gloc):
|
||||
if mesh in self._Ps:
|
||||
return self._Ps[mesh]
|
||||
|
||||
P0 = mesh.getInterpolationMat(self.locs[0], Gloc)
|
||||
P1 = mesh.getInterpolationMat(self.locs[1], Gloc)
|
||||
P = P0 - P1
|
||||
if self.storeProjections:
|
||||
self._Ps[mesh] = P
|
||||
return P
|
||||
|
||||
def eval(self, kys, src, mesh, f):
|
||||
P = self.getP(mesh, self.projGLoc(f))
|
||||
Pf = P*f[src, self.projField,:]
|
||||
return self.IntTrapezoidal(kys, Pf, y=0.)
|
||||
|
||||
def evalDeriv(self, ky, src, mesh, f, v, adjoint=False):
|
||||
P = self.getP(mesh, self.projGLoc(f))
|
||||
if not adjoint:
|
||||
return P*v
|
||||
elif adjoint:
|
||||
return P.T*v
|
||||
|
||||
def IntTrapezoidal(self, kys, Pf, y=0.):
|
||||
phi = np.zeros(Pf.shape[0])
|
||||
nky = kys.size
|
||||
dky = np.diff(kys)
|
||||
dky = np.r_[dky[0], dky]
|
||||
phi0 = 1./np.pi*Pf[:,0]
|
||||
for iky in range(nky):
|
||||
phi1 = 1./np.pi*Pf[:,iky]
|
||||
phi += phi1*dky[iky]/2.*np.cos(kys[iky]*y)
|
||||
phi += phi0*dky[iky]/2.*np.cos(kys[iky]*y)
|
||||
phi0 = phi1.copy()
|
||||
return phi
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
import SimPEG
|
||||
# from SimPEG.EM.Base import BaseEMSurvey
|
||||
from SimPEG.Utils import Zero, closestPoints, mkvc
|
||||
import numpy as np
|
||||
|
||||
class BaseSrc(SimPEG.Survey.BaseSrc):
|
||||
|
||||
current = 1.0
|
||||
loc = None
|
||||
|
||||
def __init__(self, rxList, **kwargs):
|
||||
SimPEG.Survey.BaseSrc.__init__(self, rxList, **kwargs)
|
||||
|
||||
def eval(self, prob):
|
||||
raise NotImplementedError
|
||||
|
||||
def evalDeriv(self, prob):
|
||||
return Zero()
|
||||
|
||||
|
||||
class Dipole(BaseSrc):
|
||||
|
||||
def __init__(self, rxList, locA, locB, **kwargs):
|
||||
assert locA.shape == locB.shape, 'Shape of locA and locB should be the same'
|
||||
self.loc = [locA, locB]
|
||||
BaseSrc.__init__(self, rxList, **kwargs)
|
||||
|
||||
def eval(self, prob):
|
||||
if prob._formulation == 'HJ':
|
||||
inds = closestPoints(prob.mesh, self.loc, gridLoc='CC')
|
||||
q = np.zeros(prob.mesh.nC)
|
||||
q[inds] = self.current * np.r_[1., -1.]
|
||||
elif prob._formulation == 'EB':
|
||||
qa = prob.mesh.getInterpolationMat(self.loc[0], locType='N').todense()
|
||||
qb = -prob.mesh.getInterpolationMat(self.loc[1], locType='N').todense()
|
||||
q = self.current * mkvc(qa+qb)
|
||||
return q
|
||||
|
||||
class Pole(BaseSrc):
|
||||
|
||||
def __init__(self, rxList, loc, **kwargs):
|
||||
BaseSrc.__init__(self, rxList, loc=loc, **kwargs)
|
||||
|
||||
def eval(self, prob):
|
||||
if prob._formulation == 'HJ':
|
||||
inds = closestPoints(prob.mesh, self.loc)
|
||||
q = np.zeros(prob.mesh.nC)
|
||||
q[inds] = self.current * np.r_[1.]
|
||||
elif prob._formulation == 'EB':
|
||||
q = prob.mesh.getInterpolationMat(self.loc, locType='N').todense()
|
||||
q = self.current * mkvc(q)
|
||||
return q
|
||||
|
||||
|
||||
# class Dipole_ky(BaseSrc):
|
||||
|
||||
# def __init__(self, rxList, locA, locB, **kwargs):
|
||||
# assert locA.shape == locB.shape, 'Shape of locA and locB should be the same'
|
||||
# self.loc = [locA[[0,2]], locB[[0,2]]]
|
||||
# BaseSrc.__init__(self, rxList, **kwargs)
|
||||
|
||||
# def eval(self, prob):
|
||||
# if prob._formulation == 'HJ':
|
||||
# inds = closestPoints(prob.mesh, self.loc, gridLoc='CC')
|
||||
# q = np.zeros(prob.mesh.nC)
|
||||
# q[inds] = self.current * np.r_[1., -1.]
|
||||
# elif prob._formulation == 'EB':
|
||||
# qa = prob.mesh.getInterpolationMat(self.loc[0], locType='N').todense()
|
||||
# qb = -prob.mesh.getInterpolationMat(self.loc[1], locType='N').todense()
|
||||
# q = self.current * mkvc(qa+qb)
|
||||
# return q
|
||||
|
||||
# class Pole_ky(BaseSrc):
|
||||
|
||||
# def __init__(self, rxList, loc, **kwargs):
|
||||
# BaseSrc.__init__(self, rxList, loc=loc, **kwargs)
|
||||
|
||||
# def eval(self, prob):
|
||||
# if prob._formulation == 'HJ':
|
||||
# inds = closestPoints(prob.mesh, self.loc[[0,2]])
|
||||
# q = np.zeros(prob.mesh.nC)
|
||||
# q[inds] = self.current * np.r_[1.]
|
||||
# elif prob._formulation == 'EB':
|
||||
# q = prob.mesh.getInterpolationMat(self.loc[[0,2]], locType='N').todense()
|
||||
# q = self.current * mkvc(q)
|
||||
# return q
|
||||
@@ -0,0 +1,38 @@
|
||||
import SimPEG
|
||||
from SimPEG.EM.Base import BaseEMSurvey
|
||||
from SimPEG import sp, Survey
|
||||
from SimPEG.Utils import Zero, Identity
|
||||
from RxDC import BaseRx
|
||||
from SrcDC import BaseSrc
|
||||
|
||||
class Survey(BaseEMSurvey):
|
||||
rxPair = BaseRx
|
||||
srcPair = BaseSrc
|
||||
|
||||
def __init__(self, srcList, **kwargs):
|
||||
self.srcList = srcList
|
||||
BaseEMSurvey.__init__(self, srcList, **kwargs)
|
||||
|
||||
class Survey_ky(BaseEMSurvey):
|
||||
rxPair = BaseRx
|
||||
srcPair = BaseSrc
|
||||
|
||||
def __init__(self, srcList, **kwargs):
|
||||
self.srcList = srcList
|
||||
BaseEMSurvey.__init__(self, srcList, **kwargs)
|
||||
|
||||
def eval(self, f):
|
||||
"""
|
||||
Project fields to receiver locations
|
||||
:param Fields u: fields object
|
||||
:rtype: numpy.ndarray
|
||||
:return: data
|
||||
"""
|
||||
data = SimPEG.Survey.Data(self)
|
||||
kys = self.prob.kys
|
||||
for src in self.srcList:
|
||||
for rx in src.rxList:
|
||||
data[src, rx] = rx.eval(kys, src, self.mesh, f)
|
||||
return data
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import numpy as np
|
||||
|
||||
def WennerSrcList(nElecs, aSpacing, in2D=False, plotIt=False):
|
||||
|
||||
import SimPEG.EM.Static.DC as DC
|
||||
|
||||
elocs = np.arange(0,aSpacing*nElecs,aSpacing)
|
||||
elocs -= (nElecs*aSpacing - aSpacing)/2
|
||||
space = 1
|
||||
WENNER = np.zeros((0,),dtype=int)
|
||||
for ii in range(nElecs):
|
||||
for jj in range(nElecs):
|
||||
test = np.r_[jj,jj+space,jj+space*2,jj+space*3]
|
||||
if np.any(test >= nElecs):
|
||||
break
|
||||
WENNER = np.r_[WENNER, test]
|
||||
space += 1
|
||||
WENNER = WENNER.reshape((-1,4))
|
||||
|
||||
|
||||
if plotIt:
|
||||
for i, s in enumerate('rbkg'):
|
||||
plt.plot(elocs[WENNER[:,i]],s+'.')
|
||||
plt.show()
|
||||
|
||||
# Create sources and receivers
|
||||
i = 0
|
||||
if in2D:
|
||||
getLoc = lambda ii, abmn: np.r_[elocs[WENNER[ii,abmn]],0]
|
||||
else:
|
||||
getLoc = lambda ii, abmn: np.r_[elocs[WENNER[ii,abmn]],0, 0]
|
||||
srcList = []
|
||||
for i in range(WENNER.shape[0]):
|
||||
rx = DC.Rx.Dipole(getLoc(i,1).reshape([1,-1]),getLoc(i,2).reshape([1,-1]))
|
||||
src = DC.Src.Dipole([rx], getLoc(i,0),getLoc(i,3))
|
||||
srcList += [src]
|
||||
|
||||
return srcList
|
||||
@@ -0,0 +1,8 @@
|
||||
from ProblemDC import Problem3D_CC, Problem3D_N
|
||||
from ProblemDC_2D import Problem2D_CC, Problem2D_N
|
||||
from SurveyDC import Survey, Survey_ky
|
||||
import SrcDC as Src #Pole
|
||||
import RxDC as Rx
|
||||
from FieldsDC import Fields_CC
|
||||
from BoundaryUtils import getxBCyBC_CC
|
||||
import Utils
|
||||
@@ -0,0 +1,374 @@
|
||||
from SimPEG import Problem, Utils, Maps, Mesh
|
||||
from SimPEG.EM.Base import BaseEMProblem
|
||||
from SimPEG.EM.Static.DC.FieldsDC import Fields, Fields_CC, Fields_N
|
||||
from SimPEG.Utils import sdiag
|
||||
import numpy as np
|
||||
from SimPEG.Utils import Zero
|
||||
from SimPEG.EM.Static.DC import getxBCyBC_CC
|
||||
from SurveyIP import Survey
|
||||
|
||||
class IPPropMap(Maps.PropMap):
|
||||
"""
|
||||
Property Map for IP Problems. The electrical chargeability,
|
||||
(\\(\\eta\\)) is the default inversion property
|
||||
"""
|
||||
eta = Maps.Property("Electrical Chargeability", defaultInvProp = True)
|
||||
|
||||
class BaseIPProblem(BaseEMProblem):
|
||||
|
||||
surveyPair = Survey
|
||||
fieldsPair = Fields
|
||||
PropMap = IPPropMap
|
||||
Ainv = None
|
||||
sigma = None
|
||||
rho = None
|
||||
f = None
|
||||
Ainv = None
|
||||
|
||||
def fields(self, m):
|
||||
self.curModel = m
|
||||
if self.f is None:
|
||||
self.f = self.fieldsPair(self.mesh, self.survey)
|
||||
if self.Ainv == None:
|
||||
A = self.getA()
|
||||
self.Ainv = self.Solver(A, **self.solverOpts)
|
||||
RHS = self.getRHS()
|
||||
u = self.Ainv * RHS
|
||||
Srcs = self.survey.srcList
|
||||
self.f[Srcs, self._solutionType] = u
|
||||
return self.f
|
||||
|
||||
def Jvec(self, m, v, f=None):
|
||||
|
||||
if f is None:
|
||||
f = self.fields(m)
|
||||
|
||||
self.curModel = m
|
||||
|
||||
Jv = self.dataPair(self.survey) #same size as the data
|
||||
|
||||
A = self.getA()
|
||||
|
||||
for src in self.survey.srcList:
|
||||
u_src = f[src, self._solutionType] # solution vector
|
||||
dA_dm_v = self.getADeriv(u_src, v)
|
||||
dRHS_dm_v = self.getRHSDeriv(src, v)
|
||||
du_dm_v = self.Ainv * ( - dA_dm_v + dRHS_dm_v )
|
||||
|
||||
for rx in src.rxList:
|
||||
df_dmFun = getattr(f, '_%sDeriv'%rx.projField, None)
|
||||
df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False)
|
||||
Jv[src, rx] = rx.evalDeriv(src, self.mesh, f, df_dm_v)
|
||||
# Conductivity (d u / d log sigma)
|
||||
if self._formulation is 'EB':
|
||||
return -Utils.mkvc(Jv)
|
||||
# Conductivity (d u / d log rho)
|
||||
if self._formulation is 'HJ':
|
||||
return Utils.mkvc(Jv)
|
||||
|
||||
def Jtvec(self, m, v, f=None):
|
||||
if f is None:
|
||||
f = self.fields(m)
|
||||
|
||||
self.curModel = m
|
||||
|
||||
# Ensure v is a data object.
|
||||
if not isinstance(v, self.dataPair):
|
||||
v = self.dataPair(self.survey, v)
|
||||
|
||||
Jtv = np.zeros(m.size)
|
||||
AT = self.getA()
|
||||
|
||||
for src in self.survey.srcList:
|
||||
u_src = f[src, self._solutionType]
|
||||
for rx in src.rxList:
|
||||
PTv = rx.evalDeriv(src, self.mesh, f, v[src, rx], adjoint=True) # wrt f, need possibility wrt m
|
||||
df_duTFun = getattr(f, '_%sDeriv'%rx.projField, None)
|
||||
df_duT, df_dmT = df_duTFun(src, None, PTv, adjoint=True)
|
||||
ATinvdf_duT = self.Ainv * df_duT
|
||||
dA_dmT = self.getADeriv(u_src, ATinvdf_duT, adjoint=True)
|
||||
dRHS_dmT = self.getRHSDeriv(src, ATinvdf_duT, adjoint=True)
|
||||
du_dmT = -dA_dmT + dRHS_dmT
|
||||
Jtv += (df_dmT + du_dmT).astype(float)
|
||||
# Conductivity ((d u / d log sigma).T)
|
||||
if self._formulation is 'EB':
|
||||
return -Utils.mkvc(Jtv)
|
||||
# Conductivity ((d u / d log rho).T)
|
||||
if self._formulation is 'HJ':
|
||||
return Utils.mkvc(Jtv)
|
||||
|
||||
def getSourceTerm(self):
|
||||
"""
|
||||
takes concept of source and turns it into a matrix
|
||||
"""
|
||||
"""
|
||||
Evaluates the sources, and puts them in matrix form
|
||||
|
||||
:rtype: (numpy.ndarray, numpy.ndarray)
|
||||
:return: q (nC or nN, nSrc)
|
||||
"""
|
||||
|
||||
Srcs = self.survey.srcList
|
||||
|
||||
if self._formulation is 'EB':
|
||||
n = self.mesh.nN
|
||||
# return NotImplementedError
|
||||
|
||||
elif self._formulation is 'HJ':
|
||||
n = self.mesh.nC
|
||||
|
||||
q = np.zeros((n, len(Srcs)))
|
||||
|
||||
for i, src in enumerate(Srcs):
|
||||
q[:,i] = src.eval(self)
|
||||
return q
|
||||
|
||||
@property
|
||||
def deleteTheseOnModelUpdate(self):
|
||||
toDelete = []
|
||||
return toDelete
|
||||
|
||||
# assume log rho or log cond
|
||||
@property
|
||||
def MeSigma(self):
|
||||
"""
|
||||
Edge inner product matrix for \\(\\sigma\\). Used in the E-B formulation
|
||||
"""
|
||||
if getattr(self, '_MeSigma', None) is None:
|
||||
self._MeSigma = self.mesh.getEdgeInnerProduct(self.sigma)
|
||||
return self._MeSigma
|
||||
|
||||
@property
|
||||
def MfRhoI(self):
|
||||
"""
|
||||
Inverse of :code:`MfRho`
|
||||
"""
|
||||
if getattr(self, '_MfRhoI', None) is None:
|
||||
self._MfRhoI = self.mesh.getFaceInnerProduct(self.rho, invMat=True)
|
||||
return self._MfRhoI
|
||||
|
||||
def MfRhoIDeriv(self,u):
|
||||
"""
|
||||
Derivative of :code:`MfRhoI` with respect to the model.
|
||||
"""
|
||||
|
||||
dMfRhoI_dI = -self.MfRhoI**2
|
||||
dMf_drho = self.mesh.getFaceInnerProductDeriv(self.rho)(u)
|
||||
drho_dlogrho = Utils.sdiag(self.rho)*self.curModel.etaDeriv
|
||||
return dMfRhoI_dI * ( dMf_drho * ( drho_dlogrho))
|
||||
|
||||
# TODO: This should take a vector
|
||||
def MeSigmaDeriv(self, u):
|
||||
"""
|
||||
Derivative of MeSigma with respect to the model
|
||||
"""
|
||||
dsigma_dlogsigma = Utils.sdiag(self.sigma)*self.curModel.etaDeriv
|
||||
return self.mesh.getEdgeInnerProductDeriv(self.sigma)(u) * dsigma_dlogsigma
|
||||
|
||||
class Problem3D_CC(BaseIPProblem):
|
||||
|
||||
_solutionType = 'phiSolution'
|
||||
_formulation = 'HJ' # CC potentials means J is on faces
|
||||
fieldsPair = Fields_CC
|
||||
|
||||
def __init__(self, mesh, **kwargs):
|
||||
BaseIPProblem.__init__(self, mesh, **kwargs)
|
||||
self.setBC()
|
||||
|
||||
def getA(self):
|
||||
"""
|
||||
|
||||
Make the A matrix for the cell centered DC resistivity problem
|
||||
|
||||
A = D MfRhoI D^\\top V
|
||||
|
||||
"""
|
||||
|
||||
D = self.Div
|
||||
G = self.Grad
|
||||
# TODO: this won't work for full anisotropy
|
||||
MfRhoI = self.MfRhoI
|
||||
A = D * MfRhoI * G
|
||||
|
||||
# I think we should deprecate this for DC problem.
|
||||
# if self._makeASymmetric is True:
|
||||
# return V.T * A
|
||||
return A
|
||||
|
||||
def getADeriv(self, u, v, adjoint= False):
|
||||
|
||||
D = self.Div
|
||||
G = self.Grad
|
||||
MfRhoIDeriv = self.MfRhoIDeriv
|
||||
|
||||
if adjoint:
|
||||
# if self._makeASymmetric is True:
|
||||
# v = V * v
|
||||
return(MfRhoIDeriv( G * u ).T) * ( D.T * v)
|
||||
|
||||
# I think we should deprecate this for DC problem.
|
||||
# if self._makeASymmetric is True:
|
||||
# return V.T * ( D * ( MfRhoIDeriv( D.T * ( V * u ) ) * v ) )
|
||||
return D * (MfRhoIDeriv( G * u ) * v)
|
||||
|
||||
def getRHS(self):
|
||||
"""
|
||||
RHS for the DC problem
|
||||
|
||||
q
|
||||
"""
|
||||
|
||||
RHS = self.getSourceTerm()
|
||||
|
||||
# I think we should deprecate this for DC problem.
|
||||
# if self._makeASymmetric is True:
|
||||
# return self.Vol.T * RHS
|
||||
|
||||
return RHS
|
||||
|
||||
def getRHSDeriv(self, src, v, adjoint=False):
|
||||
"""
|
||||
Derivative of the right hand side with respect to the model
|
||||
"""
|
||||
# TODO: add qDeriv for RHS depending on m
|
||||
# qDeriv = src.evalDeriv(self, adjoint=adjoint)
|
||||
# return qDeriv
|
||||
return Zero()
|
||||
|
||||
def setBC(self):
|
||||
if self.mesh.dim==3:
|
||||
fxm,fxp,fym,fyp,fzm,fzp = self.mesh.faceBoundaryInd
|
||||
gBFxm = self.mesh.gridFx[fxm,:]
|
||||
gBFxp = self.mesh.gridFx[fxp,:]
|
||||
gBFym = self.mesh.gridFy[fym,:]
|
||||
gBFyp = self.mesh.gridFy[fyp,:]
|
||||
gBFzm = self.mesh.gridFz[fzm,:]
|
||||
gBFzp = self.mesh.gridFz[fzp,:]
|
||||
|
||||
# Setup Mixed B.C (alpha, beta, gamma)
|
||||
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
|
||||
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
|
||||
temp_zm, temp_zp = np.ones_like(gBFzm[:,2]), np.ones_like(gBFzp[:,2])
|
||||
|
||||
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
|
||||
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
|
||||
alpha_zm, alpha_zp = temp_zm*0., temp_zp*0.
|
||||
|
||||
beta_xm, beta_xp = temp_xm, temp_xp
|
||||
beta_ym, beta_yp = temp_ym, temp_yp
|
||||
beta_zm, beta_zp = temp_zm, temp_zp
|
||||
|
||||
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
|
||||
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
|
||||
gamma_zm, gamma_zp = temp_zm*0., temp_zp*0.
|
||||
|
||||
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp, alpha_zm, alpha_zp]
|
||||
beta = [beta_xm, beta_xp, beta_ym, beta_yp, beta_zm, beta_zp]
|
||||
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp, gamma_zm, gamma_zp]
|
||||
|
||||
elif self.mesh.dim==2:
|
||||
|
||||
fxm,fxp,fym,fyp = self.mesh.faceBoundaryInd
|
||||
gBFxm = self.mesh.gridFx[fxm,:]
|
||||
gBFxp = self.mesh.gridFx[fxp,:]
|
||||
gBFym = self.mesh.gridFy[fym,:]
|
||||
gBFyp = self.mesh.gridFy[fyp,:]
|
||||
|
||||
# Setup Mixed B.C (alpha, beta, gamma)
|
||||
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
|
||||
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
|
||||
|
||||
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
|
||||
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
|
||||
|
||||
beta_xm, beta_xp = temp_xm, temp_xp
|
||||
beta_ym, beta_yp = temp_ym, temp_yp
|
||||
|
||||
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
|
||||
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
|
||||
|
||||
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp]
|
||||
beta = [beta_xm, beta_xp, beta_ym, beta_yp]
|
||||
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp]
|
||||
|
||||
x_BC, y_BC = getxBCyBC_CC(self.mesh, alpha, beta, gamma)
|
||||
V = self.Vol
|
||||
self.Div = V * self.mesh.faceDiv
|
||||
P_BC, B = self.mesh.getBCProjWF_simple()
|
||||
M = B*self.mesh.aveCC2F
|
||||
self.Grad = self.Div.T - P_BC*Utils.sdiag(y_BC)*M
|
||||
|
||||
|
||||
class Problem3D_N(BaseIPProblem):
|
||||
|
||||
_solutionType = 'phiSolution'
|
||||
_formulation = 'EB' # N potentials means B is on faces
|
||||
fieldsPair = Fields_N
|
||||
|
||||
def __init__(self, mesh, **kwargs):
|
||||
BaseIPProblem.__init__(self, mesh, **kwargs)
|
||||
|
||||
def getA(self):
|
||||
"""
|
||||
|
||||
Make the A matrix for the cell centered DC resistivity problem
|
||||
|
||||
A = D MfRhoI D^\\top V
|
||||
|
||||
"""
|
||||
|
||||
# TODO: this won't work for full anisotropy
|
||||
MeSigma = self.MeSigma
|
||||
Grad = self.mesh.nodalGrad
|
||||
A = Grad.T * MeSigma * Grad
|
||||
|
||||
# Handling Null space of A
|
||||
A[0,0] = A[0,0] + 1.
|
||||
|
||||
return A
|
||||
|
||||
def getADeriv(self, u, v, adjoint=False):
|
||||
"""
|
||||
|
||||
Product of the derivative of our system matrix with respect to the model and a vector
|
||||
|
||||
"""
|
||||
MeSigma = self.MeSigma
|
||||
Grad = self.mesh.nodalGrad
|
||||
if not adjoint:
|
||||
return Grad.T*(self.MeSigmaDeriv(Grad*u)*v)
|
||||
elif adjoint:
|
||||
return self.MeSigmaDeriv(Grad*u).T * (Grad*v)
|
||||
|
||||
|
||||
def getRHS(self):
|
||||
"""
|
||||
RHS for the DC problem
|
||||
|
||||
q
|
||||
"""
|
||||
|
||||
RHS = self.getSourceTerm()
|
||||
return RHS
|
||||
|
||||
def getRHSDeriv(self, src, v, adjoint=False):
|
||||
"""
|
||||
Derivative of the right hand side with respect to the model
|
||||
"""
|
||||
# TODO: add qDeriv for RHS depending on m
|
||||
# qDeriv = src.evalDeriv(self, adjoint=adjoint)
|
||||
# return qDeriv
|
||||
return Zero()
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
|
||||
cs = 12.5
|
||||
hx = [(cs,7, -1.3),(cs,21),(cs,7, 1.3)]
|
||||
hy = [(cs,7, -1.3),(cs,21),(cs,7, 1.3)]
|
||||
hz = [(cs,7, -1.3),(cs,20)]
|
||||
mesh = Mesh.TensorMesh([hx, hy, hz],x0="CCN")
|
||||
sigma = np.ones(mesh.nC)
|
||||
prob = BaseIPProblem(mesh, sigma=sigma)
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import SimPEG
|
||||
from SimPEG.EM.Base import BaseEMSurvey
|
||||
from SimPEG import sp, Survey
|
||||
from SimPEG.Utils import Zero, Identity
|
||||
from SimPEG.EM.Static.DC.SrcDC import BaseSrc
|
||||
from SimPEG.EM.Static.DC.RxDC import BaseRx
|
||||
|
||||
class Survey(BaseEMSurvey):
|
||||
rxPair = BaseRx
|
||||
srcPair = BaseSrc
|
||||
|
||||
def __init__(self, srcList, **kwargs):
|
||||
self.srcList = srcList
|
||||
BaseEMSurvey.__init__(self, srcList, **kwargs)
|
||||
|
||||
def dpred(self, m, f=None):
|
||||
"""
|
||||
Predicted data.
|
||||
|
||||
.. math::
|
||||
d_\\text{pred} = Pf(m)
|
||||
"""
|
||||
return self.prob.Jvec(m, m, f=f)
|
||||
@@ -0,0 +1,2 @@
|
||||
from ProblemIP import Problem3D_CC, Problem3D_N
|
||||
from SurveyIP import Survey
|
||||
@@ -0,0 +1,445 @@
|
||||
from SimPEG import Problem, Utils, Maps, Mesh
|
||||
from SimPEG.EM.Base import BaseEMProblem
|
||||
from SimPEG.EM.Static.DC.FieldsDC import Fields, Fields_CC, Fields_N
|
||||
from SimPEG.Utils import sdiag
|
||||
import numpy as np
|
||||
from SimPEG.Utils import Zero
|
||||
from SimPEG.EM.Static.DC import getxBCyBC_CC
|
||||
from SurveySIP import Survey, Data
|
||||
|
||||
class ColeColePropMap(Maps.PropMap):
|
||||
"""
|
||||
Property Map for EM Problems. The electrical conductivity (\\(\\sigma\\)) is the default inversion property, and the default value of the magnetic permeability is that of free space (\\(\\mu = 4\\pi\\times 10^{-7} \\) H/m)
|
||||
"""
|
||||
|
||||
eta = Maps.Property("Electrical Conductivity", defaultInvProp=True)
|
||||
tau = Maps.Property("Electrical Conductivity", defaultVal=0.1, propertyLink=('taui', Maps.ReciprocalMap))
|
||||
taui = Maps.Property("Electrical Conductivity", defaultVal=1., propertyLink=('tau', Maps.ReciprocalMap))
|
||||
c = Maps.Property("Electrical Conductivity", defaultVal=1.)
|
||||
|
||||
|
||||
class BaseSIPProblem(BaseEMProblem):
|
||||
|
||||
surveyPair = Survey
|
||||
fieldsPair = Fields
|
||||
dataPair = Data
|
||||
PropMap = ColeColePropMap
|
||||
Ainv = None
|
||||
sigma = None
|
||||
rho = None
|
||||
f = None
|
||||
Ainv = None
|
||||
|
||||
def DebyeTime(self, t):
|
||||
peta = self.curModel.eta*np.exp(-self.curModel.taui*t)
|
||||
return peta
|
||||
|
||||
def EtaDeriv(self, t, v, adjoint=False):
|
||||
v = np.array(v, dtype=float)
|
||||
if adjoint:
|
||||
return self.curModel.etaDeriv.T * (np.exp(-self.curModel.taui*t)*v)
|
||||
else:
|
||||
return np.exp(-self.curModel.taui*t) * (self.curModel.etaDeriv*v)
|
||||
|
||||
|
||||
def TauiDeriv(self, t, v, adjoint=False):
|
||||
v = np.array(v, dtype=float)
|
||||
if adjoint:
|
||||
return -self.curModel.tauiDeriv.T * (self.curModel.eta*t*np.exp(-self.curModel.taui*t)*v)
|
||||
else:
|
||||
return -self.curModel.eta*t*np.exp(-self.curModel.taui*t) * (self.curModel.tauiDeriv*v)
|
||||
|
||||
def fields(self, m):
|
||||
self.curModel = m
|
||||
if self.f is None:
|
||||
self.f = self.fieldsPair(self.mesh, self.survey)
|
||||
if self.Ainv == None:
|
||||
A = self.getA()
|
||||
self.Ainv = self.Solver(A, **self.solverOpts)
|
||||
RHS = self.getRHS()
|
||||
u = self.Ainv * RHS
|
||||
Srcs = self.survey.srcList
|
||||
self.f[Srcs, self._solutionType] = u
|
||||
return self.f
|
||||
|
||||
def forward(self, m, f=None):
|
||||
|
||||
if f is None:
|
||||
f = self.fields(m)
|
||||
|
||||
self.curModel = m
|
||||
Jv = self.dataPair(self.survey) #same size as the data
|
||||
# A = self.getA()
|
||||
JvAll = []
|
||||
for tind in range(len(self.survey.times)):
|
||||
#Pseudo-chareability
|
||||
t = self.survey.times[tind]
|
||||
v = self.DebyeTime(t)
|
||||
for src in self.survey.srcList:
|
||||
u_src = f[src, self._solutionType] # solution vector
|
||||
dA_dm_v = self.getADeriv(u_src, v)
|
||||
dRHS_dm_v = self.getRHSDeriv(src, v)
|
||||
du_dm_v = self.Ainv * ( - dA_dm_v + dRHS_dm_v )
|
||||
for rx in src.rxList:
|
||||
timeindex = rx.getTimeP(self.survey.times)
|
||||
if timeindex[tind]:
|
||||
df_dmFun = getattr(f, '_%sDeriv'%rx.projField, None)
|
||||
df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False)
|
||||
Jv[src, rx, t] = rx.evalDeriv(src, self.mesh, f, df_dm_v)
|
||||
|
||||
# Conductivity (d u / d log sigma)
|
||||
if self._formulation is 'EB':
|
||||
return -Utils.mkvc(Jv)
|
||||
# Resistivity (d u / d log rho)
|
||||
if self._formulation is 'HJ':
|
||||
return Utils.mkvc(Jv)
|
||||
|
||||
def Jvec(self, m, v, f=None):
|
||||
|
||||
if f is None:
|
||||
f = self.fields(m)
|
||||
|
||||
self.curModel = m
|
||||
Jv = self.dataPair(self.survey) #same size as the data
|
||||
# A = self.getA()
|
||||
JvAll = []
|
||||
#Assume only eta and tau (eta first then tau)
|
||||
# v = [2*Mx1]
|
||||
v = v.reshape((int(v.size/2), 2), order='F')
|
||||
|
||||
for tind in range(len(self.survey.times)):
|
||||
t = self.survey.times[tind]
|
||||
v0 = self.EtaDeriv(t, v[:,0])
|
||||
v1 = self.TauiDeriv(t, v[:,1])
|
||||
for src in self.survey.srcList:
|
||||
u_src = f[src, self._solutionType] # solution vector
|
||||
dA_dm_v0 = self.getADeriv(u_src, v0)
|
||||
dRHS_dm_v0 = self.getRHSDeriv(src, v0)
|
||||
du_dm_v0 = self.Ainv * ( - dA_dm_v0 + dRHS_dm_v0 )
|
||||
dA_dm_v1 = self.getADeriv(u_src, v1)
|
||||
dRHS_dm_v1 = self.getRHSDeriv(src, v1)
|
||||
du_dm_v1 = self.Ainv * ( - dA_dm_v1 + dRHS_dm_v1 )
|
||||
for rx in src.rxList:
|
||||
timeindex = rx.getTimeP(self.survey.times)
|
||||
if timeindex[tind]:
|
||||
df_dmFun = getattr(f, '_%sDeriv'%rx.projField, None)
|
||||
df_dm_v0 = df_dmFun(src, du_dm_v0, v0, adjoint=False)
|
||||
df_dm_v1 = df_dmFun(src, du_dm_v1, v1, adjoint=False)
|
||||
Jv[src, rx, t] = rx.evalDeriv(src, self.mesh, f, df_dm_v0)
|
||||
Jv[src, rx, t] += rx.evalDeriv(src, self.mesh, f, df_dm_v1)
|
||||
# Conductivity (d u / d log sigma)
|
||||
if self._formulation is 'EB':
|
||||
return -Jv.tovec()
|
||||
# Resistivity (d u / d log rho)
|
||||
if self._formulation is 'HJ':
|
||||
return Jv.tovec()
|
||||
|
||||
def Jtvec(self, m, v, f=None):
|
||||
if f is None:
|
||||
f = self.fields(m)
|
||||
|
||||
self.curModel = m
|
||||
|
||||
# Ensure v is a data object.
|
||||
if not isinstance(v, self.dataPair):
|
||||
v = self.dataPair(self.survey, v)
|
||||
|
||||
Jtv= np.zeros(m.size)
|
||||
for tind in range(len(self.survey.times)):
|
||||
t = self.survey.times[tind]
|
||||
for src in self.survey.srcList:
|
||||
u_src = f[src, self._solutionType]
|
||||
for rx in src.rxList:
|
||||
timeindex = rx.getTimeP(self.survey.times)
|
||||
if timeindex[tind]:
|
||||
PTv = rx.evalDeriv(src, self.mesh, f, v[src, rx, t], adjoint=True) # wrt f, need possibility wrt m
|
||||
df_duTFun = getattr(f, '_%sDeriv'%rx.projField, None)
|
||||
df_duT, df_dmT = df_duTFun(src, None, PTv, adjoint=True)
|
||||
ATinvdf_duT = self.Ainv * df_duT
|
||||
dA_dmT = self.getADeriv(u_src, ATinvdf_duT, adjoint=True)
|
||||
dRHS_dmT = self.getRHSDeriv(src, ATinvdf_duT, adjoint=True)
|
||||
du_dmT = -dA_dmT + dRHS_dmT
|
||||
Jtv += np.r_[self.EtaDeriv(self.survey.times[tind], du_dmT, adjoint=True), self.TauiDeriv(self.survey.times[tind], du_dmT, adjoint=True)]
|
||||
|
||||
# Conductivity ((d u / d log sigma).T)
|
||||
if self._formulation is 'EB':
|
||||
return -Jtv
|
||||
# Conductivity ((d u / d log rho).T)
|
||||
if self._formulation is 'HJ':
|
||||
return Jtv
|
||||
|
||||
def getSourceTerm(self):
|
||||
"""
|
||||
takes concept of source and turns it into a matrix
|
||||
"""
|
||||
"""
|
||||
Evaluates the sources, and puts them in matrix form
|
||||
|
||||
:rtype: (numpy.ndarray, numpy.ndarray)
|
||||
:return: q (nC or nN, nSrc)
|
||||
"""
|
||||
|
||||
Srcs = self.survey.srcList
|
||||
|
||||
if self._formulation is 'EB':
|
||||
n = self.mesh.nN
|
||||
# return NotImplementedError
|
||||
|
||||
elif self._formulation is 'HJ':
|
||||
n = self.mesh.nC
|
||||
|
||||
q = np.zeros((n, len(Srcs)))
|
||||
|
||||
for i, src in enumerate(Srcs):
|
||||
q[:,i] = src.eval(self)
|
||||
return q
|
||||
|
||||
@property
|
||||
def deleteTheseOnModelUpdate(self):
|
||||
toDelete = []
|
||||
return toDelete
|
||||
|
||||
# assume log rho or log cond
|
||||
@property
|
||||
def MeSigma(self):
|
||||
"""
|
||||
Edge inner product matrix for \\(\\sigma\\). Used in the E-B formulation
|
||||
"""
|
||||
if getattr(self, '_MeSigma', None) is None:
|
||||
self._MeSigma = self.mesh.getEdgeInnerProduct(self.sigma)
|
||||
return self._MeSigma
|
||||
|
||||
@property
|
||||
def MfRhoI(self):
|
||||
"""
|
||||
Inverse of :code:`MfRho`
|
||||
"""
|
||||
if getattr(self, '_MfRhoI', None) is None:
|
||||
self._MfRhoI = self.mesh.getFaceInnerProduct(self.rho, invMat=True)
|
||||
return self._MfRhoI
|
||||
|
||||
def MfRhoIDeriv(self,u):
|
||||
"""
|
||||
Derivative of :code:`MfRhoI` with respect to the model.
|
||||
"""
|
||||
|
||||
dMfRhoI_dI = -self.MfRhoI**2
|
||||
dMf_drho = self.mesh.getFaceInnerProductDeriv(self.rho)(u)
|
||||
drho_dlogrho = Utils.sdiag(self.rho)
|
||||
return dMfRhoI_dI * ( dMf_drho * ( drho_dlogrho))
|
||||
|
||||
# TODO: This should take a vector
|
||||
def MeSigmaDeriv(self, u):
|
||||
"""
|
||||
Derivative of MeSigma with respect to the model
|
||||
"""
|
||||
dsigma_dlogsigma = Utils.sdiag(self.sigma)
|
||||
return self.mesh.getEdgeInnerProductDeriv(self.sigma)(u) * dsigma_dlogsigma
|
||||
|
||||
class Problem3D_CC(BaseSIPProblem):
|
||||
|
||||
_solutionType = 'phiSolution'
|
||||
_formulation = 'HJ' # CC potentials means J is on faces
|
||||
fieldsPair = Fields_CC
|
||||
|
||||
def __init__(self, mesh, **kwargs):
|
||||
BaseSIPProblem.__init__(self, mesh, **kwargs)
|
||||
self.setBC()
|
||||
|
||||
def getA(self):
|
||||
"""
|
||||
|
||||
Make the A matrix for the cell centered DC resistivity problem
|
||||
|
||||
A = D MfRhoI D^\\top V
|
||||
|
||||
"""
|
||||
|
||||
D = self.Div
|
||||
G = self.Grad
|
||||
# TODO: this won't work for full anisotropy
|
||||
MfRhoI = self.MfRhoI
|
||||
A = D * MfRhoI * G
|
||||
|
||||
# I think we should deprecate this for DC problem.
|
||||
# if self._makeASymmetric is True:
|
||||
# return V.T * A
|
||||
return A
|
||||
|
||||
def getADeriv(self, u, v, adjoint= False):
|
||||
|
||||
D = self.Div
|
||||
G = self.Grad
|
||||
MfRhoIDeriv = self.MfRhoIDeriv
|
||||
|
||||
if adjoint:
|
||||
# if self._makeASymmetric is True:
|
||||
# v = V * v
|
||||
return(MfRhoIDeriv( G * u ).T) * ( D.T * v)
|
||||
|
||||
# I think we should deprecate this for DC problem.
|
||||
# if self._makeASymmetric is True:
|
||||
# return V.T * ( D * ( MfRhoIDeriv( D.T * ( V * u ) ) * v ) )
|
||||
return D * (MfRhoIDeriv( G * u ) * v)
|
||||
|
||||
def getRHS(self):
|
||||
"""
|
||||
RHS for the DC problem
|
||||
|
||||
q
|
||||
"""
|
||||
|
||||
RHS = self.getSourceTerm()
|
||||
|
||||
# I think we should deprecate this for DC problem.
|
||||
# if self._makeASymmetric is True:
|
||||
# return self.Vol.T * RHS
|
||||
|
||||
return RHS
|
||||
|
||||
def getRHSDeriv(self, src, v, adjoint=False):
|
||||
"""
|
||||
Derivative of the right hand side with respect to the model
|
||||
"""
|
||||
# TODO: add qDeriv for RHS depending on m
|
||||
# qDeriv = src.evalDeriv(self, adjoint=adjoint)
|
||||
# return qDeriv
|
||||
return Zero()
|
||||
|
||||
def setBC(self):
|
||||
if self.mesh.dim==3:
|
||||
fxm,fxp,fym,fyp,fzm,fzp = self.mesh.faceBoundaryInd
|
||||
gBFxm = self.mesh.gridFx[fxm,:]
|
||||
gBFxp = self.mesh.gridFx[fxp,:]
|
||||
gBFym = self.mesh.gridFy[fym,:]
|
||||
gBFyp = self.mesh.gridFy[fyp,:]
|
||||
gBFzm = self.mesh.gridFz[fzm,:]
|
||||
gBFzp = self.mesh.gridFz[fzp,:]
|
||||
|
||||
# Setup Mixed B.C (alpha, beta, gamma)
|
||||
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
|
||||
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
|
||||
temp_zm, temp_zp = np.ones_like(gBFzm[:,2]), np.ones_like(gBFzp[:,2])
|
||||
|
||||
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
|
||||
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
|
||||
alpha_zm, alpha_zp = temp_zm*0., temp_zp*0.
|
||||
|
||||
beta_xm, beta_xp = temp_xm, temp_xp
|
||||
beta_ym, beta_yp = temp_ym, temp_yp
|
||||
beta_zm, beta_zp = temp_zm, temp_zp
|
||||
|
||||
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
|
||||
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
|
||||
gamma_zm, gamma_zp = temp_zm*0., temp_zp*0.
|
||||
|
||||
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp, alpha_zm, alpha_zp]
|
||||
beta = [beta_xm, beta_xp, beta_ym, beta_yp, beta_zm, beta_zp]
|
||||
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp, gamma_zm, gamma_zp]
|
||||
|
||||
elif self.mesh.dim==2:
|
||||
|
||||
fxm,fxp,fym,fyp = self.mesh.faceBoundaryInd
|
||||
gBFxm = self.mesh.gridFx[fxm,:]
|
||||
gBFxp = self.mesh.gridFx[fxp,:]
|
||||
gBFym = self.mesh.gridFy[fym,:]
|
||||
gBFyp = self.mesh.gridFy[fyp,:]
|
||||
|
||||
# Setup Mixed B.C (alpha, beta, gamma)
|
||||
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
|
||||
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
|
||||
|
||||
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
|
||||
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
|
||||
|
||||
beta_xm, beta_xp = temp_xm, temp_xp
|
||||
beta_ym, beta_yp = temp_ym, temp_yp
|
||||
|
||||
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
|
||||
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
|
||||
|
||||
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp]
|
||||
beta = [beta_xm, beta_xp, beta_ym, beta_yp]
|
||||
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp]
|
||||
|
||||
x_BC, y_BC = getxBCyBC_CC(self.mesh, alpha, beta, gamma)
|
||||
V = self.Vol
|
||||
self.Div = V * self.mesh.faceDiv
|
||||
P_BC, B = self.mesh.getBCProjWF_simple()
|
||||
M = B*self.mesh.aveCC2F
|
||||
self.Grad = self.Div.T - P_BC*Utils.sdiag(y_BC)*M
|
||||
|
||||
|
||||
class Problem3D_N(BaseSIPProblem):
|
||||
|
||||
_solutionType = 'phiSolution'
|
||||
_formulation = 'EB' # N potentials means B is on faces
|
||||
fieldsPair = Fields_N
|
||||
|
||||
def __init__(self, mesh, **kwargs):
|
||||
BaseSIPProblem.__init__(self, mesh, **kwargs)
|
||||
|
||||
def getA(self):
|
||||
"""
|
||||
|
||||
Make the A matrix for the cell centered DC resistivity problem
|
||||
|
||||
A = D MfRhoI D^\\top V
|
||||
|
||||
"""
|
||||
|
||||
# TODO: this won't work for full anisotropy
|
||||
MeSigma = self.MeSigma
|
||||
Grad = self.mesh.nodalGrad
|
||||
A = Grad.T * MeSigma * Grad
|
||||
|
||||
# Handling Null space of A
|
||||
A[0,0] = A[0,0] + 1.
|
||||
|
||||
return A
|
||||
|
||||
def getADeriv(self, u, v, adjoint=False):
|
||||
"""
|
||||
|
||||
Product of the derivative of our system matrix with respect to the model and a vector
|
||||
|
||||
"""
|
||||
MeSigma = self.MeSigma
|
||||
Grad = self.mesh.nodalGrad
|
||||
if not adjoint:
|
||||
return Grad.T*(self.MeSigmaDeriv(Grad*u)*v)
|
||||
elif adjoint:
|
||||
return self.MeSigmaDeriv(Grad*u).T * (Grad*v)
|
||||
|
||||
|
||||
def getRHS(self):
|
||||
"""
|
||||
RHS for the DC problem
|
||||
|
||||
q
|
||||
"""
|
||||
|
||||
RHS = self.getSourceTerm()
|
||||
return RHS
|
||||
|
||||
def getRHSDeriv(self, src, v, adjoint=False):
|
||||
"""
|
||||
Derivative of the right hand side with respect to the model
|
||||
"""
|
||||
# TODO: add qDeriv for RHS depending on m
|
||||
# qDeriv = src.evalDeriv(self, adjoint=adjoint)
|
||||
# return qDeriv
|
||||
return Zero()
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
|
||||
cs = 12.5
|
||||
hx = [(cs,7, -1.3),(cs,21),(cs,7, 1.3)]
|
||||
hy = [(cs,7, -1.3),(cs,21),(cs,7, 1.3)]
|
||||
hz = [(cs,7, -1.3),(cs,20)]
|
||||
mesh = Mesh.TensorMesh([hx, hy, hz],x0="CCN")
|
||||
sigma = np.ones(mesh.nC)
|
||||
prob = BaseSIPProblem(mesh, sigma=sigma)
|
||||
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
from SimPEG import Utils, Maps, Mesh, sp, np
|
||||
from SimPEG.Regularization import BaseRegularization, Simple
|
||||
|
||||
class MultiRegularization(Simple):
|
||||
"""
|
||||
**MultiRegularization Class**
|
||||
|
||||
This is used to regularize the model space
|
||||
having multiple models [m1, m2, m3, ...] ::
|
||||
|
||||
reg = Regularization(mesh)
|
||||
|
||||
"""
|
||||
nModels = None # Number of models
|
||||
ratios = None # Ratio for different models
|
||||
crossgrad = False # Use cross gradient or not
|
||||
betacross = 1.
|
||||
wx = []
|
||||
wy = []
|
||||
wz = []
|
||||
|
||||
def __init__(self, mesh, mapping=None, indActive=None, **kwargs):
|
||||
BaseRegularization.__init__(self, mesh, mapping=mapping, indActive=indActive, **kwargs)
|
||||
if self.nModels == None:
|
||||
raise Exception("Put nModels as a initial input!")
|
||||
if self.ratios == None:
|
||||
self.ratios = [1. for imodel in range(self.nModels)]
|
||||
|
||||
@property
|
||||
def Wsmall(self):
|
||||
"""Regularization matrix Wsmall"""
|
||||
if getattr(self,'_Wsmall', None) is None:
|
||||
vecs = []
|
||||
for imodel in range(self.nModels):
|
||||
vecs.append((self.regmesh.vol*self.alpha_s*self.wght*self.ratios[imodel])**0.5)
|
||||
self._Wsmall = Utils.sdiag(np.hstack(vecs))
|
||||
return self._Wsmall
|
||||
|
||||
@property
|
||||
def Wx(self):
|
||||
"""Regularization matrix Wx"""
|
||||
if getattr(self, '_Wx', None) is None:
|
||||
mats = []
|
||||
for imodel in range(self.nModels):
|
||||
self.wx.append(Utils.sdiag((self.regmesh.aveCC2Fx * self.regmesh.vol*self.alpha_x*self.ratios[imodel]*(self.regmesh.aveCC2Fx*self.wght))**0.5))
|
||||
mats.append(self.wx[imodel]*self.regmesh.cellDiffxStencil)
|
||||
self._Wx = sp.block_diag(mats)
|
||||
return self._Wx
|
||||
|
||||
@property
|
||||
def Wy(self):
|
||||
"""Regularization matrix Wy"""
|
||||
if getattr(self, '_Wy', None) is None:
|
||||
mats = []
|
||||
for imodel in range(self.nModels):
|
||||
self.wy.append(Utils.sdiag((self.regmesh.aveCC2Fy * self.regmesh.vol*self.alpha_y*self.ratios[imodel]*(self.regmesh.aveCC2Fy*self.wght))**0.5))
|
||||
mats.append(self.wy[imodel]*self.regmesh.cellDiffyStencil)
|
||||
self._Wy = sp.block_diag(mats)
|
||||
return self._Wy
|
||||
|
||||
@property
|
||||
def Wz(self):
|
||||
"""Regularization matrix Wz"""
|
||||
if getattr(self, '_Wz', None) is None:
|
||||
mats = []
|
||||
for imodel in range(self.nModels):
|
||||
self.wz.append(Utils.sdiag((self.regmesh.aveCC2Fz * self.regmesh.vol*self.alpha_z*self.ratios[imodel]*(self.regmesh.aveCC2Fz*self.wght))**0.5))
|
||||
mats.append(self.wz[imodel]*self.regmesh.cellDiffzStencil)
|
||||
self._Wz = sp.block_diag(mats)
|
||||
return self._Wz
|
||||
|
||||
@property
|
||||
def Wsmooth(self):
|
||||
"""Full smoothness regularization matrix W"""
|
||||
if getattr(self, '_Wsmooth', None) is None:
|
||||
wlist = (self.Wx,)
|
||||
if self.regmesh.dim > 1:
|
||||
wlist += (self.Wy,)
|
||||
if self.regmesh.dim > 2:
|
||||
wlist += (self.Wz,)
|
||||
self._Wsmooth = sp.vstack(wlist)
|
||||
return self._Wsmooth
|
||||
|
||||
@property
|
||||
def W(self):
|
||||
"""Full regularization matrix W"""
|
||||
if getattr(self, '_W', None) is None:
|
||||
wlist = (self.Wsmall, self.Wsmooth)
|
||||
self._W = sp.vstack(wlist)
|
||||
return self._W
|
||||
|
||||
|
||||
@Utils.timeIt
|
||||
def eval(self, m):
|
||||
return self._evalSmall(m) + self._evalSmooth(m)
|
||||
|
||||
@Utils.timeIt
|
||||
def _evalSmall(self, m):
|
||||
r = self.Wsmall * ( self.mapping * (m - self.mref) )
|
||||
return 0.5 * r.dot(r)
|
||||
|
||||
@Utils.timeIt
|
||||
def _evalSmooth(self, m):
|
||||
if self.mrefInSmooth == True:
|
||||
r = self.Wsmooth * ( self.mapping * (m - self.mref) )
|
||||
elif self.mrefInSmooth == False:
|
||||
r = self.Wsmooth * ( self.mapping * m)
|
||||
return 0.5 * r.dot(r)
|
||||
|
||||
def cross(a,b):
|
||||
ax, ay, az = a[0], a[1], a[2]
|
||||
bx, by, bz = b[0], b[1], b[2]
|
||||
cx = ay*bz - az*by
|
||||
cy = az*bx - ax*bz
|
||||
cz = ax*by - ay*bx
|
||||
return [cx, cy, cz]
|
||||
|
||||
# TODO: Implement Cross Gradients..
|
||||
@Utils.timeIt
|
||||
def _evalCross(self, m):
|
||||
if self.crossgrad == False:
|
||||
return 0.
|
||||
elif self.crossgrad == True:
|
||||
M = (self.mapping * m).reshape((self.regmesh.nC, self.nModels), order="F")
|
||||
|
||||
ax = self.regmesh.aveFx2CC*self.regmesh.wx[0]*M[:,0]
|
||||
ay = self.regmesh.aveFy2CC*self.regmesh.wy[0]*M[:,0]
|
||||
az = self.regmesh.aveFz2CC*self.regmesh.wz[0]*M[:,0]
|
||||
bx = self.regmesh.aveFx2CC*self.regmesh.wx[1]*M[:,1]
|
||||
by = self.regmesh.aveFy2CC*self.regmesh.wy[1]*M[:,1]
|
||||
bz = self.regmesh.aveFz2CC*self.regmesh.wz[1]*M[:,1]
|
||||
#ab
|
||||
out_ab = cross([ax, ay, az], [bx, by, bz])
|
||||
r = np.r_[out_ab[0], out_ab[1], out_ab[2]]*np.sqrt(self.betacross)
|
||||
|
||||
if self.nModels == 3:
|
||||
cx = self.regmesh.aveFx2CC*self.regmesh.wx[1]*M[:,1]
|
||||
cy = self.regmesh.aveFy2CC*self.regmesh.wy[1]*M[:,1]
|
||||
cz = self.regmesh.aveFz2CC*self.regmesh.wz[1]*M[:,1]
|
||||
#ac
|
||||
out_ac = cross([ax, ay, az], [cx, cy, cz])
|
||||
#bc
|
||||
out_bc = cross([bx, by, bz], [cx, cy, cz])
|
||||
r = np.r_[r, np.hstack(out_ac)*np.sqrt(self.betacross), np.hstack(out_bc)*np.sqrt(self.betacross)]
|
||||
|
||||
return 0.5 * r.dot(r)
|
||||
|
||||
@Utils.timeIt
|
||||
def evalDeriv(self, m):
|
||||
"""
|
||||
The regularization is:
|
||||
|
||||
.. math::
|
||||
|
||||
R(m) = \\frac{1}{2}\mathbf{(m-m_\\text{ref})^\\top W^\\top W(m-m_\\text{ref})}
|
||||
|
||||
So the derivative is straight forward:
|
||||
|
||||
.. math::
|
||||
|
||||
R(m) = \mathbf{W^\\top W (m-m_\\text{ref})}
|
||||
|
||||
"""
|
||||
deriv = self._evalSmallDeriv(m) + self._evalSmoothDeriv(m)
|
||||
if self.crossgrad==True:
|
||||
deriv += self._evalCrossDeriv(m)
|
||||
return deriv
|
||||
|
||||
@Utils.timeIt
|
||||
def _evalCrossDeriv(self,m):
|
||||
r = self.Wsmall * ( self.mapping * (m - self.mref) )
|
||||
return r.T * ( self.Wsmall * self.mapping.deriv(m - self.mref) )
|
||||
|
||||
@Utils.timeIt
|
||||
def eval2Deriv(self, m, v=None):
|
||||
"""
|
||||
Second derivative
|
||||
|
||||
:param numpy.array m: geophysical model
|
||||
:param numpy.array v: vector to multiply
|
||||
:rtype: scipy.sparse.csr_matrix or numpy.ndarray
|
||||
:return: WtW or WtW*v
|
||||
|
||||
The regularization is:
|
||||
|
||||
.. math::
|
||||
|
||||
R(m) = \\frac{1}{2}\mathbf{(m-m_\\text{ref})^\\top W^\\top W(m-m_\\text{ref})}
|
||||
|
||||
So the second derivative is straight forward:
|
||||
|
||||
.. math::
|
||||
|
||||
R(m) = \mathbf{W^\\top W}
|
||||
|
||||
"""
|
||||
mD = self.mapping.deriv(m - self.mref)
|
||||
if v is None:
|
||||
return mD.T * self.W.T * self.W * mD
|
||||
|
||||
return mD.T * ( self.W.T * ( self.W * ( mD * v) ) )
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import SimPEG
|
||||
import numpy as np
|
||||
from SimPEG.Utils import Zero, closestPoints
|
||||
|
||||
class BaseRx(SimPEG.Survey.BaseTimeRx):
|
||||
locs = None
|
||||
rxType = None
|
||||
|
||||
knownRxTypes = {
|
||||
'phi':['phi',None],
|
||||
'ex':['e','x'],
|
||||
'ey':['e','y'],
|
||||
'ez':['e','z'],
|
||||
'jx':['j','x'],
|
||||
'jy':['j','y'],
|
||||
'jz':['j','z'],
|
||||
}
|
||||
|
||||
def __init__(self, locs, times, rxType, **kwargs):
|
||||
SimPEG.Survey.BaseTimeRx.__init__(self, locs, times, rxType, **kwargs)
|
||||
|
||||
@property
|
||||
def projField(self):
|
||||
"""Field Type projection (e.g. e b ...)"""
|
||||
return self.knownRxTypes[self.rxType][0]
|
||||
|
||||
def projGLoc(self, f):
|
||||
"""Grid Location projection (e.g. Ex Fy ...)"""
|
||||
comp = self.knownRxTypes[self.rxType][1]
|
||||
if comp is not None:
|
||||
return f._GLoc(self.rxType) + comp
|
||||
return f._GLoc(self.rxType)
|
||||
|
||||
def getTimeP(self, timesall):
|
||||
"""
|
||||
Returns the time projection matrix.
|
||||
|
||||
.. note::
|
||||
|
||||
This is not stored in memory, but is created on demand.
|
||||
"""
|
||||
time_inds = np.in1d(timesall, self.times)
|
||||
return time_inds
|
||||
|
||||
def evalDeriv(self, src, mesh, f, v, adjoint=False):
|
||||
P = self.getP(mesh, self.projGLoc(f))
|
||||
if not adjoint:
|
||||
return P*v
|
||||
elif adjoint:
|
||||
return P.T*v
|
||||
|
||||
|
||||
# DC.Rx.Dipole(locs)
|
||||
class Dipole(BaseRx):
|
||||
|
||||
def __init__(self, locsM, locsN, times, rxType = 'phi', **kwargs):
|
||||
assert locsM.shape == locsN.shape, 'locsM and locsN need to be the same size'
|
||||
locs = [locsM, locsN]
|
||||
# We may not need this ...
|
||||
BaseRx.__init__(self, locs, times, rxType)
|
||||
|
||||
@property
|
||||
def nD(self):
|
||||
"""Number of data in the receiver."""
|
||||
# return self.locs[0].shape[0] * len(self.times)
|
||||
return self.locs[0].shape[0]
|
||||
|
||||
@property
|
||||
def nRx(self):
|
||||
"""Number of data in the receiver."""
|
||||
return self.locs[0].shape[0]
|
||||
|
||||
# Not sure why ...
|
||||
# return int(self.locs[0].size / 2)
|
||||
|
||||
|
||||
def getP(self, mesh, Gloc):
|
||||
if mesh in self._Ps:
|
||||
return self._Ps[mesh]
|
||||
|
||||
P0 = mesh.getInterpolationMat(self.locs[0], Gloc)
|
||||
P1 = mesh.getInterpolationMat(self.locs[1], Gloc)
|
||||
P = P0 - P1
|
||||
|
||||
if self.storeProjections:
|
||||
self._Ps[mesh] = P
|
||||
|
||||
return P
|
||||
@@ -0,0 +1,64 @@
|
||||
import SimPEG
|
||||
# from SimPEG.EM.Base import BaseEMSurvey
|
||||
from SimPEG.Utils import Zero, closestPoints, mkvc
|
||||
import numpy as np
|
||||
|
||||
class BaseSrc(SimPEG.Survey.BaseSrc):
|
||||
|
||||
current = 1.0
|
||||
loc = None
|
||||
|
||||
def __init__(self, rxList, **kwargs):
|
||||
SimPEG.Survey.BaseSrc.__init__(self, rxList, **kwargs)
|
||||
|
||||
def eval(self, prob):
|
||||
raise NotImplementedError
|
||||
|
||||
def evalDeriv(self, prob):
|
||||
return Zero()
|
||||
|
||||
@property
|
||||
def nD(self):
|
||||
"""Number of data"""
|
||||
return self.vnD.sum()
|
||||
|
||||
@property
|
||||
def vnD(self):
|
||||
"""Vector number of data"""
|
||||
return np.array([rx.nD*len(rx.times) for rx in self.rxList])
|
||||
|
||||
|
||||
|
||||
class Dipole(BaseSrc):
|
||||
|
||||
def __init__(self, rxList, locA, locB, **kwargs):
|
||||
assert locA.shape == locB.shape, 'Shape of locA and locB should be the same'
|
||||
self.loc = [locA, locB]
|
||||
BaseSrc.__init__(self, rxList, **kwargs)
|
||||
|
||||
def eval(self, prob):
|
||||
if prob._formulation == 'HJ':
|
||||
inds = closestPoints(prob.mesh, self.loc, gridLoc='CC')
|
||||
q = np.zeros(prob.mesh.nC)
|
||||
q[inds] = self.current * np.r_[1., -1.]
|
||||
elif prob._formulation == 'EB':
|
||||
qa = prob.mesh.getInterpolationMat(self.loc[0], locType='N').todense()
|
||||
qb = -prob.mesh.getInterpolationMat(self.loc[1], locType='N').todense()
|
||||
q = self.current * mkvc(qa+qb)
|
||||
return q
|
||||
|
||||
class Pole(BaseSrc):
|
||||
|
||||
def __init__(self, rxList, loc, **kwargs):
|
||||
BaseSrc.__init__(self, rxList, loc=loc, **kwargs)
|
||||
|
||||
def eval(self, prob):
|
||||
if prob._formulation == 'HJ':
|
||||
inds = closestPoints(prob.mesh, self.loc)
|
||||
q = np.zeros(prob.mesh.nC)
|
||||
q[inds] = self.current * np.r_[1.]
|
||||
elif prob._formulation == 'EB':
|
||||
q = prob.mesh.getInterpolationMat(self.loc, locType='N').todense()
|
||||
q = self.current * mkvc(q)
|
||||
return q
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
import SimPEG
|
||||
from SimPEG.EM.Base import BaseEMSurvey
|
||||
from SimPEG import np, sp, Survey, Utils
|
||||
from SimPEG.Utils import Zero, Identity
|
||||
from SimPEG.EM.Static.SIP.SrcSIP import BaseSrc
|
||||
from SimPEG.EM.Static.SIP.RxSIP import BaseRx
|
||||
import uuid
|
||||
|
||||
|
||||
class Survey(BaseEMSurvey):
|
||||
rxPair = BaseRx
|
||||
srcPair = BaseSrc
|
||||
times = None
|
||||
|
||||
def __init__(self, srcList, **kwargs):
|
||||
self.srcList = srcList
|
||||
BaseEMSurvey.__init__(self, srcList, **kwargs)
|
||||
self.getUniqueTimes()
|
||||
|
||||
def getUniqueTimes(self):
|
||||
time_rx = []
|
||||
for src in self.srcList:
|
||||
for rx in src.rxList:
|
||||
time_rx.append(rx.times)
|
||||
self.times = np.unique(np.hstack(time_rx))
|
||||
|
||||
def dpred(self, m, f=None):
|
||||
"""
|
||||
Predicted data.
|
||||
|
||||
.. math::
|
||||
d_\\text{pred} = Pf(m)
|
||||
"""
|
||||
return self.prob.forward(m, f=f)
|
||||
|
||||
|
||||
class Data(SimPEG.Survey.Data):
|
||||
"""Fancy data storage by Src and Rx"""
|
||||
|
||||
def __init__(self, survey, v=None):
|
||||
self.uid = str(uuid.uuid4())
|
||||
self.survey = survey
|
||||
self._dataDict = {}
|
||||
for src in self.survey.srcList:
|
||||
self._dataDict[src] = {}
|
||||
for rx in src.rxList:
|
||||
self._dataDict[src][rx] = {}
|
||||
|
||||
if v is not None:
|
||||
self.fromvec(v)
|
||||
|
||||
def _ensureCorrectKey(self, key):
|
||||
if type(key) is tuple:
|
||||
if len(key) is not 3:
|
||||
raise KeyError('Key must be [Src, Rx, tInd]')
|
||||
if key[0] not in self.survey.srcList:
|
||||
raise KeyError('Src Key must be a source in the survey.')
|
||||
if key[1] not in key[0].rxList:
|
||||
raise KeyError('Rx Key must be a receiver for the source.')
|
||||
return key
|
||||
elif isinstance(key, self.survey.srcPair):
|
||||
if key not in self.survey.srcList:
|
||||
raise KeyError('Key must be a source in the survey.')
|
||||
return key, None, None
|
||||
else:
|
||||
raise KeyError('Key must be [Src] or [Src,Rx] or [Src, Rx, tInd]')
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
src, rx, t = self._ensureCorrectKey(key)
|
||||
assert rx is not None, 'set data using [Src, Rx]'
|
||||
assert isinstance(value, np.ndarray), 'value must by ndarray'
|
||||
assert value.size == rx.nD, "value must have the same number of data as the source."
|
||||
self._dataDict[src][rx][t] = Utils.mkvc(value)
|
||||
|
||||
def __getitem__(self, key):
|
||||
src, rx, t = self._ensureCorrectKey(key)
|
||||
if rx is not None:
|
||||
if rx not in self._dataDict[src]:
|
||||
raise Exception('Data for receiver has not yet been set.')
|
||||
return self._dataDict[src][rx][t]
|
||||
|
||||
return np.concatenate([self[src,rx, t] for rx in src.rxList])
|
||||
|
||||
def tovec(self):
|
||||
val = []
|
||||
for src in self.survey.srcList:
|
||||
for rx in src.rxList:
|
||||
for t in rx.times:
|
||||
val.append(self[src, rx, t])
|
||||
return np.concatenate(val)
|
||||
|
||||
|
||||
def fromvec(self, v):
|
||||
v = Utils.mkvc(v)
|
||||
assert v.size == self.survey.nD, 'v must have the correct number of data.'
|
||||
indBot, indTop = 0, 0
|
||||
for src in self.survey.srcList:
|
||||
for rx in src.rxList:
|
||||
for t in rx.times:
|
||||
indTop += rx.nRx
|
||||
self[src, rx, t] = v[indBot:indTop]
|
||||
indBot += rx.nRx
|
||||
@@ -0,0 +1,5 @@
|
||||
from ProblemSIP import Problem3D_CC, Problem3D_N
|
||||
from SurveySIP import Survey, Data
|
||||
import SrcSIP as Src #Pole
|
||||
import RxSIP as Rx
|
||||
from Regularization import MultiRegularization
|
||||
@@ -0,0 +1,317 @@
|
||||
from SimPEG import np
|
||||
from SimPEG.EM.Static import DC, IP
|
||||
|
||||
def plot_pseudoSection(DCsurvey, axs, stype='dpdp', dtype="appc", clim=None):
|
||||
"""
|
||||
Read list of 2D tx-rx location and plot a speudo-section of apparent
|
||||
resistivity.
|
||||
|
||||
Assumes flat topo for now...
|
||||
|
||||
Input:
|
||||
:param d2D, z0
|
||||
:switch stype -> Either 'pdp' (pole-dipole) | 'dpdp' (dipole-dipole)
|
||||
:switch dtype=-> Either 'appr' (app. res) | 'appc' (app. con) | 'volt' (potential)
|
||||
Output:
|
||||
:figure scatter plot overlayed on image
|
||||
|
||||
Edited Feb 17th, 2016
|
||||
|
||||
@author: dominiquef
|
||||
|
||||
"""
|
||||
from SimPEG import np
|
||||
from scipy.interpolate import griddata
|
||||
import pylab as plt
|
||||
|
||||
# Set depth to 0 for now
|
||||
z0 = 0.
|
||||
|
||||
# Pre-allocate
|
||||
midx = []
|
||||
midz = []
|
||||
rho = []
|
||||
LEG = []
|
||||
count = 0 # Counter for data
|
||||
for ii in range(DCsurvey.nSrc):
|
||||
|
||||
Tx = DCsurvey.srcList[ii].loc
|
||||
Rx = DCsurvey.srcList[ii].rxList[0].locs
|
||||
|
||||
nD = DCsurvey.srcList[ii].rxList[0].nD
|
||||
|
||||
data = DCsurvey.dobs[count:count+nD]
|
||||
count += nD
|
||||
|
||||
# Get distances between each poles A-B-M-N
|
||||
if stype == 'pdp':
|
||||
MA = np.abs(Tx[0] - Rx[0][:,0])
|
||||
NA = np.abs(Tx[0] - Rx[1][:,0])
|
||||
MN = np.abs(Rx[1][:,0] - Rx[0][:,0])
|
||||
|
||||
# Create mid-point location
|
||||
Cmid = Tx[0]
|
||||
Pmid = (Rx[0][:,0] + Rx[1][:,0])/2
|
||||
if DCsurvey.mesh.dim == 2:
|
||||
zsrc = Tx[1]
|
||||
elif DCsurvey.mesh.dim ==3:
|
||||
zsrc = Tx[2]
|
||||
|
||||
elif stype == 'dpdp':
|
||||
MA = np.abs(Tx[0][0] - Rx[0][:,0])
|
||||
MB = np.abs(Tx[1][0] - Rx[0][:,0])
|
||||
NA = np.abs(Tx[0][0] - Rx[1][:,0])
|
||||
NB = np.abs(Tx[1][0] - Rx[1][:,0])
|
||||
|
||||
# Create mid-point location
|
||||
Cmid = (Tx[0][0] + Tx[1][0])/2
|
||||
Pmid = (Rx[0][:,0] + Rx[1][:,0])/2
|
||||
if DCsurvey.mesh.dim == 2:
|
||||
zsrc = (Tx[0][1] + Tx[1][1])/2
|
||||
elif DCsurvey.mesh.dim ==3:
|
||||
zsrc = (Tx[0][2] + Tx[1][2])/2
|
||||
|
||||
# Change output for dtype
|
||||
if dtype == 'volt':
|
||||
|
||||
rho = np.hstack([rho,data])
|
||||
|
||||
else:
|
||||
|
||||
# Compute pant leg of apparent rho
|
||||
if stype == 'pdp':
|
||||
|
||||
leg = data * 2*np.pi * MA * ( MA + MN ) / MN
|
||||
|
||||
elif stype == 'dpdp':
|
||||
|
||||
leg = data * 2*np.pi / ( 1/MA - 1/MB + 1/NB - 1/NA )
|
||||
LEG.append(1./(2*np.pi) *( 1/MA - 1/MB + 1/NB - 1/NA ))
|
||||
else:
|
||||
print """dtype must be 'pdp'(pole-dipole) | 'dpdp' (dipole-dipole) """
|
||||
break
|
||||
|
||||
|
||||
if dtype == 'appc':
|
||||
|
||||
leg = np.log10(abs(1./leg))
|
||||
rho = np.hstack([rho,leg])
|
||||
|
||||
elif dtype == 'appr':
|
||||
|
||||
leg = np.log10(abs(leg))
|
||||
rho = np.hstack([rho,leg])
|
||||
|
||||
else:
|
||||
print """dtype must be 'appr' | 'appc' | 'volt' """
|
||||
break
|
||||
|
||||
|
||||
midx = np.hstack([midx, ( Cmid + Pmid )/2 ])
|
||||
if DCsurvey.mesh.dim==3:
|
||||
midz = np.hstack([midz, -np.abs(Cmid-Pmid)/2 + zsrc ])
|
||||
elif DCsurvey.mesh.dim==2:
|
||||
midz = np.hstack([midz, -np.abs(Cmid-Pmid)/2 + zsrc ])
|
||||
ax = axs
|
||||
|
||||
# Grid points
|
||||
grid_x, grid_z = np.mgrid[np.min(midx):np.max(midx), np.min(midz):np.max(midz)]
|
||||
grid_rho = griddata(np.c_[midx,midz], rho.T, (grid_x, grid_z), method='linear')
|
||||
|
||||
if clim == None:
|
||||
vmin, vmax = rho.min(), rho.max()
|
||||
else:
|
||||
vmin, vmax = clim[0], clim[1]
|
||||
|
||||
grid_rho = np.ma.masked_where(np.isnan(grid_rho), grid_rho)
|
||||
ph = plt.pcolormesh(grid_x[:,0],grid_z[0,:],grid_rho.T, clim=(vmin, vmax), vmin=vmin, vmax=vmax)
|
||||
cbar = plt.colorbar(format="$10^{%.1f}$",fraction=0.04,orientation="horizontal")
|
||||
|
||||
cmin,cmax = cbar.get_clim()
|
||||
ticks = np.linspace(cmin,cmax,3)
|
||||
cbar.set_ticks(ticks)
|
||||
cbar.ax.tick_params(labelsize=10)
|
||||
|
||||
if dtype == 'appc':
|
||||
cbar.set_label("App.Cond",size=12)
|
||||
elif dtype == 'appr':
|
||||
cbar.set_label("App.Res.",size=12)
|
||||
elif dtype == 'volt':
|
||||
cbar.set_label("Potential (V)",size=12)
|
||||
|
||||
# Plot apparent resistivity
|
||||
ax.scatter(midx,midz,s=10,c=rho.T, vmin =vmin, vmax = vmax, clim=(vmin, vmax))
|
||||
|
||||
#ax.set_xticklabels([])
|
||||
#ax.set_yticklabels([])
|
||||
|
||||
plt.gca().set_aspect('equal', adjustable='box')
|
||||
|
||||
|
||||
|
||||
return ph, LEG
|
||||
|
||||
def gen_DCIPsurvey(endl, mesh, stype, a, b, n):
|
||||
"""
|
||||
Load in endpoints and survey specifications to generate Tx, Rx location
|
||||
stations.
|
||||
|
||||
Assumes flat topo for now...
|
||||
|
||||
Input:
|
||||
:param endl -> input endpoints [x1, y1, z1, x2, y2, z2]
|
||||
:object mesh -> SimPEG mesh object
|
||||
:switch stype -> "dpdp" (dipole-dipole) | "pdp" (pole-dipole) | 'gradient'
|
||||
: param a, n -> pole seperation, number of rx dipoles per tx
|
||||
|
||||
Output:
|
||||
:param Tx, Rx -> List objects for each tx location
|
||||
Lines: P1x, P1y, P1z, P2x, P2y, P2z
|
||||
|
||||
Created on Wed December 9th, 2015
|
||||
|
||||
@author: dominiquef
|
||||
!! Require clean up to deal with DCsurvey
|
||||
"""
|
||||
|
||||
from SimPEG import np
|
||||
|
||||
def xy_2_r(x1,x2,y1,y2):
|
||||
r = np.sqrt( np.sum((x2 - x1)**2 + (y2 - y1)**2) )
|
||||
return r
|
||||
|
||||
## Evenly distribute electrodes and put on surface
|
||||
# Mesure survey length and direction
|
||||
dl_len = xy_2_r(endl[0,0],endl[1,0],endl[0,1],endl[1,1])
|
||||
|
||||
dl_x = ( endl[1,0] - endl[0,0] ) / dl_len
|
||||
dl_y = ( endl[1,1] - endl[0,1] ) / dl_len
|
||||
|
||||
nstn = np.floor( dl_len / a )
|
||||
|
||||
# Compute discrete pole location along line
|
||||
stn_x = endl[0,0] + np.array(range(int(nstn)))*dl_x*a
|
||||
stn_y = endl[0,1] + np.array(range(int(nstn)))*dl_y*a
|
||||
|
||||
if mesh.dim==2:
|
||||
ztop = mesh.vectorNy[-1]
|
||||
# Create line of P1 locations
|
||||
M = np.c_[stn_x, np.ones(nstn).T*ztop]
|
||||
# Create line of P2 locations
|
||||
N = np.c_[stn_x+a*dl_x, np.ones(nstn).T*ztop]
|
||||
|
||||
elif mesh.dim==3:
|
||||
ztop = mesh.vectorNz[-1]
|
||||
# Create line of P1 locations
|
||||
M = np.c_[stn_x, stn_y, np.ones(nstn).T*ztop]
|
||||
# Create line of P2 locations
|
||||
N = np.c_[stn_x+a*dl_x, stn_y+a*dl_y, np.ones(nstn).T*ztop]
|
||||
|
||||
|
||||
## Build list of Tx-Rx locations depending on survey type
|
||||
# Dipole-dipole: Moving tx with [a] spacing -> [AB a MN1 a MN2 ... a MNn]
|
||||
# Pole-dipole: Moving pole on one end -> [A a MN1 a MN2 ... MNn a B]
|
||||
SrcList = []
|
||||
|
||||
|
||||
if stype != 'gradient':
|
||||
|
||||
for ii in range(0, int(nstn)-1):
|
||||
|
||||
|
||||
if stype == 'dpdp':
|
||||
tx = np.c_[M[ii,:],N[ii,:]]
|
||||
elif stype == 'pdp':
|
||||
tx = np.c_[M[ii,:],M[ii,:]]
|
||||
|
||||
# Rx.append(np.c_[M[ii+1:indx,:],N[ii+1:indx,:]])
|
||||
|
||||
# Current elctrode seperation
|
||||
AB = xy_2_r(tx[0,1],endl[1,0],tx[1,1],endl[1,1])
|
||||
|
||||
# Number of receivers to fit
|
||||
nstn = np.min([np.floor( (AB - b) / a ) , n])
|
||||
|
||||
# Check if there is enough space, else break the loop
|
||||
if nstn <= 0:
|
||||
continue
|
||||
|
||||
# Compute discrete pole location along line
|
||||
stn_x = N[ii,0] + dl_x*b + np.array(range(int(nstn)))*dl_x*a
|
||||
stn_y = N[ii,1] + dl_y*b + np.array(range(int(nstn)))*dl_y*a
|
||||
|
||||
# Create receiver poles
|
||||
|
||||
if mesh.dim==3:
|
||||
# Create line of P1 locations
|
||||
P1 = np.c_[stn_x, stn_y, np.ones(nstn).T*ztop]
|
||||
# Create line of P2 locations
|
||||
P2 = np.c_[stn_x+a*dl_x, stn_y+a*dl_y, np.ones(nstn).T*ztop]
|
||||
rxClass = DC.Rx.Dipole(P1, P2)
|
||||
|
||||
elif mesh.dim==2:
|
||||
# Create line of P1 locations
|
||||
P1 = np.c_[stn_x, np.ones(nstn).T*ztop]
|
||||
# Create line of P2 locations
|
||||
P2 = np.c_[stn_x+a*dl_x, np.ones(nstn).T*ztop]
|
||||
rxClass = DC.Rx.Dipole_ky(P1, P2)
|
||||
|
||||
if stype == 'dpdp':
|
||||
srcClass = DC.Src.Dipole([rxClass], M[ii,:],N[ii,:])
|
||||
elif stype == 'pdp':
|
||||
srcClass = DC.Src.Pole([rxClass], M[ii,:])
|
||||
SrcList.append(srcClass)
|
||||
|
||||
elif stype == 'gradient':
|
||||
|
||||
# Gradient survey only requires Tx at end of line and creates a square
|
||||
# grid of receivers at in the middle at a pre-set minimum distance
|
||||
|
||||
# Get the edge limit of survey area
|
||||
min_x = endl[0,0] + dl_x * b
|
||||
min_y = endl[0,1] + dl_y * b
|
||||
|
||||
max_x = endl[1,0] - dl_x * b
|
||||
max_y = endl[1,1] - dl_y * b
|
||||
|
||||
box_l = np.sqrt( (min_x - max_x)**2 + (min_y - max_y)**2 )
|
||||
box_w = box_l/2.
|
||||
|
||||
nstn = np.floor( box_l / a )
|
||||
|
||||
# Compute discrete pole location along line
|
||||
stn_x = min_x + np.array(range(int(nstn)))*dl_x*a
|
||||
stn_y = min_y + np.array(range(int(nstn)))*dl_y*a
|
||||
|
||||
# Define number of cross lines
|
||||
nlin = int(np.floor( box_w / a ))
|
||||
lind = range(-nlin,nlin+1)
|
||||
|
||||
ngrad = nstn * len(lind)
|
||||
|
||||
rx = np.zeros([ngrad,6])
|
||||
for ii in range( len(lind) ):
|
||||
|
||||
# Move line in perpendicular direction by dipole spacing
|
||||
lxx = stn_x - lind[ii]*a*dl_y
|
||||
lyy = stn_y + lind[ii]*a*dl_x
|
||||
|
||||
|
||||
M = np.c_[ lxx, lyy , np.ones(nstn).T*ztop]
|
||||
N = np.c_[ lxx+a*dl_x, lyy+a*dl_y, np.ones(nstn).T*ztop]
|
||||
rx[(ii*nstn):((ii+1)*nstn),:] = np.c_[M,N]
|
||||
|
||||
if mesh.dim==3:
|
||||
rxClass = DC.Rx.Dipole(rx[:,:3], rx[:,3:])
|
||||
elif mesh.dim==2:
|
||||
M = M[:,[0,2]]
|
||||
N = N[:,[0,2]]
|
||||
rxClass = DC.Rx.Dipole_ky(rx[:,[0,2]], rx[:,[3,5]])
|
||||
srcClass = DC.Src.Dipole([rxClass], M[0,:], N[-1,:])
|
||||
SrcList.append(srcClass)
|
||||
else:
|
||||
print """stype must be either 'pdp', 'dpdp' or 'gradient'. """
|
||||
|
||||
|
||||
return SrcList
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
from StaticUtils import *
|
||||
@@ -0,0 +1,3 @@
|
||||
import DC
|
||||
import IP
|
||||
import SIP
|
||||
@@ -87,7 +87,7 @@ class SrcTDEM_VMD_MVP(SrcTDEM):
|
||||
def getInitialFields(self, mesh):
|
||||
"""Vertical magnetic dipole, magnetic vector potential"""
|
||||
if self.waveformType == "STEPOFF":
|
||||
print ">> Step waveform: Non-zero initial condition"
|
||||
print ">> Step waveform: Non-zero initial condition"
|
||||
if mesh._meshType is 'CYL':
|
||||
if mesh.isSymmetric:
|
||||
MVP = MagneticDipoleVectorPotential(self.loc, mesh, 'Ey')
|
||||
@@ -96,8 +96,8 @@ class SrcTDEM_VMD_MVP(SrcTDEM):
|
||||
elif mesh._meshType is 'TENSOR':
|
||||
MVP = MagneticDipoleVectorPotential(self.loc, mesh, ['Ex','Ey','Ez'])
|
||||
else:
|
||||
raise Exception('Unknown mesh for VMD')
|
||||
return {"b": mesh.edgeCurl*MVP}
|
||||
raise Exception('Unknown mesh for VMD')
|
||||
return {"b": mesh.edgeCurl*MVP}
|
||||
elif self.waveformType == "GENERAL":
|
||||
print ">> General waveform: Zero initial condition"
|
||||
return {"b": np.zeros(mesh.nF)}
|
||||
@@ -113,7 +113,7 @@ class SrcTDEM_VMD_MVP(SrcTDEM):
|
||||
elif mesh._meshType is 'TENSOR':
|
||||
MVP = MagneticDipoleVectorPotential(self.loc, mesh, ['Ex','Ey','Ez'])
|
||||
else:
|
||||
raise Exception('Unknown mesh for VMD')
|
||||
raise Exception('Unknown mesh for VMD')
|
||||
return mesh.edgeCurl.T*MfMui*mesh.edgeCurl*MVP
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ class SrcTDEM_CircularLoop_MVP(SrcTDEM):
|
||||
self.loc = loc
|
||||
self.radius = radius
|
||||
self.waveformType = waveformType
|
||||
SrcTDEM.__init__(self,rxList)
|
||||
SrcTDEM.__init__(self,rxList)
|
||||
|
||||
def getInitialFields(self, mesh):
|
||||
"""Circular Loop, magnetic vector potential"""
|
||||
@@ -153,7 +153,7 @@ class SrcTDEM_CircularLoop_MVP(SrcTDEM):
|
||||
elif mesh._meshType is 'TENSOR':
|
||||
MVP = MagneticLoopVectorPotential(self.loc, mesh, ['Ex','Ey','Ez'], self.radius)
|
||||
else:
|
||||
raise Exception('Unknown mesh for CircularLoop')
|
||||
raise Exception('Unknown mesh for CircularLoop')
|
||||
return mesh.edgeCurl.T*MfMui*mesh.edgeCurl*MVP
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ def getFDEMProblem(fdemType, comp, SrcList, freq, useMu=False, verbose=False):
|
||||
mesh = Mesh.TensorMesh([hx,hy,hz],['C','C','C'])
|
||||
|
||||
if useMu is True:
|
||||
mapping = [('sigma', Maps.ExpMap(mesh)), ('mu', Maps.IdentityMap(mesh))]
|
||||
mapping = [('sigma', Maps.ExpMap(mesh)), ('mu', Maps.IdentityMap(mesh))]
|
||||
else:
|
||||
mapping = Maps.ExpMap(mesh)
|
||||
|
||||
@@ -37,39 +37,20 @@ def getFDEMProblem(fdemType, comp, SrcList, freq, useMu=False, verbose=False):
|
||||
Src.append(EM.FDEM.Src.MagDipole_Bfield([Rx0], freq=freq, loc=np.r_[0.,0.,0.]))
|
||||
elif SrcType is 'CircularLoop':
|
||||
Src.append(EM.FDEM.Src.CircularLoop([Rx0], freq=freq, loc=np.r_[0.,0.,0.]))
|
||||
|
||||
elif SrcType is 'RawVec':
|
||||
if fdemType is 'e' or fdemType is 'b':
|
||||
S_m = np.zeros(mesh.nF)
|
||||
S_e = np.zeros(mesh.nE)
|
||||
S_m[Utils.closestPoints(mesh,[0.,0.,0.],'Fz') + np.sum(mesh.vnF[:1])] = 1e-3
|
||||
S_e[Utils.closestPoints(mesh,[0.,0.,0.],'Ez') + np.sum(mesh.vnE[:1])] = 1e-3
|
||||
Src.append(EM.FDEM.Src.RawVec([Rx0], freq, S_m, S_e, integrate=True))
|
||||
Src.append(EM.FDEM.Src.RawVec([Rx0], freq, S_m, S_e))
|
||||
|
||||
elif fdemType is 'h' or fdemType is 'j':
|
||||
S_m = np.zeros(mesh.nE)
|
||||
S_e = np.zeros(mesh.nF)
|
||||
S_m[Utils.closestPoints(mesh,[0.,0.,0.],'Ez') + np.sum(mesh.vnE[:1])] = 1e-3
|
||||
S_e[Utils.closestPoints(mesh,[0.,0.,0.],'Fz') + np.sum(mesh.vnF[:1])] = 1e-3
|
||||
Src.append(EM.FDEM.Src.RawVec([Rx0], freq, S_m, S_e, integrate=True))
|
||||
|
||||
elif SrcType is 'PrimSec':
|
||||
primSrc = EM.FDEM.Src.MagDipole([], freq, np.r_[0.,0.,0.])
|
||||
primarySurvey = EM.FDEM.Survey([primSrc])
|
||||
primaryProblem = EM.FDEM.Problem_e(mesh,mapping=mapping)
|
||||
mPrimary = np.ones(mapping.nP)*np.log(CONDUCTIVITY)
|
||||
Src.append(EM.FDEM.Src.PrimSec([Rx0], freq, mPrimary, prob=primaryProblem, survey=primarySurvey))
|
||||
|
||||
elif SrcType is 'PrimSecCyl':
|
||||
hx = [(cs,ncx + 2), (cs,npad + 2,1.3)]
|
||||
hz = [(cs,npad + 2 ,-1.3), (cs,ncz+2), (cs,npad+2,1.3)]
|
||||
primmesh = Mesh.CylMesh([hx,1,hz], '00C')
|
||||
|
||||
primSrc = EM.FDEM.Src.MagDipole([], freq, np.r_[0.,0.,0.])
|
||||
primarySurvey = EM.FDEM.Survey([primSrc])
|
||||
primaryProblem = EM.FDEM.Problem_e(primmesh)
|
||||
mPrimary = np.ones(primmesh.nC)*CONDUCTIVITY
|
||||
Src.append(EM.FDEM.Src.PrimSec([Rx0], freq, mPrimary, prob=primaryProblem, survey=primarySurvey))
|
||||
Src.append(EM.FDEM.Src.RawVec([Rx0], freq, S_m, S_e))
|
||||
|
||||
if verbose:
|
||||
print ' Fetching %s problem' % (fdemType)
|
||||
@@ -109,7 +90,7 @@ def crossCheckTest(SrcList, fdemType1, fdemType2, comp, addrandoms = False, useM
|
||||
prb1 = getFDEMProblem(fdemType1, comp, SrcList, freq, useMu, verbose)
|
||||
mesh = prb1.mesh
|
||||
print 'Cross Checking Forward: %s, %s formulations - %s' % (fdemType1, fdemType2, comp)
|
||||
|
||||
|
||||
logsig = np.log(np.ones(mesh.nC)*CONDUCTIVITY)
|
||||
mu = np.ones(mesh.nC)*MU
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import TDEM
|
||||
import FDEM
|
||||
import Static
|
||||
import Base
|
||||
import Analytics
|
||||
import Utils
|
||||
|
||||
@@ -2,19 +2,27 @@ from SimPEG import Mesh, Utils, np, sp
|
||||
import SimPEG.DCIP as DC
|
||||
import time
|
||||
|
||||
def run(loc=None, sig=None, radi=None, param=None, stype='dpdp', plotIt=True):
|
||||
def run(loc=None, sig=None, radi=None, param=None, stype='dpdp', dtype='appc', plotIt=True):
|
||||
"""
|
||||
DC Forward Simulation
|
||||
=====================
|
||||
|
||||
Forward model conductive spheres in a half-space and plot a pseudo-section
|
||||
Forward model two conductive spheres in a half-space and plot a
|
||||
pseudo-section. Assumes an infinite line source and measures along the
|
||||
center of the spheres.
|
||||
|
||||
Created by @fourndo on Mon Feb 01 19:28:06 2016
|
||||
INPUT:
|
||||
loc = Location of spheres [[x1,y1,z1],[x2,y2,z2]]
|
||||
radi = Radius of spheres [r1,r2]
|
||||
param = Conductivity of background and two spheres [m0,m1,m2]
|
||||
stype = survey type "pdp" (pole dipole) or "dpdp" (dipole dipole)
|
||||
dtype = Data type "appr" (app res) | "appc" (app cond) | "volt" (potential)
|
||||
Created by @fourndo
|
||||
|
||||
"""
|
||||
|
||||
assert stype in ['pdp', 'dpdp'], "Source type (stype) must be pdp or dpdp (pole dipole or dipole dipole)"
|
||||
|
||||
assert dtype in ['appr', 'appc', 'volt'], "Data type (dtype) must be appr (app res) or appc (app cond) or volt (potential)"
|
||||
|
||||
if loc is None:
|
||||
loc = np.c_[[-50.,0.,-50.],[50.,0.,-50.]]
|
||||
@@ -27,7 +35,6 @@ def run(loc=None, sig=None, radi=None, param=None, stype='dpdp', plotIt=True):
|
||||
|
||||
|
||||
# First we need to create a mesh and a model.
|
||||
|
||||
# This is our mesh
|
||||
dx = 5.
|
||||
|
||||
@@ -52,14 +59,10 @@ def run(loc=None, sig=None, radi=None, param=None, stype='dpdp', plotIt=True):
|
||||
# Get index of the center
|
||||
indy = int(mesh.nCy/2)
|
||||
|
||||
|
||||
# Plot the model for reference
|
||||
# Define core mesh extent
|
||||
xlim = 200
|
||||
zlim = 125
|
||||
|
||||
# Specify the survey type: "pdp" | "dpdp"
|
||||
|
||||
zlim = 100
|
||||
|
||||
# Then specify the end points of the survey. Let's keep it simple for now and survey above the anomalies, top of the mesh
|
||||
ends = [(-175,0),(175,0)]
|
||||
@@ -77,12 +80,13 @@ def run(loc=None, sig=None, radi=None, param=None, stype='dpdp', plotIt=True):
|
||||
dl_len = np.sqrt( np.sum((locs[0,:] - locs[1,:])**2) )
|
||||
dl_x = ( Tx[-1][0,1] - Tx[0][0,0] ) / dl_len
|
||||
dl_y = ( Tx[-1][1,1] - Tx[0][1,0] ) / dl_len
|
||||
azm = np.arctan(dl_y/dl_x)
|
||||
#azm = np.arctan(dl_y/dl_x)
|
||||
|
||||
#Set boundary conditions
|
||||
mesh.setCellGradBC('neumann')
|
||||
|
||||
# Define the differential operators needed for the DC problem
|
||||
# Define the linear system needed for the DC problem. We assume an infitite
|
||||
# line source for simplicity.
|
||||
Div = mesh.faceDiv
|
||||
Grad = mesh.cellGrad
|
||||
Msig = Utils.sdiag(1./(mesh.aveF2CC.T*(1./model)))
|
||||
@@ -145,16 +149,23 @@ def run(loc=None, sig=None, radi=None, param=None, stype='dpdp', plotIt=True):
|
||||
print 'Forward completed'
|
||||
|
||||
# Let's just convert the 3D format into 2D (distance along line) and plot
|
||||
# [Tx2d, Rx2d] = DC.convertObs_DC3D_to_2D(survey, np.ones(survey.nSrc))
|
||||
survey2D = DC.convertObs_DC3D_to_2D(survey, np.ones(survey.nSrc))
|
||||
survey2D = DC.convertObs_DC3D_to_2D(survey, np.ones(survey.nSrc) , 'Xloc')
|
||||
survey2D.dobs =np.hstack(data)
|
||||
# Here is an example for the first tx-rx array
|
||||
|
||||
if plotIt:
|
||||
import matplotlib.pyplot as plt
|
||||
fig = plt.figure()
|
||||
fig = plt.figure(figsize=(7,7))
|
||||
ax = plt.subplot(2,1,1, aspect='equal')
|
||||
mesh.plotSlice(np.log10(model), ax =ax, normal = 'Y', ind = indy,grid=True)
|
||||
ax.set_title('E-W section at '+str(mesh.vectorCCy[indy])+' m')
|
||||
# Plot the location of the spheres for reference
|
||||
circle1=plt.Circle((loc[0,0],loc[2,0]),radi[0],color='w',fill=False, lw=3)
|
||||
circle2=plt.Circle((loc[0,1],loc[2,1]),radi[1],color='k',fill=False, lw=3)
|
||||
ax.add_artist(circle1)
|
||||
ax.add_artist(circle2)
|
||||
|
||||
dat = mesh.plotSlice(np.log10(model), ax =ax, normal = 'Y',
|
||||
ind = indy,grid=True, clim = np.log10([sig.min(),sig.max()]))
|
||||
|
||||
ax.set_title('3-D model')
|
||||
plt.gca().set_aspect('equal', adjustable='box')
|
||||
|
||||
plt.scatter(Tx[0][0,:],Tx[0][2,:],s=40,c='g', marker='v')
|
||||
@@ -163,22 +174,34 @@ def run(loc=None, sig=None, radi=None, param=None, stype='dpdp', plotIt=True):
|
||||
plt.ylim([-zlim,mesh.vectorNz[-1]+dx])
|
||||
|
||||
|
||||
ax = plt.subplot(2,1,2, aspect='equal')
|
||||
pos = ax.get_position()
|
||||
ax.set_position([pos.x0 , pos.y0 + 0.025 , pos.width, pos.height])
|
||||
pos = ax.get_position()
|
||||
cbarax = fig.add_axes([pos.x0 , pos.y0 + 0.025 , pos.width, pos.height * 0.04]) ## the parameters are the specified position you set
|
||||
cb = fig.colorbar(dat[0],cax=cbarax, orientation="horizontal",
|
||||
ax = ax, ticks=np.linspace(np.log10(sig.min()),
|
||||
np.log10(sig.max()), 3), format="$10^{%.1f}$")
|
||||
cb.set_label("Conductivity (S/m)",size=12)
|
||||
cb.ax.tick_params(labelsize=12)
|
||||
|
||||
# Second plot for the predicted apparent resistivity data
|
||||
ax2 = plt.subplot(2,1,2, aspect='equal')
|
||||
|
||||
# Plot the location of the spheres for reference
|
||||
circle1=plt.Circle((loc[0,0]-Tx[0][0,0],loc[2,0]),radi[0],color='w',fill=False, lw=3)
|
||||
circle2=plt.Circle((loc[0,1]-Tx[0][0,0],loc[2,1]),radi[1],color='k',fill=False, lw=3)
|
||||
ax.add_artist(circle1)
|
||||
ax.add_artist(circle2)
|
||||
circle1=plt.Circle((loc[0,0],loc[2,0]),radi[0],color='w',fill=False, lw=3)
|
||||
circle2=plt.Circle((loc[0,1],loc[2,1]),radi[1],color='k',fill=False, lw=3)
|
||||
ax2.add_artist(circle1)
|
||||
ax2.add_artist(circle2)
|
||||
|
||||
# Add the speudo section
|
||||
DC.plot_pseudoSection(survey2D,ax,stype)
|
||||
dat = DC.plot_pseudoSection(survey2D,ax2,stype=stype, dtype = dtype)
|
||||
|
||||
# plt.scatter(Tx2d[0][:],Tx[0][2,:],s=40,c='g', marker='v')
|
||||
# plt.scatter(Rx2d[0][:],Rx[0][:,2::3],s=40,c='y')
|
||||
# plt.plot(np.r_[Tx2d[0][0],Rx2d[-1][-1,-1]],np.ones(2)*mesh.vectorNz[-1], color='k')
|
||||
plt.ylim([-zlim,mesh.vectorNz[-1]+dx])
|
||||
ax2.set_title('Apparent Conductivity data')
|
||||
|
||||
plt.ylim([-zlim,mesh.vectorNz[-1]+dx])
|
||||
plt.show()
|
||||
|
||||
return fig, ax
|
||||
|
||||
@@ -48,8 +48,7 @@ def run(plotIt=True):
|
||||
freqs = np.logspace(1,3,10)
|
||||
srcLoc = np.array([0., 0., 10.])
|
||||
|
||||
srcList = []
|
||||
[srcList.append(EM.FDEM.Src.MagDipole([bzi],freq, srcLoc,orientation='Z')) for freq in freqs]
|
||||
srcList = [EM.FDEM.Src.MagDipole([bzi],freq, srcLoc,orientation='Z') for freq in freqs]
|
||||
|
||||
survey = EM.FDEM.Survey(srcList)
|
||||
prb = EM.FDEM.Problem_b(mesh, mapping=mapping)
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
from SimPEG import *
|
||||
from SimPEG.EM import FDEM, Analytics, mu_0
|
||||
import time
|
||||
|
||||
try:
|
||||
from pymatsolver import MumpsSolver
|
||||
solver = MumpsSolver
|
||||
except Exception:
|
||||
solver = SolverLU
|
||||
pass
|
||||
|
||||
def run(plotIt=True):
|
||||
"""
|
||||
EM: Schenkel and Morrison Casing Model
|
||||
======================================
|
||||
|
||||
Here we create and run a FDEM forward simulation to calculate the vertical
|
||||
current inside a steel-cased. The model is based on the Schenkel and
|
||||
Morrison Casing Model, and the results are used in a 2016 SEG abstract by
|
||||
Yang et al.
|
||||
|
||||
- Schenkel, C.J., and H.F. Morrison, 1990, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686.
|
||||
|
||||
|
||||
The model consists of:
|
||||
- Air: Conductivity 1e-8 S/m, above z = 0
|
||||
- Background: conductivity 1e-2 S/m, below z = 0
|
||||
- Casing: conductivity 1e6 S/m
|
||||
- 300m long
|
||||
- radius of 0.1m
|
||||
- thickness of 6e-3m
|
||||
|
||||
Inside the casing, we take the same conductivity as the background.
|
||||
|
||||
We are using an EM code to simulate DC, so we use frequency low enough
|
||||
that the skin depth inside the casing is longer than the casing length (f
|
||||
= 1e-6 Hz). The plot produced is of the current inside the casing.
|
||||
|
||||
These results are shown in the SEG abstract by Yang et al., 2016: 3D DC
|
||||
resistivity modeling of steel casing for reservoir monitoring using
|
||||
equivalent resistor network. The solver used to produce these results and
|
||||
achieve the CPU time of ~30s is Mumps, which was installed using pymatsolver_
|
||||
|
||||
.. _pymatsolver: https://github.com/rowanc1/pymatsolver
|
||||
|
||||
This example is on figshare: https://dx.doi.org/10.6084/m9.figshare.3126961.v1
|
||||
|
||||
If you would use this example for a code comparison, or build upon it, a
|
||||
citation would be much appreciated!
|
||||
|
||||
"""
|
||||
|
||||
if plotIt:
|
||||
import matplotlib.pylab as plt
|
||||
|
||||
# ------------------ MODEL ------------------
|
||||
sigmaair = 1e-8 # air
|
||||
sigmaback = 1e-2 # background
|
||||
sigmacasing = 1e6 # casing
|
||||
sigmainside = sigmaback # inside the casing
|
||||
|
||||
|
||||
casing_t = 0.006 # 1cm thickness
|
||||
casing_l = 300 # length of the casing
|
||||
|
||||
casing_r = 0.1
|
||||
casing_a = casing_r - casing_t/2. # inner radius
|
||||
casing_b = casing_r + casing_t/2. # outer radius
|
||||
casing_z = np.r_[-casing_l,0.]
|
||||
|
||||
|
||||
# ------------------ SURVEY PARAMETERS ------------------
|
||||
freqs = np.r_[1e-6] #[1e-1, 1, 5] # frequencies
|
||||
dsz = -300 # down-hole z source location
|
||||
src_loc = np.r_[0.,0.,dsz]
|
||||
inf_loc = np.r_[0.,0.,1e4]
|
||||
|
||||
print 'Skin Depth: ', [(500./np.sqrt(sigmaback*_)) for _ in freqs]
|
||||
|
||||
|
||||
# ------------------ MESH ------------------
|
||||
# fine cells near well bore
|
||||
csx1, csx2 = 2e-3, 60.
|
||||
pfx1, pfx2 = 1.3, 1.3
|
||||
ncx1 = np.ceil(casing_b/csx1+2)
|
||||
|
||||
# pad nicely to second cell size
|
||||
npadx1 = np.floor(np.log(csx2/csx1) / np.log(pfx1))
|
||||
hx1a,hx1b = Utils.meshTensor([(csx1,ncx1)]),Utils.meshTensor([(csx1,npadx1,pfx1)])
|
||||
dx1 = sum(hx1a)+sum(hx1b)
|
||||
dx1 = np.floor(dx1/csx2)
|
||||
hx1b *= (dx1*csx2 - sum(hx1a))/sum(hx1b)
|
||||
|
||||
# second chunk of mesh
|
||||
dx2 = 300. # uniform mesh out to here
|
||||
ncx2 = np.ceil((dx2 - dx1)/csx2)
|
||||
npadx2 = 45
|
||||
hx2a, hx2b = Utils.meshTensor([(csx2,ncx2)]), Utils.meshTensor([(csx2,npadx2,pfx2)])
|
||||
hx = np.hstack([hx1a,hx1b,hx2a,hx2b])
|
||||
|
||||
# z-direction
|
||||
csz = 0.05
|
||||
nza = 10
|
||||
ncz, npadzu, npadzd = np.int(np.ceil(np.diff(casing_z)[0]/csz))+10, 68, 68 # cell size, number of core cells, number of padding cells in the x- direction
|
||||
hz = Utils.meshTensor([(csz,npadzd,-1.3), (csz,ncz), (csz,npadzu,1.3)]) # vector of cell widths in the z-direction
|
||||
|
||||
# Mesh
|
||||
mesh = Mesh.CylMesh([hx,1.,hz], [0.,0.,-np.sum(hz[:npadzu+ncz-nza])])
|
||||
|
||||
print 'Mesh Extent xmax: %f,: zmin: %f, zmax: %f'%(mesh.vectorCCx.max(), mesh.vectorCCz.min(), mesh.vectorCCz.max())
|
||||
print 'Number of cells', mesh.nC
|
||||
|
||||
if plotIt is True:
|
||||
fig, ax = plt.subplots(1, 1, figsize=(6, 4))
|
||||
ax.set_title('Simulation Mesh')
|
||||
mesh.plotGrid(ax=ax)
|
||||
plt.show()
|
||||
|
||||
# Put the model on the mesh
|
||||
sigWholespace = sigmaback*np.ones((mesh.nC))
|
||||
|
||||
sigBack = sigWholespace.copy()
|
||||
sigBack[mesh.gridCC[:,2] > 0.] = sigmaair
|
||||
|
||||
sigCasing = sigBack.copy()
|
||||
iCasingZ = (mesh.gridCC[:,2] <= casing_z[1]) & (mesh.gridCC[:,2] >= casing_z[0])
|
||||
iCasingX = (mesh.gridCC[:,0] >= casing_a) & (mesh.gridCC[:,0] <= casing_b)
|
||||
iCasing = iCasingX & iCasingZ
|
||||
sigCasing[iCasing] = sigmacasing
|
||||
|
||||
|
||||
if plotIt is True:
|
||||
|
||||
# plotting parameters
|
||||
xlim = np.r_[0., 0.2]
|
||||
zlim = np.r_[-350., 10.]
|
||||
clim_sig = np.r_[-8,6]
|
||||
|
||||
# plot models
|
||||
fig, ax = plt.subplots(1,1,figsize=(4,4))
|
||||
|
||||
f = plt.colorbar(mesh.plotImage(np.log10(sigCasing),ax=ax)[0], ax=ax)
|
||||
ax.grid(which='both')
|
||||
ax.set_title('Log_10 (Sigma)')
|
||||
ax.set_xlim(xlim)
|
||||
ax.set_ylim(zlim)
|
||||
f.set_clim(clim_sig)
|
||||
|
||||
plt.show()
|
||||
|
||||
|
||||
# -------------- Sources --------------------
|
||||
# Define Custom Current Sources
|
||||
|
||||
# surface source
|
||||
sg_x = np.zeros(mesh.vnF[0],dtype=complex)
|
||||
sg_y = np.zeros(mesh.vnF[1],dtype=complex)
|
||||
sg_z = np.zeros(mesh.vnF[2],dtype=complex)
|
||||
|
||||
nza = 2 # put the wire two cells above the surface
|
||||
ncin = 2
|
||||
|
||||
# vertically directed wire
|
||||
sgv_indx = (mesh.gridFz[:,0] > casing_a) & (mesh.gridFz[:,0] < casing_a + csx1) # hook it up to casing at the surface
|
||||
sgv_indz = (mesh.gridFz[:,2] <= +csz*nza) & (mesh.gridFz[:,2] >= -csz*2)
|
||||
sgv_ind = sgv_indx & sgv_indz
|
||||
sg_z[sgv_ind] = -1.
|
||||
|
||||
# horizontally directed wire
|
||||
sgh_indx = (mesh.gridFx[:,0] > casing_a) & (mesh.gridFx[:,0] <= inf_loc[2])
|
||||
sgh_indz = (mesh.gridFx[:,2] > csz*(nza-0.5)) & (mesh.gridFx[:,2] < csz*(nza+0.5))
|
||||
sgh_ind = sgh_indx & sgh_indz
|
||||
sg_x[sgh_ind] = -1.
|
||||
|
||||
sgv2_indx = (mesh.gridFz[:,0] >= mesh.gridFx[sgh_ind,0].max()) & (mesh.gridFz[:,0] <= inf_loc[2]*1.2) # hook it up to casing at the surface
|
||||
sgv2_indz = (mesh.gridFz[:,2] <= +csz*nza) & (mesh.gridFz[:,2] >= -csz*2)
|
||||
sgv2_ind = sgv2_indx & sgv2_indz
|
||||
sg_z[sgv2_ind] = 1.
|
||||
|
||||
# assemble the source
|
||||
sg = np.hstack([sg_x,sg_y,sg_z])
|
||||
sg_p = [FDEM.Src.RawVec_e([],_,sg/mesh.area) for _ in freqs]
|
||||
|
||||
# downhole source
|
||||
dg_x = np.zeros(mesh.vnF[0],dtype=complex)
|
||||
dg_y = np.zeros(mesh.vnF[1],dtype=complex)
|
||||
dg_z = np.zeros(mesh.vnF[2],dtype=complex)
|
||||
|
||||
# vertically directed wire
|
||||
dgv_indx = (mesh.gridFz[:,0] < csx1) # go through the center of the well
|
||||
dgv_indz = (mesh.gridFz[:,2] <= +csz*nza) & (mesh.gridFz[:,2] > dsz + csz/2.)
|
||||
dgv_ind = dgv_indx & dgv_indz
|
||||
dg_z[dgv_ind] = -1.
|
||||
|
||||
# couple to the casing downhole
|
||||
dgh_indx = mesh.gridFx[:,0] < casing_a + csx1
|
||||
dgh_indz = (mesh.gridFx[:,2] < dsz + csz) & (mesh.gridFx[:,2] >= dsz)
|
||||
dgh_ind = dgh_indx & dgh_indz
|
||||
dg_x[dgh_ind] = 1.
|
||||
|
||||
# horizontal part at surface
|
||||
dgh2_indx = mesh.gridFx[:,0] <= inf_loc[2]*1.2
|
||||
dgh2_indz = sgh_indz.copy()
|
||||
dgh2_ind = dgh2_indx & dgh2_indz
|
||||
dg_x[dgh2_ind] = -1.
|
||||
|
||||
# vertical part at surface
|
||||
dgv2_ind = sgv2_ind.copy()
|
||||
dg_z[dgv2_ind] = 1.
|
||||
|
||||
# assemble the source
|
||||
dg = np.hstack([dg_x,dg_y,dg_z])
|
||||
dg_p = [FDEM.Src.RawVec_e([],_,dg/mesh.area) for _ in freqs]
|
||||
|
||||
# ------------ Problem and Survey ---------------
|
||||
survey = FDEM.Survey(sg_p + dg_p)
|
||||
mapping = [('sigma', Maps.IdentityMap(mesh))]
|
||||
problem = FDEM.Problem_h(mesh, mapping=mapping)
|
||||
problem.pair(survey)
|
||||
|
||||
# ------------- Solve ---------------------------
|
||||
t0 = time.time()
|
||||
fieldsCasing = problem.fields(sigCasing)
|
||||
print 'Time to solve 2 sources', time.time() - t0
|
||||
|
||||
# Plot current
|
||||
|
||||
# current density
|
||||
jn0 = fieldsCasing[dg_p,'j']
|
||||
jn1 = fieldsCasing[sg_p,'j']
|
||||
|
||||
# current
|
||||
in0 = [mesh.area*fieldsCasing[dg_p,'j'][:,i] for i in range(len(freqs))]
|
||||
in1 = [mesh.area*fieldsCasing[sg_p,'j'][:,i] for i in range(len(freqs))]
|
||||
|
||||
in0 = np.vstack(in0).T
|
||||
in1 = np.vstack(in1).T
|
||||
|
||||
# integrate to get z-current inside casing
|
||||
inds_inx = (mesh.gridFz[:,0] >= casing_a) & (mesh.gridFz[:,0] <= casing_b)
|
||||
inds_inz = (mesh.gridFz[:,2] >= dsz ) & (mesh.gridFz[:,2] <= 0)
|
||||
inds_fz = inds_inx & inds_inz
|
||||
|
||||
indsx = [False]*mesh.nFx
|
||||
inds = list(indsx) + list(inds_fz)
|
||||
|
||||
in0_in = in0[np.r_[inds]]
|
||||
in1_in = in1[np.r_[inds]]
|
||||
z_in = mesh.gridFz[inds_fz,2]
|
||||
|
||||
in0_in = in0_in.reshape([in0_in.shape[0]/3,3])
|
||||
in1_in = in1_in.reshape([in1_in.shape[0]/3,3])
|
||||
z_in = z_in.reshape([z_in.shape[0]/3,3])
|
||||
|
||||
I0 = in0_in.sum(1).real
|
||||
I1 = in1_in.sum(1).real
|
||||
z_in = z_in[:,0]
|
||||
|
||||
if plotIt is True:
|
||||
fig, ax = plt.subplots(1,2,figsize=(12,4))
|
||||
|
||||
ax[0].plot(z_in,np.absolute(I0), z_in,np.absolute(I1))
|
||||
ax[0].legend(['top casing', 'bottom casing'],loc='best')
|
||||
ax[0].set_title('Magnitude of Vertical Current in Casing')
|
||||
|
||||
ax[1].semilogy(z_in,np.absolute(I0), z_in,np.absolute(I1))
|
||||
ax[1].legend(['top casing', 'bottom casing'],loc='best')
|
||||
ax[1].set_title('Magnitude of Vertical Current in Casing')
|
||||
ax[1].set_ylim([1e-2, 1.])
|
||||
|
||||
plt.show()
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
from SimPEG import *
|
||||
|
||||
|
||||
def run(N=200, plotIt=True):
|
||||
"""
|
||||
Inversion: Linear Problem
|
||||
=========================
|
||||
|
||||
Here we go over the basics of creating a linear problem and inversion.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
np.random.seed(1)
|
||||
|
||||
std_noise = 1e-2
|
||||
|
||||
mesh = Mesh.TensorMesh([N])
|
||||
|
||||
m0 = np.ones(mesh.nC) * 1e-4
|
||||
nk = 10
|
||||
jk = np.linspace(1.,nk,nk)
|
||||
p = -2.
|
||||
q = 1.
|
||||
|
||||
g = lambda k: np.exp(p*jk[k]*mesh.vectorCCx)*np.cos(np.pi*q*jk[k]*mesh.vectorCCx)
|
||||
|
||||
G = np.empty((nk, mesh.nC))
|
||||
|
||||
for i in range(nk):
|
||||
G[i,:] = g(i)
|
||||
|
||||
mtrue = np.zeros(mesh.nC)
|
||||
mtrue[mesh.vectorCCx > 0.3] = 1.
|
||||
mtrue[mesh.vectorCCx > 0.45] = -0.5
|
||||
mtrue[mesh.vectorCCx > 0.6] = 0
|
||||
|
||||
|
||||
prob = Problem.LinearProblem(mesh, G)
|
||||
survey = Survey.LinearSurvey()
|
||||
survey.pair(prob)
|
||||
survey.dobs = prob.fields(mtrue) + std_noise * np.random.randn(nk)
|
||||
#survey.makeSyntheticData(mtrue, std=std_noise)
|
||||
|
||||
wd = np.ones(nk) * std_noise
|
||||
|
||||
#print survey.std[0]
|
||||
#M = prob.mesh
|
||||
# Distance weighting
|
||||
wr = np.sum(prob.G**2.,axis=0)**0.5
|
||||
wr = ( wr/np.max(wr) )
|
||||
|
||||
reg = Regularization.Simple(mesh)
|
||||
reg.wght = wr
|
||||
|
||||
dmis = DataMisfit.l2_DataMisfit(survey)
|
||||
dmis.Wd = 1./wd
|
||||
|
||||
opt = Optimization.ProjectedGNCG(maxIter=30,lower=-2.,upper=2., maxIterCG= 20, tolCG = 1e-4)
|
||||
invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
|
||||
invProb.curModel = m0
|
||||
|
||||
beta = Directives.BetaSchedule(coolingFactor=2, coolingRate=1)
|
||||
target = Directives.TargetMisfit()
|
||||
|
||||
betaest = Directives.BetaEstimate_ByEig()
|
||||
inv = Inversion.BaseInversion(invProb, directiveList=[beta, betaest, target])
|
||||
|
||||
|
||||
mrec = inv.run(m0)
|
||||
ml2 = mrec
|
||||
print "Final misfit:" + str(invProb.dmisfit.eval(mrec))
|
||||
|
||||
# Switch regularization to sparse
|
||||
phim = invProb.phi_m_last
|
||||
phid = invProb.phi_d
|
||||
|
||||
reg = Regularization.Sparse(mesh)
|
||||
|
||||
#==============================================================================
|
||||
# fig, axes = plt.subplots(1,2,figsize=(12*1.2,4*1.2))
|
||||
# dmdx = reg.mesh.cellDiffxStencil * mrec
|
||||
# plt.plot(np.sort(dmdx))
|
||||
#==============================================================================
|
||||
|
||||
#reg.recModel = mrec
|
||||
reg.wght = np.ones(mesh.nC)
|
||||
reg.mref = np.zeros(mesh.nC)
|
||||
reg.eps_p = 2e-3
|
||||
reg.eps_q = 2e-3
|
||||
reg.norms = [0., 0., 2., 2.]
|
||||
reg.wght = wr
|
||||
|
||||
opt = Optimization.ProjectedGNCG(maxIter=5 ,lower=-2.,upper=2., maxIterCG= 100, tolCG = 1e-3)
|
||||
invProb = InvProblem.BaseInvProblem(dmis, reg, opt, beta = invProb.beta*2.)
|
||||
beta = Directives.BetaSchedule(coolingFactor=1, coolingRate=1)
|
||||
#betaest = Directives.BetaEstimate_ByEig()
|
||||
target = Directives.TargetMisfit()
|
||||
IRLS =Directives.Update_IRLS( phi_m_last = phim, phi_d_last = phid )
|
||||
|
||||
inv = Inversion.BaseInversion(invProb, directiveList=[beta,IRLS])
|
||||
|
||||
m0 = mrec
|
||||
|
||||
# Run inversion
|
||||
mrec = inv.run(m0)
|
||||
|
||||
print "Final misfit:" + str(invProb.dmisfit.eval(mrec))
|
||||
|
||||
|
||||
if plotIt:
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
fig, axes = plt.subplots(1,2,figsize=(12*1.2,4*1.2))
|
||||
for i in range(prob.G.shape[0]):
|
||||
axes[0].plot(prob.G[i,:])
|
||||
axes[0].set_title('Columns of matrix G')
|
||||
|
||||
axes[1].plot(mesh.vectorCCx, mtrue, 'b-')
|
||||
axes[1].plot(mesh.vectorCCx, ml2, 'r-')
|
||||
#axes[1].legend(('True Model', 'Recovered Model'))
|
||||
axes[1].set_ylim(-1.0,1.25)
|
||||
|
||||
axes[1].plot(mesh.vectorCCx, mrec, 'k-',lw = 2)
|
||||
axes[1].legend(('True Model', 'Smooth l2-l2',
|
||||
'Sparse lp:' + str(reg.norms[0]) + ', lqx:' + str(reg.norms[1]) ), fontsize = 12)
|
||||
plt.show()
|
||||
|
||||
return prob, survey, mesh, mrec
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
@@ -100,7 +100,7 @@ def run(plotIt=True):
|
||||
# Regularization - with a regularization mesh
|
||||
regMesh = simpeg.Mesh.TensorMesh([m1d.hx[problem.mapping.sigmaMap.maps[-1].indActive]],m1d.x0)
|
||||
reg = simpeg.Regularization.Tikhonov(regMesh)
|
||||
reg.smoothModel = True
|
||||
reg.mrefInSmooth = True
|
||||
reg.alpha_s = 1e-7
|
||||
reg.alpha_x = 1.
|
||||
# Inversion problem
|
||||
|
||||
@@ -5,9 +5,11 @@ import DC_Analytic_Dipole
|
||||
import DC_Forward_PseudoSection
|
||||
import EM_FDEM_1D_Inversion
|
||||
import EM_FDEM_Analytic_MagDipoleWholespace
|
||||
import EM_Schenkel_Morrison_Casing
|
||||
import EM_TDEM_1D_Inversion
|
||||
import FLOW_Richards_1D_Celia1990
|
||||
import Forward_BasicDirectCurrent
|
||||
import Inversion_IRLS
|
||||
import Inversion_Linear
|
||||
import Mesh_Basic_PlotImage
|
||||
import Mesh_Basic_Types
|
||||
@@ -19,7 +21,7 @@ import Mesh_Tensor_Creation
|
||||
import MT_1D_ForwardAndInversion
|
||||
import MT_3D_Foward
|
||||
|
||||
__examples__ = ["DC_Analytic_Dipole", "DC_Forward_PseudoSection", "EM_FDEM_1D_Inversion", "EM_FDEM_Analytic_MagDipoleWholespace", "EM_TDEM_1D_Inversion", "FLOW_Richards_1D_Celia1990", "Forward_BasicDirectCurrent", "Inversion_Linear", "Mesh_Basic_PlotImage", "Mesh_Basic_Types", "Mesh_Operators_CahnHilliard", "Mesh_QuadTree_Creation", "Mesh_QuadTree_FaceDiv", "Mesh_QuadTree_HangingNodes", "Mesh_Tensor_Creation", "MT_1D_ForwardAndInversion", "MT_3D_Foward"]
|
||||
__examples__ = ["DC_Analytic_Dipole", "DC_Forward_PseudoSection", "EM_FDEM_1D_Inversion", "EM_FDEM_Analytic_MagDipoleWholespace", "EM_Schenkel_Morrison_Casing", "EM_TDEM_1D_Inversion", "FLOW_Richards_1D_Celia1990", "Forward_BasicDirectCurrent", "Inversion_IRLS", "Inversion_Linear", "Mesh_Basic_PlotImage", "Mesh_Basic_Types", "Mesh_Operators_CahnHilliard", "Mesh_QuadTree_Creation", "Mesh_QuadTree_FaceDiv", "Mesh_QuadTree_HangingNodes", "Mesh_Tensor_Creation", "MT_1D_ForwardAndInversion", "MT_3D_Foward"]
|
||||
|
||||
##### AUTOIMPORTS #####
|
||||
|
||||
|
||||
+3
-1
@@ -33,7 +33,9 @@ class BaseInversion(object):
|
||||
self._directiveList = value
|
||||
self._directiveList.inversion = self
|
||||
|
||||
def __init__(self, invProb, directiveList=[], **kwargs):
|
||||
def __init__(self, invProb, directiveList=None, **kwargs):
|
||||
if directiveList is None:
|
||||
directiveList = []
|
||||
self.directiveList = directiveList
|
||||
Utils.setKwargs(self, **kwargs)
|
||||
|
||||
|
||||
+26
-11
@@ -759,15 +759,29 @@ class PolyMap(IdentityMap):
|
||||
|
||||
m = [\sigma_1, \sigma_2, c]
|
||||
|
||||
Can take in an actInd vector to account for topography.
|
||||
|
||||
"""
|
||||
def __init__(self, mesh, order, logSigma=True, normal='X'):
|
||||
def __init__(self, mesh, order, logSigma=True, normal='X', actInd = None):
|
||||
IdentityMap.__init__(self, mesh)
|
||||
self.logSigma = logSigma
|
||||
self.order = order
|
||||
self.normal = normal
|
||||
self.actInd = actInd
|
||||
|
||||
if getattr(self, 'actInd', None) is None:
|
||||
self.actInd = range(self.mesh.nC)
|
||||
self.nC = self.mesh.nC
|
||||
|
||||
else:
|
||||
self.nC = len(self.actInd)
|
||||
|
||||
slope = 1e4
|
||||
|
||||
@property
|
||||
def shape(self):
|
||||
return (self.nC, self.nP)
|
||||
|
||||
@property
|
||||
def nP(self):
|
||||
if np.isscalar(self.order):
|
||||
@@ -785,8 +799,8 @@ class PolyMap(IdentityMap):
|
||||
sig1, sig2 = np.exp(sig1), np.exp(sig2)
|
||||
#2D
|
||||
if self.mesh.dim == 2:
|
||||
X = self.mesh.gridCC[:,0]
|
||||
Y = self.mesh.gridCC[:,1]
|
||||
X = self.mesh.gridCC[self.actInd,0]
|
||||
Y = self.mesh.gridCC[self.actInd,1]
|
||||
if self.normal =='X':
|
||||
f = polynomial.polyval(Y, c) - X
|
||||
elif self.normal =='Y':
|
||||
@@ -795,9 +809,9 @@ class PolyMap(IdentityMap):
|
||||
raise(Exception("Input for normal = X or Y or Z"))
|
||||
#3D
|
||||
elif self.mesh.dim == 3:
|
||||
X = self.mesh.gridCC[:,0]
|
||||
Y = self.mesh.gridCC[:,1]
|
||||
Z = self.mesh.gridCC[:,2]
|
||||
X = self.mesh.gridCC[self.actInd,0]
|
||||
Y = self.mesh.gridCC[self.actInd,1]
|
||||
Z = self.mesh.gridCC[self.actInd,2]
|
||||
if self.normal =='X':
|
||||
f = polynomial.polyval2d(Y, Z, c.reshape((self.order[0]+1,self.order[1]+1))) - X
|
||||
elif self.normal =='Y':
|
||||
@@ -806,6 +820,7 @@ class PolyMap(IdentityMap):
|
||||
f = polynomial.polyval2d(X, Y, c.reshape((self.order[0]+1,self.order[1]+1))) - Z
|
||||
else:
|
||||
raise(Exception("Input for normal = X or Y or Z"))
|
||||
|
||||
else:
|
||||
raise(Exception("Only supports 2D"))
|
||||
|
||||
@@ -819,8 +834,8 @@ class PolyMap(IdentityMap):
|
||||
sig1, sig2 = np.exp(sig1), np.exp(sig2)
|
||||
#2D
|
||||
if self.mesh.dim == 2:
|
||||
X = self.mesh.gridCC[:,0]
|
||||
Y = self.mesh.gridCC[:,1]
|
||||
X = self.mesh.gridCC[self.actInd,0]
|
||||
Y = self.mesh.gridCC[self.actInd,1]
|
||||
|
||||
if self.normal =='X':
|
||||
f = polynomial.polyval(Y, c) - X
|
||||
@@ -832,9 +847,9 @@ class PolyMap(IdentityMap):
|
||||
raise(Exception("Input for normal = X or Y or Z"))
|
||||
#3D
|
||||
elif self.mesh.dim == 3:
|
||||
X = self.mesh.gridCC[:,0]
|
||||
Y = self.mesh.gridCC[:,1]
|
||||
Z = self.mesh.gridCC[:,2]
|
||||
X = self.mesh.gridCC[self.actInd,0]
|
||||
Y = self.mesh.gridCC[self.actInd,1]
|
||||
Z = self.mesh.gridCC[self.actInd,2]
|
||||
|
||||
if self.normal =='X':
|
||||
f = polynomial.polyval2d(Y, Z, c.reshape((self.order[0]+1,self.order[1]+1))) - X
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import numpy as np
|
||||
import scipy.sparse as sp
|
||||
from SimPEG import Utils
|
||||
|
||||
|
||||
@@ -595,63 +594,3 @@ class BaseRectangularMesh(BaseMesh):
|
||||
return out
|
||||
else:
|
||||
return switchKernal(x)
|
||||
|
||||
|
||||
def getInterpolationMatMesh2Mesh(self, mesh2, locType='CC', locTypeFrom=None):
|
||||
"""
|
||||
Interpolates variables from the current mesh to a new mesh (mesh2)
|
||||
|
||||
:param Mesh mesh2: SimPEG mesh which we interpolate values to
|
||||
:param string locType: location of variables 'CC', 'E', 'F', 'N'
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return P: interpolation matrix
|
||||
"""
|
||||
|
||||
# import warnings
|
||||
# warnings.warn(
|
||||
# "`getInterpolationMatMesh2Mesh` will be slow. If you want to interpolate a vector from one mesh to another, use `InterpolateVecMesh2Mesh`",
|
||||
# RuntimeWarning)
|
||||
|
||||
if locTypeFrom is None:
|
||||
locTypeFrom = locType # assume that we are interpolating to and from the same place
|
||||
|
||||
# Error Checking
|
||||
if self._meshType == 'CYL':
|
||||
assert self.isSymmetric, "Currently, we do not support non-symmetric cyl meshes"
|
||||
if mesh2._meshType == 'CYL':
|
||||
assert self._meshType == 'CYL', "Interpolation from 3D mesh to Cyl mesh is not supported"
|
||||
|
||||
# if Cyl to cart call
|
||||
if self._meshType == 'CYL' and mesh2._meshType != 'CYL':
|
||||
return self.getInterpolationMatCartMesh(mesh2, locType)
|
||||
|
||||
# Scalars
|
||||
if locType in ['CC', 'CCVx', 'CCVy', 'CCVz', 'N', 'Fx', 'Fy', 'Fz', 'Ex', 'Ey', 'Ez']:
|
||||
grid = getattr(mesh2, 'grid%s'%locTypeFrom)
|
||||
return self.getInterpolationMat(grid, locType)
|
||||
|
||||
# Vectors
|
||||
else:
|
||||
if self._meshType == 'CYL':
|
||||
if locType == 'F':
|
||||
X = self.getInterpolationMatMesh2Mesh(mesh2, locType='Fx', locTypeFrom=locTypeFrom+'x')
|
||||
Z = self.getInterpolationMatMesh2Mesh(mesh2, locType='Fz', locTypeFrom=locTypeFrom+'z')
|
||||
return sp.block_diag([X, Z])
|
||||
elif locType == 'E':
|
||||
return self.getInterpolationMatMesh2Mesh(mesh2, locType='Ey', locTypeFrom=locTypeFrom+'y')
|
||||
|
||||
if self.dim == 1:
|
||||
return self.getInterpolationMatMesh2Mesh(mesh2, locType='%sx'%locType, locTypeFrom=locTypeFrom+'x')
|
||||
elif self.dim == 2:
|
||||
X = self.getInterpolationMatMesh2Mesh(mesh2, locType='%sx'%locType, locTypeFrom=locTypeFrom+'x')
|
||||
Y = self.getInterpolationMatMesh2Mesh(mesh2, locType='%sy'%locType, locTypeFrom=locTypeFrom+'y')
|
||||
return sp.block_diag([X, Y])
|
||||
elif self.dim == 3:
|
||||
X = self.getInterpolationMatMesh2Mesh(mesh2, locType='%sx'%locType, locTypeFrom=locTypeFrom+'x')
|
||||
Y = self.getInterpolationMatMesh2Mesh(mesh2, locType='%sy'%locType, locTypeFrom=locTypeFrom+'y')
|
||||
Z = self.getInterpolationMatMesh2Mesh(mesh2, locType='%sz'%locType, locTypeFrom=locTypeFrom+'z')
|
||||
return sp.block_diag([X, Y, Z])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+109
-30
@@ -307,24 +307,28 @@ class DiffOperators(object):
|
||||
return BC
|
||||
_cellGradBC_list = 'neumann'
|
||||
|
||||
def _cellGradStencil(self):
|
||||
BC = self.setCellGradBC(self._cellGradBC_list)
|
||||
n = self.vnC
|
||||
if(self.dim == 1):
|
||||
G = ddxCellGrad(n[0], BC[0])
|
||||
elif(self.dim == 2):
|
||||
G1 = sp.kron(speye(n[1]), ddxCellGrad(n[0], BC[0]))
|
||||
G2 = sp.kron(ddxCellGrad(n[1], BC[1]), speye(n[0]))
|
||||
G = sp.vstack((G1, G2), format="csr")
|
||||
elif(self.dim == 3):
|
||||
G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGrad(n[0], BC[0]))
|
||||
G2 = kron3(speye(n[2]), ddxCellGrad(n[1], BC[1]), speye(n[0]))
|
||||
G3 = kron3(ddxCellGrad(n[2], BC[2]), speye(n[1]), speye(n[0]))
|
||||
G = sp.vstack((G1, G2, G3), format="csr")
|
||||
return G
|
||||
|
||||
def cellGrad():
|
||||
doc = "The cell centered Gradient, takes you to cell faces."
|
||||
|
||||
def fget(self):
|
||||
if(self._cellGrad is None):
|
||||
BC = self.setCellGradBC(self._cellGradBC_list)
|
||||
n = self.vnC
|
||||
if(self.dim == 1):
|
||||
G = ddxCellGrad(n[0], BC[0])
|
||||
elif(self.dim == 2):
|
||||
G1 = sp.kron(speye(n[1]), ddxCellGrad(n[0], BC[0]))
|
||||
G2 = sp.kron(ddxCellGrad(n[1], BC[1]), speye(n[0]))
|
||||
G = sp.vstack((G1, G2), format="csr")
|
||||
elif(self.dim == 3):
|
||||
G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGrad(n[0], BC[0]))
|
||||
G2 = kron3(speye(n[2]), ddxCellGrad(n[1], BC[1]), speye(n[0]))
|
||||
G3 = kron3(ddxCellGrad(n[2], BC[2]), speye(n[1]), speye(n[0]))
|
||||
G = sp.vstack((G1, G2, G3), format="csr")
|
||||
G = self._cellGradStencil()
|
||||
# Compute areas of cell faces & volumes
|
||||
S = self.area
|
||||
V = self.aveCC2F*self.vol # Average volume between adjacent cells
|
||||
@@ -361,19 +365,24 @@ class DiffOperators(object):
|
||||
_cellGradBC = None
|
||||
cellGradBC = property(**cellGradBC())
|
||||
|
||||
def _cellGradxStencil(self):
|
||||
BC = ['neumann', 'neumann']
|
||||
n = self.vnC
|
||||
if(self.dim == 1):
|
||||
G1 = ddxCellGrad(n[0], BC)
|
||||
elif(self.dim == 2):
|
||||
G1 = sp.kron(speye(n[1]), ddxCellGrad(n[0], BC))
|
||||
elif(self.dim == 3):
|
||||
G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGrad(n[0], BC))
|
||||
return G1
|
||||
|
||||
|
||||
def cellGradx():
|
||||
doc = "Cell centered Gradient in the x dimension. Has neumann boundary conditions."
|
||||
|
||||
def fget(self):
|
||||
if getattr(self, '_cellGradx', None) is None:
|
||||
BC = ['neumann', 'neumann']
|
||||
n = self.vnC
|
||||
if(self.dim == 1):
|
||||
G1 = ddxCellGrad(n[0], BC)
|
||||
elif(self.dim == 2):
|
||||
G1 = sp.kron(speye(n[1]), ddxCellGrad(n[0], BC))
|
||||
elif(self.dim == 3):
|
||||
G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGrad(n[0], BC))
|
||||
G1 = self._cellGradxStencil()
|
||||
# Compute areas of cell faces & volumes
|
||||
V = self.aveCC2F*self.vol
|
||||
L = self.r(self.area/V, 'F','Fx', 'V')
|
||||
@@ -382,17 +391,22 @@ class DiffOperators(object):
|
||||
return locals()
|
||||
cellGradx = property(**cellGradx())
|
||||
|
||||
def _cellGradyStencil(self):
|
||||
if self.dim < 2: return None
|
||||
BC = ['neumann', 'neumann']
|
||||
n = self.vnC
|
||||
if(self.dim == 2):
|
||||
G2 = sp.kron(ddxCellGrad(n[1], BC), speye(n[0]))
|
||||
elif(self.dim == 3):
|
||||
G2 = kron3(speye(n[2]), ddxCellGrad(n[1], BC), speye(n[0]))
|
||||
return G2
|
||||
|
||||
def cellGrady():
|
||||
doc = "Cell centered Gradient in the x dimension. Has neumann boundary conditions."
|
||||
def fget(self):
|
||||
if self.dim < 2: return None
|
||||
if getattr(self, '_cellGrady', None) is None:
|
||||
BC = ['neumann', 'neumann']
|
||||
n = self.vnC
|
||||
if(self.dim == 2):
|
||||
G2 = sp.kron(ddxCellGrad(n[1], BC), speye(n[0]))
|
||||
elif(self.dim == 3):
|
||||
G2 = kron3(speye(n[2]), ddxCellGrad(n[1], BC), speye(n[0]))
|
||||
G2 = self._cellGradyStencil()
|
||||
# Compute areas of cell faces & volumes
|
||||
V = self.aveCC2F*self.vol
|
||||
L = self.r(self.area/V, 'F','Fy', 'V')
|
||||
@@ -401,14 +415,19 @@ class DiffOperators(object):
|
||||
return locals()
|
||||
cellGrady = property(**cellGrady())
|
||||
|
||||
def _cellGradzStencil(self):
|
||||
if self.dim < 3: return None
|
||||
BC = ['neumann', 'neumann']
|
||||
n = self.vnC
|
||||
G3 = kron3(ddxCellGrad(n[2], BC), speye(n[1]), speye(n[0]))
|
||||
return G3
|
||||
|
||||
def cellGradz():
|
||||
doc = "Cell centered Gradient in the x dimension. Has neumann boundary conditions."
|
||||
def fget(self):
|
||||
if self.dim < 3: return None
|
||||
if getattr(self, '_cellGradz', None) is None:
|
||||
BC = ['neumann', 'neumann']
|
||||
n = self.vnC
|
||||
G3 = kron3(ddxCellGrad(n[2], BC), speye(n[1]), speye(n[0]))
|
||||
G3 = self._cellGradzStencil()
|
||||
# Compute areas of cell faces & volumes
|
||||
V = self.aveCC2F*self.vol
|
||||
L = self.r(self.area/V, 'F','Fz', 'V')
|
||||
@@ -565,7 +584,67 @@ class DiffOperators(object):
|
||||
|
||||
return Pbc, Pin, Pout
|
||||
|
||||
def getBCProjWF_simple(self, discretization='CC'):
|
||||
"""
|
||||
|
||||
The weak form boundary condition projection matrices
|
||||
when mixed boundary condition is used
|
||||
|
||||
|
||||
"""
|
||||
|
||||
if discretization is not 'CC':
|
||||
raise NotImplementedError('Boundary conditions only implemented for CC discretization.')
|
||||
|
||||
def projBC(n):
|
||||
ij = ([0,n], [0,1])
|
||||
vals = [0,0]
|
||||
vals[0] = 1
|
||||
vals[1] = 1
|
||||
return sp.csr_matrix((vals, ij), shape=(n+1,2))
|
||||
|
||||
def projDirichlet(n, bc):
|
||||
bc = checkBC(bc)
|
||||
ij = ([0,n], [0,1])
|
||||
vals = [0,0]
|
||||
if(bc[0] == 'dirichlet'):
|
||||
vals[0] = -1
|
||||
if(bc[1] == 'dirichlet'):
|
||||
vals[1] = 1
|
||||
return sp.csr_matrix((vals, ij), shape=(n+1,2))
|
||||
|
||||
BC = [['dirichlet','dirichlet'],['dirichlet','dirichlet'],['dirichlet','dirichlet']]
|
||||
n = self.vnC
|
||||
indF = self.faceBoundaryInd
|
||||
if(self.dim == 1):
|
||||
Pbc = projDirichlet(n[0], BC[0])
|
||||
B = projBC(n[0])
|
||||
indF = indF[0] | indF[1]
|
||||
Pbc = Pbc*sdiag(self.area[indF])
|
||||
|
||||
elif(self.dim == 2):
|
||||
Pbc1 = sp.kron(speye(n[1]), projDirichlet(n[0], BC[0]))
|
||||
Pbc2 = sp.kron(projDirichlet(n[1], BC[1]), speye(n[0]))
|
||||
Pbc = sp.block_diag((Pbc1, Pbc2), format="csr")
|
||||
B1 = sp.kron(speye(n[1]), projBC(n[0]))
|
||||
B2 = sp.kron(projBC(n[1]), speye(n[0]))
|
||||
B = sp.block_diag((B1, B2), format="csr")
|
||||
indF = np.r_[(indF[0] | indF[1]), (indF[2] | indF[3])]
|
||||
Pbc = Pbc*sdiag(self.area[indF])
|
||||
|
||||
elif(self.dim == 3):
|
||||
Pbc1 = kron3(speye(n[2]), speye(n[1]), projDirichlet(n[0], BC[0]))
|
||||
Pbc2 = kron3(speye(n[2]), projDirichlet(n[1], BC[1]), speye(n[0]))
|
||||
Pbc3 = kron3(projDirichlet(n[2], BC[2]), speye(n[1]), speye(n[0]))
|
||||
Pbc = sp.block_diag((Pbc1, Pbc2, Pbc3), format="csr")
|
||||
B1 = kron3(speye(n[2]), speye(n[1]), projBC(n[0]))
|
||||
B2 = kron3(speye(n[2]), projBC(n[1]), speye(n[0]))
|
||||
B3 = kron3(projBC(n[2]), speye(n[1]), speye(n[0]))
|
||||
B = sp.block_diag((B1, B2, B3), format="csr")
|
||||
indF = np.r_[(indF[0] | indF[1]), (indF[2] | indF[3]), (indF[4] | indF[5])]
|
||||
Pbc = Pbc*sdiag(self.area[indF])
|
||||
|
||||
return Pbc, B.T
|
||||
# --------------- Averaging ---------------------
|
||||
|
||||
@property
|
||||
|
||||
@@ -21,7 +21,7 @@ class TensorMeshIO(object):
|
||||
if '*' in seg:
|
||||
st = seg
|
||||
sp = seg.split('*')
|
||||
re = np.array(sp[0],dtype=int)*(' ' + sp[1])
|
||||
re = int(sp[0])*(' ' + sp[1])
|
||||
line = line.replace(st,re.strip())
|
||||
return np.array(line.split(),dtype=float)
|
||||
|
||||
|
||||
@@ -2131,10 +2131,16 @@ class TreeMesh(BaseTensorMesh, InnerProducts, TreeMeshIO):
|
||||
def plotSlice(self, v, vType='CC',
|
||||
normal='Z', ind=None, grid=True, view='real',
|
||||
ax=None, clim=None, showIt=False,
|
||||
pcolorOpts={},
|
||||
streamOpts={'color':'k'},
|
||||
gridOpts={'color':'k', 'alpha':0.5}):
|
||||
pcolorOpts=None,
|
||||
streamOpts=None,
|
||||
gridOpts=None):
|
||||
|
||||
if pcolorOpts is None:
|
||||
pcolorOpts = {}
|
||||
if streamOpts is None:
|
||||
streamOpts = {'color':'k'}
|
||||
if gridOpts is None:
|
||||
gridOpts = {'color':'k', 'alpha':0.5}
|
||||
assert vType in ['CC','F','E']
|
||||
assert self.dim == 3
|
||||
|
||||
|
||||
+28
-10
@@ -42,9 +42,9 @@ class TensorView(object):
|
||||
|
||||
def plotImage(self, v, vType='CC', grid=False, view='real',
|
||||
ax=None, clim=None, showIt=False,
|
||||
pcolorOpts={},
|
||||
streamOpts={'color':'k'},
|
||||
gridOpts={'color':'k'},
|
||||
pcolorOpts=None,
|
||||
streamOpts=None,
|
||||
gridOpts=None,
|
||||
numbering=True, annotationColor='w'
|
||||
):
|
||||
"""
|
||||
@@ -84,6 +84,12 @@ class TensorView(object):
|
||||
M.plotImage(v, annotationColor='k', showIt=True)
|
||||
|
||||
"""
|
||||
if pcolorOpts is None:
|
||||
pcolorOpts = {}
|
||||
if streamOpts is None:
|
||||
streamOpts = {'color':'k'}
|
||||
if gridOpts is None:
|
||||
gridOpts = {'color':'k'}
|
||||
|
||||
if ax is None:
|
||||
fig = plt.figure()
|
||||
@@ -174,9 +180,9 @@ class TensorView(object):
|
||||
def plotSlice(self, v, vType='CC',
|
||||
normal='Z', ind=None, grid=False, view='real',
|
||||
ax=None, clim=None, showIt=False,
|
||||
pcolorOpts={},
|
||||
streamOpts={'color':'k'},
|
||||
gridOpts={'color':'k', 'alpha':0.5}
|
||||
pcolorOpts=None,
|
||||
streamOpts=None,
|
||||
gridOpts=None
|
||||
):
|
||||
|
||||
"""
|
||||
@@ -197,6 +203,12 @@ class TensorView(object):
|
||||
M.plotSlice(M.cellGrad*b, 'F', view='vec', grid=True, showIt=True, pcolorOpts={'alpha':0.8})
|
||||
|
||||
"""
|
||||
if pcolorOpts is None:
|
||||
pcolorOpts = {}
|
||||
if streamOpts is None:
|
||||
streamOpts = {'color':'k'}
|
||||
if gridOpts is None:
|
||||
gridOpts = {'color':'k', 'alpha':0.5}
|
||||
if type(vType) in [list, tuple]:
|
||||
assert ax is None, "cannot specify an axis to plot on with this function."
|
||||
fig, axs = plt.subplots(1,len(vType))
|
||||
@@ -206,7 +218,7 @@ class TensorView(object):
|
||||
return out
|
||||
viewOpts = ['real','imag','abs','vec']
|
||||
normalOpts = ['X', 'Y', 'Z']
|
||||
vTypeOpts = ['CC', 'CCv','F','E','Fx','Fy','Fz','E','Ex','Ey','Ez']
|
||||
vTypeOpts = ['CC', 'CCv','N','F','E','Fx','Fy','Fz','E','Ex','Ey','Ez']
|
||||
|
||||
# Some user error checking
|
||||
assert vType in vTypeOpts, "vType must be in ['%s']" % "','".join(vTypeOpts)
|
||||
@@ -289,11 +301,17 @@ class TensorView(object):
|
||||
|
||||
def _plotImage2D(self, v, vType='CC', grid=False, view='real',
|
||||
ax=None, clim=None, showIt=False,
|
||||
pcolorOpts={},
|
||||
streamOpts={'color':'k'},
|
||||
gridOpts={'color':'k'}
|
||||
pcolorOpts=None,
|
||||
streamOpts=None,
|
||||
gridOpts=None
|
||||
):
|
||||
|
||||
if pcolorOpts is None:
|
||||
pcolorOpts = {}
|
||||
if streamOpts is None:
|
||||
streamOpts = {'color':'k'}
|
||||
if gridOpts is None:
|
||||
gridOpts = {'color':'k'}
|
||||
vTypeOptsCC = ['N','CC','Fx','Fy','Ex','Ey']
|
||||
vTypeOptsV = ['CCv','F','E']
|
||||
vTypeOpts = vTypeOptsCC + vTypeOptsV
|
||||
|
||||
@@ -888,6 +888,8 @@ class ProjectedGNCG(BFGS, Minimize, Remember):
|
||||
maxIterCG = 5
|
||||
tolCG = 1e-1
|
||||
|
||||
stepOffBoundsFact = 0.1 # perturbation of the inactive set off the bounds
|
||||
|
||||
lower = -np.inf
|
||||
upper = np.inf
|
||||
|
||||
@@ -990,4 +992,20 @@ class ProjectedGNCG(BFGS, Minimize, Remember):
|
||||
cgFlag = 1
|
||||
# End CG Iterations
|
||||
|
||||
# Take a gradient step on the active cells if exist
|
||||
if temp != self.xc.size:
|
||||
|
||||
rhs_a = (Active) * -self.g
|
||||
|
||||
dm_i = max( abs( delx ) )
|
||||
dm_a = max( abs(rhs_a) )
|
||||
|
||||
# perturb inactive set off of bounds so that they are included in the step
|
||||
delx = delx + self.stepOffBoundsFact * (rhs_a * dm_i / dm_a)
|
||||
|
||||
|
||||
# Only keep gradients going in the right direction on the active set
|
||||
indx = ((self.xc<=self.lower) & (delx < 0)) | ((self.xc>=self.upper) & (delx > 0))
|
||||
delx[indx] = 0.
|
||||
|
||||
return delx
|
||||
|
||||
+517
-300
@@ -1,5 +1,289 @@
|
||||
import Utils, Maps, Mesh, numpy as np, scipy.sparse as sp
|
||||
|
||||
class RegularizationMesh(object):
|
||||
"""
|
||||
**Regularization Mesh**
|
||||
|
||||
This contains the operators used in the regularization. Note that these
|
||||
are not necessarily true differential operators, but are constructed from
|
||||
a SimPEG Mesh.
|
||||
|
||||
:param Mesh mesh: problem mesh
|
||||
:param numpy.array indActive: bool array, size nC, that is True where we have active cells. Used to reduce the operators so we regularize only on active cells
|
||||
"""
|
||||
|
||||
def __init__(self, mesh, indActive=None):
|
||||
self.mesh = mesh
|
||||
assert indActive is None or indActive.dtype == 'bool', 'indActive needs to be None or a bool'
|
||||
self.indActive = indActive
|
||||
|
||||
@property
|
||||
def vol(self):
|
||||
"""
|
||||
reduced volume vector
|
||||
:rtype: numpy.array
|
||||
:return: reduced cell volume
|
||||
"""
|
||||
if getattr(self, '_vol', None) is None:
|
||||
self._vol = self._Pac.T * self.mesh.vol
|
||||
return self._vol
|
||||
|
||||
@property
|
||||
def nC(self):
|
||||
"""
|
||||
reduced number of cells
|
||||
:rtype: int
|
||||
:return: number of cells being regularized
|
||||
"""
|
||||
if getattr(self, '_nC', None) is None:
|
||||
if self.indActive is None:
|
||||
self._nC = self.mesh.nC
|
||||
else:
|
||||
self._nC = sum(self.indActive)
|
||||
return self._nC
|
||||
|
||||
@property
|
||||
def dim(self):
|
||||
"""
|
||||
dimension of regularization mesh (1D, 2D, 3D)
|
||||
:rtype: int
|
||||
:return: dimension
|
||||
"""
|
||||
if getattr(self, '_dim', None) is None:
|
||||
self._dim = self.mesh.dim
|
||||
return self._dim
|
||||
|
||||
|
||||
@property
|
||||
def _Pac(self):
|
||||
"""
|
||||
projection matrix that takes from the reduced space of active cells to full modelling space (ie. nC x nindActive)
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: active cell projection matrix
|
||||
"""
|
||||
if getattr(self, '__Pac', None) is None:
|
||||
if self.indActive is None:
|
||||
self.__Pac = Utils.speye(self.mesh.nC)
|
||||
else:
|
||||
self.__Pac = Utils.speye(self.mesh.nC)[:,self.indActive]
|
||||
return self.__Pac
|
||||
|
||||
@property
|
||||
def _Pafx(self):
|
||||
"""
|
||||
projection matrix that takes from the reduced space of active x-faces to full modelling space (ie. nFx x nindActive_Fx )
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: active face-x projection matrix
|
||||
"""
|
||||
if getattr(self, '__Pafx', None) is None:
|
||||
if self.indActive is None:
|
||||
self.__Pafx = Utils.speye(self.mesh.nFx)
|
||||
else:
|
||||
indActive_Fx = (self.mesh.aveFx2CC.T * self.indActive) == 1
|
||||
self.__Pafx = Utils.speye(self.mesh.nFx)[:,indActive_Fx]
|
||||
return self.__Pafx
|
||||
|
||||
@property
|
||||
def _Pafy(self):
|
||||
"""
|
||||
projection matrix that takes from the reduced space of active y-faces to full modelling space (ie. nFy x nindActive_Fy )
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: active face-y projection matrix
|
||||
"""
|
||||
if getattr(self, '__Pafy', None) is None:
|
||||
if self.indActive is None:
|
||||
self.__Pafy = Utils.speye(self.mesh.nFy)
|
||||
else:
|
||||
indActive_Fy = (self.mesh.aveFy2CC.T * self.indActive) == 1
|
||||
self.__Pafy = Utils.speye(self.mesh.nFy)[:,indActive_Fy]
|
||||
return self.__Pafy
|
||||
|
||||
@property
|
||||
def _Pafz(self):
|
||||
"""
|
||||
projection matrix that takes from the reduced space of active z-faces to full modelling space (ie. nFz x nindActive_Fz )
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: active face-z projection matrix
|
||||
"""
|
||||
if getattr(self, '__Pafz', None) is None:
|
||||
if self.indActive is None:
|
||||
self.__Pafz = Utils.speye(self.mesh.nFz)
|
||||
else:
|
||||
indActive_Fz = (self.mesh.aveFz2CC.T * self.indActive) == 1
|
||||
self.__Pafz = Utils.speye(self.mesh.nFz)[:,indActive_Fz]
|
||||
return self.__Pafz
|
||||
|
||||
@property
|
||||
def aveFx2CC(self):
|
||||
"""
|
||||
averaging from active cell centers to active x-faces
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: averaging from active cell centers to active x-faces
|
||||
"""
|
||||
if getattr(self, '_aveFx2CC', None) is None:
|
||||
self._aveFx2CC = self._Pac.T * self.mesh.aveFx2CC * self._Pafx
|
||||
return self._aveFx2CC
|
||||
|
||||
@property
|
||||
def aveCC2Fx(self):
|
||||
"""
|
||||
averaging from active x-faces to active cell centers
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: averaging matrix from active x-faces to active cell centers
|
||||
"""
|
||||
if getattr(self, '_aveCC2Fx', None) is None:
|
||||
self._aveCC2Fx = Utils.sdiag(1./(self.aveFx2CC.T).sum(1)) * self.aveFx2CC.T
|
||||
return self._aveCC2Fx
|
||||
|
||||
@property
|
||||
def aveFy2CC(self):
|
||||
"""
|
||||
averaging from active cell centers to active y-faces
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: averaging from active cell centers to active y-faces
|
||||
"""
|
||||
if getattr(self, '_aveFy2CC', None) is None:
|
||||
self._aveFy2CC = self._Pac.T * self.mesh.aveFy2CC * self._Pafy
|
||||
return self._aveFy2CC
|
||||
|
||||
@property
|
||||
def aveCC2Fy(self):
|
||||
"""
|
||||
averaging from active y-faces to active cell centers
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: averaging matrix from active y-faces to active cell centers
|
||||
"""
|
||||
if getattr(self, '_aveCC2Fy', None) is None:
|
||||
self._aveCC2Fy = Utils.sdiag(1./(self.aveFy2CC.T).sum(1)) * self.aveFy2CC.T
|
||||
return self._aveCC2Fy
|
||||
|
||||
@property
|
||||
def aveFz2CC(self):
|
||||
"""
|
||||
averaging from active cell centers to active z-faces
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: averaging from active cell centers to active z-faces
|
||||
"""
|
||||
if getattr(self, '_aveFz2CC', None) is None:
|
||||
self._aveFz2CC = self._Pac.T * self.mesh.aveFz2CC * self._Pafz
|
||||
return self._aveFz2CC
|
||||
|
||||
@property
|
||||
def aveCC2Fz(self):
|
||||
"""
|
||||
averaging from active z-faces to active cell centers
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: averaging matrix from active z-faces to active cell centers
|
||||
"""
|
||||
if getattr(self, '_aveCC2Fz', None) is None:
|
||||
self._aveCC2Fz = Utils.sdiag(1./(self.aveFz2CC.T).sum(1)) * self.aveFz2CC.T
|
||||
return self._aveCC2Fz
|
||||
|
||||
@property
|
||||
def cellDiffx(self):
|
||||
"""
|
||||
cell centered difference in the x-direction
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: differencing matrix for active cells in the x-direction
|
||||
"""
|
||||
if getattr(self, '_cellDiffx', None) is None:
|
||||
self._cellDiffx = self._Pafx.T * self.mesh.cellGradx * self._Pac
|
||||
return self._cellDiffx
|
||||
|
||||
@property
|
||||
def cellDiffy(self):
|
||||
"""
|
||||
cell centered difference in the y-direction
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: differencing matrix for active cells in the y-direction
|
||||
"""
|
||||
if getattr(self, '_cellDiffy', None) is None:
|
||||
self._cellDiffy = self._Pafy.T * self.mesh.cellGrady * self._Pac
|
||||
return self._cellDiffy
|
||||
|
||||
@property
|
||||
def cellDiffz(self):
|
||||
"""
|
||||
cell centered difference in the z-direction
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: differencing matrix for active cells in the z-direction
|
||||
"""
|
||||
if getattr(self, '_cellDiffz', None) is None:
|
||||
self._cellDiffz = self._Pafz.T * self.mesh.cellGradz * self._Pac
|
||||
return self._cellDiffz
|
||||
|
||||
@property
|
||||
def faceDiffx(self):
|
||||
"""
|
||||
x-face differences
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: differencing matrix for active faces in the x-direction
|
||||
"""
|
||||
if getattr(self, '_faceDiffx', None) is None:
|
||||
self._faceDiffx = self._Pac.T * self.mesh.faceDivx * self._Pafx
|
||||
return self._faceDiffx
|
||||
|
||||
@property
|
||||
def faceDiffy(self):
|
||||
"""
|
||||
y-face differences
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: differencing matrix for active faces in the y-direction
|
||||
"""
|
||||
if getattr(self, '_faceDiffy', None) is None:
|
||||
self._faceDiffy = self._Pac.T * self.mesh.faceDivy * self._Pafy
|
||||
return self._faceDiffy
|
||||
|
||||
@property
|
||||
def faceDiffz(self):
|
||||
"""
|
||||
z-face differences
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: differencing matrix for active faces in the z-direction
|
||||
"""
|
||||
if getattr(self, '_faceDiffz', None) is None:
|
||||
self._faceDiffz = self._Pac.T * self.mesh.faceDivz * self._Pafz
|
||||
return self._faceDiffz
|
||||
|
||||
@property
|
||||
def cellDiffxStencil(self):
|
||||
"""
|
||||
cell centered difference stencil (no cell lengths include) in the x-direction
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: differencing matrix for active cells in the x-direction
|
||||
"""
|
||||
if getattr(self, '_cellDiffxStencil', None) is None:
|
||||
|
||||
self._cellDiffxStencil = self._Pafx.T * self.mesh._cellGradxStencil() * self._Pac
|
||||
return self._cellDiffxStencil
|
||||
|
||||
@property
|
||||
def cellDiffyStencil(self):
|
||||
"""
|
||||
cell centered difference stencil (no cell lengths include) in the y-direction
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: differencing matrix for active cells in the y-direction
|
||||
"""
|
||||
if self.dim < 2: return None
|
||||
if getattr(self, '_cellDiffyStencil', None) is None:
|
||||
|
||||
self._cellDiffyStencil = self._Pafy.T * self.mesh._cellGradyStencil() * self._Pac
|
||||
return self._cellDiffyStencil
|
||||
|
||||
@property
|
||||
def cellDiffzStencil(self):
|
||||
"""
|
||||
cell centered difference stencil (no cell lengths include) in the y-direction
|
||||
:rtype: scipy.sparse.csr_matrix
|
||||
:return: differencing matrix for active cells in the y-direction
|
||||
"""
|
||||
if self.dim < 3: return None
|
||||
if getattr(self, '_cellDiffzStencil', None) is None:
|
||||
|
||||
self._cellDiffzStencil = self._Pafz.T * self.mesh._cellGradzStencil() * self._Pac
|
||||
return self._cellDiffzStencil
|
||||
|
||||
|
||||
class BaseRegularization(object):
|
||||
"""
|
||||
**Base Regularization Class**
|
||||
@@ -18,12 +302,16 @@ class BaseRegularization(object):
|
||||
|
||||
mapping = None #: A SimPEG.Map instance.
|
||||
mesh = None #: A SimPEG.Mesh instance.
|
||||
mref = None #: Reference model.
|
||||
mref = None #: Reference model.
|
||||
|
||||
def __init__(self, mesh, mapping=None, indActive=None, **kwargs):
|
||||
Utils.setKwargs(self, **kwargs)
|
||||
self.mesh = mesh
|
||||
assert isinstance(mesh, Mesh.BaseMesh), "mesh must be a SimPEG.Mesh object."
|
||||
if indActive is not None and indActive.dtype != 'bool':
|
||||
tmp = indActive
|
||||
indActive = np.zeros(mesh.nC, dtype=bool)
|
||||
indActive[tmp] = True
|
||||
self.regmesh = RegularizationMesh(mesh,indActive)
|
||||
self.mapping = mapping or self.mapPair(mesh)
|
||||
self.mapping._assertMatchesPair(self.mapPair)
|
||||
self.indActive = indActive
|
||||
@@ -55,8 +343,7 @@ class BaseRegularization(object):
|
||||
@property
|
||||
def W(self):
|
||||
"""Full regularization weighting matrix W."""
|
||||
return sp.identity(self.mapping.nP)
|
||||
|
||||
return sp.identity(self.regmesh.nC)
|
||||
|
||||
@Utils.timeIt
|
||||
def eval(self, m):
|
||||
@@ -87,11 +374,12 @@ class BaseRegularization(object):
|
||||
@Utils.timeIt
|
||||
def eval2Deriv(self, m, v=None):
|
||||
"""
|
||||
Second derivative
|
||||
|
||||
:param numpy.array m: geophysical model
|
||||
:param numpy.array v: vector to multiply
|
||||
:rtype: scipy.sparse.csr_matrix or numpy.ndarray
|
||||
:return: WtW or WtW*v
|
||||
:param numpy.array m: geophysical model
|
||||
:param numpy.array v: vector to multiply
|
||||
:rtype: scipy.sparse.csr_matrix or numpy.ndarray
|
||||
:return: WtW or WtW*v
|
||||
|
||||
The regularization is:
|
||||
|
||||
@@ -112,112 +400,94 @@ class BaseRegularization(object):
|
||||
|
||||
return mD.T * ( self.W.T * ( self.W * ( mD * v) ) )
|
||||
|
||||
|
||||
class Tikhonov(BaseRegularization):
|
||||
"""
|
||||
L2 Tikhonov regularization with both smallness and smoothness (first order
|
||||
derivative) contributions.
|
||||
|
||||
.. math::
|
||||
\phi_m(\mathbf{m}) = \\alpha_s \| W_s (\mathbf{m} - \mathbf{m_{ref}} ) \|^2
|
||||
+ \\alpha_x \| W_x \\frac{\partial}{\partial x} (\mathbf{m} - \mathbf{m_{ref}} ) \|^2
|
||||
+ \\alpha_y \| W_y \\frac{\partial}{\partial y} (\mathbf{m} - \mathbf{m_{ref}} ) \|^2
|
||||
+ \\alpha_z \| W_z \\frac{\partial}{\partial z} (\mathbf{m} - \mathbf{m_{ref}} ) \|^2
|
||||
|
||||
Note if the key word argument `mrefInSmooth` is False, then mref is not
|
||||
included in the smoothness contribution.
|
||||
|
||||
:param Mesh mesh: SimPEG mesh
|
||||
:param Maps mapping: regularization mapping, takes the model from model space to the thing you want to regularize
|
||||
:param numpy.ndarray indActive: active cell indices for reducing the size of differential operators in the definition of a regularization mesh
|
||||
:param bool mrefInSmooth: (default = False) put mref in the smoothness component?
|
||||
:param float alpha_s: (default 1e-6) smallness weight
|
||||
:param float alpha_x: (default 1) smoothness weight for first derivative in the x-direction
|
||||
:param float alpha_y: (default 1) smoothness weight for first derivative in the y-direction
|
||||
:param float alpha_z: (default 1) smoothness weight for first derivative in the z-direction
|
||||
:param float alpha_xx: (default 1) smoothness weight for second derivative in the x-direction
|
||||
:param float alpha_yy: (default 1) smoothness weight for second derivative in the y-direction
|
||||
:param float alpha_zz: (default 1) smoothness weight for second derivative in the z-direction
|
||||
"""
|
||||
smoothModel = True #: SMOOTH and SMOOTH_MOD_DIF options
|
||||
alpha_s = Utils.dependentProperty('_alpha_s', 1e-6, ['_W', '_Ws'], "Smallness weight")
|
||||
alpha_x = Utils.dependentProperty('_alpha_x', 1.0, ['_W', '_Wx'], "Weight for the first derivative in the x direction")
|
||||
alpha_y = Utils.dependentProperty('_alpha_y', 1.0, ['_W', '_Wy'], "Weight for the first derivative in the y direction")
|
||||
alpha_z = Utils.dependentProperty('_alpha_z', 1.0, ['_W', '_Wz'], "Weight for the first derivative in the z direction")
|
||||
alpha_xx = Utils.dependentProperty('_alpha_xx', 0.0, ['_W', '_Wxx'], "Weight for the second derivative in the x direction")
|
||||
alpha_yy = Utils.dependentProperty('_alpha_yy', 0.0, ['_W', '_Wyy'], "Weight for the second derivative in the y direction")
|
||||
alpha_zz = Utils.dependentProperty('_alpha_zz', 0.0, ['_W', '_Wzz'], "Weight for the second derivative in the z direction")
|
||||
mrefInSmooth = False # put mref in the smoothness contribution
|
||||
alpha_s = Utils.dependentProperty('_alpha_s', 1e-6, ['_W', '_Wsmall'], "Smallness weight")
|
||||
alpha_x = Utils.dependentProperty('_alpha_x', 1.0, ['_W', '_Wx'], "Weight for the first derivative in the x direction")
|
||||
alpha_y = Utils.dependentProperty('_alpha_y', 1.0, ['_W', '_Wy'], "Weight for the first derivative in the y direction")
|
||||
alpha_z = Utils.dependentProperty('_alpha_z', 1.0, ['_W', '_Wz'], "Weight for the first derivative in the z direction")
|
||||
alpha_xx = Utils.dependentProperty('_alpha_xx', 0.0, ['_W', '_Wxx'], "Weight for the second derivative in the x direction")
|
||||
alpha_yy = Utils.dependentProperty('_alpha_yy', 0.0, ['_W', '_Wyy'], "Weight for the second derivative in the y direction")
|
||||
alpha_zz = Utils.dependentProperty('_alpha_zz', 0.0, ['_W', '_Wzz'], "Weight for the second derivative in the z direction")
|
||||
|
||||
def __init__(self, mesh, mapping=None, indActive = None, **kwargs):
|
||||
BaseRegularization.__init__(self, mesh, mapping=mapping, **kwargs)
|
||||
self.indActive = indActive
|
||||
BaseRegularization.__init__(self, mesh, mapping=mapping, indActive=indActive, **kwargs)
|
||||
|
||||
@property
|
||||
def Ws(self):
|
||||
"""Regularization matrix Ws"""
|
||||
if getattr(self,'_Ws', None) is None:
|
||||
self._Ws = Utils.sdiag((self.mesh.vol*self.alpha_s)**0.5)
|
||||
if self.indActive is not None:
|
||||
Pac = Utils.speye(self.mesh.nC)[:,self.indActive]
|
||||
self._Ws = Pac.T * self._Ws * Pac
|
||||
return self._Ws
|
||||
def Wsmall(self):
|
||||
"""Regularization matrix Wsmall"""
|
||||
if getattr(self,'_Wsmall', None) is None:
|
||||
self._Wsmall = Utils.sdiag((self.regmesh.vol*self.alpha_s)**0.5)
|
||||
return self._Wsmall
|
||||
|
||||
@property
|
||||
def Wx(self):
|
||||
"""Regularization matrix Wx"""
|
||||
if getattr(self, '_Wx', None) is None:
|
||||
Ave_x_vol = self.mesh.aveF2CC[:,:self.mesh.nFx].T*self.mesh.vol
|
||||
self._Wx = Utils.sdiag((Ave_x_vol*self.alpha_x)**0.5)*self.mesh.cellGradx
|
||||
|
||||
if self.indActive is not None:
|
||||
indActive_Fx = (self.mesh.aveFx2CC.T * self.indActive) == 1
|
||||
Pac = Utils.speye(self.mesh.nC)[:,self.indActive]
|
||||
Pafx = Utils.speye(self.mesh.nFx)[:,indActive_Fx]
|
||||
self._Wx = Pafx.T*self._Wx*Pac
|
||||
|
||||
Ave_x_vol = self.regmesh.aveCC2Fx * self.regmesh.vol
|
||||
self._Wx = Utils.sdiag((Ave_x_vol*self.alpha_x)**0.5)*self.regmesh.cellDiffx
|
||||
return self._Wx
|
||||
|
||||
@property
|
||||
def Wy(self):
|
||||
"""Regularization matrix Wy"""
|
||||
if getattr(self, '_Wy', None) is None:
|
||||
Ave_y_vol = self.mesh.aveF2CC[:,self.mesh.nFx:np.sum(self.mesh.vnF[:2])].T*self.mesh.vol
|
||||
self._Wy = Utils.sdiag((Ave_y_vol*self.alpha_y)**0.5)*self.mesh.cellGrady
|
||||
|
||||
if self.indActive is not None:
|
||||
indActive_Fy = (self.mesh.aveFy2CC.T * self.indActive) == 1
|
||||
Pac = Utils.speye(self.mesh.nC)[:,self.indActive]
|
||||
Pafy = Utils.speye(self.mesh.nFy)[:,indActive_Fy]
|
||||
self._Wy = Pafy.T*self._Wy*Pac
|
||||
|
||||
Ave_y_vol = self.regmesh.aveCC2Fy * self.regmesh.vol
|
||||
self._Wy = Utils.sdiag((Ave_y_vol*self.alpha_y)**0.5)*self.regmesh.cellDiffy
|
||||
return self._Wy
|
||||
|
||||
@property
|
||||
def Wz(self):
|
||||
"""Regularization matrix Wz"""
|
||||
if getattr(self, '_Wz', None) is None:
|
||||
Ave_z_vol = self.mesh.aveF2CC[:,np.sum(self.mesh.vnF[:2]):].T*self.mesh.vol
|
||||
self._Wz = Utils.sdiag((Ave_z_vol*self.alpha_z)**0.5)*self.mesh.cellGradz
|
||||
|
||||
if self.indActive is not None:
|
||||
indActive_Fz = (self.mesh.aveFz2CC.T * self.indActive) == 1
|
||||
Pac = Utils.speye(self.mesh.nC)[:,self.indActive]
|
||||
Pafz = Utils.speye(self.mesh.nFz)[:,indActive_Fz]
|
||||
self._Wz = Pafz.T*self._Wz*Pac
|
||||
|
||||
Ave_z_vol = self.regmesh.aveCC2Fz * self.regmesh.vol
|
||||
self._Wz = Utils.sdiag((Ave_z_vol*self.alpha_z)**0.5)*self.regmesh.cellDiffz
|
||||
return self._Wz
|
||||
|
||||
@property
|
||||
def Wxx(self):
|
||||
"""Regularization matrix Wxx"""
|
||||
if getattr(self, '_Wxx', None) is None:
|
||||
self._Wxx = Utils.sdiag((self.mesh.vol*self.alpha_xx)**0.5)*self.mesh.faceDivx*self.mesh.cellGradx
|
||||
|
||||
if self.indActive is not None:
|
||||
Pac = Utils.speye(self.mesh.nC)[:,self.indActive]
|
||||
self._Wxx = Pac.T*self._Wxx*Pac
|
||||
|
||||
self._Wxx = Utils.sdiag((self.regmesh.vol*self.alpha_xx)**0.5)*self.regmesh.faceDiffx*self.regmesh.cellDiffx
|
||||
return self._Wxx
|
||||
|
||||
@property
|
||||
def Wyy(self):
|
||||
"""Regularization matrix Wyy"""
|
||||
if getattr(self, '_Wyy', None) is None:
|
||||
self._Wyy = Utils.sdiag((self.mesh.vol*self.alpha_yy)**0.5)*self.mesh.faceDivy*self.mesh.cellGrady
|
||||
|
||||
if self.indActive is not None:
|
||||
Pac = Utils.speye(self.mesh.nC)[:,self.indActive]
|
||||
self._Wyy = Pac.T*self._Wyy*Pac
|
||||
|
||||
self._Wyy = Utils.sdiag((self.regmesh.vol*self.alpha_yy)**0.5)*self.regmesh.faceDiffy*self.regmesh.cellDiffy
|
||||
return self._Wyy
|
||||
|
||||
@property
|
||||
def Wzz(self):
|
||||
"""Regularization matrix Wzz"""
|
||||
if getattr(self, '_Wzz', None) is None:
|
||||
self._Wzz = Utils.sdiag((self.mesh.vol*self.alpha_zz)**0.5)*self.mesh.faceDivz*self.mesh.cellGradz
|
||||
|
||||
if self.indActive is not None:
|
||||
Pac = Utils.speye(self.mesh.nC)[:,self.indActive]
|
||||
self._Wzz = Pac.T*self._Wzz*Pac
|
||||
|
||||
self._Wzz = Utils.sdiag((self.regmesh.vol*self.alpha_zz)**0.5)*self.regmesh.faceDiffz*self.regmesh.cellDiffz
|
||||
return self._Wzz
|
||||
|
||||
@property
|
||||
@@ -225,9 +495,9 @@ class Tikhonov(BaseRegularization):
|
||||
"""Full smoothness regularization matrix W"""
|
||||
if getattr(self, '_Wsmooth', None) is None:
|
||||
wlist = (self.Wx, self.Wxx)
|
||||
if self.mesh.dim > 1:
|
||||
if self.regmesh.dim > 1:
|
||||
wlist += (self.Wy, self.Wyy)
|
||||
if self.mesh.dim > 2:
|
||||
if self.regmesh.dim > 2:
|
||||
wlist += (self.Wz, self.Wzz)
|
||||
self._Wsmooth = sp.vstack(wlist)
|
||||
return self._Wsmooth
|
||||
@@ -236,25 +506,44 @@ class Tikhonov(BaseRegularization):
|
||||
def W(self):
|
||||
"""Full regularization matrix W"""
|
||||
if getattr(self, '_W', None) is None:
|
||||
wlist = (self.Ws, self.Wsmooth)
|
||||
wlist = (self.Wsmall, self.Wsmooth)
|
||||
self._W = sp.vstack(wlist)
|
||||
return self._W
|
||||
|
||||
@Utils.timeIt
|
||||
def eval(self, m):
|
||||
if self.smoothModel == True:
|
||||
r1 = self.Wsmooth * ( self.mapping * (m) )
|
||||
r2 = self.Ws * ( self.mapping * (m - self.mref) )
|
||||
return 0.5*(r1.dot(r1)+r2.dot(r2))
|
||||
elif self.smoothModel == False:
|
||||
r = self.W * ( self.mapping * (m - self.mref) )
|
||||
return 0.5*r.dot(r)
|
||||
def _evalSmall(self, m):
|
||||
r = self.Wsmall * ( self.mapping * (m - self.mref) )
|
||||
return 0.5 * r.dot(r)
|
||||
|
||||
@Utils.timeIt
|
||||
def _evalSmooth(self, m):
|
||||
if self.mrefInSmooth == True:
|
||||
r = self.Wsmooth * ( self.mapping * (m - self.mref) )
|
||||
elif self.mrefInSmooth == False:
|
||||
r = self.Wsmooth * ( self.mapping * (m) )
|
||||
return 0.5 * r.dot(r)
|
||||
|
||||
@Utils.timeIt
|
||||
def eval(self, m):
|
||||
return self._evalSmall(m) + self._evalSmooth(m)
|
||||
|
||||
@Utils.timeIt
|
||||
def _evalSmallDeriv(self,m):
|
||||
r = self.Wsmall * ( self.mapping * (m - self.mref) )
|
||||
return r.T * ( self.Wsmall * self.mapping.deriv(m - self.mref) )
|
||||
|
||||
@Utils.timeIt
|
||||
def _evalSmoothDeriv(self,m):
|
||||
if self.mrefInSmooth == True:
|
||||
r = self.Wsmooth * ( self.mapping * ( m - self.mref ) )
|
||||
return r.T * ( self.Wsmooth * self.mapping.deriv(m - self.mref) )
|
||||
elif self.mrefInSmooth == False:
|
||||
r = self.Wsmooth * ( self.mapping * m )
|
||||
return r.T * ( self.Wsmooth * self.mapping.deriv(m) )
|
||||
|
||||
@Utils.timeIt
|
||||
def evalDeriv(self, m):
|
||||
"""
|
||||
|
||||
The regularization is:
|
||||
|
||||
.. math::
|
||||
@@ -268,257 +557,185 @@ class Tikhonov(BaseRegularization):
|
||||
R(m) = \mathbf{W^\\top W (m-m_\\text{ref})}
|
||||
|
||||
"""
|
||||
if self.smoothModel == True:
|
||||
mD1 = self.mapping.deriv(m)
|
||||
mD2 = self.mapping.deriv(m - self.mref)
|
||||
r1 = self.Wsmooth * ( self.mapping * (m))
|
||||
r2 = self.Ws * ( self.mapping * (m - self.mref) )
|
||||
out1 = mD1.T * ( self.Wsmooth.T * r1 )
|
||||
out2 = mD2.T * ( self.Ws.T * r2 )
|
||||
out = out1+out2
|
||||
elif self.smoothModel == False:
|
||||
mD = self.mapping.deriv(m - self.mref)
|
||||
r = self.W * ( self.mapping * (m - self.mref) )
|
||||
out = mD.T * ( self.W.T * r )
|
||||
return out
|
||||
|
||||
# <<<<<<< HEAD
|
||||
|
||||
# class Simple(BaseRegularization):
|
||||
# """
|
||||
# Only for tensor mesh
|
||||
# """
|
||||
|
||||
# smoothModel = True #: SMOOTH and SMOOTH_MOD_DIF options
|
||||
# alpha_s = Utils.dependentProperty('_alpha_s', 1.0, ['_W', '_Ws'], "Smallness weight")
|
||||
# alpha_x = Utils.dependentProperty('_alpha_x', 1.0, ['_W', '_Wx'], "Weight for the first derivative in the x direction")
|
||||
# alpha_y = Utils.dependentProperty('_alpha_y', 1.0, ['_W', '_Wy'], "Weight for the first derivative in the y direction")
|
||||
# alpha_z = Utils.dependentProperty('_alpha_z', 1.0, ['_W', '_Wz'], "Weight for the first derivative in the z direction")
|
||||
# alpha_xx = Utils.dependentProperty('_alpha_xx', 0.0, ['_W', '_Wxx'], "Weight for the second derivative in the x direction")
|
||||
# alpha_yy = Utils.dependentProperty('_alpha_yy', 0.0, ['_W', '_Wyy'], "Weight for the second derivative in the y direction")
|
||||
# alpha_zz = Utils.dependentProperty('_alpha_zz', 0.0, ['_W', '_Wzz'], "Weight for the second derivative in the z direction")
|
||||
|
||||
# def __init__(self, mesh, mapping=None, **kwargs):
|
||||
# BaseRegularization.__init__(self, mesh, mapping=mapping, **kwargs)
|
||||
return self._evalSmallDeriv(m) + self._evalSmoothDeriv(m)
|
||||
|
||||
|
||||
class Simple(Tikhonov):
|
||||
"""
|
||||
Simple regularization that does not include length scales in the derivatives.
|
||||
"""
|
||||
|
||||
# @property
|
||||
# def Ws(self):
|
||||
# """Regularization matrix Ws"""
|
||||
# if getattr(self,'_Ws', None) is None:
|
||||
# self._Ws = Utils.sdiag((self.mesh.vol*self.alpha_s)**0.5)
|
||||
# return self._Ws
|
||||
mrefInSmooth = False #: SMOOTH and SMOOTH_MOD_DIF options
|
||||
alpha_s = Utils.dependentProperty('_alpha_s', 1.0, ['_W', '_Wsmall'], "Smallness weight")
|
||||
alpha_x = Utils.dependentProperty('_alpha_x', 1.0, ['_W', '_Wx'], "Weight for the first derivative in the x direction")
|
||||
alpha_y = Utils.dependentProperty('_alpha_y', 1.0, ['_W', '_Wy'], "Weight for the first derivative in the y direction")
|
||||
alpha_z = Utils.dependentProperty('_alpha_z', 1.0, ['_W', '_Wz'], "Weight for the first derivative in the z direction")
|
||||
wght = 1.
|
||||
|
||||
# @property
|
||||
# def Wx(self):
|
||||
# """Regularization matrix Wx"""
|
||||
# if getattr(self, '_Wx', None) is None:
|
||||
# self._Wx = Utils.sdiag((self.mesh.vol*self.alpha_x)**0.5)*self.mesh.unitCellGradx
|
||||
# return self._Wx
|
||||
def __init__(self, mesh, mapping=None, indActive=None, **kwargs):
|
||||
BaseRegularization.__init__(self, mesh, mapping=mapping, indActive=indActive, **kwargs)
|
||||
|
||||
# @property
|
||||
# def Wy(self):
|
||||
# """Regularization matrix Wy"""
|
||||
# if getattr(self, '_Wy', None) is None:
|
||||
# self._Wy = Utils.sdiag((self.mesh.vol*self.alpha_y)**0.5)*self.mesh.unitCellGrady
|
||||
# return self._Wy
|
||||
if isinstance(self.wght,float):
|
||||
self.wght = np.ones(self.regmesh.nC) * self.wght
|
||||
|
||||
# @property
|
||||
# def Wz(self):
|
||||
# """Regularization matrix Wz"""
|
||||
# if getattr(self, '_Wz', None) is None:
|
||||
# self._Wz = Utils.sdiag((self.mesh.vol*self.alpha_z)**0.5)*self.mesh.unitCellGradz
|
||||
# return self._Wz
|
||||
@property
|
||||
def Wsmall(self):
|
||||
"""Regularization matrix Wsmall"""
|
||||
if getattr(self,'_Wsmall', None) is None:
|
||||
self._Wsmall = Utils.sdiag((self.regmesh.vol*self.alpha_s*self.wght)**0.5)
|
||||
return self._Wsmall
|
||||
|
||||
# @property
|
||||
# def Wxx(self):
|
||||
# """Regularization matrix Wxx"""
|
||||
# if getattr(self, '_Wxx', None) is None:
|
||||
# self._Wxx = Utils.sdiag((self.mesh.vol*self.alpha_xx)**0.5)*self.mesh.faceDivx*self.mesh.cellGradx
|
||||
# return self._Wxx
|
||||
@property
|
||||
def Wx(self):
|
||||
"""Regularization matrix Wx"""
|
||||
if getattr(self, '_Wx', None) is None:
|
||||
self._Wx = Utils.sdiag((self.regmesh.aveCC2Fx * self.regmesh.vol*self.alpha_x*(self.regmesh.aveCC2Fx*self.wght))**0.5)*self.regmesh.cellDiffxStencil
|
||||
return self._Wx
|
||||
|
||||
# @property
|
||||
# def Wyy(self):
|
||||
# """Regularization matrix Wyy"""
|
||||
# if getattr(self, '_Wyy', None) is None:
|
||||
# self._Wyy = Utils.sdiag((self.mesh.vol*self.alpha_yy)**0.5)*self.mesh.faceDivy*self.mesh.cellGrady
|
||||
# return self._Wyy
|
||||
@property
|
||||
def Wy(self):
|
||||
"""Regularization matrix Wy"""
|
||||
if getattr(self, '_Wy', None) is None:
|
||||
self._Wy = Utils.sdiag((self.regmesh.aveCC2Fy * self.regmesh.vol * self.alpha_y*(self.regmesh.aveCC2Fy*self.wght))**0.5)*self.regmesh.cellDiffyStencil
|
||||
return self._Wy
|
||||
|
||||
# @property
|
||||
# def Wzz(self):
|
||||
# """Regularization matrix Wzz"""
|
||||
# if getattr(self, '_Wzz', None) is None:
|
||||
# self._Wzz = Utils.sdiag((self.mesh.vol*self.alpha_zz)**0.5)*self.mesh.faceDivz*self.mesh.cellGradz
|
||||
# return self._Wzz
|
||||
@property
|
||||
def Wz(self):
|
||||
"""Regularization matrix Wz"""
|
||||
if getattr(self, '_Wz', None) is None:
|
||||
self._Wz = Utils.sdiag((self.regmesh.aveCC2Fz * self.regmesh.vol*self.alpha_z*(self.regmesh.aveCC2Fz*self.wght))**0.5)*self.regmesh.cellDiffzStencil
|
||||
return self._Wz
|
||||
|
||||
# @property
|
||||
# def Wsmooth(self):
|
||||
# """Full smoothness regularization matrix W"""
|
||||
# if getattr(self, '_Wsmooth', None) is None:
|
||||
# wlist = (self.Wx, self.Wxx)
|
||||
# if self.mesh.dim > 1:
|
||||
# wlist += (self.Wy, self.Wyy)
|
||||
# if self.mesh.dim > 2:
|
||||
# wlist += (self.Wz, self.Wzz)
|
||||
# self._Wsmooth = sp.vstack(wlist)
|
||||
# return self._Wsmooth
|
||||
@property
|
||||
def Wsmooth(self):
|
||||
"""Full smoothness regularization matrix W"""
|
||||
if getattr(self, '_Wsmooth', None) is None:
|
||||
wlist = (self.Wx,)
|
||||
if self.regmesh.dim > 1:
|
||||
wlist += (self.Wy,)
|
||||
if self.regmesh.dim > 2:
|
||||
wlist += (self.Wz,)
|
||||
self._Wsmooth = sp.vstack(wlist)
|
||||
return self._Wsmooth
|
||||
|
||||
# @property
|
||||
# def W(self):
|
||||
# """Full regularization matrix W"""
|
||||
# if getattr(self, '_W', None) is None:
|
||||
# wlist = (self.Ws, self.Wsmooth)
|
||||
# self._W = sp.vstack(wlist)
|
||||
# return self._W
|
||||
@property
|
||||
def W(self):
|
||||
"""Full regularization matrix W"""
|
||||
if getattr(self, '_W', None) is None:
|
||||
wlist = (self.Wsmall, self.Wsmooth)
|
||||
self._W = sp.vstack(wlist)
|
||||
return self._W
|
||||
|
||||
# @Utils.timeIt
|
||||
# def eval(self, m):
|
||||
# if self.smoothModel == True:
|
||||
# r1 = self.Wsmooth * ( self.mapping * (m) )
|
||||
# r2 = self.Ws * ( self.mapping * (m - self.mref) )
|
||||
# return 0.5*(r1.dot(r1)+r2.dot(r2))
|
||||
# elif self.smoothModel == False:
|
||||
# r = self.W * ( self.mapping * (m - self.mref) )
|
||||
# return 0.5*r.dot(r)
|
||||
@Utils.timeIt
|
||||
def _evalSmall(self, m):
|
||||
r = self.Wsmall * ( self.mapping * (m - self.mref) )
|
||||
return 0.5 * r.dot(r)
|
||||
|
||||
@Utils.timeIt
|
||||
def _evalSmooth(self, m):
|
||||
if self.mrefInSmooth == True:
|
||||
r = self.Wsmooth * ( self.mapping * (m - self.mref) )
|
||||
elif self.mrefInSmooth == False:
|
||||
r = self.Wsmooth * ( self.mapping * m)
|
||||
return 0.5 * r.dot(r)
|
||||
|
||||
|
||||
# @Utils.timeIt
|
||||
# def evalDeriv(self, m):
|
||||
# """
|
||||
class Sparse(Simple):
|
||||
|
||||
# The regularization is:
|
||||
# set default values
|
||||
eps_p = 1e-1
|
||||
eps_q = 1e-1
|
||||
curModel = None # use a model to compute the weights
|
||||
gamma = 1.
|
||||
norms = [0., 2., 2., 2.]
|
||||
wght = 1.
|
||||
|
||||
# .. math::
|
||||
def __init__(self, mesh, mapping=None, indActive=None, **kwargs):
|
||||
Simple.__init__(self, mesh, mapping=mapping, indActive=indActive, **kwargs)
|
||||
|
||||
# R(m) = \\frac{1}{2}\mathbf{(m-m_\\text{ref})^\\top W^\\top W(m-m_\\text{ref})}
|
||||
if isinstance(self.wght,float):
|
||||
self.wght = np.ones(self.regmesh.nC) * self.wght
|
||||
|
||||
# So the derivative is straight forward:
|
||||
@property
|
||||
def Wsmall(self):
|
||||
"""Regularization matrix Wsmall"""
|
||||
if getattr(self, 'curModel', None) is None:
|
||||
self.Rs = Utils.speye(self.regmesh.nC)
|
||||
|
||||
# .. math::
|
||||
else:
|
||||
f_m = self.curModel - self.reg.mref
|
||||
self.rs = self.R(f_m , self.eps_p, self.norms[0])
|
||||
#print "Min rs: " + str(np.max(self.rs)) + "Max rs: " + str(np.min(self.rs))
|
||||
self.Rs = Utils.sdiag( self.rs )
|
||||
|
||||
# R(m) = \mathbf{W^\\top W (m-m_\\text{ref})}
|
||||
|
||||
# """
|
||||
# if self.smoothModel == True:
|
||||
# mD1 = self.mapping.deriv(m)
|
||||
# mD2 = self.mapping.deriv(m - self.mref)
|
||||
# r1 = self.Wsmooth * ( self.mapping * (m))
|
||||
# r2 = self.Ws * ( self.mapping * (m - self.mref) )
|
||||
# out1 = mD1.T * ( self.Wsmooth.T * r1 )
|
||||
# out2 = mD2.T * ( self.Ws.T * r2 )
|
||||
# out = out1+out2
|
||||
# elif self.smoothModel == False:
|
||||
# mD = self.mapping.deriv(m - self.mref)
|
||||
# r = self.W * ( self.mapping * (m - self.mref) )
|
||||
# out = mD.T * ( self.W.T * r )
|
||||
# return out
|
||||
|
||||
# class SparseRegularization(Simple):
|
||||
|
||||
# eps = 1e-1
|
||||
|
||||
# m = None
|
||||
# gamma = 1.
|
||||
# p = 0.
|
||||
# qx = 2.
|
||||
# qy = 2.
|
||||
# qz = 2.
|
||||
|
||||
# def __init__(self, mesh, mapping=None, **kwargs):
|
||||
# Simple.__init__(self, mesh, mapping=mapping, **kwargs)
|
||||
return Utils.sdiag((self.regmesh.vol*self.alpha_s*self.gamma*self.wght)**0.5)*self.Rs
|
||||
|
||||
|
||||
# @property
|
||||
# def Wsmooth(self):
|
||||
# """Full smoothness regularization matrix W"""
|
||||
# if getattr(self, '_Wsmooth', None) is None:
|
||||
# wlist = (self.Wx, self.Wxx)
|
||||
# if self.mesh.dim > 1:
|
||||
# wlist += (self.Wy, self.Wyy)
|
||||
# if self.mesh.dim > 2:
|
||||
# wlist += (self.Wz, self.Wzz)
|
||||
# self._Wsmooth = sp.vstack(wlist)
|
||||
# return self._Wsmooth
|
||||
@property
|
||||
def Wx(self):
|
||||
"""Regularization matrix Wx"""
|
||||
|
||||
# @property
|
||||
# def W(self):
|
||||
# """Full regularization matrix W"""
|
||||
# if getattr(self, '_W', None) is None:
|
||||
# wlist = (self.Ws, self.Wsmooth)
|
||||
# self._W = sp.vstack(wlist)
|
||||
# return self._W
|
||||
if getattr(self, 'curModel', None) is None:
|
||||
self.Rx = Utils.speye(self.regmesh.cellDiffxStencil.shape[0])
|
||||
|
||||
# @property
|
||||
# def Ws(self):
|
||||
# """Regularization matrix Ws"""
|
||||
# if getattr(self, 'm', None) is None:
|
||||
# self.Rs = Utils.speye(self.mesh.nC)
|
||||
else:
|
||||
f_m = self.regmesh.cellDiffxStencil * self.curModel
|
||||
self.rx = self.R( f_m , self.eps_q, self.norms[1])
|
||||
self.Rx = Utils.sdiag( self.rx )
|
||||
|
||||
# else:
|
||||
# f_m = self.m
|
||||
# self.rs = self.R(f_m , self.p, self.eps)
|
||||
# #print "Min rs: " + str(np.max(self.rs)) + "Max rs: " + str(np.min(self.rs))
|
||||
# self.Rs = Utils.sdiag( self.rs )
|
||||
return Utils.sdiag(( (self.regmesh.aveCC2Fx * self.regmesh.vol) *self.alpha_x*self.gamma*(self.regmesh.aveCC2Fx*self.wght))**0.5)*self.Rx*self.regmesh.cellDiffxStencil
|
||||
|
||||
# self._Ws = Utils.sdiag((self.mesh.vol*self.alpha_s*self.gamma)**0.5)*self.Rs
|
||||
@property
|
||||
def Wy(self):
|
||||
"""Regularization matrix Wy"""
|
||||
|
||||
# return self._Ws
|
||||
if getattr(self, 'curModel', None) is None:
|
||||
self.Ry = Utils.speye(self.regmesh.cellDiffyStencil.shape[0])
|
||||
|
||||
# @property
|
||||
# def Wx(self):
|
||||
# """Regularization matrix Wx"""
|
||||
else:
|
||||
f_m = self.regmesh.cellDiffyStencil * self.curModel
|
||||
self.ry = self.R( f_m , self.eps_q, self.norms[2])
|
||||
self.Ry = Utils.sdiag( self.ry )
|
||||
|
||||
# if getattr(self, 'm', None) is None:
|
||||
# self.Rx = Utils.speye(self.mesh.unitCellGradx.shape[0])
|
||||
return Utils.sdiag(((self.regmesh.aveCC2Fy * self.regmesh.vol)*self.alpha_y*self.gamma*(self.regmesh.aveCC2Fy*self.wght))**0.5)*self.Ry*self.regmesh.cellDiffyStencil
|
||||
|
||||
# else:
|
||||
# f_m = self.mesh.unitCellGradx * self.m
|
||||
# self.rx = self.R( f_m , self.qx, self.eps)
|
||||
# self.Rx = Utils.sdiag( self.rx )
|
||||
@property
|
||||
def Wz(self):
|
||||
"""Regularization matrix Wz"""
|
||||
|
||||
# if getattr(self, '_Wx', None) is None:
|
||||
# self._Wx = Utils.sdiag((self.mesh.vol*self.alpha_x*self.gamma)**0.5)*self.Rx*self.mesh.unitCellGradx
|
||||
# return self._Wx
|
||||
if getattr(self, 'curModel', None) is None:
|
||||
self.Rz = Utils.speye(self.regmesh.cellDiffzStencil.shape[0])
|
||||
|
||||
# @property
|
||||
# def Wy(self):
|
||||
# """Regularization matrix Wy"""
|
||||
else:
|
||||
f_m = self.regmesh.cellDiffzStencil * self.curModel
|
||||
self.rz = self.R( f_m , self.eps_q, self.norms[3])
|
||||
self.Rz = Utils.sdiag( self.rz )
|
||||
|
||||
# if getattr(self, 'm', None) is None:
|
||||
# self.Ry = Utils.speye(self.mesh.unitCellGrady.shape[0])
|
||||
return Utils.sdiag(((self.regmesh.aveCC2Fz * self.regmesh.vol)*self.alpha_z*self.gamma*(self.regmesh.aveCC2Fz*self.wght))**0.5)*self.Rz*self.regmesh.cellDiffzStencil
|
||||
|
||||
# else:
|
||||
# f_m = self.mesh.unitCellGrady * self.m
|
||||
# self.ry = self.R( f_m , self.qy, self.eps)
|
||||
# self.Ry = Utils.sdiag( self.ry )
|
||||
@property
|
||||
def Wsmooth(self):
|
||||
"""Full smoothness regularization matrix W"""
|
||||
#if getattr(self, '_Wsmooth', None) is None:
|
||||
wlist = (self.Wx,)
|
||||
if self.regmesh.dim > 1:
|
||||
wlist += (self.Wy,)
|
||||
if self.regmesh.dim > 2:
|
||||
wlist += (self.Wz,)
|
||||
#self._Wsmooth = sp.vstack(wlist)
|
||||
return sp.vstack(wlist)
|
||||
|
||||
# if getattr(self, '_Wy', None) is None:
|
||||
# self._Wy = Utils.sdiag((self.mesh.vol*self.alpha_y*self.gamma)**0.5)*self.Ry*self.mesh.unitCellGrady
|
||||
# return self._Wy
|
||||
@property
|
||||
def W(self):
|
||||
"""Full regularization matrix W"""
|
||||
#if getattr(self, '_W', None) is None:
|
||||
wlist = (self.Wsmall, self.Wsmooth)
|
||||
#self._W = sp.vstack(wlist)
|
||||
return sp.vstack(wlist)
|
||||
|
||||
# @property
|
||||
# def Wz(self):
|
||||
# """Regularization matrix Wz"""
|
||||
def R(self, f_m , eps, exponent):
|
||||
|
||||
# if getattr(self, 'm', None) is None:
|
||||
# self.Rz = Utils.speye(self.mesh.unitCellGradz.shape[0])
|
||||
eta = (eps**(1-exponent/2.))**0.5
|
||||
r = eta / (f_m**2.+ eps**2.)**((1-exponent/2.)/2.)
|
||||
|
||||
# else:
|
||||
# f_m = self.mesh.unitCellGradz * self.m
|
||||
# self.rz = self.R( f_m , self.qz, self.eps)
|
||||
# self.Rz = Utils.sdiag( self.rz )
|
||||
|
||||
# if getattr(self, '_Wz', None) is None:
|
||||
# self._Wz = Utils.sdiag((self.mesh.vol*self.alpha_z*self.gamma)**0.5)*self.Rz*self.mesh.unitCellGradz
|
||||
# return self._Wz
|
||||
|
||||
|
||||
# def R(self, f_m , p, dec):
|
||||
|
||||
# eta = (self.eps**(1-p/2.))**0.5
|
||||
# r = eta / (f_m**2.+self.eps**2.)**((1-p/2.)/2.)
|
||||
|
||||
# return r
|
||||
# =======
|
||||
# >>>>>>> 834de582844e8e1eac95819fbe03eed55dbeb001
|
||||
return r
|
||||
|
||||
+35
-44
@@ -82,14 +82,14 @@ class OrderTest(unittest.TestCase):
|
||||
_meshType = meshTypes[0]
|
||||
meshDimension = 3
|
||||
|
||||
def makeMesh(self, nc, meshType=_meshType, meshDimension=meshDimension):
|
||||
def setupMesh(self, nc):
|
||||
"""
|
||||
For a given number of cells nc, generate a TensorMesh with uniform cells with edge length h=1/nc.
|
||||
"""
|
||||
if 'TensorMesh' in meshType:
|
||||
if 'uniform' in meshType:
|
||||
if 'TensorMesh' in self._meshType:
|
||||
if 'uniform' in self._meshType:
|
||||
h = [nc, nc, nc]
|
||||
elif 'random' in meshType:
|
||||
elif 'random' in self._meshType:
|
||||
h1 = np.random.rand(nc)*nc*0.5 + nc*0.5
|
||||
h2 = np.random.rand(nc)*nc*0.5 + nc*0.5
|
||||
h3 = np.random.rand(nc)*nc*0.5 + nc*0.5
|
||||
@@ -97,46 +97,46 @@ class OrderTest(unittest.TestCase):
|
||||
else:
|
||||
raise Exception('Unexpected meshType')
|
||||
|
||||
M = TensorMesh(h[:meshDimension])
|
||||
max_h = max([np.max(hi) for hi in M.h])
|
||||
return M, max_h
|
||||
self.M = TensorMesh(h[:self.meshDimension])
|
||||
max_h = max([np.max(hi) for hi in self.M.h])
|
||||
return max_h
|
||||
|
||||
elif 'CylMesh' in meshType:
|
||||
if 'uniform' in meshType:
|
||||
elif 'CylMesh' in self._meshType:
|
||||
if 'uniform' in self._meshType:
|
||||
h = [nc, nc, nc]
|
||||
else:
|
||||
raise Exception('Unexpected meshType')
|
||||
|
||||
if meshDimension == 2:
|
||||
M = CylMesh([h[0], 1, h[2]])
|
||||
max_h = max([np.max(hi) for hi in [M.hx, M.hz]])
|
||||
elif meshDimension == 3:
|
||||
M = CylMesh(h)
|
||||
max_h = max([np.max(hi) for hi in M.h])
|
||||
return M, max_h
|
||||
if self.meshDimension == 2:
|
||||
self.M = CylMesh([h[0], 1, h[2]])
|
||||
max_h = max([np.max(hi) for hi in [self.M.hx, self.M.hz]])
|
||||
elif self.meshDimension == 3:
|
||||
self.M = CylMesh(h)
|
||||
max_h = max([np.max(hi) for hi in self.M.h])
|
||||
return max_h
|
||||
|
||||
elif 'Curv' in meshType:
|
||||
if 'uniform' in meshType:
|
||||
elif 'Curv' in self._meshType:
|
||||
if 'uniform' in self._meshType:
|
||||
kwrd = 'rect'
|
||||
elif 'rotate' in meshType:
|
||||
elif 'rotate' in self._meshType:
|
||||
kwrd = 'rotate'
|
||||
else:
|
||||
raise Exception('Unexpected meshType')
|
||||
if meshDimension == 1:
|
||||
if self.meshDimension == 1:
|
||||
raise Exception('Lom not supported for 1D')
|
||||
elif meshDimension == 2:
|
||||
elif self.meshDimension == 2:
|
||||
X, Y = Utils.exampleLrmGrid([nc, nc], kwrd)
|
||||
M = CurvilinearMesh([X, Y])
|
||||
elif meshDimension == 3:
|
||||
self.M = CurvilinearMesh([X, Y])
|
||||
elif self.meshDimension == 3:
|
||||
X, Y, Z = Utils.exampleLrmGrid([nc, nc, nc], kwrd)
|
||||
M = CurvilinearMesh([X, Y, Z])
|
||||
return M, 1./nc
|
||||
self.M = CurvilinearMesh([X, Y, Z])
|
||||
return 1./nc
|
||||
|
||||
elif 'Tree' in meshType:
|
||||
elif 'Tree' in self._meshType:
|
||||
nc *= 2
|
||||
if 'uniform' in meshType or 'notatree' in meshType:
|
||||
if 'uniform' in self._meshType or 'notatree' in self._meshType:
|
||||
h = [nc, nc, nc]
|
||||
elif 'random' in meshType:
|
||||
elif 'random' in self._meshType:
|
||||
h1 = np.random.rand(nc)*nc*0.5 + nc*0.5
|
||||
h2 = np.random.rand(nc)*nc*0.5 + nc*0.5
|
||||
h3 = np.random.rand(nc)*nc*0.5 + nc*0.5
|
||||
@@ -145,29 +145,20 @@ class OrderTest(unittest.TestCase):
|
||||
raise Exception('Unexpected meshType')
|
||||
|
||||
levels = int(np.log(nc)/np.log(2))
|
||||
M = Tree(h[:meshDimension], levels=levels)
|
||||
self.M = Tree(h[:self.meshDimension], levels=levels)
|
||||
def function(cell):
|
||||
if 'notatree' in meshType:
|
||||
if 'notatree' in self._meshType:
|
||||
return levels - 1
|
||||
r = cell.center - np.array([0.5]*len(cell.center))
|
||||
dist = np.sqrt(r.dot(r))
|
||||
if dist < 0.2:
|
||||
return levels
|
||||
return levels - 1
|
||||
M.refine(function,balance=False)
|
||||
M.number(balance=False)
|
||||
# M.plotGrid(showIt=True)
|
||||
max_h = max([np.max(hi) for hi in M.h])
|
||||
return M, max_h
|
||||
|
||||
|
||||
def setupMesh(self, nc):
|
||||
"""
|
||||
For a given number of cells nc, generate a TensorMesh with uniform cells with edge length h=1/nc.
|
||||
"""
|
||||
M, h = self.makeMesh(nc, meshType=self._meshType, meshDimension=self.meshDimension)
|
||||
self.M = M
|
||||
return h
|
||||
self.M.refine(function,balance=False)
|
||||
self.M.number(balance=False)
|
||||
# self.M.plotGrid(showIt=True)
|
||||
max_h = max([np.max(hi) for hi in self.M.h])
|
||||
return max_h
|
||||
|
||||
def getError(self):
|
||||
"""For given h, generate A[h], f and A(f) and return norm of error."""
|
||||
|
||||
@@ -88,12 +88,14 @@ def getIndicesBlock(p0,p1,ccMesh):
|
||||
# Return a tuple
|
||||
return ind
|
||||
|
||||
def defineBlock(ccMesh,p0,p1,vals=[0,1]):
|
||||
def defineBlock(ccMesh,p0,p1,vals=None):
|
||||
"""
|
||||
Build a block with the conductivity specified by condVal. Returns an array.
|
||||
vals[0] conductivity of the block
|
||||
vals[1] conductivity of the ground
|
||||
"""
|
||||
if vals is None:
|
||||
vals = [0,1]
|
||||
sigma = np.zeros(ccMesh.shape[0]) + vals[1]
|
||||
ind = getIndicesBlock(p0,p1,ccMesh)
|
||||
|
||||
@@ -101,7 +103,11 @@ def defineBlock(ccMesh,p0,p1,vals=[0,1]):
|
||||
|
||||
return mkvc(sigma)
|
||||
|
||||
def defineElipse(ccMesh, center=[0,0,0], anisotropy=[1,1,1], slope=10., theta=0.):
|
||||
def defineElipse(ccMesh, center=None, anisotropy=None, slope=10., theta=0.):
|
||||
if center is None:
|
||||
center = [0,0,0]
|
||||
if anisotropy is None:
|
||||
anisotropy = [1,1,1]
|
||||
G = ccMesh.copy()
|
||||
dim = ccMesh.shape[1]
|
||||
for i in range(dim):
|
||||
@@ -156,7 +162,7 @@ def getIndicesSphere(center,radius,ccMesh):
|
||||
# Return a tuple
|
||||
return ind
|
||||
|
||||
def defineTwoLayers(ccMesh,depth,vals=[0,1]):
|
||||
def defineTwoLayers(ccMesh,depth,vals=None):
|
||||
"""
|
||||
Define a two layered model. Depth of the first layer must be specified.
|
||||
CondVals vector with the conductivity values of the layers. Eg:
|
||||
@@ -167,6 +173,8 @@ def defineTwoLayers(ccMesh,depth,vals=[0,1]):
|
||||
0 depth zf
|
||||
1st layer 2nd layer
|
||||
"""
|
||||
if vals is None:
|
||||
vals = [0,1]
|
||||
sigma = np.zeros(ccMesh.shape[0]) + vals[1]
|
||||
|
||||
dim = np.size(ccMesh[0,:])
|
||||
@@ -252,7 +260,7 @@ def layeredModel(ccMesh, layerTops, layerValues):
|
||||
|
||||
|
||||
|
||||
def randomModel(shape, seed=None, anisotropy=None, its=100, bounds=[0,1]):
|
||||
def randomModel(shape, seed=None, anisotropy=None, its=100, bounds=None):
|
||||
"""
|
||||
Create a random model by convolving a kernel with a
|
||||
uniformly distributed model.
|
||||
@@ -276,6 +284,8 @@ def randomModel(shape, seed=None, anisotropy=None, its=100, bounds=[0,1]):
|
||||
|
||||
|
||||
"""
|
||||
if bounds is None:
|
||||
bounds = [0,1]
|
||||
|
||||
if seed is None:
|
||||
seed = np.random.randint(1e3)
|
||||
|
||||
@@ -55,8 +55,10 @@ def hook(obj, method, name=None, overwrite=False, silent=False):
|
||||
print 'Method '+name+' was not overwritten.'
|
||||
|
||||
|
||||
def setKwargs(obj, ignore=[], **kwargs):
|
||||
def setKwargs(obj, ignore=None, **kwargs):
|
||||
"""Sets key word arguments (kwargs) that are present in the object, throw an error if they don't exist."""
|
||||
if ignore is None:
|
||||
ignore = []
|
||||
for attr in kwargs:
|
||||
if attr in ignore:
|
||||
continue
|
||||
|
||||
@@ -27,7 +27,7 @@ def mkvc(x, numDims=1):
|
||||
|
||||
if isinstance(x, Zero):
|
||||
return x
|
||||
|
||||
|
||||
assert isinstance(x, np.ndarray), "Vector must be a numpy array"
|
||||
|
||||
if numDims == 1:
|
||||
@@ -422,9 +422,9 @@ class Zero(object):
|
||||
def __ge__(self, v):return 0 >= v
|
||||
def __gt__(self, v):return 0 > v
|
||||
|
||||
@property
|
||||
@property
|
||||
def transpose(self): return Zero()
|
||||
|
||||
|
||||
@property
|
||||
def T(self): return Zero()
|
||||
|
||||
|
||||
@@ -12,8 +12,16 @@
|
||||
DC Forward Simulation
|
||||
=====================
|
||||
|
||||
Forward model conductive spheres in a half-space and plot a pseudo-section
|
||||
Forward model two conductive spheres in a half-space and plot a
|
||||
pseudo-section. Assumes an infinite line source and measures along the
|
||||
center of the spheres.
|
||||
|
||||
INPUT:
|
||||
loc = Location of spheres [[x1,y1,z1],[x2,y2,z2]]
|
||||
radi = Radius of spheres [r1,r2]
|
||||
param = Conductivity of background and two spheres [m0,m1,m2]
|
||||
stype = survey type "pdp" (pole dipole) or "dpdp" (dipole dipole)
|
||||
dtype = Data type "appr" (app res) | "appc" (app cond) | "volt" (potential)
|
||||
Created by @fourndo on Mon Feb 01 19:28:06 2016
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
.. _examples_EM_Schenkel_Morrison_Casing:
|
||||
|
||||
.. --------------------------------- ..
|
||||
.. ..
|
||||
.. THIS FILE IS AUTO GENEREATED ..
|
||||
.. ..
|
||||
.. SimPEG/Examples/__init__.py ..
|
||||
.. ..
|
||||
.. --------------------------------- ..
|
||||
|
||||
|
||||
EM: Schenkel and Morrison Casing Model
|
||||
======================================
|
||||
|
||||
Here we create and run a FDEM forward simulation to calculate the vertical
|
||||
current inside a steel-cased. The model is based on the Schenkel and
|
||||
Morrison Casing Model, and the results are used in a 2016 SEG abstract by
|
||||
Yang et al.
|
||||
|
||||
- Schenkel, C.J., and H.F. Morrison, 1990, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686.
|
||||
|
||||
|
||||
The model consists of:
|
||||
- Air: Conductivity 1e-8 S/m, above z = 0
|
||||
- Background: conductivity 1e-2 S/m, below z = 0
|
||||
- Casing: conductivity 1e6 S/m
|
||||
- 300m long
|
||||
- radius of 0.1m
|
||||
- thickness of 6e-3m
|
||||
|
||||
Inside the casing, we take the same conductivity as the background.
|
||||
|
||||
We are using an EM code to simulate DC, so we use frequency low enough
|
||||
that the skin depth inside the casing is longer than the casing length (f
|
||||
= 1e-6 Hz). The plot produced is of the current inside the casing.
|
||||
|
||||
These results are shown in the SEG abstract by Yang et al., 2016: 3D DC
|
||||
resistivity modeling of steel casing for reservoir monitoring using
|
||||
equivalent resistor network. The solver used to produce these results and
|
||||
achieve the CPU time of ~30s is Mumps, which was installed using pymatsolver_
|
||||
|
||||
.. _pymatsolver: https://github.com/rowanc1/pymatsolver
|
||||
|
||||
This example is on figshare: https://dx.doi.org/10.6084/m9.figshare.3126961.v1
|
||||
|
||||
If you would use this example for a code comparison, or build upon it, a
|
||||
citation would be much appreciated!
|
||||
|
||||
|
||||
|
||||
.. plot::
|
||||
|
||||
from SimPEG import Examples
|
||||
Examples.EM_Schenkel_Morrison_Casing.run()
|
||||
|
||||
.. literalinclude:: ../../SimPEG/Examples/EM_Schenkel_Morrison_Casing.py
|
||||
:language: python
|
||||
:linenos:
|
||||
@@ -0,0 +1,26 @@
|
||||
.. _examples_Inversion_IRLS:
|
||||
|
||||
.. --------------------------------- ..
|
||||
.. ..
|
||||
.. THIS FILE IS AUTO GENEREATED ..
|
||||
.. ..
|
||||
.. SimPEG/Examples/__init__.py ..
|
||||
.. ..
|
||||
.. --------------------------------- ..
|
||||
|
||||
|
||||
Inversion: Linear Problem
|
||||
=========================
|
||||
|
||||
Here we go over the basics of creating a linear problem and inversion.
|
||||
|
||||
|
||||
|
||||
.. plot::
|
||||
|
||||
from SimPEG import Examples
|
||||
Examples.Inversion_IRLS.run()
|
||||
|
||||
.. literalinclude:: ../../SimPEG/Examples/Inversion_IRLS.py
|
||||
:language: python
|
||||
:linenos:
|
||||
@@ -5,6 +5,8 @@ from scipy.sparse.linalg import dsolve
|
||||
import inspect
|
||||
|
||||
TOL = 1e-20
|
||||
testReg = True
|
||||
testRegMesh = True
|
||||
|
||||
class RegularizationTests(unittest.TestCase):
|
||||
|
||||
@@ -16,44 +18,82 @@ class RegularizationTests(unittest.TestCase):
|
||||
mesh3 = Mesh.TensorMesh([hx, hy, hz])
|
||||
self.meshlist = [mesh1,mesh2, mesh3]
|
||||
|
||||
def test_regularization(self):
|
||||
for R in dir(Regularization):
|
||||
r = getattr(Regularization, R)
|
||||
if not inspect.isclass(r): continue
|
||||
if not issubclass(r, Regularization.BaseRegularization):
|
||||
continue
|
||||
if testReg:
|
||||
def test_regularization(self):
|
||||
for R in dir(Regularization):
|
||||
r = getattr(Regularization, R)
|
||||
if not inspect.isclass(r): continue
|
||||
if not issubclass(r, Regularization.BaseRegularization):
|
||||
continue
|
||||
|
||||
for i, mesh in enumerate(self.meshlist):
|
||||
|
||||
print 'Testing %iD'%mesh.dim
|
||||
|
||||
mapping = r.mapPair(mesh)
|
||||
reg = r(mesh, mapping=mapping)
|
||||
m = np.random.rand(mapping.nP)
|
||||
reg.mref = np.ones_like(m)*np.mean(m)
|
||||
|
||||
print 'Check: phi_m (mref) = %f' %reg.eval(reg.mref)
|
||||
passed = reg.eval(reg.mref) < TOL
|
||||
self.assertTrue(passed)
|
||||
|
||||
print 'Check:', R
|
||||
passed = Tests.checkDerivative(lambda m : [reg.eval(m), reg.evalDeriv(m)], m, plotIt=False)
|
||||
self.assertTrue(passed)
|
||||
|
||||
print 'Check 2 Deriv:', R
|
||||
passed = Tests.checkDerivative(lambda m : [reg.evalDeriv(m), reg.eval2Deriv(m)], m, plotIt=False)
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_regularization_ActiveCells(self):
|
||||
for R in dir(Regularization):
|
||||
r = getattr(Regularization, R)
|
||||
if not inspect.isclass(r): continue
|
||||
if not issubclass(r, Regularization.BaseRegularization):
|
||||
continue
|
||||
|
||||
for i, mesh in enumerate(self.meshlist):
|
||||
|
||||
print 'Testing Active Cells %iD'%(mesh.dim)
|
||||
|
||||
if mesh.dim == 1:
|
||||
indActive = Utils.mkvc(mesh.gridCC <= 0.8)
|
||||
elif mesh.dim == 2:
|
||||
indActive = Utils.mkvc(mesh.gridCC[:,-1] <= 2*np.sin(2*np.pi*mesh.gridCC[:,0])+0.5)
|
||||
elif mesh.dim == 3:
|
||||
indActive = Utils.mkvc(mesh.gridCC[:,-1] <= 2*np.sin(2*np.pi*mesh.gridCC[:,0])+0.5 * 2*np.sin(2*np.pi*mesh.gridCC[:,1])+0.5)
|
||||
|
||||
mapping = Maps.IdentityMap(nP=indActive.nonzero()[0].size)
|
||||
|
||||
for indAct in [indActive, indActive.nonzero()[0]]: # test both bool and integers
|
||||
reg = r(mesh, mapping=mapping, indActive=indAct)
|
||||
m = np.random.rand(mesh.nC)[indAct]
|
||||
reg.mref = np.ones_like(m)*np.mean(m)
|
||||
|
||||
print 'Check: phi_m (mref) = %f' %reg.eval(reg.mref)
|
||||
passed = reg.eval(reg.mref) < TOL
|
||||
self.assertTrue(passed)
|
||||
|
||||
print 'Check:', R
|
||||
passed = Tests.checkDerivative(lambda m : [reg.eval(m), reg.evalDeriv(m)], m, plotIt=False)
|
||||
self.assertTrue(passed)
|
||||
|
||||
print 'Check 2 Deriv:', R
|
||||
passed = Tests.checkDerivative(lambda m : [reg.evalDeriv(m), reg.eval2Deriv(m)], m, plotIt=False)
|
||||
self.assertTrue(passed)
|
||||
|
||||
if testRegMesh:
|
||||
def test_regularizationMesh(self):
|
||||
|
||||
for i, mesh in enumerate(self.meshlist):
|
||||
|
||||
print 'Testing %iD'%mesh.dim
|
||||
|
||||
mapping = r.mapPair(mesh)
|
||||
reg = r(mesh, mapping=mapping)
|
||||
m = np.random.rand(mapping.nP)
|
||||
reg.mref = np.ones_like(m)*np.mean(m)
|
||||
|
||||
print 'Check: phi_m (mref) = %f' %reg.eval(reg.mref)
|
||||
passed = reg.eval(reg.mref) < TOL
|
||||
self.assertTrue(passed)
|
||||
|
||||
print 'Check:', R
|
||||
passed = Tests.checkDerivative(lambda m : [reg.eval(m), reg.evalDeriv(m)], m, plotIt=False)
|
||||
self.assertTrue(passed)
|
||||
|
||||
print 'Check 2 Deriv:', R
|
||||
passed = Tests.checkDerivative(lambda m : [reg.evalDeriv(m), reg.eval2Deriv(m)], m, plotIt=False)
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_regularization_ActiveCells(self):
|
||||
for R in dir(Regularization):
|
||||
r = getattr(Regularization, R)
|
||||
if not inspect.isclass(r): continue
|
||||
if not issubclass(r, Regularization.BaseRegularization):
|
||||
continue
|
||||
|
||||
for i, mesh in enumerate(self.meshlist):
|
||||
|
||||
print 'Testing Active Cells %iD'%(mesh.dim)
|
||||
# mapping = r.mapPair(mesh)
|
||||
# reg = r(mesh, mapping=mapping)
|
||||
# m = np.random.rand(mapping.nP)
|
||||
|
||||
if mesh.dim == 1:
|
||||
indAct = Utils.mkvc(mesh.gridCC <= 0.8)
|
||||
@@ -62,23 +102,9 @@ class RegularizationTests(unittest.TestCase):
|
||||
elif mesh.dim == 3:
|
||||
indAct = Utils.mkvc(mesh.gridCC[:,-1] <= 2*np.sin(2*np.pi*mesh.gridCC[:,0])+0.5 * 2*np.sin(2*np.pi*mesh.gridCC[:,1])+0.5)
|
||||
|
||||
mapping = Maps.IdentityMap(nP=indAct.nonzero()[0].size)
|
||||
regmesh = Regularization.RegularizationMesh(mesh, indActive=indAct)
|
||||
|
||||
reg = r(mesh, mapping=mapping, indActive=indAct)
|
||||
m = np.random.rand(mesh.nC)[indAct]
|
||||
reg.mref = np.ones_like(m)*np.mean(m)
|
||||
|
||||
print 'Check: phi_m (mref) = %f' %reg.eval(reg.mref)
|
||||
passed = reg.eval(reg.mref) < TOL
|
||||
self.assertTrue(passed)
|
||||
|
||||
print 'Check:', R
|
||||
passed = Tests.checkDerivative(lambda m : [reg.eval(m), reg.evalDeriv(m)], m, plotIt=False)
|
||||
self.assertTrue(passed)
|
||||
|
||||
print 'Check 2 Deriv:', R
|
||||
passed = Tests.checkDerivative(lambda m : [reg.evalDeriv(m), reg.eval2Deriv(m)], m, plotIt=False)
|
||||
self.assertTrue(passed)
|
||||
assert (regmesh.vol == mesh.vol[indAct]).all()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -8,8 +8,8 @@ from SimPEG.EM.Utils.testingUtils import getFDEMProblem
|
||||
|
||||
testE = True
|
||||
testB = True
|
||||
testH = False
|
||||
testJ = False
|
||||
testH = True
|
||||
testJ = True
|
||||
|
||||
verbose = False
|
||||
|
||||
@@ -20,8 +20,8 @@ MU = mu_0
|
||||
freq = 1e-1
|
||||
addrandoms = True
|
||||
|
||||
# SrcType = ['MagDipole', 'RawVec'] #or 'MAgDipole_Bfield', 'CircularLoop', 'RawVec'
|
||||
SrcType = ['PrimSecCyl']
|
||||
SrcType = ['MagDipole', 'RawVec'] #or 'MAgDipole_Bfield', 'CircularLoop', 'RawVec'
|
||||
|
||||
|
||||
def derivTest(fdemType, comp):
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import os
|
||||
import glob
|
||||
import unittest
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_file_strings = glob.glob('test_*.py')
|
||||
module_strings = [str[0:len(str)-3] for str in test_file_strings]
|
||||
suites = [unittest.defaultTestLoader.loadTestsFromName(str) for str
|
||||
in module_strings]
|
||||
testSuite = unittest.TestSuite(suites)
|
||||
|
||||
unittest.TextTestRunner(verbosity=2).run(testSuite)
|
||||
@@ -0,0 +1,69 @@
|
||||
import unittest
|
||||
from SimPEG import Mesh, Utils, EM, Maps, np
|
||||
import SimPEG.EM.Static.DC as DC
|
||||
|
||||
class DCProblemAnalyticTests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
cs = 12.5
|
||||
hx = [(cs,7, -1.3),(cs,61),(cs,7, 1.3)]
|
||||
hy = [(cs,7, -1.3),(cs,20)]
|
||||
mesh = Mesh.TensorMesh([hx, hy],x0="CN")
|
||||
sighalf = 1e-2
|
||||
sigma = np.ones(mesh.nC)*sighalf
|
||||
x = np.linspace(-135, 250., 20)
|
||||
M = Utils.ndgrid(x-12.5, np.r_[0.])
|
||||
N = Utils.ndgrid(x+12.5, np.r_[0.])
|
||||
A0loc = np.r_[-150, 0.]
|
||||
A1loc = np.r_[-130, 0.]
|
||||
rxloc = [np.c_[M, np.zeros(20)], np.c_[N, np.zeros(20)]]
|
||||
data_anal = EM.Analytics.DCAnalyticHalf(np.r_[A0loc, 0.], rxloc, sighalf, flag="halfspace")
|
||||
|
||||
rx = DC.Rx.Dipole(M, N)
|
||||
src0 = DC.Src.Pole([rx], A0loc)
|
||||
survey = DC.Survey_ky([src0])
|
||||
|
||||
self.survey = survey
|
||||
self.mesh = mesh
|
||||
self.sigma = sigma
|
||||
self.data_anal = data_anal
|
||||
|
||||
try:
|
||||
from pymatsolver import MumpsSolver
|
||||
self.Solver = MumpsSolver
|
||||
except ImportError, e:
|
||||
self.Solver = SolverLU
|
||||
|
||||
def test_Problem3D_N(self):
|
||||
|
||||
problem = DC.Problem2D_N(self.mesh)
|
||||
problem.Solver = self.Solver
|
||||
problem.pair(self.survey)
|
||||
data = self.survey.dpred(self.sigma)
|
||||
err= np.linalg.norm((data-self.data_anal)/self.data_anal)**2 / self.data_anal.size
|
||||
if err < 0.05:
|
||||
passed = True
|
||||
print ">> DC analytic test for Problem3D_N is passed"
|
||||
else:
|
||||
passed = False
|
||||
print ">> DC analytic test for Problem3D_N is failed"
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_Problem3D_CC(self):
|
||||
problem = DC.Problem2D_CC(self.mesh)
|
||||
problem.Solver = self.Solver
|
||||
problem.pair(self.survey)
|
||||
data = self.survey.dpred(self.sigma)
|
||||
err= np.linalg.norm((data-self.data_anal)/self.data_anal)**2 / self.data_anal.size
|
||||
if err < 0.05:
|
||||
passed = True
|
||||
print ">> DC analytic test for Problem3D_CC is passed"
|
||||
else:
|
||||
passed = False
|
||||
print ">> DC analytic test for Problem3D_CC is failed"
|
||||
self.assertTrue(passed)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
import unittest
|
||||
from SimPEG import *
|
||||
import SimPEG.EM.Static.DC as DC
|
||||
|
||||
|
||||
class DCProblem_2DTestsCC(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
cs = 12.5
|
||||
hx = [(cs,7, -1.3),(cs,61),(cs,7, 1.3)]
|
||||
hy = [(cs,7, -1.3),(cs,20)]
|
||||
mesh = Mesh.TensorMesh([hx, hy],x0="CN")
|
||||
x = np.linspace(-135, 250., 20)
|
||||
M = Utils.ndgrid(x-12.5, np.r_[0.])
|
||||
N = Utils.ndgrid(x+12.5, np.r_[0.])
|
||||
A0loc = np.r_[-150, 0.]
|
||||
A1loc = np.r_[-130, 0.]
|
||||
rxloc = [np.c_[M, np.zeros(20)], np.c_[N, np.zeros(20)]]
|
||||
rx = DC.Rx.Dipole_ky(M, N)
|
||||
src0 = DC.Src.Pole([rx], A0loc)
|
||||
src1 = DC.Src.Pole([rx], A1loc)
|
||||
survey = DC.Survey_ky([src0, src1])
|
||||
problem = DC.Problem2D_CC(mesh, mapping=[('rho', Maps.IdentityMap(mesh))])
|
||||
problem.pair(survey)
|
||||
|
||||
mSynth = np.ones(mesh.nC)*1.
|
||||
survey.makeSyntheticData(mSynth)
|
||||
|
||||
# Now set up the problem to do some minimization
|
||||
dmis = DataMisfit.l2_DataMisfit(survey)
|
||||
reg = Regularization.Tikhonov(mesh)
|
||||
opt = Optimization.InexactGaussNewton(maxIterLS=20, maxIter=10, tolF=1e-6, tolX=1e-6, tolG=1e-6, maxIterCG=6)
|
||||
invProb = InvProblem.BaseInvProblem(dmis, reg, opt, beta=1e0)
|
||||
inv = Inversion.BaseInversion(invProb)
|
||||
|
||||
self.inv = inv
|
||||
self.reg = reg
|
||||
self.p = problem
|
||||
self.mesh = mesh
|
||||
self.m0 = mSynth
|
||||
self.survey = survey
|
||||
self.dmis = dmis
|
||||
|
||||
def test_misfit(self):
|
||||
derChk = lambda m: [self.survey.dpred(m), lambda mx: self.p.Jvec(self.m0, mx)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_adjoint(self):
|
||||
# Adjoint Test
|
||||
u = np.random.rand(self.mesh.nC*self.survey.nSrc)
|
||||
v = np.random.rand(self.mesh.nC)
|
||||
w = np.random.rand(self.survey.dobs.shape[0])
|
||||
wtJv = w.dot(self.p.Jvec(self.m0, v))
|
||||
vtJtw = v.dot(self.p.Jtvec(self.m0, w))
|
||||
passed = np.abs(wtJv - vtJtw) < 1e-10
|
||||
print 'Adjoint Test', np.abs(wtJv - vtJtw), passed
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_dataObj(self):
|
||||
derChk = lambda m: [self.dmis.eval(m), self.dmis.evalDeriv(m)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
class DCProblemTestsN(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
cs = 12.5
|
||||
hx = [(cs,7, -1.3),(cs,61),(cs,7, 1.3)]
|
||||
hy = [(cs,7, -1.3),(cs,20)]
|
||||
mesh = Mesh.TensorMesh([hx, hy],x0="CN")
|
||||
x = np.linspace(-135, 250., 20)
|
||||
M = Utils.ndgrid(x-12.5, np.r_[0.])
|
||||
N = Utils.ndgrid(x+12.5, np.r_[0.])
|
||||
A0loc = np.r_[-150, 0.]
|
||||
A1loc = np.r_[-130, 0.]
|
||||
rxloc = [np.c_[M, np.zeros(20)], np.c_[N, np.zeros(20)]]
|
||||
rx = DC.Rx.Dipole_ky(M, N)
|
||||
src0 = DC.Src.Pole([rx], A0loc)
|
||||
src1 = DC.Src.Pole([rx], A1loc)
|
||||
survey = DC.Survey_ky([src0, src1])
|
||||
problem = DC.Problem2D_N(mesh, mapping=[('rho', Maps.IdentityMap(mesh))])
|
||||
problem.pair(survey)
|
||||
|
||||
mSynth = np.ones(mesh.nC)*1.
|
||||
survey.makeSyntheticData(mSynth)
|
||||
|
||||
# Now set up the problem to do some minimization
|
||||
dmis = DataMisfit.l2_DataMisfit(survey)
|
||||
reg = Regularization.Tikhonov(mesh)
|
||||
opt = Optimization.InexactGaussNewton(maxIterLS=20, maxIter=10, tolF=1e-6, tolX=1e-6, tolG=1e-6, maxIterCG=6)
|
||||
invProb = InvProblem.BaseInvProblem(dmis, reg, opt, beta=1e0)
|
||||
inv = Inversion.BaseInversion(invProb)
|
||||
|
||||
self.inv = inv
|
||||
self.reg = reg
|
||||
self.p = problem
|
||||
self.mesh = mesh
|
||||
self.m0 = mSynth
|
||||
self.survey = survey
|
||||
self.dmis = dmis
|
||||
|
||||
def test_misfit(self):
|
||||
derChk = lambda m: [self.survey.dpred(m), lambda mx: self.p.Jvec(self.m0, mx)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_adjoint(self):
|
||||
# Adjoint Test
|
||||
u = np.random.rand(self.mesh.nC*self.survey.nSrc)
|
||||
v = np.random.rand(self.mesh.nC)
|
||||
w = np.random.rand(self.survey.dobs.shape[0])
|
||||
wtJv = w.dot(self.p.Jvec(self.m0, v))
|
||||
vtJtw = v.dot(self.p.Jtvec(self.m0, w))
|
||||
passed = np.abs(wtJv - vtJtw) < 1e-8
|
||||
print 'Adjoint Test', np.abs(wtJv - vtJtw), passed
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_dataObj(self):
|
||||
derChk = lambda m: [self.dmis.eval(m), self.dmis.evalDeriv(m)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,71 @@
|
||||
import unittest
|
||||
from SimPEG import Mesh, Utils, EM, Maps, np
|
||||
import SimPEG.EM.Static.DC as DC
|
||||
|
||||
class DCProblemAnalyticTests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
cs = 25.
|
||||
hx = [(cs,7, -1.3),(cs,21),(cs,7, 1.3)]
|
||||
hy = [(cs,7, -1.3),(cs,21),(cs,7, 1.3)]
|
||||
hz = [(cs,7, -1.3),(cs,20)]
|
||||
mesh = Mesh.TensorMesh([hx, hy, hz],x0="CCN")
|
||||
sigma = np.ones(mesh.nC)*1e-2
|
||||
|
||||
x = mesh.vectorCCx[(mesh.vectorCCx>-155.)&(mesh.vectorCCx<155.)]
|
||||
y = mesh.vectorCCx[(mesh.vectorCCy>-155.)&(mesh.vectorCCy<155.)]
|
||||
Aloc = np.r_[-200., 0., 0.]
|
||||
Bloc = np.r_[200., 0., 0.]
|
||||
M = Utils.ndgrid(x-25.,y, np.r_[0.])
|
||||
N = Utils.ndgrid(x+25.,y, np.r_[0.])
|
||||
phiA = EM.Analytics.DCAnalyticHalf(Aloc, [M,N], 1e-2, flag="halfspace")
|
||||
phiB = EM.Analytics.DCAnalyticHalf(Bloc, [M,N], 1e-2, flag="halfspace")
|
||||
data_anal = phiA-phiB
|
||||
|
||||
rx = DC.Rx.Dipole(M, N)
|
||||
src = DC.Src.Dipole([rx], Aloc, Bloc)
|
||||
survey = DC.Survey([src])
|
||||
|
||||
self.survey = survey
|
||||
self.mesh = mesh
|
||||
self.sigma = sigma
|
||||
self.data_anal = data_anal
|
||||
|
||||
try:
|
||||
from pymatsolver import MumpsSolver
|
||||
self.Solver = MumpsSolver
|
||||
except ImportError, e:
|
||||
self.Solver = SolverLU
|
||||
|
||||
def test_Problem3D_N(self):
|
||||
problem = DC.Problem3D_N(self.mesh)
|
||||
problem.Solver = self.Solver
|
||||
problem.pair(self.survey)
|
||||
data = self.survey.dpred(self.sigma)
|
||||
err= np.linalg.norm(data-self.data_anal)/np.linalg.norm(self.data_anal)
|
||||
if err < 0.2:
|
||||
passed = True
|
||||
print ">> DC analytic test for Problem3D_N is passed"
|
||||
else:
|
||||
passed = False
|
||||
print ">> DC analytic test for Problem3D_N is failed"
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_Problem3D_CC(self):
|
||||
problem = DC.Problem3D_CC(self.mesh)
|
||||
problem.Solver = self.Solver
|
||||
problem.pair(self.survey)
|
||||
data = self.survey.dpred(self.sigma)
|
||||
err= np.linalg.norm(data-self.data_anal)/np.linalg.norm(self.data_anal)
|
||||
if err < 0.2:
|
||||
passed = True
|
||||
print ">> DC analytic test for Problem3D_CC is passed"
|
||||
else:
|
||||
passed = False
|
||||
print ">> DC analytic test for Problem3D_CC is failed"
|
||||
self.assertTrue(passed)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
import unittest
|
||||
from SimPEG import *
|
||||
import SimPEG.EM.Static.DC as DC
|
||||
|
||||
|
||||
class DCProblemTestsCC(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
aSpacing=2.5
|
||||
nElecs=5
|
||||
|
||||
surveySize = nElecs*aSpacing - aSpacing
|
||||
cs = surveySize/nElecs/4
|
||||
|
||||
mesh = Mesh.TensorMesh([
|
||||
[(cs,10, -1.3),(cs,surveySize/cs),(cs,10, 1.3)],
|
||||
[(cs,3, -1.3),(cs,3,1.3)],
|
||||
# [(cs,5, -1.3),(cs,10)]
|
||||
],'CN')
|
||||
|
||||
srcList = DC.Utils.WennerSrcList(nElecs, aSpacing, in2D=True)
|
||||
survey = DC.Survey(srcList)
|
||||
problem = DC.Problem3D_CC(mesh, mapping=[('rho', Maps.IdentityMap(mesh))])
|
||||
problem.pair(survey)
|
||||
|
||||
mSynth = np.ones(mesh.nC)
|
||||
survey.makeSyntheticData(mSynth)
|
||||
|
||||
# Now set up the problem to do some minimization
|
||||
dmis = DataMisfit.l2_DataMisfit(survey)
|
||||
reg = Regularization.Tikhonov(mesh)
|
||||
opt = Optimization.InexactGaussNewton(maxIterLS=20, maxIter=10, tolF=1e-6, tolX=1e-6, tolG=1e-6, maxIterCG=6)
|
||||
invProb = InvProblem.BaseInvProblem(dmis, reg, opt, beta=1e4)
|
||||
inv = Inversion.BaseInversion(invProb)
|
||||
|
||||
self.inv = inv
|
||||
self.reg = reg
|
||||
self.p = problem
|
||||
self.mesh = mesh
|
||||
self.m0 = mSynth
|
||||
self.survey = survey
|
||||
self.dmis = dmis
|
||||
|
||||
def test_misfit(self):
|
||||
derChk = lambda m: [self.survey.dpred(m), lambda mx: self.p.Jvec(self.m0, mx)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_adjoint(self):
|
||||
# Adjoint Test
|
||||
u = np.random.rand(self.mesh.nC*self.survey.nSrc)
|
||||
v = np.random.rand(self.mesh.nC)
|
||||
w = np.random.rand(self.survey.dobs.shape[0])
|
||||
wtJv = w.dot(self.p.Jvec(self.m0, v))
|
||||
vtJtw = v.dot(self.p.Jtvec(self.m0, w))
|
||||
passed = np.abs(wtJv - vtJtw) < 1e-10
|
||||
print 'Adjoint Test', np.abs(wtJv - vtJtw), passed
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_dataObj(self):
|
||||
derChk = lambda m: [self.dmis.eval(m), self.dmis.evalDeriv(m)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
class DCProblemTestsN(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
aSpacing=2.5
|
||||
nElecs=10
|
||||
|
||||
surveySize = nElecs*aSpacing - aSpacing
|
||||
cs = surveySize/nElecs/4
|
||||
|
||||
mesh = Mesh.TensorMesh([
|
||||
[(cs,10, -1.3),(cs,surveySize/cs),(cs,10, 1.3)],
|
||||
[(cs,3, -1.3),(cs,3,1.3)],
|
||||
# [(cs,5, -1.3),(cs,10)]
|
||||
],'CN')
|
||||
|
||||
srcList = DC.Utils.WennerSrcList(nElecs, aSpacing, in2D=True)
|
||||
survey = DC.Survey(srcList)
|
||||
problem = DC.Problem3D_N(mesh, mapping=[('rho', Maps.IdentityMap(mesh))])
|
||||
problem.pair(survey)
|
||||
|
||||
mSynth = np.ones(mesh.nC)
|
||||
survey.makeSyntheticData(mSynth)
|
||||
|
||||
# Now set up the problem to do some minimization
|
||||
dmis = DataMisfit.l2_DataMisfit(survey)
|
||||
reg = Regularization.Tikhonov(mesh)
|
||||
opt = Optimization.InexactGaussNewton(maxIterLS=20, maxIter=10, tolF=1e-6, tolX=1e-6, tolG=1e-6, maxIterCG=6)
|
||||
invProb = InvProblem.BaseInvProblem(dmis, reg, opt, beta=1e4)
|
||||
inv = Inversion.BaseInversion(invProb)
|
||||
|
||||
self.inv = inv
|
||||
self.reg = reg
|
||||
self.p = problem
|
||||
self.mesh = mesh
|
||||
self.m0 = mSynth
|
||||
self.survey = survey
|
||||
self.dmis = dmis
|
||||
|
||||
def test_misfit(self):
|
||||
derChk = lambda m: [self.survey.dpred(m), lambda mx: self.p.Jvec(self.m0, mx)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False)
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_adjoint(self):
|
||||
# Adjoint Test
|
||||
u = np.random.rand(self.mesh.nC*self.survey.nSrc)
|
||||
v = np.random.rand(self.mesh.nC)
|
||||
w = np.random.rand(self.survey.dobs.shape[0])
|
||||
wtJv = w.dot(self.p.Jvec(self.m0, v))
|
||||
vtJtw = v.dot(self.p.Jtvec(self.m0, w))
|
||||
passed = np.abs(wtJv - vtJtw) < 1e-8
|
||||
print 'Adjoint Test', np.abs(wtJv - vtJtw), passed
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_dataObj(self):
|
||||
derChk = lambda m: [self.dmis.eval(m), self.dmis.evalDeriv(m)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False)
|
||||
self.assertTrue(passed)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,96 @@
|
||||
import unittest
|
||||
from SimPEG import Mesh, Utils, EM, Maps, np
|
||||
import SimPEG.EM.Static.DC as DC
|
||||
import SimPEG.EM.Static.IP as IP
|
||||
|
||||
class IPProblemAnalyticTests(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
cs = 12.5
|
||||
npad=2
|
||||
hx = [(cs,npad, -1.3),(cs,21),(cs,npad, 1.3)]
|
||||
hy = [(cs,npad, -1.3),(cs,21),(cs,npad, 1.3)]
|
||||
hz = [(cs,npad, -1.3),(cs,20)]
|
||||
mesh = Mesh.TensorMesh([hx, hy, hz],x0="CCN")
|
||||
|
||||
x = mesh.vectorCCx[(mesh.vectorCCx>-80.)&(mesh.vectorCCx<80.)]
|
||||
y = mesh.vectorCCx[(mesh.vectorCCy>-80.)&(mesh.vectorCCy<80.)]
|
||||
Aloc = np.r_[-100., 0., 0.]
|
||||
Bloc = np.r_[100., 0., 0.]
|
||||
M = Utils.ndgrid(x-12.5,y, np.r_[0.])
|
||||
N = Utils.ndgrid(x+12.5,y, np.r_[0.])
|
||||
radius = 50.
|
||||
xc = np.r_[0., 0., -100]
|
||||
blkind = Utils.ModelBuilder.getIndicesSphere(xc, radius, mesh.gridCC)
|
||||
sigmaInf = np.ones(mesh.nC)*1e-2
|
||||
eta = np.zeros(mesh.nC)
|
||||
eta[blkind] = 0.1
|
||||
sigma0 = sigmaInf*(1.-eta)
|
||||
|
||||
rx = DC.Rx.Dipole(M, N)
|
||||
src = DC.Src.Dipole([rx], Aloc, Bloc)
|
||||
surveyDC = DC.Survey([src])
|
||||
|
||||
self.surveyDC = surveyDC
|
||||
self.mesh = mesh
|
||||
self.sigmaInf = sigmaInf
|
||||
self.sigma0 = sigma0
|
||||
self.src = src
|
||||
self.eta = eta
|
||||
|
||||
try:
|
||||
from pymatsolver import MumpsSolver
|
||||
self.Solver = MumpsSolver
|
||||
except ImportError, e:
|
||||
self.Solver = SolverLU
|
||||
|
||||
def test_Problem3D_N(self):
|
||||
|
||||
problemDC = DC.Problem3D_N(self.mesh)
|
||||
problemDC.Solver = self.Solver
|
||||
problemDC.pair(self.surveyDC)
|
||||
data0 = self.surveyDC.dpred(self.sigma0)
|
||||
finf = problemDC.fields(self.sigmaInf)
|
||||
datainf = self.surveyDC.dpred(self.sigmaInf, f=finf)
|
||||
problemIP = IP.Problem3D_N(self.mesh, sigma=self.sigmaInf, Ainv=problemDC.Ainv, f=finf)
|
||||
problemIP.Solver = self.Solver
|
||||
surveyIP = IP.Survey([self.src])
|
||||
problemIP.pair(surveyIP)
|
||||
data_full = data0 - datainf
|
||||
data = surveyIP.dpred(self.eta)
|
||||
err= np.linalg.norm((data-data_full)/data_full)**2 / data_full.size
|
||||
if err < 0.05:
|
||||
passed = True
|
||||
print ">> IP forward test for Problem3D_N is passed"
|
||||
else:
|
||||
passed = False
|
||||
print ">> IP forward test for Problem3D_N is failed"
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_Problem3D_CC(self):
|
||||
|
||||
problemDC = DC.Problem3D_CC(self.mesh)
|
||||
problemDC.Solver = self.Solver
|
||||
problemDC.pair(self.surveyDC)
|
||||
data0 = self.surveyDC.dpred(self.sigma0)
|
||||
finf = problemDC.fields(self.sigmaInf)
|
||||
datainf = self.surveyDC.dpred(self.sigmaInf, f=finf)
|
||||
problemIP = IP.Problem3D_CC(self.mesh, rho=1./self.sigmaInf, Ainv=problemDC.Ainv, f=finf)
|
||||
problemIP.Solver = self.Solver
|
||||
surveyIP = IP.Survey([self.src])
|
||||
problemIP.pair(surveyIP)
|
||||
data_full = data0 - datainf
|
||||
data = surveyIP.dpred(self.eta)
|
||||
err= np.linalg.norm((data-data_full)/data_full)**2 / data_full.size
|
||||
if err < 0.05:
|
||||
passed = True
|
||||
print ">> IP forward test for Problem3D_CC is passed"
|
||||
else:
|
||||
passed = False
|
||||
print ">> IP forward test for Problem3D_CC is failed"
|
||||
self.assertTrue(passed)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
import unittest
|
||||
from SimPEG import *
|
||||
import SimPEG.EM.Static.DC as DC
|
||||
import SimPEG.EM.Static.IP as IP
|
||||
|
||||
|
||||
class IPProblemTestsCC(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
aSpacing=2.5
|
||||
nElecs=5
|
||||
|
||||
surveySize = nElecs*aSpacing - aSpacing
|
||||
cs = surveySize/nElecs/4
|
||||
|
||||
mesh = Mesh.TensorMesh([
|
||||
[(cs,10, -1.3),(cs,surveySize/cs),(cs,10, 1.3)],
|
||||
[(cs,3, -1.3),(cs,3,1.3)],
|
||||
# [(cs,5, -1.3),(cs,10)]
|
||||
],'CN')
|
||||
|
||||
srcList = DC.Utils.WennerSrcList(nElecs, aSpacing, in2D=True)
|
||||
survey = IP.Survey(srcList)
|
||||
sigma = np.ones(mesh.nC)
|
||||
problem = IP.Problem3D_CC(mesh, rho=1./sigma)
|
||||
problem.pair(survey)
|
||||
mSynth = np.ones(mesh.nC)*0.1
|
||||
survey.makeSyntheticData(mSynth)
|
||||
# Now set up the problem to do some minimization
|
||||
dmis = DataMisfit.l2_DataMisfit(survey)
|
||||
reg = Regularization.Tikhonov(mesh)
|
||||
opt = Optimization.InexactGaussNewton(maxIterLS=20, maxIter=10, tolF=1e-6, tolX=1e-6, tolG=1e-6, maxIterCG=6)
|
||||
invProb = InvProblem.BaseInvProblem(dmis, reg, opt, beta=1e4)
|
||||
inv = Inversion.BaseInversion(invProb)
|
||||
|
||||
self.inv = inv
|
||||
self.reg = reg
|
||||
self.p = problem
|
||||
self.mesh = mesh
|
||||
self.m0 = mSynth
|
||||
self.survey = survey
|
||||
self.dmis = dmis
|
||||
|
||||
def test_misfit(self):
|
||||
derChk = lambda m: [self.survey.dpred(m), lambda mx: self.p.Jvec(self.m0, mx)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_adjoint(self):
|
||||
# Adjoint Test
|
||||
u = np.random.rand(self.mesh.nC*self.survey.nSrc)
|
||||
v = np.random.rand(self.mesh.nC)
|
||||
w = np.random.rand(self.survey.dobs.shape[0])
|
||||
wtJv = w.dot(self.p.Jvec(self.m0, v))
|
||||
vtJtw = v.dot(self.p.Jtvec(self.m0, w))
|
||||
passed = np.abs(wtJv - vtJtw) < 1e-10
|
||||
print 'Adjoint Test', np.abs(wtJv - vtJtw), passed
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_dataObj(self):
|
||||
derChk = lambda m: [self.dmis.eval(m), self.dmis.evalDeriv(m)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
class IPProblemTestsN(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
aSpacing=2.5
|
||||
nElecs=5
|
||||
|
||||
surveySize = nElecs*aSpacing - aSpacing
|
||||
cs = surveySize/nElecs/4
|
||||
|
||||
mesh = Mesh.TensorMesh([
|
||||
[(cs,10, -1.3),(cs,surveySize/cs),(cs,10, 1.3)],
|
||||
[(cs,3, -1.3),(cs,3,1.3)],
|
||||
# [(cs,5, -1.3),(cs,10)]
|
||||
],'CN')
|
||||
|
||||
srcList = DC.Utils.WennerSrcList(nElecs, aSpacing, in2D=True)
|
||||
survey = IP.Survey(srcList)
|
||||
sigma = np.ones(mesh.nC)
|
||||
problem = IP.Problem3D_N(mesh, sigma=sigma)
|
||||
problem.pair(survey)
|
||||
mSynth = np.ones(mesh.nC)*0.1
|
||||
survey.makeSyntheticData(mSynth)
|
||||
# Now set up the problem to do some minimization
|
||||
dmis = DataMisfit.l2_DataMisfit(survey)
|
||||
reg = Regularization.Tikhonov(mesh)
|
||||
opt = Optimization.InexactGaussNewton(maxIterLS=20, maxIter=10, tolF=1e-6, tolX=1e-6, tolG=1e-6, maxIterCG=6)
|
||||
invProb = InvProblem.BaseInvProblem(dmis, reg, opt, beta=1e4)
|
||||
inv = Inversion.BaseInversion(invProb)
|
||||
|
||||
self.inv = inv
|
||||
self.reg = reg
|
||||
self.p = problem
|
||||
self.mesh = mesh
|
||||
self.m0 = mSynth
|
||||
self.survey = survey
|
||||
self.dmis = dmis
|
||||
|
||||
def test_misfit(self):
|
||||
derChk = lambda m: [self.survey.dpred(m), lambda mx: self.p.Jvec(self.m0, mx)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_adjoint(self):
|
||||
# Adjoint Test
|
||||
u = np.random.rand(self.mesh.nC*self.survey.nSrc)
|
||||
v = np.random.rand(self.mesh.nC)
|
||||
w = np.random.rand(self.survey.dobs.shape[0])
|
||||
wtJv = w.dot(self.p.Jvec(self.m0, v))
|
||||
vtJtw = v.dot(self.p.Jtvec(self.m0, w))
|
||||
passed = np.abs(wtJv - vtJtw) < 1e-8
|
||||
print 'Adjoint Test', np.abs(wtJv - vtJtw), passed
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_dataObj(self):
|
||||
derChk = lambda m: [self.dmis.eval(m), self.dmis.evalDeriv(m)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,232 @@
|
||||
import unittest
|
||||
from SimPEG import *
|
||||
import SimPEG
|
||||
from SimPEG import Mesh, Utils, EM, Maps, np, Survey
|
||||
from SimPEG.EM.Static import SIP, DC, IP
|
||||
from pymatsolver import MumpsSolver
|
||||
|
||||
|
||||
class IPProblemTestsCC(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
cs = 25.
|
||||
hx = [(cs,0, -1.3),(cs,21),(cs,0, 1.3)]
|
||||
hy = [(cs,0, -1.3),(cs,21),(cs,0, 1.3)]
|
||||
hz = [(cs,0, -1.3),(cs,20)]
|
||||
mesh = Mesh.TensorMesh([hx, hy, hz],x0="CCN")
|
||||
blkind0 = Utils.ModelBuilder.getIndicesSphere(np.r_[-100., -100., -200.], 75., mesh.gridCC)
|
||||
blkind1 = Utils.ModelBuilder.getIndicesSphere(np.r_[100., 100., -200.], 75., mesh.gridCC)
|
||||
sigma = np.ones(mesh.nC)*1e-2
|
||||
eta = np.zeros(mesh.nC)
|
||||
tau = np.ones_like(sigma)*1.
|
||||
eta[blkind0] = 0.1
|
||||
eta[blkind1] = 0.1
|
||||
tau[blkind0] = 0.1
|
||||
tau[blkind1] = 0.01
|
||||
|
||||
x = mesh.vectorCCx[(mesh.vectorCCx>-155.)&(mesh.vectorCCx<155.)]
|
||||
y = mesh.vectorCCx[(mesh.vectorCCy>-155.)&(mesh.vectorCCy<155.)]
|
||||
Aloc = np.r_[-200., 0., 0.]
|
||||
Bloc = np.r_[200., 0., 0.]
|
||||
M = Utils.ndgrid(x-25.,y, np.r_[0.])
|
||||
N = Utils.ndgrid(x+25.,y, np.r_[0.])
|
||||
|
||||
times = np.arange(10)*1e-3 + 1e-3
|
||||
rx = SIP.Rx.Dipole(M, N, times)
|
||||
src = SIP.Src.Dipole([rx], Aloc, Bloc)
|
||||
survey = SIP.Survey([src])
|
||||
colemap = [("eta", Maps.IdentityMap(mesh)), ("taui", Maps.IdentityMap(mesh))]
|
||||
problem = SIP.Problem3D_CC(mesh, rho=1./sigma, mapping=colemap)
|
||||
problem.Solver = MumpsSolver
|
||||
problem.pair(survey)
|
||||
mSynth = np.r_[eta, 1./tau]
|
||||
survey.makeSyntheticData(mSynth)
|
||||
# Now set up the problem to do some minimization
|
||||
dmis = DataMisfit.l2_DataMisfit(survey)
|
||||
reg = Regularization.Tikhonov(mesh)
|
||||
opt = Optimization.InexactGaussNewton(maxIterLS=20, maxIter=10, tolF=1e-6, tolX=1e-6, tolG=1e-6, maxIterCG=6)
|
||||
invProb = InvProblem.BaseInvProblem(dmis, reg, opt, beta=1e4)
|
||||
inv = Inversion.BaseInversion(invProb)
|
||||
|
||||
self.inv = inv
|
||||
self.reg = reg
|
||||
self.p = problem
|
||||
self.mesh = mesh
|
||||
self.m0 = mSynth
|
||||
self.survey = survey
|
||||
self.dmis = dmis
|
||||
|
||||
def test_misfit(self):
|
||||
derChk = lambda m: [self.survey.dpred(m), lambda mx: self.p.Jvec(self.m0, mx)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_adjoint(self):
|
||||
# Adjoint Test
|
||||
u = np.random.rand(self.mesh.nC*self.survey.nSrc)
|
||||
v = np.random.rand(self.mesh.nC*2)
|
||||
w = np.random.rand(self.survey.dobs.shape[0])
|
||||
wtJv = w.dot(self.p.Jvec(self.m0, v))
|
||||
vtJtw = v.dot(self.p.Jtvec(self.m0, w))
|
||||
passed = np.abs(wtJv - vtJtw) < 1e-10
|
||||
print 'Adjoint Test', np.abs(wtJv - vtJtw), passed
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_dataObj(self):
|
||||
derChk = lambda m: [self.dmis.eval(m), self.dmis.evalDeriv(m)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
class IPProblemTestsN(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
cs = 25.
|
||||
hx = [(cs,0, -1.3),(cs,21),(cs,0, 1.3)]
|
||||
hy = [(cs,0, -1.3),(cs,21),(cs,0, 1.3)]
|
||||
hz = [(cs,0, -1.3),(cs,20)]
|
||||
mesh = Mesh.TensorMesh([hx, hy, hz],x0="CCN")
|
||||
blkind0 = Utils.ModelBuilder.getIndicesSphere(np.r_[-100., -100., -200.], 75., mesh.gridCC)
|
||||
blkind1 = Utils.ModelBuilder.getIndicesSphere(np.r_[100., 100., -200.], 75., mesh.gridCC)
|
||||
sigma = np.ones(mesh.nC)*1e-2
|
||||
eta = np.zeros(mesh.nC)
|
||||
tau = np.ones_like(sigma)*1.
|
||||
eta[blkind0] = 0.1
|
||||
eta[blkind1] = 0.1
|
||||
tau[blkind0] = 0.1
|
||||
tau[blkind1] = 0.01
|
||||
|
||||
x = mesh.vectorCCx[(mesh.vectorCCx>-155.)&(mesh.vectorCCx<155.)]
|
||||
y = mesh.vectorCCx[(mesh.vectorCCy>-155.)&(mesh.vectorCCy<155.)]
|
||||
Aloc = np.r_[-200., 0., 0.]
|
||||
Bloc = np.r_[200., 0., 0.]
|
||||
M = Utils.ndgrid(x-25.,y, np.r_[0.])
|
||||
N = Utils.ndgrid(x+25.,y, np.r_[0.])
|
||||
|
||||
times = np.arange(10)*1e-3 + 1e-3
|
||||
rx = SIP.Rx.Dipole(M, N, times)
|
||||
src = SIP.Src.Dipole([rx], Aloc, Bloc)
|
||||
survey = SIP.Survey([src])
|
||||
colemap = [("eta", Maps.IdentityMap(mesh)), ("taui", Maps.IdentityMap(mesh))]
|
||||
problem = SIP.Problem3D_N(mesh, sigma=sigma, mapping=colemap)
|
||||
problem.Solver = MumpsSolver
|
||||
problem.pair(survey)
|
||||
mSynth = np.r_[eta, 1./tau]
|
||||
survey.makeSyntheticData(mSynth)
|
||||
# Now set up the problem to do some minimization
|
||||
dmis = DataMisfit.l2_DataMisfit(survey)
|
||||
reg = Regularization.Tikhonov(mesh)
|
||||
opt = Optimization.InexactGaussNewton(maxIterLS=20, maxIter=10, tolF=1e-6, tolX=1e-6, tolG=1e-6, maxIterCG=6)
|
||||
invProb = InvProblem.BaseInvProblem(dmis, reg, opt, beta=1e4)
|
||||
inv = Inversion.BaseInversion(invProb)
|
||||
|
||||
self.inv = inv
|
||||
self.reg = reg
|
||||
self.p = problem
|
||||
self.mesh = mesh
|
||||
self.m0 = mSynth
|
||||
self.survey = survey
|
||||
self.dmis = dmis
|
||||
|
||||
def test_misfit(self):
|
||||
derChk = lambda m: [self.survey.dpred(m), lambda mx: self.p.Jvec(self.m0, mx)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_adjoint(self):
|
||||
# Adjoint Test
|
||||
u = np.random.rand(self.mesh.nC*self.survey.nSrc)
|
||||
v = np.random.rand(self.mesh.nC*2)
|
||||
w = np.random.rand(self.survey.dobs.shape[0])
|
||||
wtJv = w.dot(self.p.Jvec(self.m0, v))
|
||||
vtJtw = v.dot(self.p.Jtvec(self.m0, w))
|
||||
passed = np.abs(wtJv - vtJtw) < 1e-8
|
||||
print 'Adjoint Test', np.abs(wtJv - vtJtw), passed
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_dataObj(self):
|
||||
derChk = lambda m: [self.dmis.eval(m), self.dmis.evalDeriv(m)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
class IPProblemTestsN_air(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
cs = 25.
|
||||
hx = [(cs,0, -1.3),(cs,21),(cs,0, 1.3)]
|
||||
hy = [(cs,0, -1.3),(cs,21),(cs,0, 1.3)]
|
||||
hz = [(cs,0, -1.3),(cs,20),(cs,0, 1.3)]
|
||||
mesh = Mesh.TensorMesh([hx, hy, hz],x0="CCC")
|
||||
blkind0 = Utils.ModelBuilder.getIndicesSphere(np.r_[-100., -100., -200.], 75., mesh.gridCC)
|
||||
blkind1 = Utils.ModelBuilder.getIndicesSphere(np.r_[100., 100., -200.], 75., mesh.gridCC)
|
||||
sigma = np.ones(mesh.nC)*1e-2
|
||||
airind = mesh.gridCC[:,2]>0.
|
||||
sigma[airind] = 1e-8
|
||||
eta = np.zeros(mesh.nC)
|
||||
tau = np.ones_like(sigma)*1.
|
||||
eta[blkind0] = 0.1
|
||||
eta[blkind1] = 0.1
|
||||
tau[blkind0] = 0.1
|
||||
tau[blkind1] = 0.01
|
||||
|
||||
actmapeta = Maps.InjectActiveCells(mesh, ~airind, 0.)
|
||||
actmaptau = Maps.InjectActiveCells(mesh, ~airind, 1.)
|
||||
|
||||
x = mesh.vectorCCx[(mesh.vectorCCx>-155.)&(mesh.vectorCCx<155.)]
|
||||
y = mesh.vectorCCx[(mesh.vectorCCy>-155.)&(mesh.vectorCCy<155.)]
|
||||
Aloc = np.r_[-200., 0., 0.]
|
||||
Bloc = np.r_[200., 0., 0.]
|
||||
M = Utils.ndgrid(x-25.,y, np.r_[0.])
|
||||
N = Utils.ndgrid(x+25.,y, np.r_[0.])
|
||||
|
||||
times = np.arange(10)*1e-3 + 1e-3
|
||||
rx = SIP.Rx.Dipole(M, N, times)
|
||||
src = SIP.Src.Dipole([rx], Aloc, Bloc)
|
||||
survey = SIP.Survey([src])
|
||||
colemap = [("eta", Maps.IdentityMap(mesh)*actmapeta), ("taui", Maps.IdentityMap(mesh)*actmaptau)]
|
||||
problem = SIP.Problem3D_N(mesh, sigma=sigma, mapping=colemap)
|
||||
problem.Solver = MumpsSolver
|
||||
problem.pair(survey)
|
||||
mSynth = np.r_[eta[~airind], 1./tau[~airind]]
|
||||
survey.makeSyntheticData(mSynth)
|
||||
# Now set up the problem to do some minimization
|
||||
dmis = DataMisfit.l2_DataMisfit(survey)
|
||||
regmap = Maps.IdentityMap(nP=int(mSynth[~airind].size*2))
|
||||
reg = SIP.MultiRegularization(mesh, mapping=regmap, nModels=2, indActive=~airind)
|
||||
opt = Optimization.InexactGaussNewton(maxIterLS=20, maxIter=10, tolF=1e-6, tolX=1e-6, tolG=1e-6, maxIterCG=6)
|
||||
invProb = InvProblem.BaseInvProblem(dmis, reg, opt, beta=1e4)
|
||||
inv = Inversion.BaseInversion(invProb)
|
||||
|
||||
self.inv = inv
|
||||
self.reg = reg
|
||||
self.p = problem
|
||||
self.mesh = mesh
|
||||
self.m0 = mSynth
|
||||
self.survey = survey
|
||||
self.dmis = dmis
|
||||
|
||||
def test_misfit(self):
|
||||
derChk = lambda m: [self.survey.dpred(m), lambda mx: self.p.Jvec(self.m0, mx)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_adjoint(self):
|
||||
# Adjoint Test
|
||||
u = np.random.rand(self.mesh.nC*self.survey.nSrc)
|
||||
v = np.random.rand(self.mesh.nC)
|
||||
w = np.random.rand(self.survey.dobs.shape[0])
|
||||
wtJv = w.dot(self.p.Jvec(self.m0, v))
|
||||
vtJtw = v.dot(self.p.Jtvec(self.m0, w))
|
||||
passed = np.abs(wtJv - vtJtw) < 1e-8
|
||||
print 'Adjoint Test', np.abs(wtJv - vtJtw), passed
|
||||
self.assertTrue(passed)
|
||||
|
||||
def test_dataObj(self):
|
||||
derChk = lambda m: [self.dmis.eval(m), self.dmis.evalDeriv(m)]
|
||||
passed = Tests.checkDerivative(derChk, self.m0, plotIt=False, num=3)
|
||||
self.assertTrue(passed)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -10,7 +10,9 @@ except ImportError, e:
|
||||
MumpsSolver = SolverLU
|
||||
|
||||
|
||||
def halfSpaceProblemAnaDiff(meshType, sig_half=1e-2, rxOffset=50., bounds=[1e-5,1e-3], showIt=False):
|
||||
def halfSpaceProblemAnaDiff(meshType, sig_half=1e-2, rxOffset=50., bounds=None, showIt=False):
|
||||
if bounds is None:
|
||||
bounds = [1e-5,1e-3]
|
||||
if meshType == 'CYL':
|
||||
cs, ncx, ncz, npad = 5., 30, 10, 15
|
||||
hx = [(cs,ncx), (cs,npad,1.3)]
|
||||
|
||||
@@ -1,353 +0,0 @@
|
||||
import numpy as np
|
||||
import unittest
|
||||
from SimPEG.Utils import mkvc
|
||||
from SimPEG import Mesh, Tests
|
||||
import unittest
|
||||
|
||||
test1D = True
|
||||
test2D = True
|
||||
test3D = False
|
||||
|
||||
call1 = lambda fun, xyz: fun(xyz)
|
||||
call2 = lambda fun, xyz: fun(xyz[:, 0], xyz[:, -1])
|
||||
call3 = lambda fun, xyz: fun(xyz[:, 0], xyz[:, 1], xyz[:, 2])
|
||||
cart_row2 = lambda g, xfun, yfun: np.c_[call2(xfun, g), call2(yfun, g)]
|
||||
cart_row3 = lambda g, xfun, yfun, zfun: np.c_[call3(xfun, g), call3(yfun, g), call3(zfun, g)]
|
||||
cartF2 = lambda M, fx, fy: np.vstack((cart_row2(M.gridFx, fx, fy), cart_row2(M.gridFy, fx, fy)))
|
||||
cartF2Cyl = lambda M, fx, fy: np.vstack((cart_row2(M.gridFx, fx, fy), cart_row2(M.gridFz, fx, fy)))
|
||||
cartE2 = lambda M, ex, ey: np.vstack((cart_row2(M.gridEx, ex, ey), cart_row2(M.gridEy, ex, ey)))
|
||||
cartE2Cyl = lambda M, ex, ey: cart_row2(M.gridEy, ex, ey)
|
||||
cartF3 = lambda M, fx, fy, fz: np.vstack((cart_row3(M.gridFx, fx, fy, fz), cart_row3(M.gridFy, fx, fy, fz), cart_row3(M.gridFz, fx, fy, fz)))
|
||||
cartE3 = lambda M, ex, ey, ez: np.vstack((cart_row3(M.gridEx, ex, ey, ez), cart_row3(M.gridEy, ex, ey, ez), cart_row3(M.gridEz, ex, ey, ez)))
|
||||
|
||||
TOL = 1e-7
|
||||
|
||||
if test1D:
|
||||
class TestInterpolationMesh2Mesh_Tensor1D(Tests.OrderTest):
|
||||
|
||||
name = 'Mesh2Mesh Tensor1D'
|
||||
meshSizes = [8, 16, 32]
|
||||
meshTypes = ['uniformTensorMesh']
|
||||
meshDimension = 1
|
||||
|
||||
def getError(self):
|
||||
funX = lambda x: np.cos(2*np.pi*x)
|
||||
|
||||
mesh2, _ = self.makeMesh(self.M.nC-1, meshType=self._meshType, meshDimension=self.meshDimension )
|
||||
ana = call1(funX, getattr(mesh2, 'grid%s'%self.type))
|
||||
|
||||
v = call1(funX, getattr(self.M, 'grid%s'%self.type))
|
||||
P = self.M.getInterpolationMatMesh2Mesh(mesh2, locType=self.type)
|
||||
num = P*v
|
||||
|
||||
return np.linalg.norm((num - ana), np.inf)
|
||||
|
||||
def test_orderCC_1D(self):
|
||||
self.type = 'CC'
|
||||
self.name = 'Mesh2Mesh Tensor1D: CC'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderN_1D(self):
|
||||
self.type = 'N'
|
||||
self.name = 'Mesh2Mesh Tensor1D: N'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderEx_1D(self):
|
||||
self.type = 'Ex'
|
||||
self.name = 'Mesh2Mesh Tensor1D: Ex'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderFx_1D(self):
|
||||
self.type = 'Fx'
|
||||
self.name = 'Mesh2Mesh Tensor1D: Fx'
|
||||
self.orderTest()
|
||||
|
||||
if test2D:
|
||||
class TestInterpolationMesh2Mesh_Tensor2D(Tests.OrderTest):
|
||||
|
||||
name = 'Mesh2Mesh Tensor2D'
|
||||
meshSizes = [4, 8, 16]
|
||||
meshTypes = ['uniformTensorMesh']
|
||||
meshDimension = 2
|
||||
|
||||
def getError(self):
|
||||
funX = lambda x, y: np.cos(2*np.pi*y)
|
||||
funY = lambda x, y: np.cos(2*np.pi*x)
|
||||
|
||||
mesh2, _ = self.makeMesh(self.M.nC-1, meshType=self._meshType, meshDimension=self.meshDimension )
|
||||
|
||||
if 'x' in self.type:
|
||||
ana = call2(funX, getattr(mesh2, 'grid%s'%self.type))
|
||||
elif 'y' in self.type:
|
||||
ana = call2(funY, getattr(mesh2, 'grid%s'%self.type))
|
||||
elif 'F' in self.type:
|
||||
ana = cartF2(mesh2, funX, funY)
|
||||
ana = mesh2.projectFaceVector(ana)
|
||||
elif 'E' in self.type:
|
||||
ana = cartE2(mesh2, funX, funY)
|
||||
ana = mesh2.projectEdgeVector(ana)
|
||||
else:
|
||||
ana = call2(funX, getattr(mesh2, 'grid%s'%self.type))
|
||||
|
||||
|
||||
if 'F' in self.type:
|
||||
v = cartF2(self.M, funX, funY)
|
||||
if 'x' in self.type or 'y' in self.type:
|
||||
v = self.M.projectFaceVector(v)
|
||||
else:
|
||||
v = mkvc(v)
|
||||
elif 'E' in self.type:
|
||||
v = cartE2(self.M, funX, funY)
|
||||
if 'x' in self.type or 'y' in self.type:
|
||||
v = self.M.projectEdgeVector(v)
|
||||
else:
|
||||
v = mkvc(v)
|
||||
elif 'CC' == self.type:
|
||||
v = call2(funX, self.M.gridCC)
|
||||
elif 'N' == self.type:
|
||||
v = call2(funX, self.M.gridN)
|
||||
|
||||
P = self.M.getInterpolationMatMesh2Mesh(mesh2, locType=self.type)
|
||||
# print P.shape, v.shape
|
||||
num = P*v
|
||||
|
||||
return np.linalg.norm((num - ana), np.inf)
|
||||
|
||||
def test_orderCC_2D(self):
|
||||
self.type = 'CC'
|
||||
self.name = 'Mesh2Mesh Tensor2D: CC'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderN_2D(self):
|
||||
self.type = 'N'
|
||||
self.name = 'Mesh2Mesh Tensor2D: N'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderE_2D(self):
|
||||
self.type = 'E'
|
||||
self.name = 'Mesh2Mesh Tensor2D: E'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderEx_2D(self):
|
||||
self.type = 'Ex'
|
||||
self.name = 'Mesh2Mesh Tensor2D: Ex'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderEy_2D(self):
|
||||
self.type = 'Ey'
|
||||
self.name = 'Mesh2Mesh Tensor2D: Ey'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderF_2D(self):
|
||||
self.type = 'F'
|
||||
self.name = 'Mesh2Mesh Tensor2D: F'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderFx_2D(self):
|
||||
self.type = 'Fx'
|
||||
self.name = 'Mesh2Mesh Tensor2D: Fx'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderFy_2D(self):
|
||||
self.type = 'Fy'
|
||||
self.name = 'Mesh2Mesh Tensor2D: Fy'
|
||||
self.orderTest()
|
||||
|
||||
class TestInterpolationMesh2Mesh_Cyl(Tests.OrderTest):
|
||||
|
||||
name = 'Mesh2Mesh Cyl'
|
||||
meshSizes = [4, 8, 16]
|
||||
meshTypes = ['uniformCylMesh']
|
||||
meshDimension = 2
|
||||
|
||||
def getError(self):
|
||||
funX = lambda x, y: np.cos(2*np.pi*y)
|
||||
funY = lambda x, y: np.cos(2*np.pi*x)
|
||||
|
||||
mesh2, _ = self.makeMesh(self.M.nC-1, meshType=self._meshType, meshDimension=self.meshDimension )
|
||||
|
||||
if 'x' in self.type:
|
||||
ana = call2(funX, getattr(mesh2, 'grid%s'%self.type))
|
||||
elif 'y' in self.type:
|
||||
ana = call2(funY, getattr(mesh2, 'grid%s'%self.type))
|
||||
elif 'z' in self.type:
|
||||
ana = call2(funY, getattr(mesh2, 'grid%s'%self.type))
|
||||
elif 'F' in self.type:
|
||||
ana = cartF2Cyl(mesh2, funX, funY)
|
||||
ana = np.c_[ana[:,0], np.zeros_like(ana[:,0]), ana[:,1]]
|
||||
ana = mesh2.projectFaceVector(ana)
|
||||
elif 'E' in self.type:
|
||||
ana = cartE2Cyl(mesh2, funX, funY)
|
||||
ana = np.c_[np.zeros_like(ana[:,1]),ana[:,1],np.zeros_like(ana[:,1])]
|
||||
ana = mesh2.projectEdgeVector(ana)
|
||||
else:
|
||||
ana = call2(funX, getattr(mesh2, 'grid%s'%self.type))
|
||||
|
||||
|
||||
if 'F' in self.type:
|
||||
v = cartF2Cyl(self.M, funX, funY)
|
||||
v = np.c_[v[:,0], np.zeros_like(v[:,0]),v[:,1]]
|
||||
if 'x' in self.type or 'z' in self.type:
|
||||
v = self.M.projectFaceVector(v)
|
||||
else:
|
||||
v = np.c_[v[:,0], v[:,2]]
|
||||
v = mkvc(v)
|
||||
elif 'E' in self.type:
|
||||
v = cartE2Cyl(self.M, funX, funY)
|
||||
v = np.c_[np.zeros_like(v[:,1]), v[:,1],np.zeros_like(v[:,1])]
|
||||
v = self.M.projectEdgeVector(v)
|
||||
|
||||
elif 'CC' == self.type:
|
||||
v = call2(funX, self.M.gridCC)
|
||||
elif 'N' == self.type:
|
||||
v = call2(funX, self.M.gridN)
|
||||
|
||||
P = self.M.getInterpolationMatMesh2Mesh(mesh2, locType=self.type)
|
||||
num = P*v
|
||||
|
||||
return np.linalg.norm((num - ana), np.inf)
|
||||
|
||||
def test_orderCC_Cyl(self):
|
||||
self.type = 'CC'
|
||||
self.name = 'Mesh2Mesh Tensor2D: CC'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderN_Cyl(self):
|
||||
self.type = 'N'
|
||||
self.name = 'Mesh2Mesh Tensor2D: N'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderE_Cyl(self):
|
||||
self.type = 'E'
|
||||
self.name = 'Mesh2Mesh Tensor2D: E'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderEy_Cyl(self):
|
||||
self.type = 'Ey'
|
||||
self.name = 'Mesh2Mesh Tensor2D: Ey'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderF_Cyl(self):
|
||||
self.type = 'F'
|
||||
self.name = 'Mesh2Mesh Tensor2D: F'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderFx_Cyl(self):
|
||||
self.type = 'Fx'
|
||||
self.name = 'Mesh2Mesh Tensor2D: Fx'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderFz_Cyl(self):
|
||||
self.type = 'Fz'
|
||||
self.name = 'Mesh2Mesh Tensor2D: Fz'
|
||||
self.orderTest()
|
||||
|
||||
if test3D:
|
||||
class TestInterpolationMesh2Mesh_Tensor3D(Tests.OrderTest):
|
||||
|
||||
name = 'Mesh2Mesh Tensor3D'
|
||||
meshSizes = [4, 8, 16]
|
||||
meshTypes = ['uniformTensorMesh']
|
||||
meshDimension = 3
|
||||
|
||||
def getError(self):
|
||||
funX = lambda x, y, z: np.cos(2*np.pi*y)
|
||||
funY = lambda x, y, z: np.cos(2*np.pi*z)
|
||||
funZ = lambda x, y, z: np.cos(2*np.pi*x)
|
||||
|
||||
mesh2, _ = self.makeMesh(self.M.nC-1, meshType=self._meshType, meshDimension=self.meshDimension )
|
||||
|
||||
if 'x' in self.type:
|
||||
ana = call3(funX, getattr(mesh2, 'grid%s'%self.type))
|
||||
elif 'y' in self.type:
|
||||
ana = call3(funY, getattr(mesh2, 'grid%s'%self.type))
|
||||
elif 'z' in self.type:
|
||||
ana = call3(funZ, getattr(mesh2, 'grid%s'%self.type))
|
||||
elif 'F' in self.type:
|
||||
ana = cartF3(mesh2, funX, funY, funZ)
|
||||
ana = mesh2.projectFaceVector(ana)
|
||||
elif 'E' in self.type:
|
||||
ana = cartE3(mesh2, funX, funY, funZ)
|
||||
ana = mesh2.projectFaceVector(ana)
|
||||
else:
|
||||
ana = call3(funX, getattr(mesh2, 'grid%s'%self.type))
|
||||
|
||||
|
||||
if 'F' in self.type:
|
||||
v = cartF3(self.M, funX, funY, funZ)
|
||||
if 'x' in self.type or 'y' in self.type or 'z' in self.type:
|
||||
v = self.M.projectFaceVector(v)
|
||||
else:
|
||||
v = mkvc(v)
|
||||
elif 'E' in self.type:
|
||||
v = cartE3(self.M, funX, funY, funZ)
|
||||
if 'x' in self.type or 'y' in self.type or 'z' in self.type:
|
||||
v = self.M.projectFaceVector(v)
|
||||
else:
|
||||
v = mkvc(v)
|
||||
elif 'CC' == self.type:
|
||||
v = call3(funX, self.M.gridCC)
|
||||
elif 'N' == self.type:
|
||||
v = call3(funX, self.M.gridN)
|
||||
|
||||
P = self.M.getInterpolationMatMesh2Mesh(mesh2, locType=self.type)
|
||||
# print P.shape, v.shape
|
||||
num = P*v
|
||||
|
||||
return np.linalg.norm((num - ana), np.inf)
|
||||
|
||||
def test_orderCC_3D(self):
|
||||
self.type = 'CC'
|
||||
self.name = 'Mesh2Mesh Tensor3D: CC'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderN_3D(self):
|
||||
self.type = 'N'
|
||||
self.name = 'Mesh2Mesh Tensor3D: N'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderE_3D(self):
|
||||
self.type = 'E'
|
||||
self.name = 'Mesh2Mesh Tensor3D: E'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderEx_3D(self):
|
||||
self.type = 'Ex'
|
||||
self.name = 'Mesh2Mesh Tensor3D: Ex'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderEy_3D(self):
|
||||
self.type = 'Ey'
|
||||
self.name = 'Mesh2Mesh Tensor3D: Ey'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderEz_3D(self):
|
||||
self.type = 'Ez'
|
||||
self.name = 'Mesh2Mesh Tensor3D: Ez'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderF_3D(self):
|
||||
self.type = 'F'
|
||||
self.name = 'Mesh2Mesh Tensor3D: F'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderFx_3D(self):
|
||||
self.type = 'Fx'
|
||||
self.name = 'Mesh2Mesh Tensor3D: Fx'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderFy_3D(self):
|
||||
self.type = 'Fy'
|
||||
self.name = 'Mesh2Mesh Tensor3D: Fy'
|
||||
self.orderTest()
|
||||
|
||||
def test_orderFz_3D(self):
|
||||
self.type = 'Fz'
|
||||
self.name = 'Mesh2Mesh Tensor3D: Fz'
|
||||
self.orderTest()
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,411 @@
|
||||
import numpy as np
|
||||
import scipy.sparse as sp
|
||||
import unittest
|
||||
import matplotlib.pyplot as plt
|
||||
from SimPEG import *
|
||||
|
||||
MESHTYPES = ['uniformTensorMesh']
|
||||
|
||||
def getxBCyBC_CC(mesh, alpha, beta, gamma):
|
||||
# def getxBCyBC(mesh, alpha, beta, gamma):
|
||||
"""
|
||||
This is a subfunction generating mixed-boundary condition:
|
||||
|
||||
.. math::
|
||||
|
||||
\nabla \cdot \vec{j} = -\nabla \cdot \vec{j}_s = q
|
||||
|
||||
\rho \vec{j} = -\nabla \phi \phi
|
||||
|
||||
\alpha \phi + \beta \frac{\partial \phi}{\partial r} = \gamma \ at \ r = \partial \Omega
|
||||
|
||||
xBC = f_1(\alpha, \beta, \gamma)
|
||||
yBC = f(\alpha, \beta, \gamma)
|
||||
|
||||
Computes xBC and yBC for cell-centered discretizations
|
||||
"""
|
||||
if mesh.dim == 1: #1D
|
||||
if (len(alpha) != 2 or len(beta) != 2 or len(gamma) != 2):
|
||||
raise Exception("Lenght of list, alpha should be 2")
|
||||
fCCxm,fCCxp = mesh.cellBoundaryInd
|
||||
nBC = fCCxm.sum()+fCCxp.sum()
|
||||
h_xm, h_xp = mesh.gridCC[fCCxm], mesh.gridCC[fCCxp]
|
||||
|
||||
alpha_xm, beta_xm, gamma_xm = alpha[0], beta[0], gamma[0]
|
||||
alpha_xp, beta_xp, gamma_xp = alpha[1], beta[1], gamma[1]
|
||||
|
||||
# h_xm, h_xp = mesh.gridCC[fCCxm], mesh.gridCC[fCCxp]
|
||||
h_xm, h_xp = mesh.hx[0], mesh.hx[-1]
|
||||
|
||||
a_xm = gamma_xm/(0.5*alpha_xm-beta_xm/h_xm)
|
||||
b_xm = (0.5*alpha_xm+beta_xm/h_xm)/(0.5*alpha_xm-beta_xm/h_xm)
|
||||
a_xp = gamma_xp/(0.5*alpha_xp-beta_xp/h_xp)
|
||||
b_xp = (0.5*alpha_xp+beta_xp/h_xp)/(0.5*alpha_xp-beta_xp/h_xp)
|
||||
|
||||
xBC_xm = 0.5*a_xm
|
||||
xBC_xp = 0.5*a_xp/b_xp
|
||||
yBC_xm = 0.5*(1.-b_xm)
|
||||
yBC_xp = 0.5*(1.-1./b_xp)
|
||||
|
||||
xBC = np.r_[xBC_xm, xBC_xp]
|
||||
yBC = np.r_[yBC_xm, yBC_xp]
|
||||
|
||||
elif mesh.dim == 2: #2D
|
||||
if (len(alpha) != 4 or len(beta) != 4 or len(gamma) != 4):
|
||||
raise Exception("Lenght of list, alpha should be 4")
|
||||
|
||||
fxm,fxp,fym,fyp = mesh.faceBoundaryInd
|
||||
nBC = fxm.sum()+fxp.sum()+fxm.sum()+fxp.sum()
|
||||
|
||||
alpha_xm, beta_xm, gamma_xm = alpha[0], beta[0], gamma[0]
|
||||
alpha_xp, beta_xp, gamma_xp = alpha[1], beta[1], gamma[1]
|
||||
alpha_ym, beta_ym, gamma_ym = alpha[2], beta[2], gamma[2]
|
||||
alpha_yp, beta_yp, gamma_yp = alpha[3], beta[3], gamma[3]
|
||||
|
||||
# h_xm, h_xp = mesh.gridCC[fCCxm,0], mesh.gridCC[fCCxp,0]
|
||||
# h_ym, h_yp = mesh.gridCC[fCCym,1], mesh.gridCC[fCCyp,1]
|
||||
|
||||
h_xm, h_xp = mesh.hx[0]*np.ones_like(alpha_xm), mesh.hx[-1]*np.ones_like(alpha_xp)
|
||||
h_ym, h_yp = mesh.hy[0]*np.ones_like(alpha_ym), mesh.hy[-1]*np.ones_like(alpha_yp)
|
||||
|
||||
a_xm = gamma_xm/(0.5*alpha_xm-beta_xm/h_xm)
|
||||
b_xm = (0.5*alpha_xm+beta_xm/h_xm)/(0.5*alpha_xm-beta_xm/h_xm)
|
||||
a_xp = gamma_xp/(0.5*alpha_xp-beta_xp/h_xp)
|
||||
b_xp = (0.5*alpha_xp+beta_xp/h_xp)/(0.5*alpha_xp-beta_xp/h_xp)
|
||||
|
||||
a_ym = gamma_ym/(0.5*alpha_ym-beta_ym/h_ym)
|
||||
b_ym = (0.5*alpha_ym+beta_ym/h_ym)/(0.5*alpha_ym-beta_ym/h_ym)
|
||||
a_yp = gamma_yp/(0.5*alpha_yp-beta_yp/h_yp)
|
||||
b_yp = (0.5*alpha_yp+beta_yp/h_yp)/(0.5*alpha_yp-beta_yp/h_yp)
|
||||
|
||||
xBC_xm = 0.5*a_xm
|
||||
xBC_xp = 0.5*a_xp/b_xp
|
||||
yBC_xm = 0.5*(1.-b_xm)
|
||||
yBC_xp = 0.5*(1.-1./b_xp)
|
||||
xBC_ym = 0.5*a_ym
|
||||
xBC_yp = 0.5*a_yp/b_yp
|
||||
yBC_ym = 0.5*(1.-b_ym)
|
||||
yBC_yp = 0.5*(1.-1./b_yp)
|
||||
|
||||
sortindsfx = np.argsort(np.r_[np.arange(mesh.nFx)[fxm], np.arange(mesh.nFx)[fxp]])
|
||||
sortindsfy = np.argsort(np.r_[np.arange(mesh.nFy)[fym], np.arange(mesh.nFy)[fyp]])
|
||||
|
||||
xBC_x = np.r_[xBC_xm, xBC_xp][sortindsfx]
|
||||
xBC_y = np.r_[xBC_ym, xBC_yp][sortindsfy]
|
||||
yBC_x = np.r_[yBC_xm, yBC_xp][sortindsfx]
|
||||
yBC_y = np.r_[yBC_ym, yBC_yp][sortindsfy]
|
||||
|
||||
xBC = np.r_[xBC_x, xBC_y]
|
||||
yBC = np.r_[yBC_x, yBC_y]
|
||||
|
||||
elif mesh.dim == 3: #3D
|
||||
if (len(alpha) != 6 or len(beta) != 6 or len(gamma) != 6):
|
||||
raise Exception("Lenght of list, alpha should be 6")
|
||||
# fCCxm,fCCxp,fCCym,fCCyp,fCCzm,fCCzp = mesh.cellBoundaryInd
|
||||
fxm,fxp,fym,fyp,fzm,fzp = mesh.faceBoundaryInd
|
||||
nBC = fxm.sum()+fxp.sum()+fxm.sum()+fxp.sum()
|
||||
|
||||
alpha_xm, beta_xm, gamma_xm = alpha[0], beta[0], gamma[0]
|
||||
alpha_xp, beta_xp, gamma_xp = alpha[1], beta[1], gamma[1]
|
||||
alpha_ym, beta_ym, gamma_ym = alpha[2], beta[2], gamma[2]
|
||||
alpha_yp, beta_yp, gamma_yp = alpha[3], beta[3], gamma[3]
|
||||
alpha_zm, beta_zm, gamma_zm = alpha[4], beta[4], gamma[4]
|
||||
alpha_zp, beta_zp, gamma_zp = alpha[5], beta[5], gamma[5]
|
||||
|
||||
# h_xm, h_xp = mesh.gridCC[fCCxm,0], mesh.gridCC[fCCxp,0]
|
||||
# h_ym, h_yp = mesh.gridCC[fCCym,1], mesh.gridCC[fCCyp,1]
|
||||
# h_zm, h_zp = mesh.gridCC[fCCzm,2], mesh.gridCC[fCCzp,2]
|
||||
|
||||
h_xm, h_xp = mesh.hx[0]*np.ones_like(alpha_xm), mesh.hx[-1]*np.ones_like(alpha_xp)
|
||||
h_ym, h_yp = mesh.hy[0]*np.ones_like(alpha_ym), mesh.hy[-1]*np.ones_like(alpha_yp)
|
||||
h_zm, h_zp = mesh.hz[0]*np.ones_like(alpha_zm), mesh.hz[-1]*np.ones_like(alpha_zp)
|
||||
|
||||
a_xm = gamma_xm/(0.5*alpha_xm-beta_xm/h_xm)
|
||||
b_xm = (0.5*alpha_xm+beta_xm/h_xm)/(0.5*alpha_xm-beta_xm/h_xm)
|
||||
a_xp = gamma_xp/(0.5*alpha_xp-beta_xp/h_xp)
|
||||
b_xp = (0.5*alpha_xp+beta_xp/h_xp)/(0.5*alpha_xp-beta_xp/h_xp)
|
||||
|
||||
a_ym = gamma_ym/(0.5*alpha_ym-beta_ym/h_ym)
|
||||
b_ym = (0.5*alpha_ym+beta_ym/h_ym)/(0.5*alpha_ym-beta_ym/h_ym)
|
||||
a_yp = gamma_yp/(0.5*alpha_yp-beta_yp/h_yp)
|
||||
b_yp = (0.5*alpha_yp+beta_yp/h_yp)/(0.5*alpha_yp-beta_yp/h_yp)
|
||||
|
||||
a_zm = gamma_zm/(0.5*alpha_zm-beta_zm/h_zm)
|
||||
b_zm = (0.5*alpha_zm+beta_zm/h_zm)/(0.5*alpha_zm-beta_zm/h_zm)
|
||||
a_zp = gamma_zp/(0.5*alpha_zp-beta_zp/h_zp)
|
||||
b_zp = (0.5*alpha_zp+beta_zp/h_zp)/(0.5*alpha_zp-beta_zp/h_zp)
|
||||
|
||||
xBC_xm = 0.5*a_xm
|
||||
xBC_xp = 0.5*a_xp/b_xp
|
||||
yBC_xm = 0.5*(1.-b_xm)
|
||||
yBC_xp = 0.5*(1.-1./b_xp)
|
||||
xBC_ym = 0.5*a_ym
|
||||
xBC_yp = 0.5*a_yp/b_yp
|
||||
yBC_ym = 0.5*(1.-b_ym)
|
||||
yBC_yp = 0.5*(1.-1./b_yp)
|
||||
xBC_zm = 0.5*a_zm
|
||||
xBC_zp = 0.5*a_zp/b_zp
|
||||
yBC_zm = 0.5*(1.-b_zm)
|
||||
yBC_zp = 0.5*(1.-1./b_zp)
|
||||
|
||||
sortindsfx = np.argsort(np.r_[np.arange(mesh.nFx)[fxm], np.arange(mesh.nFx)[fxp]])
|
||||
sortindsfy = np.argsort(np.r_[np.arange(mesh.nFy)[fym], np.arange(mesh.nFy)[fyp]])
|
||||
sortindsfz = np.argsort(np.r_[np.arange(mesh.nFz)[fzm], np.arange(mesh.nFz)[fzp]])
|
||||
|
||||
xBC_x = np.r_[xBC_xm, xBC_xp][sortindsfx]
|
||||
xBC_y = np.r_[xBC_ym, xBC_yp][sortindsfy]
|
||||
xBC_z = np.r_[xBC_zm, xBC_zp][sortindsfz]
|
||||
|
||||
yBC_x = np.r_[yBC_xm, yBC_xp][sortindsfx]
|
||||
yBC_y = np.r_[yBC_ym, yBC_yp][sortindsfy]
|
||||
yBC_z = np.r_[yBC_zm, yBC_zp][sortindsfz]
|
||||
|
||||
xBC = np.r_[xBC_x, xBC_y, xBC_z]
|
||||
yBC = np.r_[yBC_x, yBC_y, yBC_z]
|
||||
|
||||
return xBC, yBC
|
||||
|
||||
class Test1D_InhomogeneousMixed(Tests.OrderTest):
|
||||
name = "1D - Mixed"
|
||||
meshTypes = MESHTYPES
|
||||
meshDimension = 1
|
||||
expectedOrders = 2
|
||||
meshSizes = [4, 8, 16, 32]
|
||||
|
||||
def getError(self):
|
||||
#Test function
|
||||
phi_fun = lambda x: np.cos(np.pi*x)
|
||||
j_fun = lambda x: np.pi*np.sin(np.pi*x)
|
||||
phi_deriv = lambda x: -j_fun(x)
|
||||
q_fun = lambda x: (np.pi**2)*np.cos(np.pi*x)
|
||||
|
||||
xc_ana = phi_fun(self.M.gridCC)
|
||||
q_ana = q_fun(self.M.gridCC)
|
||||
j_ana = j_fun(self.M.gridFx)
|
||||
|
||||
# Get boundary locations
|
||||
vecN = self.M.vectorNx
|
||||
vecC = self.M.vectorCCx
|
||||
|
||||
# Setup Mixed B.C (alpha, beta, gamma)
|
||||
alpha_xm, alpha_xp = 1., 1.
|
||||
beta_xm, beta_xp = 1., 1.
|
||||
alpha = np.r_[alpha_xm, alpha_xp]
|
||||
beta = np.r_[beta_xm, beta_xp]
|
||||
vecN = self.M.vectorNx
|
||||
vecC = self.M.vectorCCx
|
||||
phi_bc = phi_fun(vecN[[0,-1]])
|
||||
phi_deriv_bc = phi_deriv(vecN[[0,-1]])
|
||||
gamma = alpha*phi_bc + beta*phi_deriv_bc
|
||||
x_BC, y_BC = getxBCyBC_CC(self.M, alpha, beta, gamma)
|
||||
|
||||
|
||||
sigma = np.ones(self.M.nC)
|
||||
Mfrho = self.M.getFaceInnerProduct(1./sigma)
|
||||
MfrhoI = self.M.getFaceInnerProduct(1./sigma, invMat=True)
|
||||
V = Utils.sdiag(self.M.vol)
|
||||
Div = V*self.M.faceDiv
|
||||
P_BC, B = self.M.getBCProjWF_simple()
|
||||
q = q_fun(self.M.gridCC)
|
||||
M = B*self.M.aveCC2F
|
||||
G = Div.T - P_BC*Utils.sdiag(y_BC)*M
|
||||
# Mrhoj = D.T V phi + P_BC*Utils.sdiag(y_BC)*M phi - P_BC*x_BC
|
||||
rhs = V*q + Div*MfrhoI*P_BC*x_BC
|
||||
A = Div*MfrhoI*G
|
||||
|
||||
if self.myTest == 'xc':
|
||||
#TODO: fix the null space
|
||||
Ainv = Solver(A)
|
||||
xc = Ainv*rhs
|
||||
err = np.linalg.norm((xc-xc_ana), np.inf)
|
||||
else:
|
||||
NotImplementedError
|
||||
return err
|
||||
|
||||
|
||||
def test_order(self):
|
||||
print "==== Testing Mixed boudary conduction for CC-problem ===="
|
||||
self.name = "1D"
|
||||
self.myTest = 'xc'
|
||||
self.orderTest()
|
||||
|
||||
class Test2D_InhomogeneousMixed(Tests.OrderTest):
|
||||
name = "2D - Mixed"
|
||||
meshTypes = MESHTYPES
|
||||
meshDimension = 2
|
||||
expectedOrders = 2
|
||||
meshSizes = [4, 8, 16, 32]
|
||||
|
||||
def getError(self):
|
||||
#Test function
|
||||
phi_fun = lambda x: np.cos(np.pi*x[:,0])*np.cos(np.pi*x[:,1])
|
||||
j_funX = lambda x: +np.pi*np.sin(np.pi*x[:,0])*np.cos(np.pi*x[:,1])
|
||||
j_funY = lambda x: +np.pi*np.cos(np.pi*x[:,0])*np.sin(np.pi*x[:,1])
|
||||
phideriv_funX = lambda x: -j_funX(x)
|
||||
phideriv_funY = lambda x: -j_funY(x)
|
||||
q_fun = lambda x: +2*(np.pi**2)*phi_fun(x)
|
||||
|
||||
xc_ana = phi_fun(self.M.gridCC)
|
||||
q_ana = q_fun(self.M.gridCC)
|
||||
jX_ana = j_funX(self.M.gridFx)
|
||||
jY_ana = j_funY(self.M.gridFy)
|
||||
j_ana = np.r_[jX_ana,jY_ana]
|
||||
|
||||
# Get boundary locations
|
||||
fxm,fxp,fym,fyp = self.M.faceBoundaryInd
|
||||
gBFxm = self.M.gridFx[fxm,:]
|
||||
gBFxp = self.M.gridFx[fxp,:]
|
||||
gBFym = self.M.gridFy[fym,:]
|
||||
gBFyp = self.M.gridFy[fyp,:]
|
||||
|
||||
# Setup Mixed B.C (alpha, beta, gamma)
|
||||
alpha_xm, alpha_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
|
||||
beta_xm, beta_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
|
||||
alpha_ym, alpha_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
|
||||
beta_ym, beta_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
|
||||
|
||||
phi_bc_xm, phi_bc_xp = phi_fun(gBFxm), phi_fun(gBFxp)
|
||||
phi_bc_ym, phi_bc_yp = phi_fun(gBFym), phi_fun(gBFyp)
|
||||
|
||||
phiderivX_bc_xm, phiderivX_bc_xp = phideriv_funX(gBFxm), phideriv_funX(gBFxp)
|
||||
phiderivY_bc_ym, phiderivY_bc_yp = phideriv_funY(gBFym), phideriv_funY(gBFyp)
|
||||
|
||||
gamma_fun = lambda alpha, beta, phi, phi_deriv: alpha*phi + beta*phi_deriv
|
||||
gamma_xm = gamma_fun(alpha_xm, beta_xm, phi_bc_xm, phiderivX_bc_xm)
|
||||
gamma_xp = gamma_fun(alpha_xp, beta_xp, phi_bc_xp, phiderivX_bc_xp)
|
||||
gamma_ym = gamma_fun(alpha_ym, beta_ym, phi_bc_ym, phiderivY_bc_ym)
|
||||
gamma_yp = gamma_fun(alpha_yp, beta_yp, phi_bc_yp, phiderivY_bc_yp)
|
||||
|
||||
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp]
|
||||
beta = [beta_xm, beta_xp, beta_ym, beta_yp]
|
||||
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp]
|
||||
|
||||
x_BC, y_BC = getxBCyBC_CC(self.M, alpha, beta, gamma)
|
||||
|
||||
|
||||
sigma = np.ones(self.M.nC)
|
||||
Mfrho = self.M.getFaceInnerProduct(1./sigma)
|
||||
MfrhoI = self.M.getFaceInnerProduct(1./sigma, invMat=True)
|
||||
V = Utils.sdiag(self.M.vol)
|
||||
Div = V*self.M.faceDiv
|
||||
P_BC, B = self.M.getBCProjWF_simple()
|
||||
q = q_fun(self.M.gridCC)
|
||||
M = B*self.M.aveCC2F
|
||||
G = Div.T - P_BC*Utils.sdiag(y_BC)*M
|
||||
rhs = V*q + Div*MfrhoI*P_BC*x_BC
|
||||
A = Div*MfrhoI*G
|
||||
|
||||
if self.myTest == 'xc':
|
||||
Ainv = Solver(A)
|
||||
xc = Ainv*rhs
|
||||
err = np.linalg.norm((xc-xc_ana), np.inf)
|
||||
else:
|
||||
NotImplementedError
|
||||
return err
|
||||
|
||||
|
||||
def test_order(self):
|
||||
print "==== Testing Mixed boudary conduction for CC-problem ===="
|
||||
self.name = "2D"
|
||||
self.myTest = 'xc'
|
||||
self.orderTest()
|
||||
|
||||
class Test3D_InhomogeneousMixed(Tests.OrderTest):
|
||||
name = "3D - Mixed"
|
||||
meshTypes = MESHTYPES
|
||||
meshDimension = 3
|
||||
expectedOrders = 2
|
||||
meshSizes = [4, 8, 16]
|
||||
|
||||
def getError(self):
|
||||
#Test function
|
||||
phi_fun = lambda x: np.cos(np.pi*x[:,0])*np.cos(np.pi*x[:,1])*np.cos(np.pi*x[:,2])
|
||||
j_funX = lambda x: +np.pi*np.sin(np.pi*x[:,0])*np.cos(np.pi*x[:,1])*np.cos(np.pi*x[:,2])
|
||||
j_funY = lambda x: +np.pi*np.cos(np.pi*x[:,0])*np.sin(np.pi*x[:,1])*np.cos(np.pi*x[:,2])
|
||||
j_funZ = lambda x: +np.pi*np.cos(np.pi*x[:,0])*np.cos(np.pi*x[:,1])*np.sin(np.pi*x[:,2])
|
||||
|
||||
phideriv_funX = lambda x: -j_funX(x)
|
||||
phideriv_funY = lambda x: -j_funY(x)
|
||||
phideriv_funZ = lambda x: -j_funZ(x)
|
||||
|
||||
q_fun = lambda x: 3*(np.pi**2)*phi_fun(x)
|
||||
|
||||
xc_ana = phi_fun(self.M.gridCC)
|
||||
q_ana = q_fun(self.M.gridCC)
|
||||
jX_ana = j_funX(self.M.gridFx)
|
||||
jY_ana = j_funY(self.M.gridFy)
|
||||
j_ana = np.r_[jX_ana,jY_ana,jY_ana]
|
||||
|
||||
# Get boundary locations
|
||||
fxm,fxp,fym,fyp,fzm,fzp = self.M.faceBoundaryInd
|
||||
gBFxm = self.M.gridFx[fxm,:]
|
||||
gBFxp = self.M.gridFx[fxp,:]
|
||||
gBFym = self.M.gridFy[fym,:]
|
||||
gBFyp = self.M.gridFy[fyp,:]
|
||||
gBFzm = self.M.gridFz[fzm,:]
|
||||
gBFzp = self.M.gridFz[fzp,:]
|
||||
|
||||
# Setup Mixed B.C (alpha, beta, gamma)
|
||||
alpha_xm, alpha_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
|
||||
beta_xm, beta_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
|
||||
alpha_ym, alpha_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
|
||||
beta_ym, beta_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
|
||||
alpha_zm, alpha_zp = np.ones_like(gBFzm[:,2]), np.ones_like(gBFzp[:,2])
|
||||
beta_zm, beta_zp = np.ones_like(gBFzm[:,2]), np.ones_like(gBFzp[:,2])
|
||||
|
||||
|
||||
phi_bc_xm, phi_bc_xp = phi_fun(gBFxm), phi_fun(gBFxp)
|
||||
phi_bc_ym, phi_bc_yp = phi_fun(gBFym), phi_fun(gBFyp)
|
||||
phi_bc_zm, phi_bc_zp = phi_fun(gBFzm), phi_fun(gBFzp)
|
||||
|
||||
phiderivX_bc_xm, phiderivX_bc_xp = phideriv_funX(gBFxm), phideriv_funX(gBFxp)
|
||||
phiderivY_bc_ym, phiderivY_bc_yp = phideriv_funY(gBFym), phideriv_funY(gBFyp)
|
||||
phiderivY_bc_zm, phiderivY_bc_zp = phideriv_funZ(gBFzm), phideriv_funZ(gBFzp)
|
||||
|
||||
gamma_fun = lambda alpha, beta, phi, phi_deriv: alpha*phi + beta*phi_deriv
|
||||
gamma_xm = gamma_fun(alpha_xm, beta_xm, phi_bc_xm, phiderivX_bc_xm)
|
||||
gamma_xp = gamma_fun(alpha_xp, beta_xp, phi_bc_xp, phiderivX_bc_xp)
|
||||
gamma_ym = gamma_fun(alpha_ym, beta_ym, phi_bc_ym, phiderivY_bc_ym)
|
||||
gamma_yp = gamma_fun(alpha_yp, beta_yp, phi_bc_yp, phiderivY_bc_yp)
|
||||
gamma_zm = gamma_fun(alpha_zm, beta_zm, phi_bc_zm, phiderivY_bc_zm)
|
||||
gamma_zp = gamma_fun(alpha_zp, beta_zp, phi_bc_zp, phiderivY_bc_zp)
|
||||
|
||||
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp, alpha_zm, alpha_zp]
|
||||
beta = [beta_xm, beta_xp, beta_ym, beta_yp, beta_zm, beta_zp]
|
||||
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp, gamma_zm, gamma_zp]
|
||||
|
||||
x_BC, y_BC = getxBCyBC_CC(self.M, alpha, beta, gamma)
|
||||
|
||||
|
||||
sigma = np.ones(self.M.nC)
|
||||
Mfrho = self.M.getFaceInnerProduct(1./sigma)
|
||||
MfrhoI = self.M.getFaceInnerProduct(1./sigma, invMat=True)
|
||||
V = Utils.sdiag(self.M.vol)
|
||||
Div = V*self.M.faceDiv
|
||||
P_BC, B = self.M.getBCProjWF_simple()
|
||||
q = q_fun(self.M.gridCC)
|
||||
M = B*self.M.aveCC2F
|
||||
G = Div.T - P_BC*Utils.sdiag(y_BC)*M
|
||||
rhs = V*q + Div*MfrhoI*P_BC*x_BC
|
||||
A = Div*MfrhoI*G
|
||||
|
||||
if self.myTest == 'xc':
|
||||
#TODO: fix the null space
|
||||
Ainv = Solver(A)
|
||||
xc = Ainv*rhs
|
||||
err = np.linalg.norm((xc-xc_ana), np.inf)
|
||||
else:
|
||||
NotImplementedError
|
||||
return err
|
||||
|
||||
|
||||
def test_order(self):
|
||||
print "==== Testing Mixed boudary conduction for CC-problem ===="
|
||||
self.name = "3D"
|
||||
self.myTest = 'xc'
|
||||
self.orderTest()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user