def appResNorm(sigmaHalf): nFreq = 26 m1d = Mesh.TensorMesh([[(100,5,1.5),(100.,10),(100,5,1.5)]], x0=['C']) sigma = np.zeros(m1d.nC) + sigmaHalf sigma[m1d.gridCC[:]>200] = 1e-8 # Calculate the analytic fields freqs = np.logspace(4,-4,nFreq) Z = [] for freq in freqs: Ed, Eu, Hd, Hu = NSEM.Utils.getEHfields(m1d,sigma,freq,np.array([200])) Z.append((Ed + Eu)/(Hd + Hu)) Zarr = np.concatenate(Z) app_r, app_p = NSEM.Utils.appResPhs(freqs,Zarr) return np.linalg.norm(np.abs(app_r - np.ones(nFreq)/sigmaHalf)) / np.log10(sigmaHalf)
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 run(plotIt=True): """ 1D FDEM and TDEM inversions =========================== This example is used in the paper Heagy et al 2016 (in prep) """ # Set up cylindrically symmeric mesh cs, ncx, ncz, npad = 10., 15, 25, 13 # padded cyl mesh hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hz], '00C') # Conductivity model layerz = np.r_[-200., -100.] layer = (mesh.vectorCCz >= layerz[0]) & (mesh.vectorCCz <= layerz[1]) active = mesh.vectorCCz < 0. sig_half = 1e-2 # Half-space conductivity sig_air = 1e-8 # Air conductivity sig_layer = 5e-2 # Layer conductivity sigma = np.ones(mesh.nCz)*sig_air sigma[active] = sig_half sigma[layer] = sig_layer # Mapping actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap mtrue = np.log(sigma[active]) # ----- FDEM problem & survey ----- rxlocs = Utils.ndgrid([np.r_[50.], np.r_[0], np.r_[0.]]) bzi = FDEM.Rx.Point_bSecondary(rxlocs, 'z', 'real') bzr = FDEM.Rx.Point_bSecondary(rxlocs, 'z', 'imag') freqs = np.logspace(2, 3, 5) srcLoc = np.array([0., 0., 0.]) print('min skin depth = ', 500./np.sqrt(freqs.max() * sig_half), 'max skin depth = ', 500./np.sqrt(freqs.min() * sig_half)) print('max x ', mesh.vectorCCx.max(), 'min z ', mesh.vectorCCz.min(), 'max z ', mesh.vectorCCz.max()) srcList = [] [srcList.append(FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc, orientation='Z')) for freq in freqs] surveyFD = FDEM.Survey(srcList) prbFD = FDEM.Problem3D_b(mesh, mapping=mapping) prbFD.pair(surveyFD) std = 0.03 surveyFD.makeSyntheticData(mtrue, std) surveyFD.eps = np.linalg.norm(surveyFD.dtrue)*1e-5 # FDEM inversion np.random.seed(1) dmisfit = DataMisfit.l2_DataMisfit(surveyFD) regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = Regularization.Simple(regMesh) opt = Optimization.InexactGaussNewton(maxIterCG=10) invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt) # Inversion Directives beta = Directives.BetaSchedule(coolingFactor=4, coolingRate=3) betaest = Directives.BetaEstimate_ByEig(beta0_ratio=2.) target = Directives.TargetMisfit() inv = Inversion.BaseInversion(invProb, directiveList=[beta, betaest, target]) m0 = np.log(np.ones(mtrue.size)*sig_half) reg.alpha_s = 5e-1 reg.alpha_x = 1. prbFD.counter = opt.counter = Utils.Counter() opt.remember('xc') moptFD = inv.run(m0) # TDEM problem times = np.logspace(-4, np.log10(2e-3), 10) print('min diffusion distance ', 1.28*np.sqrt(times.min()/(sig_half*mu_0)), 'max diffusion distance ', 1.28*np.sqrt(times.max()/(sig_half*mu_0))) rx = TDEM.Rx(rxlocs, times, 'bz') src = TDEM.Src.MagDipole([rx], waveform=TDEM.Src.StepOffWaveform(), loc=srcLoc) # same src location as FDEM problem surveyTD = TDEM.Survey([src]) prbTD = TDEM.Problem3D_b(mesh, mapping=mapping) prbTD.timeSteps = [(5e-5, 10), (1e-4, 10), (5e-4, 10)] prbTD.pair(surveyTD) prbTD.Solver = SolverLU std = 0.03 surveyTD.makeSyntheticData(mtrue, std) surveyTD.std = std surveyTD.eps = np.linalg.norm(surveyTD.dtrue)*1e-5 # TDEM inversion dmisfit = DataMisfit.l2_DataMisfit(surveyTD) regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = Regularization.Simple(regMesh) opt = Optimization.InexactGaussNewton(maxIterCG=10) invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt) # Inversion Directives beta = Directives.BetaSchedule(coolingFactor=4, coolingRate=3) betaest = Directives.BetaEstimate_ByEig(beta0_ratio=2.) target = Directives.TargetMisfit() inv = Inversion.BaseInversion(invProb, directiveList=[beta, betaest, target]) m0 = np.log(np.ones(mtrue.size)*sig_half) reg.alpha_s = 5e-1 reg.alpha_x = 1. prbTD.counter = opt.counter = Utils.Counter() opt.remember('xc') moptTD = inv.run(m0) if plotIt: import matplotlib fig = plt.figure(figsize = (10, 8)) ax0 = plt.subplot2grid((2, 2), (0, 0), rowspan=2) ax1 = plt.subplot2grid((2, 2), (0, 1)) ax2 = plt.subplot2grid((2, 2), (1, 1)) fs = 13 # fontsize matplotlib.rcParams['font.size'] = fs # Plot the model ax0.semilogx(sigma[active], mesh.vectorCCz[active], 'k-', lw=2) ax0.semilogx(np.exp(moptFD), mesh.vectorCCz[active], 'bo', ms=6) ax0.semilogx(np.exp(moptTD), mesh.vectorCCz[active], 'r*', ms=10) ax0.set_ylim(-700, 0) ax0.set_xlim(5e-3, 1e-1) ax0.set_xlabel('Conductivity (S/m)', fontsize=fs) ax0.set_ylabel('Depth (m)', fontsize=fs) ax0.grid(which='both', color='k', alpha=0.5, linestyle='-', linewidth=0.2) ax0.legend(['True', 'FDEM', 'TDEM'], fontsize=fs, loc=4) # plot the data misfits - negative b/c we choose positive to be in the # direction of primary ax1.plot(freqs, -surveyFD.dobs[::2], 'k-', lw=2) ax1.plot(freqs, -surveyFD.dobs[1::2], 'k--', lw=2) dpredFD = surveyFD.dpred(moptTD) ax1.loglog(freqs, -dpredFD[::2], 'bo', ms=6) ax1.loglog(freqs, -dpredFD[1::2], 'b+', markeredgewidth=2., ms=10) ax2.loglog(times, surveyTD.dobs, 'k-', lw=2) ax2.loglog(times, surveyTD.dpred(moptTD), 'r*', ms=10) ax2.set_xlim(times.min(), times.max()) # Labels, gridlines, etc ax2.grid(which='both', alpha=0.5, linestyle='-', linewidth=0.2) ax1.grid(which='both', alpha=0.5, linestyle='-', linewidth=0.2) ax1.set_xlabel('Frequency (Hz)', fontsize=fs) ax1.set_ylabel('Vertical magnetic field (-T)', fontsize=fs) ax2.set_xlabel('Time (s)', fontsize=fs) ax2.set_ylabel('Vertical magnetic field (-T)', fontsize=fs) ax2.legend(("Obs", "Pred"), fontsize=fs) ax1.legend(("Obs (real)", "Obs (imag)", "Pred (real)", "Pred (imag)"), fontsize=fs) ax1.set_xlim(freqs.max(), freqs.min()) ax0.set_title("(a) Recovered Models", fontsize=fs) ax1.set_title("(b) FDEM observed vs. predicted", fontsize=fs) ax2.set_title("(c) TDEM observed vs. predicted", fontsize=fs) plt.tight_layout(pad=1.5) plt.show()
def plot_pseudoSection(Tx,Rx,data,z0, stype): from SimPEG import np, mkvc from scipy.interpolate import griddata from matplotlib.colors import LogNorm import pylab as plt import re """ 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) Output: :figure scatter plot overlayed on image Created on Mon December 7th, 2015 @author: dominiquef """ #d2D = np.asarray(d2D) midl = [] midz = [] rho = [] for ii in range(len(Tx)): # Get distances between each poles rC1P1 = np.abs(Tx[ii][0] - Rx[ii][:,0]) rC2P1 = np.abs(Tx[ii][1] - Rx[ii][:,0]) rC1P2 = np.abs(Tx[ii][1] - Rx[ii][:,1]) rC2P2 = np.abs(Tx[ii][0] - Rx[ii][:,1]) rP1P2 = np.abs(Rx[ii][:,1] - Rx[ii][:,0]) # Compute apparent resistivity if re.match(stype,'pdp'): rho = np.hstack([rho, data[ii] * 2*np.pi * rC1P1 * ( rC1P1 + rP1P2 ) / rP1P2] ) elif re.match(stype,'dpdp'): rho = np.hstack([rho, data[ii] * 2*np.pi / ( 1/rC1P1 - 1/rC2P1 - 1/rC1P2 + 1/rC2P2 ) ]) Cmid = (Tx[ii][0] + Tx[ii][1])/2 Pmid = (Rx[ii][:,0] + Rx[ii][:,1])/2 midl = np.hstack([midl, ( Cmid + Pmid )/2 ]) midz = np.hstack([midz, -np.abs(Cmid-Pmid)/2 + z0 ]) # Grid points grid_x, grid_z = np.mgrid[np.min(midl):np.max(midl), np.min(midz):np.max(midz)] grid_rho = griddata(np.c_[midl,midz], np.log10(abs(1/rho.T)), (grid_x, grid_z), method='linear') #plt.subplot(2,1,2) plt.imshow(grid_rho.T, extent = (np.min(midl),np.max(midl),np.min(midz),np.max(midz)), origin='lower', alpha=0.8) cbar = plt.colorbar(format = '%.2f',fraction=0.02) cmin,cmax = cbar.get_clim() ticks = np.linspace(cmin,cmax,3) cbar.set_ticks(ticks) # Plot apparent resistivity plt.scatter(midl,midz,s=50,c=np.log10(abs(1/rho.T)))
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 run(loc=None, sig=None, radi=None, param=None, stype='dpdp', plotIt=True): """ DC Forward Simulation ===================== Forward model conductive spheres in a half-space and plot a pseudo-section Created by @fourndo on Mon Feb 01 19:28:06 2016 """ assert stype in [ 'pdp', 'dpdp' ], "Source type (stype) must be pdp or dpdp (pole dipole or dipole dipole)" if loc is None: loc = np.c_[[-50., 0., -50.], [50., 0., -50.]] if sig is None: sig = np.r_[1e-2, 1e-1, 1e-3] if radi is None: radi = np.r_[25., 25.] if param is None: param = np.r_[30., 30., 5] # First we need to create a mesh and a model. # This is our mesh dx = 5. hxind = [(dx, 15, -1.3), (dx, 75), (dx, 15, 1.3)] hyind = [(dx, 15, -1.3), (dx, 10), (dx, 15, 1.3)] hzind = [(dx, 15, -1.3), (dx, 15)] mesh = Mesh.TensorMesh([hxind, hyind, hzind], 'CCN') # Set background conductivity model = np.ones(mesh.nC) * sig[0] # First anomaly ind = Utils.ModelBuilder.getIndicesSphere(loc[:, 0], radi[0], mesh.gridCC) model[ind] = sig[1] # Second anomaly ind = Utils.ModelBuilder.getIndicesSphere(loc[:, 1], radi[1], mesh.gridCC) model[ind] = sig[2] # 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" # 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)] ends = np.c_[np.asarray(ends), np.ones(2).T * mesh.vectorNz[-1]] # Snap the endpoints to the grid. Easier to create 2D section. indx = Utils.closestPoints(mesh, ends) locs = np.c_[mesh.gridCC[indx, 0], mesh.gridCC[indx, 1], np.ones(2).T * mesh.vectorNz[-1]] # We will handle the geometry of the survey for you and create all the combination of tx-rx along line # [Tx, Rx] = DC.gen_DCIPsurvey(locs, mesh, stype, param[0], param[1], param[2]) survey, Tx, Rx = DC.gen_DCIPsurvey(locs, mesh, stype, param[0], param[1], param[2]) # Define some global geometry 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) #Set boundary conditions mesh.setCellGradBC('neumann') # Define the differential operators needed for the DC problem Div = mesh.faceDiv Grad = mesh.cellGrad Msig = Utils.sdiag(1. / (mesh.aveF2CC.T * (1. / model))) A = Div * Msig * Grad # Change one corner to deal with nullspace A[0, 0] = 1 A = sp.csc_matrix(A) # We will solve the system iteratively, so a pre-conditioner is helpful # This is simply a Jacobi preconditioner (inverse of the main diagonal) dA = A.diagonal() P = sp.spdiags(1 / dA, 0, A.shape[0], A.shape[0]) # Now we can solve the system for all the transmitters # We want to store the data data = [] # There is probably a more elegant way to do this, but we can just for-loop through the transmitters for ii in range(len(Tx)): start_time = time.time() # Let's time the calculations #print("Transmitter %i / %i\r" % (ii+1,len(Tx))) # Select dipole locations for receiver rxloc_M = np.asarray(Rx[ii][:, 0:3]) rxloc_N = np.asarray(Rx[ii][:, 3:]) # For usual cases "dpdp" or "gradient" if stype == 'pdp': # Create an "inifinity" pole tx = np.squeeze(Tx[ii][:, 0:1]) tinf = tx + np.array([dl_x, dl_y, 0]) * dl_len * 2 inds = Utils.closestPoints(mesh, np.c_[tx, tinf].T) RHS = mesh.getInterpolationMat(np.asarray(Tx[ii]).T, 'CC').T * ([-1] / mesh.vol[inds]) else: inds = Utils.closestPoints(mesh, np.asarray(Tx[ii]).T) RHS = mesh.getInterpolationMat(np.asarray(Tx[ii]).T, 'CC').T * ([-1, 1] / mesh.vol[inds]) # Iterative Solve Ainvb = sp.linalg.bicgstab(P * A, P * RHS, tol=1e-5) # We now have the potential everywhere phi = Utils.mkvc(Ainvb[0]) # Solve for phi on pole locations P1 = mesh.getInterpolationMat(rxloc_M, 'CC') P2 = mesh.getInterpolationMat(rxloc_N, 'CC') # Compute the potential difference dtemp = (P1 * phi - P2 * phi) * np.pi data.append(dtemp) print '\rTransmitter {0} of {1} -> Time:{2} sec'.format( ii, len(Tx), time.time() - start_time), print 'Transmitter {0} of {1}'.format(ii, len(Tx)) 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.dobs = np.hstack(data) # Here is an example for the first tx-rx array if plotIt: import matplotlib.pyplot as plt fig = plt.figure() 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') plt.gca().set_aspect('equal', adjustable='box') plt.scatter(Tx[0][0, :], Tx[0][2, :], s=40, c='g', marker='v') plt.scatter(Rx[0][:, 0::3], Rx[0][:, 2::3], s=40, c='y') plt.xlim([-xlim, xlim]) plt.ylim([-zlim, mesh.vectorNz[-1] + dx]) ax = 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) # Add the speudo section DC.plot_pseudoSection(survey2D, ax, stype) # 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]) plt.show() return fig, ax
def run(loc=None, sig=None, radi=None, param=None, stype='dpdp', plotIt=True): """ DC Forward Simulation ===================== Forward model conductive spheres in a half-space and plot a pseudo-section Created by @fourndo on Mon Feb 01 19:28:06 2016 """ assert stype in ['pdp', 'dpdp'], "Source type (stype) must be pdp or dpdp (pole dipole or dipole dipole)" if loc is None: loc = np.c_[[-50.,0.,-50.],[50.,0.,-50.]] if sig is None: sig = np.r_[1e-2,1e-1,1e-3] if radi is None: radi = np.r_[25.,25.] if param is None: param = np.r_[30.,30.,5] # First we need to create a mesh and a model. # This is our mesh dx = 5. hxind = [(dx,15,-1.3), (dx, 75), (dx,15,1.3)] hyind = [(dx,15,-1.3), (dx, 10), (dx,15,1.3)] hzind = [(dx,15,-1.3),(dx, 15)] mesh = Mesh.TensorMesh([hxind, hyind, hzind], 'CCN') # Set background conductivity model = np.ones(mesh.nC) * sig[0] # First anomaly ind = Utils.ModelBuilder.getIndicesSphere(loc[:,0],radi[0],mesh.gridCC) model[ind] = sig[1] # Second anomaly ind = Utils.ModelBuilder.getIndicesSphere(loc[:,1],radi[1],mesh.gridCC) model[ind] = sig[2] # 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" # 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)] ends = np.c_[np.asarray(ends),np.ones(2).T*mesh.vectorNz[-1]] # Snap the endpoints to the grid. Easier to create 2D section. indx = Utils.closestPoints(mesh, ends ) locs = np.c_[mesh.gridCC[indx,0],mesh.gridCC[indx,1],np.ones(2).T*mesh.vectorNz[-1]] # We will handle the geometry of the survey for you and create all the combination of tx-rx along line # [Tx, Rx] = DC.gen_DCIPsurvey(locs, mesh, stype, param[0], param[1], param[2]) survey, Tx, Rx = DC.gen_DCIPsurvey(locs, mesh, stype, param[0], param[1], param[2]) # Define some global geometry 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) #Set boundary conditions mesh.setCellGradBC('neumann') # Define the differential operators needed for the DC problem Div = mesh.faceDiv Grad = mesh.cellGrad Msig = Utils.sdiag(1./(mesh.aveF2CC.T*(1./model))) A = Div*Msig*Grad # Change one corner to deal with nullspace A[0,0] = 1 A = sp.csc_matrix(A) # We will solve the system iteratively, so a pre-conditioner is helpful # This is simply a Jacobi preconditioner (inverse of the main diagonal) dA = A.diagonal() P = sp.spdiags(1/dA,0,A.shape[0],A.shape[0]) # Now we can solve the system for all the transmitters # We want to store the data data = [] # There is probably a more elegant way to do this, but we can just for-loop through the transmitters for ii in range(len(Tx)): start_time = time.time() # Let's time the calculations #print("Transmitter %i / %i\r" % (ii+1,len(Tx))) # Select dipole locations for receiver rxloc_M = np.asarray(Rx[ii][:,0:3]) rxloc_N = np.asarray(Rx[ii][:,3:]) # For usual cases "dpdp" or "gradient" if stype == 'pdp': # Create an "inifinity" pole tx = np.squeeze(Tx[ii][:,0:1]) tinf = tx + np.array([dl_x,dl_y,0])*dl_len*2 inds = Utils.closestPoints(mesh, np.c_[tx,tinf].T) RHS = mesh.getInterpolationMat(np.asarray(Tx[ii]).T, 'CC').T*( [-1] / mesh.vol[inds] ) else: inds = Utils.closestPoints(mesh, np.asarray(Tx[ii]).T ) RHS = mesh.getInterpolationMat(np.asarray(Tx[ii]).T, 'CC').T*( [-1,1] / mesh.vol[inds] ) # Iterative Solve Ainvb = sp.linalg.bicgstab(P*A,P*RHS, tol=1e-5) # We now have the potential everywhere phi = Utils.mkvc(Ainvb[0]) # Solve for phi on pole locations P1 = mesh.getInterpolationMat(rxloc_M, 'CC') P2 = mesh.getInterpolationMat(rxloc_N, 'CC') # Compute the potential difference dtemp = (P1*phi - P2*phi)*np.pi data.append( dtemp ) print '\rTransmitter {0} of {1} -> Time:{2} sec'.format(ii,len(Tx),time.time()- start_time), print 'Transmitter {0} of {1}'.format(ii,len(Tx)) 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.dobs =np.hstack(data) # Here is an example for the first tx-rx array if plotIt: import matplotlib.pyplot as plt fig = plt.figure() 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') plt.gca().set_aspect('equal', adjustable='box') plt.scatter(Tx[0][0,:],Tx[0][2,:],s=40,c='g', marker='v') plt.scatter(Rx[0][:,0::3],Rx[0][:,2::3],s=40,c='y') plt.xlim([-xlim,xlim]) plt.ylim([-zlim,mesh.vectorNz[-1]+dx]) ax = 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) # Add the speudo section DC.plot_pseudoSection(survey2D,ax,stype) # 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]) plt.show() return fig, ax
def plot_pseudoSection(DCsurvey, axs, stype): """ 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) 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 = [] 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 MA = np.abs(Tx[0][0] - Rx[0][:,0]) MB = np.abs(Tx[1][0] - Rx[0][:,0]) NB = np.abs(Tx[1][0] - Rx[1][:,0]) NA = np.abs(Tx[0][0] - Rx[1][:,0]) MN = np.abs(Rx[1][:,0] - Rx[0][:,0]) # Create mid-point location 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 leg = np.log10(abs(1/leg)) elif stype == 'dpdp': leg = data * 2*np.pi / ( 1/MA - 1/MB - 1/NB + 1/NA ) midx = np.hstack([midx, ( Cmid + Pmid )/2 ]) midz = np.hstack([midz, -np.abs(Cmid-Pmid)/2 + z0 ]) rho = np.hstack([rho,leg]) 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') 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") cmin,cmax = cbar.get_clim() ticks = np.linspace(cmin,cmax,3) cbar.set_ticks(ticks) # Plot apparent resistivity plt.scatter(midx,midz,s=50,c=rho.T) ax.set_xticklabels([]) ax.set_ylabel('Z') ax.yaxis.tick_right() ax.yaxis.set_label_position('right') plt.gca().set_aspect('equal', adjustable='box') return ax
def run(plotIt=True): """ 1D FDEM and TDEM inversions =========================== This example is used in the paper Heagy et al 2016 (in prep) """ # Set up cylindrically symmeric mesh cs, ncx, ncz, npad = 10., 15, 25, 13 # padded cyl mesh hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hz], '00C') # Conductivity model layerz = np.r_[-200., -100.] layer = (mesh.vectorCCz >= layerz[0]) & (mesh.vectorCCz <= layerz[1]) active = mesh.vectorCCz < 0. sig_half = 1e-2 # Half-space conductivity sig_air = 1e-8 # Air conductivity sig_layer = 5e-2 # Layer conductivity sigma = np.ones(mesh.nCz) * sig_air sigma[active] = sig_half sigma[layer] = sig_layer # Mapping actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz) mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap mtrue = np.log(sigma[active]) # ----- FDEM problem & survey ----- rxlocs = Utils.ndgrid([np.r_[50.], np.r_[0], np.r_[0.]]) bzi = FDEM.Rx.Point_bSecondary(rxlocs, 'z', 'real') bzr = FDEM.Rx.Point_bSecondary(rxlocs, 'z', 'imag') freqs = np.logspace(2, 3, 5) srcLoc = np.array([0., 0., 0.]) print('min skin depth = ', 500. / np.sqrt(freqs.max() * sig_half), 'max skin depth = ', 500. / np.sqrt(freqs.min() * sig_half)) print('max x ', mesh.vectorCCx.max(), 'min z ', mesh.vectorCCz.min(), 'max z ', mesh.vectorCCz.max()) srcList = [ FDEM.Src.MagDipole([bzr, bzi], freq, srcLoc, orientation='Z') for freq in freqs ] surveyFD = FDEM.Survey(srcList) prbFD = FDEM.Problem3D_b(mesh, sigmaMap=mapping, Solver=Solver) prbFD.pair(surveyFD) std = 0.03 surveyFD.makeSyntheticData(mtrue, std) surveyFD.eps = np.linalg.norm(surveyFD.dtrue) * 1e-5 # FDEM inversion np.random.seed(1) dmisfit = DataMisfit.l2_DataMisfit(surveyFD) regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = Regularization.Simple(regMesh) opt = Optimization.InexactGaussNewton(maxIterCG=10) invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt) # Inversion Directives beta = Directives.BetaSchedule(coolingFactor=4, coolingRate=3) betaest = Directives.BetaEstimate_ByEig(beta0_ratio=2.) target = Directives.TargetMisfit() directiveList = [beta, betaest, target] inv = Inversion.BaseInversion(invProb, directiveList=directiveList) m0 = np.log(np.ones(mtrue.size) * sig_half) reg.alpha_s = 5e-1 reg.alpha_x = 1. prbFD.counter = opt.counter = Utils.Counter() opt.remember('xc') moptFD = inv.run(m0) # TDEM problem times = np.logspace(-4, np.log10(2e-3), 10) print('min diffusion distance ', 1.28 * np.sqrt(times.min() / (sig_half * mu_0)), 'max diffusion distance ', 1.28 * np.sqrt(times.max() / (sig_half * mu_0))) rx = TDEM.Rx.Point_b(rxlocs, times, 'z') src = TDEM.Src.MagDipole( [rx], waveform=TDEM.Src.StepOffWaveform(), loc=srcLoc # same src location as FDEM problem ) surveyTD = TDEM.Survey([src]) prbTD = TDEM.Problem3D_b(mesh, sigmaMap=mapping, Solver=Solver) prbTD.timeSteps = [(5e-5, 10), (1e-4, 10), (5e-4, 10)] prbTD.pair(surveyTD) std = 0.03 surveyTD.makeSyntheticData(mtrue, std) surveyTD.std = std surveyTD.eps = np.linalg.norm(surveyTD.dtrue) * 1e-5 # TDEM inversion dmisfit = DataMisfit.l2_DataMisfit(surveyTD) regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]]) reg = Regularization.Simple(regMesh) opt = Optimization.InexactGaussNewton(maxIterCG=10) invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt) inv = Inversion.BaseInversion(invProb, directiveList=directiveList) m0 = np.log(np.ones(mtrue.size) * sig_half) reg.alpha_s = 5e-1 reg.alpha_x = 1. prbTD.counter = opt.counter = Utils.Counter() opt.remember('xc') moptTD = inv.run(m0) if plotIt: plt.figure(figsize=(10, 8)) ax0 = plt.subplot2grid((2, 2), (0, 0), rowspan=2) ax1 = plt.subplot2grid((2, 2), (0, 1)) ax2 = plt.subplot2grid((2, 2), (1, 1)) fs = 13 # fontsize matplotlib.rcParams['font.size'] = fs # Plot the model ax0.semilogx(sigma[active], mesh.vectorCCz[active], 'k-', lw=2) ax0.semilogx(np.exp(moptFD), mesh.vectorCCz[active], 'bo', ms=6) ax0.semilogx(np.exp(moptTD), mesh.vectorCCz[active], 'r*', ms=10) ax0.set_ylim(-700, 0) ax0.set_xlim(5e-3, 1e-1) ax0.set_xlabel('Conductivity (S/m)', fontsize=fs) ax0.set_ylabel('Depth (m)', fontsize=fs) ax0.grid(which='both', color='k', alpha=0.5, linestyle='-', linewidth=0.2) ax0.legend(['True', 'FDEM', 'TDEM'], fontsize=fs, loc=4) # plot the data misfits - negative b/c we choose positive to be in the # direction of primary ax1.plot(freqs, -surveyFD.dobs[::2], 'k-', lw=2) ax1.plot(freqs, -surveyFD.dobs[1::2], 'k--', lw=2) dpredFD = surveyFD.dpred(moptTD) ax1.loglog(freqs, -dpredFD[::2], 'bo', ms=6) ax1.loglog(freqs, -dpredFD[1::2], 'b+', markeredgewidth=2., ms=10) ax2.loglog(times, surveyTD.dobs, 'k-', lw=2) ax2.loglog(times, surveyTD.dpred(moptTD), 'r*', ms=10) ax2.set_xlim(times.min(), times.max()) # Labels, gridlines, etc ax2.grid(which='both', alpha=0.5, linestyle='-', linewidth=0.2) ax1.grid(which='both', alpha=0.5, linestyle='-', linewidth=0.2) ax1.set_xlabel('Frequency (Hz)', fontsize=fs) ax1.set_ylabel('Vertical magnetic field (-T)', fontsize=fs) ax2.set_xlabel('Time (s)', fontsize=fs) ax2.set_ylabel('Vertical magnetic field (-T)', fontsize=fs) ax2.legend(("Obs", "Pred"), fontsize=fs) ax1.legend(("Obs (real)", "Obs (imag)", "Pred (real)", "Pred (imag)"), fontsize=fs) ax1.set_xlim(freqs.max(), freqs.min()) ax0.set_title("(a) Recovered Models", fontsize=fs) ax1.set_title("(b) FDEM observed vs. predicted", fontsize=fs) ax2.set_title("(c) TDEM observed vs. predicted", fontsize=fs) plt.tight_layout(pad=1.5)
#============================================================================== # mesh2d = Mesh.TensorMesh([mesh.hx, mesh.hz], x0=(mesh.x0[0]-endl[0,0],mesh.x0[2])) # m3D = np.reshape(model, (mesh.nCz, mesh.nCy, mesh.nCx)) # m2D = m3D[:,1,:] #============================================================================== plt.figure() axs = plt.subplot(2,1,1) plt.xlim([0,nc*dx]) plt.ylim([mesh2d.vectorNy[-1]-dl_len/2,mesh2d.vectorNy[-1]]) plt.gca().set_aspect('equal', adjustable='box') plt.pcolormesh(mesh2d.vectorNx,mesh2d.vectorNy,np.log10(m2D),alpha=0.5, cmap='gray')#axes = [mesh2d.vectorNx[0],mesh2d.vectorNx[-1],mesh2d.vectorNy[0],mesh2d.vectorNy[-1]]) #mesh2d.plotImage(mkvc(m2D), grid=True, ax=axs) #%% Plot pseudo section DC.plot_pseudoSection(Tx2d,Rx2d,data,nz[-1],stype) plt.colorbar plt.show() #%% Create dcin2d inversion files and run inv_dir = home_dir + '\Inv2D' if not os.path.exists(inv_dir): os.makedirs(inv_dir) mshfile2d = 'Mesh_2D.msh' modfile2d = 'MtIsa_2D.con'