def _evalCross(self, m): if self.crossgrad == False: return 0.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)
def readUBC_DC2DLoc(fileName): from SimPEG import np """ Read UBC GIF 2D observation file and generate arrays for tx-rx location Input: :param fileName, path to the UBC GIF 2D model file Output: :param rx, tx :return Created on Thu Nov 12 13:14:10 2015 @author: dominiquef """ # Open fileand skip header... assume that we know the mesh already #============================================================================== # fopen = open(fileName,'r') # lines = fopen.readlines() # fopen.close() #============================================================================== # Load file obsfile = np.genfromtxt(fileName,delimiter=' \n',dtype=np.str,comments='!') # Check first line and figure out if 2D or 3D file format line = np.array(obsfile[0].split(),dtype=float) tx_A = [] tx_B = [] rx_M = [] rx_N = [] d = [] wd = [] for ii in range(obsfile.shape[0]): # If len==3, then simple format where tx-rx is listed on each line if len(line) == 4: temp = np.fromstring(obsfile[ii], dtype=float,sep=' ') tx_A = np.hstack((tx_A,temp[0])) tx_B = np.hstack((tx_B,temp[1])) rx_M = np.hstack((rx_M,temp[2])) rx_N = np.hstack((rx_N,temp[3])) rx = np.transpose(np.array((rx_M,rx_N))) tx = np.transpose(np.array((tx_A,tx_B))) return tx, rx, d, wd
def toRecArray(self,returnType='RealImag'): ''' Function that returns a numpy.recarray for a SimpegMT impedance data object. :param str returnType: Switches between returning a rec array where the impedance is split to real and imaginary ('RealImag') or is a complex ('Complex') ''' # Define the record fields dtRI = [('freq',float),('x',float),('y',float),('z',float),('zxxr',float),('zxxi',float),('zxyr',float),('zxyi',float), ('zyxr',float),('zyxi',float),('zyyr',float),('zyyi',float),('tzxr',float),('tzxi',float),('tzyr',float),('tzyi',float)] dtCP = [('freq',float),('x',float),('y',float),('z',float),('zxx',complex),('zxy',complex),('zyx',complex),('zyy',complex),('tzx',complex),('tzy',complex)] impList = ['zxxr','zxxi','zxyr','zxyi','zyxr','zyxi','zyyr','zyyi'] for src in self.survey.srcList: # Temp array for all the receivers of the source. # Note: needs to be written more generally, using diffterent rxTypes and not all the data at the locaitons # Assume the same locs for all RX locs = src.rxList[0].locs if locs.shape[1] == 1: locs = np.hstack((np.array([[0.0,0.0]]),locs)) elif locs.shape[1] == 2: locs = np.hstack((np.array([[0.0]]),locs)) tArrRec = np.concatenate((src.freq*np.ones((locs.shape[0],1)),locs,np.nan*np.ones((locs.shape[0],12))),axis=1).view(dtRI) # np.array([(src.freq,rx.locs[0,0],rx.locs[0,1],rx.locs[0,2],np.nan ,np.nan ,np.nan ,np.nan ,np.nan ,np.nan ,np.nan ,np.nan ) for rx in src.rxList],dtype=dtRI) # Get the type and the value for the DataMT object as a list typeList = [[rx.rxType.replace('z1d','zyx'),self[src,rx]] for rx in src.rxList] # Insert the values to the temp array for nr,(key,val) in enumerate(typeList): tArrRec[key] = mkvc(val,2) # Masked array mArrRec = np.ma.MaskedArray(rec2ndarr(tArrRec),mask=np.isnan(rec2ndarr(tArrRec))).view(dtype=tArrRec.dtype) # Unique freq and loc of the masked array uniFLmarr = np.unique(mArrRec[['freq','x','y','z']]).copy() try: outTemp = recFunc.stack_arrays((outTemp,mArrRec)) #outTemp = np.concatenate((outTemp,dataBlock),axis=0) except NameError as e: outTemp = mArrRec if 'RealImag' in returnType: outArr = outTemp elif 'Complex' in returnType: # Add the real and imaginary to a complex number outArr = np.empty(outTemp.shape,dtype=dtCP) for comp in ['freq','x','y','z']: outArr[comp] = outTemp[comp].copy() for comp in ['zxx','zxy','zyx','zyy','tzx','tzy']: outArr[comp] = outTemp[comp+'r'].copy() + 1j*outTemp[comp+'i'].copy() else: raise NotImplementedError('{:s} is not implemented, as to be RealImag or Complex.') # Return return outArr
def S_eDeriv_m(self, problem, v, adjoint=False): """ Get the derivative of S_e wrt to sigma (m) """ # Need to deal with if problem.mesh.dim == 1: # Need to use the faceInnerProduct MsigmaDeriv = ( problem.mesh.getFaceInnerProductDeriv(problem.curModel.sigma)(self.ePrimary(problem)[:, 1]) * problem.curModel.sigmaDeriv ) # MsigmaDeriv = ( MsigmaDeriv * MsigmaDeriv.T)**2 if problem.mesh.dim == 2: pass if problem.mesh.dim == 3: # Need to take the derivative of both u_px and u_py ePri = self.ePrimary(problem) # MsigmaDeriv = problem.MeSigmaDeriv(ePri[:,0]) + problem.MeSigmaDeriv(ePri[:,1]) # MsigmaDeriv = problem.MeSigmaDeriv(np.sum(ePri,axis=1)) if adjoint: return sp.hstack((problem.MeSigmaDeriv(ePri[:, 0]).T, problem.MeSigmaDeriv(ePri[:, 1]).T)) * v else: return np.hstack( (mkvc(problem.MeSigmaDeriv(ePri[:, 0]) * v, 2), mkvc(problem.MeSigmaDeriv(ePri[:, 1]) * v, 2)) ) if adjoint: # return MsigmaDeriv.T * v else: # v should be nC size return MsigmaDeriv * v
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
def run(plotIt=True, nFreq=1): """ MT: 3D: Forward =============== Forward model 3D MT data. """ # Make a mesh M = simpeg.Mesh.TensorMesh([[(100,5,-1.5),(100.,10),(100,5,1.5)],[(100,5,-1.5),(100.,10),(100,5,1.5)],[(100,5,1.6),(100.,10),(100,3,2)]], x0=['C','C',-3529.5360]) # Setup the model conds = [1e-2,1] sig = simpeg.Utils.ModelBuilder.defineBlock(M.gridCC,[-1000,-1000,-400],[1000,1000,-200],conds) sig[M.gridCC[:,2]>0] = 1e-8 sig[M.gridCC[:,2]<-600] = 1e-1 sigBG = np.zeros(M.nC) + conds[0] sigBG[M.gridCC[:,2]>0] = 1e-8 ## Setup the the survey object # Receiver locations rx_x, rx_y = np.meshgrid(np.arange(-500,501,50),np.arange(-500,501,50)) rx_loc = np.hstack((simpeg.Utils.mkvc(rx_x,2),simpeg.Utils.mkvc(rx_y,2),np.zeros((np.prod(rx_x.shape),1)))) # Make a receiver list rxList = [] for loc in rx_loc: # NOTE: loc has to be a (1,3) np.ndarray otherwise errors accure for rx_orientation in ['xx','xy','yx','yy']: rxList.append(NSEM.Rx.Point_impedance3D(simpeg.mkvc(loc,2).T,rx_orientation, 'real')) rxList.append(NSEM.Rx.Point_impedance3D(simpeg.mkvc(loc,2).T,rx_orientation, 'imag')) for rx_orientation in ['zx','zy']: rxList.append(NSEM.Rx.Point_tipper3D(simpeg.mkvc(loc,2).T,rx_orientation, 'real')) rxList.append(NSEM.Rx.Point_tipper3D(simpeg.mkvc(loc,2).T,rx_orientation, 'imag')) # Source list srcList =[] for freq in np.logspace(3,-3,nFreq): srcList.append(NSEM.Src.Planewave_xy_1Dprimary(rxList,freq)) # Survey MT survey = NSEM.Survey(srcList) ## Setup the problem object problem = NSEM.Problem3D_ePrimSec(M, sigmaPrimary=sigBG) problem.pair(survey) problem.Solver = Solver # Calculate the data fields = problem.fields(sig) dataVec = survey.eval(fields) # Make the data mtData = NSEM.Data(survey,dataVec) # Add plots if plotIt: pass
def getADeriv_m(self, freq, u, v, adjoint=False): """ Calculate the derivative of A wrt m. """ # This considers both polarizations and returns a nE,2 matrix for each polarization if adjoint: dMe_dsigV = sp.hstack(( self.MeSigmaDeriv( u['e_pxSolution'] ).T, self.MeSigmaDeriv(u['e_pySolution'] ).T ))*v else: # Need a nE,2 matrix to be returned dMe_dsigV = np.hstack(( mkvc(self.MeSigmaDeriv( u['e_pxSolution'] )*v,2), mkvc( self.MeSigmaDeriv(u['e_pySolution'] )*v,2) )) return 1j * omega(freq) * dMe_dsigV
def fromRecArray(cls, recArray, srcType='primary'): """ Class method that reads in a numpy record array to MTdata object. Only imports the impedance data. """ if srcType == 'primary': src = simpegMT.SurveyMT.srcMT_polxy_1Dprimary elif srcType == 'total': src = sdsimpegMT.SurveyMT.srcMT_polxy_1DhomotD else: raise NotImplementedError( '{:s} is not a valid source type for MTdata') # Find all the frequencies in recArray uniFreq = np.unique(recArray['freq']) srcList = [] dataList = [] for freq in uniFreq: # Initiate rxList rxList = [] # Find that data for freq dFreq = recArray[recArray['freq'] == freq].copy() # Find the impedance rxTypes in the recArray. rxTypes = [ comp for comp in recArray.dtype.names if (len(comp) == 4 or len(comp) == 3) and 'z' in comp ] for rxType in rxTypes: # Find index of not nan values in rxType notNaNind = ~np.isnan(dFreq[rxType]) if np.any( notNaNind): # Make sure that there is any data to add. locs = rec2ndarr(dFreq[['x', 'y', 'z']][notNaNind].copy()) if dFreq[rxType].dtype.name in 'complex128': rxList.append( simpegMT.SurveyMT.RxMT(locs, rxType + 'r')) dataList.append(dFreq[rxType][notNaNind].real.copy()) rxList.append( simpegMT.SurveyMT.RxMT(locs, rxType + 'i')) dataList.append(dFreq[rxType][notNaNind].imag.copy()) else: rxList.append(simpegMT.SurveyMT.RxMT(locs, rxType)) dataList.append(dFreq[rxType][notNaNind].copy()) srcList.append(src(rxList, freq)) # Make a survey survey = simpegMT.SurveyMT.SurveyMT(srcList) dataVec = np.hstack(dataList) return cls(survey, dataVec)
def unpackdx(fid,nrows): for ii in range(nrows): line = fid.readline() var = np.array(line.split(),dtype=float) if ii==0: x0= var[0] xvec = np.ones(int(var[2])) * (var[1] - var[0]) / int(var[2]) xend = var[1] else: xvec = np.hstack((xvec,np.ones(int(var[1])) * (var[0] - xend) / int(var[1]))) xend = var[0] return x0, xvec
def getADeriv_m(self, freq, u, v, adjoint=False): """ Calculate the derivative of A wrt m. """ # This considers both polarizations and returns a nE,2 matrix for each polarization if adjoint: dMe_dsigV = sp.hstack((self.MeSigmaDeriv(u['e_pxSolution']).T, self.MeSigmaDeriv(u['e_pySolution']).T)) * v else: # Need a nE,2 matrix to be returned dMe_dsigV = np.hstack( (mkvc(self.MeSigmaDeriv(u['e_pxSolution']) * v, 2), mkvc(self.MeSigmaDeriv(u['e_pySolution']) * v, 2))) return 1j * omega(freq) * dMe_dsigV
def fromRecArray(cls, recArray, srcType='primary'): """ Class method that reads in a numpy record array to MTdata object. Only imports the impedance data. """ if srcType=='primary': src = SrcMT.polxy_1Dprimary elif srcType=='total': src = SrcMT.polxy_1DhomotD else: raise NotImplementedError('{:s} is not a valid source type for MTdata') # Find all the frequencies in recArray uniFreq = np.unique(recArray['freq']) srcList = [] dataList = [] for freq in uniFreq: # Initiate rxList rxList = [] # Find that data for freq dFreq = recArray[recArray['freq'] == freq].copy() # Find the impedance rxTypes in the recArray. rxTypes = [ comp for comp in recArray.dtype.names if (len(comp)==4 or len(comp)==3) and 'z' in comp] for rxType in rxTypes: # Find index of not nan values in rxType notNaNind = ~np.isnan(dFreq[rxType]) if np.any(notNaNind): # Make sure that there is any data to add. locs = rec2ndarr(dFreq[['x','y','z']][notNaNind].copy()) if dFreq[rxType].dtype.name in 'complex128': rxList.append(Rx(locs,rxType+'r')) dataList.append(dFreq[rxType][notNaNind].real.copy()) rxList.append(Rx(locs,rxType+'i')) dataList.append(dFreq[rxType][notNaNind].imag.copy()) else: rxList.append(Rx(locs,rxType)) dataList.append(dFreq[rxType][notNaNind].copy()) srcList.append(src(rxList,freq)) # Make a survey survey = Survey(srcList) dataVec = np.hstack(dataList) return cls(survey,dataVec)
def run(plotIt=True): """ Maps: Parametrized Block in a Layer =================================== Parametrized description of a block confined to a layer in a wholespace. The mapping can be applied in 2D or 3D. Here we show a 2D example. The model is given by .. code:: m = np.r_[ 'value of the background', 'value in the layer', 'value in the block', 'center of the layer (depth)', 'thickness of the layer', 'x-center of block', 'width of the block' ] """ mesh = Mesh.TensorMesh([50, 50], x0='CC') # 2D Tensor Mesh mapping = Maps.ParametrizedBlockInLayer(mesh) # mapping m = np.hstack(np.r_[1., # value of the background 2., # value in the layer 3., # value in the block -0.1, # center of the layer (depth) 0.2, # thickness of the layer 0.3, # x-center of block 0.2 # width of the block ]) # apply the mapping to define the physical property on the mesh rho = mapping * m if plotIt is True: fig, ax = plt.subplots(1, 1, figsize=(4, 6)) mesh.plotImage(rho, ax=ax)
def getADeriv_m(self, freq, u, v, adjoint=False): # Nee to account for both the polarizations # dMe_dsig = (self.MeSigmaDeriv( u['e_pxSolution'] ) + self.MeSigmaDeriv( u['e_pySolution'] )) # dMe_dsig = (self.MeSigmaDeriv( u['e_pxSolution'] + u['e_pySolution'] )) # # dMe_dsig = self.MeSigmaDeriv( u ) # if adjoint: # return 1j * omega(freq) * ( dMe_dsig.T * v ) # As in simpegEM # return 1j * omega(freq) * ( dMe_dsig * v ) # As in simpegEM # This considers both polarizations and returns a nE,2 matrix for each polarization if adjoint: dMe_dsigV = sp.hstack((self.MeSigmaDeriv(u['e_pxSolution']).T, self.MeSigmaDeriv(u['e_pySolution']).T)) * v else: # Need a nE,2 matrix to be returned dMe_dsigV = np.hstack( (mkvc(self.MeSigmaDeriv(u['e_pxSolution']) * v, 2), mkvc(self.MeSigmaDeriv(u['e_pySolution']) * v, 2))) return 1j * omega(freq) * dMe_dsigV
def Jvec(self, m, v, f=None): """ Sensitivity times a vector. :param numpy.array m: inversion model (nP,) :param numpy.array v: vector which we take sensitivity product with (nP,) :param SimPEG.EM.FDEM.FieldsFDEM.FieldsFDEM u: fields object :rtype: numpy.array :return: Jv (ndata,) """ if f is None: f = self.fields(m) self.curModel = m # Jv = self.dataPair(self.survey) Jv = [] for freq in self.survey.freqs: A = self.getA(freq) Ainv = self.Solver(A, **self.solverOpts) # create the concept of Ainv (actually a solve) for src in self.survey.getSrcByFreq(freq): u_src = f[src, self._solutionType] dA_dm_v = self.getADeriv(freq, u_src, v) dRHS_dm_v = self.getRHSDeriv(freq, src, v) du_dm_v = Ainv * ( - dA_dm_v + dRHS_dm_v ) for rx in src.rxList: df_dmFun = getattr(f, '_{0}Deriv'.format(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) Jv.append(rx.evalDeriv(src, self.mesh, f, df_dm_v)) Ainv.clean() # return Utils.mkvc(Jv) return np.hstack(Jv)
def run(plotIt=True): """ Maps: Parametrized Layer ======================== Build a model of a parametrized layer in a wholespace. If you want to build a model of a parametrized layer in a halfspace, also use Maps.InjectActiveCell. The model is .. code:: m = [ 'background physical property value', 'layer physical property value', 'layer center', 'layer thickness' ] """ mesh = Mesh.TensorMesh([50, 50], x0='CC') # 2D tensor mesh mapping = Maps.ParametrizedLayer(mesh) # parametrized layer in wholespace # model m = np.hstack(np.r_[1., # background value 2., # layer value -0.1, # layer center 0.2 # layer thickness ]) rho = mapping * m # apply the mapping if plotIt is True: fig, ax = plt.subplots(1, 1, figsize=(4, 6)) mesh.plotImage(rho, ax=ax)
def evalDeriv(self, src, mesh, f, v, adjoint=False): """ The derivative of the projection wrt u :param MTsrc src: MT source :param TensorMesh mesh: Mesh defining the topology of the problem :param MTfields f: MT fields object of the source :param numpy.ndarray v: Random vector of size """ real_or_imag = self.projComp if not adjoint: if self.projType is 'Z1D': Pex = mesh.getInterpolationMat(self.locs[:,-1],'Fx') Pbx = mesh.getInterpolationMat(self.locs[:,-1],'Ex') # ex = Pex*mkvc(f[src,'e_1d'],2) # bx = Pbx*mkvc(f[src,'b_1d'],2)/mu_0 dP_de = -mkvc(Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0))*(Pex*v),2) dP_db = mkvc( Utils.sdiag(Pex*mkvc(f[src,'e_1d'],2))*(Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0)).T*Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0)))*(Pbx*f._bDeriv_u(src,v)/mu_0),2) PDeriv_complex = np.sum(np.hstack((dP_de,dP_db)),1) elif self.projType is 'Z2D': raise NotImplementedError('Has not been implement for 2D impedance tensor') elif self.projType is 'Z3D': if self.locs.ndim == 3: eFLocs = self.locs[:,:,0] bFLocs = self.locs[:,:,1] else: eFLocs = self.locs bFLocs = self.locs # Get the projection Pex = mesh.getInterpolationMat(eFLocs,'Ex') Pey = mesh.getInterpolationMat(eFLocs,'Ey') Pbx = mesh.getInterpolationMat(bFLocs,'Fx') Pby = mesh.getInterpolationMat(bFLocs,'Fy') # Get the fields at location # px: x-polaration and py: y-polaration. ex_px = Pex*f[src,'e_px'] ey_px = Pey*f[src,'e_px'] ex_py = Pex*f[src,'e_py'] ey_py = Pey*f[src,'e_py'] hx_px = Pbx*f[src,'b_px']/mu_0 hy_px = Pby*f[src,'b_px']/mu_0 hx_py = Pbx*f[src,'b_py']/mu_0 hy_py = Pby*f[src,'b_py']/mu_0 # Derivatives as lambda functions # The size of the diratives should be nD,nU ex_px_u = lambda vec: Pex*f._e_pxDeriv_u(src,vec) ey_px_u = lambda vec: Pey*f._e_pxDeriv_u(src,vec) ex_py_u = lambda vec: Pex*f._e_pyDeriv_u(src,vec) ey_py_u = lambda vec: Pey*f._e_pyDeriv_u(src,vec) # NOTE: Think b_p?Deriv_u should return a 2*nF size matrix hx_px_u = lambda vec: Pbx*f._b_pxDeriv_u(src,vec)/mu_0 hy_px_u = lambda vec: Pby*f._b_pxDeriv_u(src,vec)/mu_0 hx_py_u = lambda vec: Pbx*f._b_pyDeriv_u(src,vec)/mu_0 hy_py_u = lambda vec: Pby*f._b_pyDeriv_u(src,vec)/mu_0 # Update the input vector sDiag = lambda t: Utils.sdiag(mkvc(t,2)) # Define the components of the derivative Hd = sDiag(1./(sDiag(hx_px)*hy_py - sDiag(hx_py)*hy_px)) Hd_uV = sDiag(hy_py)*hx_px_u(v) + sDiag(hx_px)*hy_py_u(v) - sDiag(hx_py)*hy_px_u(v) - sDiag(hy_px)*hx_py_u(v) # Calculate components if 'zxx' in self.rxType: Zij = sDiag(Hd*( sDiag(ex_px)*hy_py - sDiag(ex_py)*hy_px )) ZijN_uV = sDiag(hy_py)*ex_px_u(v) + sDiag(ex_px)*hy_py_u(v) - sDiag(ex_py)*hy_px_u(v) - sDiag(hy_px)*ex_py_u(v) elif 'zxy' in self.rxType: Zij = sDiag(Hd*(-sDiag(ex_px)*hx_py + sDiag(ex_py)*hx_px )) ZijN_uV = -sDiag(hx_py)*ex_px_u(v) - sDiag(ex_px)*hx_py_u(v) + sDiag(ex_py)*hx_px_u(v) + sDiag(hx_px)*ex_py_u(v) elif 'zyx' in self.rxType: Zij = sDiag(Hd*( sDiag(ey_px)*hy_py - sDiag(ey_py)*hy_px )) ZijN_uV = sDiag(hy_py)*ey_px_u(v) + sDiag(ey_px)*hy_py_u(v) - sDiag(ey_py)*hy_px_u(v) - sDiag(hy_px)*ey_py_u(v) elif 'zyy' in self.rxType: Zij = sDiag(Hd*(-sDiag(ey_px)*hx_py + sDiag(ey_py)*hx_px )) ZijN_uV = -sDiag(hx_py)*ey_px_u(v) - sDiag(ey_px)*hx_py_u(v) + sDiag(ey_py)*hx_px_u(v) + sDiag(hx_px)*ey_py_u(v) # Calculate the complex derivative PDeriv_complex = Hd * (ZijN_uV - Zij * Hd_uV ) elif self.projType is 'T3D': if self.locs.ndim == 3: eFLocs = self.locs[:,:,0] bFLocs = self.locs[:,:,1] else: eFLocs = self.locs bFLocs = self.locs # Get the projection Pbx = mesh.getInterpolationMat(bFLocs,'Fx') Pby = mesh.getInterpolationMat(bFLocs,'Fy') Pbz = mesh.getInterpolationMat(bFLocs,'Fz') # Get the fields at location # px: x-polaration and py: y-polaration. bx_px = Pbx*f[src,'b_px'] by_px = Pby*f[src,'b_px'] bz_px = Pbz*f[src,'b_px'] bx_py = Pbx*f[src,'b_py'] by_py = Pby*f[src,'b_py'] bz_py = Pbz*f[src,'b_py'] # Derivatives as lambda functions # NOTE: Think b_p?Deriv_u should return a 2*nF size matrix bx_px_u = lambda vec: Pbx*f._b_pxDeriv_u(src,vec) by_px_u = lambda vec: Pby*f._b_pxDeriv_u(src,vec) bz_px_u = lambda vec: Pbz*f._b_pxDeriv_u(src,vec) bx_py_u = lambda vec: Pbx*f._b_pyDeriv_u(src,vec) by_py_u = lambda vec: Pby*f._b_pyDeriv_u(src,vec) bz_py_u = lambda vec: Pbz*f._b_pyDeriv_u(src,vec) # Update the input vector sDiag = lambda t: Utils.sdiag(mkvc(t,2)) # Define the components of the derivative Hd = sDiag(1./(sDiag(bx_px)*by_py - sDiag(bx_py)*by_px)) Hd_uV = sDiag(by_py)*bx_px_u(v) + sDiag(bx_px)*by_py_u(v) - sDiag(bx_py)*by_px_u(v) - sDiag(by_px)*bx_py_u(v) if 'tzx' in self.rxType: Tij = sDiag(Hd*( - sDiag(by_px)*bz_py + sDiag(by_py)*bz_px )) TijN_uV = -sDiag(by_px)*bz_py_u(v) - sDiag(bz_py)*by_px_u(v) + sDiag(by_py)*bz_px_u(v) + sDiag(bz_px)*by_py_u(v) elif 'tzy' in self.rxType: Tij = sDiag(Hd*( sDiag(bx_px)*bz_py - sDiag(bx_py)*bz_px )) TijN_uV = sDiag(bz_py)*bx_px_u(v) + sDiag(bx_px)*bz_py_u(v) - sDiag(bx_py)*bz_px_u(v) - sDiag(bz_px)*bx_py_u(v) # Calculate the complex derivative PDeriv_complex = Hd * (TijN_uV - Tij * Hd_uV ) # Extract the real number for the real/imag components. Pv = np.array(getattr(PDeriv_complex, real_or_imag)) elif adjoint: # Note: The v vector is real and the return should be complex if self.projType is 'Z1D': Pex = mesh.getInterpolationMat(self.locs[:,-1],'Fx') Pbx = mesh.getInterpolationMat(self.locs[:,-1],'Ex') # ex = Pex*mkvc(f[src,'e_1d'],2) # bx = Pbx*mkvc(f[src,'b_1d'],2)/mu_0 dP_deTv = -mkvc(Pex.T*Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0)).T*v,2) db_duv = Pbx.T/mu_0*Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0))*(Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0))).T*Utils.sdiag(Pex*mkvc(f[src,'e_1d'],2)).T*v dP_dbTv = mkvc(f._bDeriv_u(src,db_duv,adjoint=True),2) PDeriv_real = np.sum(np.hstack((dP_deTv,dP_dbTv)),1) elif self.projType is 'Z2D': raise NotImplementedError('Has not be implement for 2D impedance tensor') elif self.projType is 'Z3D': if self.locs.ndim == 3: eFLocs = self.locs[:,:,0] bFLocs = self.locs[:,:,1] else: eFLocs = self.locs bFLocs = self.locs # Get the projection Pex = mesh.getInterpolationMat(eFLocs,'Ex') Pey = mesh.getInterpolationMat(eFLocs,'Ey') Pbx = mesh.getInterpolationMat(bFLocs,'Fx') Pby = mesh.getInterpolationMat(bFLocs,'Fy') # Get the fields at location # px: x-polaration and py: y-polaration. aex_px = mkvc(mkvc(f[src,'e_px'],2).T*Pex.T) aey_px = mkvc(mkvc(f[src,'e_px'],2).T*Pey.T) aex_py = mkvc(mkvc(f[src,'e_py'],2).T*Pex.T) aey_py = mkvc(mkvc(f[src,'e_py'],2).T*Pey.T) ahx_px = mkvc(mkvc(f[src,'b_px'],2).T/mu_0*Pbx.T) ahy_px = mkvc(mkvc(f[src,'b_px'],2).T/mu_0*Pby.T) ahx_py = mkvc(mkvc(f[src,'b_py'],2).T/mu_0*Pbx.T) ahy_py = mkvc(mkvc(f[src,'b_py'],2).T/mu_0*Pby.T) # Derivatives as lambda functions aex_px_u = lambda vec: f._e_pxDeriv_u(src,Pex.T*vec,adjoint=True) aey_px_u = lambda vec: f._e_pxDeriv_u(src,Pey.T*vec,adjoint=True) aex_py_u = lambda vec: f._e_pyDeriv_u(src,Pex.T*vec,adjoint=True) aey_py_u = lambda vec: f._e_pyDeriv_u(src,Pey.T*vec,adjoint=True) ahx_px_u = lambda vec: f._b_pxDeriv_u(src,Pbx.T*vec,adjoint=True)/mu_0 ahy_px_u = lambda vec: f._b_pxDeriv_u(src,Pby.T*vec,adjoint=True)/mu_0 ahx_py_u = lambda vec: f._b_pyDeriv_u(src,Pbx.T*vec,adjoint=True)/mu_0 ahy_py_u = lambda vec: f._b_pyDeriv_u(src,Pby.T*vec,adjoint=True)/mu_0 # Update the input vector # Define shortcuts sDiag = lambda t: Utils.sdiag(mkvc(t,2)) sVec = lambda t: Utils.sp.csr_matrix(mkvc(t,2)) # Define the components of the derivative aHd = sDiag(1./(sDiag(ahx_px)*ahy_py - sDiag(ahx_py)*ahy_px)) aHd_uV = lambda x: ahx_px_u(sDiag(ahy_py)*x) + ahx_px_u(sDiag(ahy_py)*x) - ahy_px_u(sDiag(ahx_py)*x) - ahx_py_u(sDiag(ahy_px)*x) # Need to fix this to reflect the adjoint if 'zxx' in self.rxType: Zij = sDiag(aHd*( sDiag(ahy_py)*aex_px - sDiag(ahy_px)*aex_py)) ZijN_uV = lambda x: aex_px_u(sDiag(ahy_py)*x) + ahy_py_u(sDiag(aex_px)*x) - ahy_px_u(sDiag(aex_py)*x) - aex_py_u(sDiag(ahy_px)*x) elif 'zxy' in self.rxType: Zij = sDiag(aHd*(-sDiag(ahx_py)*aex_px + sDiag(ahx_px)*aex_py)) ZijN_uV = lambda x:-aex_px_u(sDiag(ahx_py)*x) - ahx_py_u(sDiag(aex_px)*x) + ahx_px_u(sDiag(aex_py)*x) + aex_py_u(sDiag(ahx_px)*x) elif 'zyx' in self.rxType: Zij = sDiag(aHd*( sDiag(ahy_py)*aey_px - sDiag(ahy_px)*aey_py)) ZijN_uV = lambda x: aey_px_u(sDiag(ahy_py)*x) + ahy_py_u(sDiag(aey_px)*x) - ahy_px_u(sDiag(aey_py)*x) - aey_py_u(sDiag(ahy_px)*x) elif 'zyy' in self.rxType: Zij = sDiag(aHd*(-sDiag(ahx_py)*aey_px + sDiag(ahx_px)*aey_py)) ZijN_uV = lambda x:-aey_px_u(sDiag(ahx_py)*x) - ahx_py_u(sDiag(aey_px)*x) + ahx_px_u(sDiag(aey_py)*x) + aey_py_u(sDiag(ahx_px)*x) # Calculate the complex derivative PDeriv_real = ZijN_uV(aHd*v) - aHd_uV(Zij.T*aHd*v)# # NOTE: Need to reshape the output to go from 2*nU array to a (nU,2) matrix for each polarization # PDeriv_real = np.hstack((mkvc(PDeriv_real[:len(PDeriv_real)/2],2),mkvc(PDeriv_real[len(PDeriv_real)/2::],2))) PDeriv_real = PDeriv_real.reshape((2,mesh.nE)).T elif self.projType is 'T3D': if self.locs.ndim == 3: bFLocs = self.locs[:,:,1] else: bFLocs = self.locs # Get the projection Pbx = mesh.getInterpolationMat(bFLocs,'Fx') Pby = mesh.getInterpolationMat(bFLocs,'Fy') Pbz = mesh.getInterpolationMat(bFLocs,'Fz') # Get the fields at location # px: x-polaration and py: y-polaration. abx_px = mkvc(mkvc(f[src,'b_px'],2).T*Pbx.T) aby_px = mkvc(mkvc(f[src,'b_px'],2).T*Pby.T) abz_px = mkvc(mkvc(f[src,'b_px'],2).T*Pbz.T) abx_py = mkvc(mkvc(f[src,'b_py'],2).T*Pbx.T) aby_py = mkvc(mkvc(f[src,'b_py'],2).T*Pby.T) abz_py = mkvc(mkvc(f[src,'b_py'],2).T*Pbz.T) # Derivatives as lambda functions abx_px_u = lambda vec: f._b_pxDeriv_u(src,Pbx.T*vec,adjoint=True) aby_px_u = lambda vec: f._b_pxDeriv_u(src,Pby.T*vec,adjoint=True) abz_px_u = lambda vec: f._b_pxDeriv_u(src,Pbz.T*vec,adjoint=True) abx_py_u = lambda vec: f._b_pyDeriv_u(src,Pbx.T*vec,adjoint=True) aby_py_u = lambda vec: f._b_pyDeriv_u(src,Pby.T*vec,adjoint=True) abz_py_u = lambda vec: f._b_pyDeriv_u(src,Pbz.T*vec,adjoint=True) # Update the input vector # Define shortcuts sDiag = lambda t: Utils.sdiag(mkvc(t,2)) sVec = lambda t: Utils.sp.csr_matrix(mkvc(t,2)) # Define the components of the derivative aHd = sDiag(1./(sDiag(abx_px)*aby_py - sDiag(abx_py)*aby_px)) aHd_uV = lambda x: abx_px_u(sDiag(aby_py)*x) + abx_px_u(sDiag(aby_py)*x) - aby_px_u(sDiag(abx_py)*x) - abx_py_u(sDiag(aby_px)*x) # Need to fix this to reflect the adjoint if 'tzx' in self.rxType: Tij = sDiag(aHd*( -sDiag(abz_py)*aby_px + sDiag(abz_px)*aby_py)) TijN_uV = lambda x: -abz_py_u(sDiag(aby_px)*x) - aby_px_u(sDiag(abz_py)*x) + aby_py_u(sDiag(abz_px)*x) + abz_px_u(sDiag(aby_py)*x) elif 'tzy' in self.rxType: Tij = sDiag(aHd*( sDiag(abz_py)*abx_px - sDiag(abz_px)*abx_py)) TijN_uV = lambda x: abx_px_u(sDiag(abz_py)*x) + abz_py_u(sDiag(abx_px)*x) - abx_py_u(sDiag(abz_px)*x) - abz_px_u(sDiag(abx_py)*x) # Calculate the complex derivative PDeriv_real = TijN_uV(aHd*v) - aHd_uV(Tij.T*aHd*v)# # NOTE: Need to reshape the output to go from 2*nU array to a (nU,2) matrix for each polarization # PDeriv_real = np.hstack((mkvc(PDeriv_real[:len(PDeriv_real)/2],2),mkvc(PDeriv_real[len(PDeriv_real)/2::],2))) PDeriv_real = PDeriv_real.reshape((2,mesh.nE)).T # Extract the data if real_or_imag == 'imag': Pv = 1j*PDeriv_real elif real_or_imag == 'real': Pv = PDeriv_real.astype(complex) return Pv
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 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 animate(ii): #for ii in range(1): removeFrame() # Grab current line and indx = np.where(lineID == ii)[0] srcLeft = [] obs_l = [] obs = [] srcRight = [] obs_r = [] srcList = [] # Split the obs file into left and right # Split the obs file into left and right for jj in range(len(indx)): # Grab corresponding data obs = np.hstack([obs, DCdobs2D.dobs[dataID == indx[jj]]]) #std = dobs2D.std[dataID==indx[jj]] srcList.append(DCdobs2D.srcList[indx[jj]]) Tx = DCdobs2D.srcList[indx[jj]].loc Rx = DCdobs2D.srcList[indx[jj]].rxList[0].locs # Create mid-point location Cmid = (Tx[0][0] + Tx[1][0]) / 2 Pmid = (Rx[0][:, 0] + Rx[1][:, 0]) / 2 ileft = Pmid < Cmid iright = Pmid >= Cmid temp = np.zeros(len(ileft)) temp[ileft] = 1 obs_l = np.hstack([obs_l, temp]) temp = np.zeros(len(iright)) temp[iright] = 1 obs_r = np.hstack([obs_r, temp]) if np.any(ileft): rx = DC.RxDipole(Rx[0][ileft, :], Rx[1][ileft, :]) srcLeft.append(DC.SrcDipole([rx], Tx[0], Tx[1])) #std_l = np.hstack([std_l,std[ileft]]) if np.any(iright): rx = DC.RxDipole(Rx[0][iright, :], Rx[1][iright, :]) srcRight.append(DC.SrcDipole([rx], Tx[0], Tx[1])) #obs_r = np.hstack([obs_r,iright]) #std_r = np.hstack([std_r,std[iright]]) DC2D_full = DC.SurveyDC(srcList) DC2D_full.dobs = np.asarray(obs) DC2D_full.std = DC2D_full.dobs * 0. DC2D_full.std[obs_l == 1] = np.abs(DC2D_full.dobs[obs_l == 1]) * 0.02 + 2e-5 DC2D_full.std[obs_r == 1] = np.abs(DC2D_full.dobs[obs_r == 1]) * 0.06 + 4e-5 # DC2D_l = DC.SurveyDC(srcLeft) # DC2D_l.dobs = np.asarray(obs[obs_l==1]) # DC2D_l.std = np.abs(np.asarray(DC2D_l.dobs))*0.05 + 2e-5 # # DC2D_r = DC.SurveyDC(srcRight) # DC2D_r.dobs = np.asarray(obs[obs_r==1]) # DC2D_r.std = np.abs(np.asarray(DC2D_r.dobs))*0.05 + 2e-5 survey = DC2D_full # Export data file DC.writeUBC_DCobs(inv_dir + dsep + obsfile2d, survey, '2D', 'SIMPLE') # Write input file fid = open(inv_dir + dsep + inp_file, 'w') fid.write('OBS LOC_X %s \n' % obsfile2d) fid.write('MESH FILE %s \n' % mshfile2d) fid.write('CHIFACT 1 \n') fid.write('TOPO DEFAULT \n') fid.write('INIT_MOD VALUE %e\n' % ini_mod) fid.write('REF_MOD VALUE %e\n' % ref_mod) fid.write('ALPHA VALUE %f %f %F\n' % (1. / dx**4., 1, 1)) fid.write('WEIGHT DEFAULT\n') fid.write('STORE_ALL_MODELS FALSE\n') fid.write('INVMODE CG\n') #fid.write('CG_PARAM 200 1e-4\n') fid.write('USE_MREF FALSE\n') #fid.write('BOUNDS VALUE 1e-4 1e+2\n') fid.close() os.chdir(inv_dir) os.system('dcinv2d ' + inp_file) #%% Load DC model and predicted data minv = DC.readUBC_DC2DModel(inv_dir + dsep + 'dcinv2d.con') minv = np.reshape(minv, (mesh2d.nCy, mesh2d.nCx)) #%% Repeat for IP data indx = np.where(IPlineID == ii)[0] srcLeft = [] obs_l = [] std_l = [] srcRight = [] obs_r = [] std_r = [] obs_full = [] std_full = [] srcList = [] # Split the obs file into left and right for jj in range(len(indx)): srcList.append(IPdobs2D.srcList[indx[jj]]) # Grab corresponding data obs = IPdobs2D.dobs[IPdataID == indx[jj]] std = IPdobs2D.std[IPdataID == indx[jj]] obs_full = np.hstack([obs_full, obs]) std_full = np.hstack([std_full, std]) Tx = IPdobs2D.srcList[indx[jj]].loc Rx = IPdobs2D.srcList[indx[jj]].rxList[0].locs # Create mid-point location Cmid = (Tx[0][0] + Tx[1][0]) / 2 Pmid = (Rx[0][:, 0] + Rx[1][:, 0]) / 2 ileft = Pmid < Cmid iright = Pmid >= Cmid temp = np.zeros(len(ileft)) temp[ileft] = 1 obs_l = np.hstack([obs_l, temp]) temp = np.zeros(len(iright)) temp[iright] = 1 obs_r = np.hstack([obs_r, temp]) if np.any(ileft): rx = DC.RxDipole(Rx[0][ileft, :], Rx[1][ileft, :]) srcLeft.append(DC.SrcDipole([rx], Tx[0], Tx[1])) #std_l = np.hstack([std_l,std[ileft]]) if np.any(iright): rx = DC.RxDipole(Rx[0][iright, :], Rx[1][iright, :]) srcRight.append(DC.SrcDipole([rx], Tx[0], Tx[1])) IP2D_full = DC.SurveyDC(srcList) IP2D_full.dobs = np.asarray(obs_full) IP2D_full.std = np.asarray(std_full) IP2D_l = DC.SurveyDC(srcLeft) IP2D_l.dobs = np.asarray(obs_full[obs_l == 1]) #IP2D_l.std = np.abs(np.asarray(obs_l))*0.03 + 2e-2 IP2D_r = DC.SurveyDC(srcRight) IP2D_r.dobs = np.asarray(obs_full[obs_r == 1]) #IP2D_r.std = np.abs(np.asarray(obs_r))*0.03 + 1e-2 id_lbe = int(IPsurvey.srcList[indx[jj]].loc[0][1]) mesh3d = Mesh.TensorMesh([hx, np.ones(1) * 100., hz], x0=(-np.sum(padx) + np.min(srcMat[0][:, 0]), id_lbe - 50, np.max(srcMat[0][0, 2]) - np.sum(hz))) Mesh.TensorMesh.writeUBC(mesh3d, home_dir + dsep + 'Mesh' + str(id_lbe) + '.msh') global ax1, ax2, ax3, ax5, ax6, fig ax2 = plt.subplot(3, 2, 2) ph = DC.plot_pseudoSection(IP2D_r, ax2, stype='pdp', dtype='volt', colorbar=False) ax2.set_title('Observed P-DP', fontsize=10) plt.xlim([xmin, xmax]) plt.ylim([zmin, zmax]) plt.gca().set_aspect('equal', adjustable='box') ax2.set_xticklabels([]) ax2.set_yticklabels([]) ax1 = plt.subplot(3, 2, 1) DC.plot_pseudoSection(IP2D_l, ax1, stype='pdp', dtype='volt', clim=(ph[0].get_clim()[0], ph[0].get_clim()[1]), colorbar=False) ax1.set_title('Observed DP-P', fontsize=10) plt.xlim([xmin, xmax]) plt.ylim([zmin, zmax]) plt.gca().set_aspect('equal', adjustable='box') ax1.set_xticklabels([]) z = np.linspace(np.min(ph[2]), np.max(ph[2]), 5) z_label = np.linspace(20, 1, 5) ax1.set_yticks(map(int, z)) ax1.set_yticklabels(map(str, map(int, z_label)), size=8) ax1.set_ylabel('n-spacing', fontsize=8) #%% Add labels bbox_props = dict(boxstyle="circle,pad=0.3", fc="r", ec="k", lw=1) ax2.text(0.00, 1, 'A', transform=ax2.transAxes, ha="left", va="center", size=6, bbox=bbox_props) bbox_props = dict(boxstyle="circle,pad=0.3", fc="y", ec="k", lw=1) ax2.text(0.1, 1, 'M', transform=ax2.transAxes, ha="left", va="center", size=6, bbox=bbox_props) bbox_props = dict(boxstyle="circle,pad=0.3", fc="g", ec="k", lw=1) ax2.text(0.2, 1, 'N', transform=ax2.transAxes, ha="left", va="center", size=6, bbox=bbox_props) bbox_props = dict(boxstyle="circle,pad=0.3", fc="g", ec="k", lw=1) ax1.text(0.00, 1, 'N', transform=ax1.transAxes, ha="left", va="center", size=6, bbox=bbox_props) bbox_props = dict(boxstyle="circle,pad=0.3", fc="y", ec="k", lw=1) ax1.text(0.1, 1, 'M', transform=ax1.transAxes, ha="left", va="center", size=6, bbox=bbox_props) bbox_props = dict(boxstyle="circle,pad=0.3", fc="r", ec="k", lw=1) ax1.text(0.2, 1, 'A', transform=ax1.transAxes, ha="left", va="center", size=6, bbox=bbox_props) survey = IP2D_full # Export data file DC.writeUBC_DCobs(inv_dir + dsep + ipfile2d, survey, '2D', 'SIMPLE', iptype=1) fid = open(inv_dir + dsep + inp_file, 'w') fid.write('OBS LOC_X %s \n' % ipfile2d) fid.write('MESH FILE %s \n' % mshfile2d) fid.write('CHIFACT 4 \n') fid.write('COND FILE dcinv2d.con\n') fid.write('TOPO DEFAULT \n') fid.write('INIT_MOD VALUE %e\n' % ini_mod) fid.write('REF_MOD VALUE 0.0\n') fid.write('ALPHA VALUE %f %f %F\n' % (1. / dx**4., 1, 1)) fid.write('WEIGHT DEFAULT\n') fid.write('STORE_ALL_MODELS FALSE\n') fid.write('INVMODE CG\n') #fid.write('CG_PARAM 200 1e-4\n') fid.write('USE_MREF FALSE\n') #fid.write('BOUNDS VALUE 1e-4 1e+2\n') fid.close() os.chdir(inv_dir) os.system('ipinv2d ' + inp_file) #%% Load model and predicted data minv = DC.readUBC_DC2DModel(inv_dir + dsep + 'ipinv2d.chg') minv = np.reshape(minv, (mesh2d.nCy, mesh2d.nCx)) Mesh.TensorMesh.writeModelUBC( mesh3d, home_dir + dsep + 'Model' + str(id_lbe) + '.chg', minv.T) dpre = DC.readUBC_DC2Dpre(inv_dir + dsep + 'ipinv2d.pre') DCpre = dpre['DCsurvey'] DCtemp = IP2D_l DCtemp.dobs = DCpre.dobs[obs_l == 1] ax5 = plt.subplot(3, 2, 3) DC.plot_pseudoSection(DCtemp, ax5, stype='pdp', dtype='volt', clim=(ph[0].get_clim()[0], ph[0].get_clim()[1]), colorbar=False) ax5.set_title('Predicted', fontsize=10) plt.xlim([xmin, xmax]) plt.ylim([zmin, zmax]) plt.gca().set_aspect('equal', adjustable='box') ax5.set_xticklabels([]) z = np.linspace(np.min(ph[2]), np.max(ph[2]), 5) z_label = np.linspace(20, 1, 5) ax5.set_yticks(map(int, z)) ax5.set_yticklabels(map(str, map(int, z_label)), size=8) ax5.set_ylabel('n-spacing', fontsize=8) DCtemp = IP2D_r DCtemp.dobs = DCpre.dobs[obs_r == 1] ax6 = plt.subplot(3, 2, 4) DC.plot_pseudoSection(DCtemp, ax6, stype='pdp', dtype='volt', clim=(ph[0].get_clim()[0], ph[0].get_clim()[1]), colorbar=False) ax6.set_title('Predicted', fontsize=10) plt.xlim([xmin, xmax]) plt.ylim([zmin, zmax]) plt.gca().set_aspect('equal', adjustable='box') ax6.set_xticklabels([]) ax6.set_yticklabels([]) pos = ax6.get_position() cbarax = fig.add_axes([ pos.x0 + 0.325, pos.y0 + 0.2, pos.width * 0.1, pos.height * 0.5 ]) ## the parameters are the specified position you set cb = fig.colorbar(ph[0], cax=cbarax, orientation="vertical", ax=ax6, ticks=np.linspace(ph[0].get_clim()[0], ph[0].get_clim()[1], 4), format="$10^{%.1f}$") cb.set_label("App. Charg.", size=8) ax3 = plt.subplot(3, 1, 3) ax3.set_title('2-D Model (S/m)', fontsize=10) ax3.set_xticks(map(int, x)) ax3.set_xticklabels(map(str, map(int, x))) ax3.set_xlabel('Easting (m)', fontsize=8) ax3.set_yticks(map(int, z)) ax3.set_yticklabels(map(str, map(int, z)), rotation='vertical') ax3.set_ylabel('Depth (m)', fontsize=8) plt.xlim([xmin, xmax]) plt.ylim([zmin / 2, zmax]) plt.gca().set_aspect('equal', adjustable='box') ph2 = plt.pcolormesh(mesh2d.vectorNx, mesh2d.vectorNy, (minv), vmin=vmin, vmax=vmax) plt.gca().tick_params(axis='both', which='major', labelsize=8) plt.draw() for ss in range(survey.nSrc): Tx = survey.srcList[ss].loc[0] plt.scatter(Tx[0], mesh2d.vectorNy[-1] + 10, s=10) pos = ax3.get_position() ax3.set_position([pos.x0 + 0.025, pos.y0, pos.width, pos.height]) pos = ax3.get_position() cbarax = fig.add_axes([ pos.x0 + 0.65, pos.y0 + 0.01, pos.width * 0.05, pos.height * 0.75 ]) ## the parameters are the specified position you set cb = fig.colorbar(ph2, cax=cbarax, orientation="vertical", ax=ax3, ticks=np.linspace(vmin, vmax, 4), format="%4.1f") cb.set_label("Chargeability", size=8) pos = ax1.get_position() ax1.set_position([pos.x0 + 0.03, pos.y0, pos.width, pos.height]) pos = ax5.get_position() ax5.set_position([pos.x0 + 0.03, pos.y0, pos.width, pos.height]) pos = ax2.get_position() ax2.set_position([pos.x0 - 0.03, pos.y0, pos.width, pos.height]) pos = ax6.get_position() ax6.set_position([pos.x0 - 0.03, pos.y0, pos.width, pos.height]) #%% Add the extra bbox_props = dict(boxstyle="rarrow,pad=0.3", fc="w", ec="k", lw=2) ax2.text(0.01, (float(ii) + 1.) / (len(uniqueID) + 2), 'N: ' + str(id_lbe), transform=fig.transFigure, ha="left", va="center", size=8, bbox=bbox_props) mrk_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=2) ax2.text(0.01, 0.9, 'Line ID#', transform=fig.transFigure, ha="left", va="center", size=8, bbox=mrk_props) mrk_props = dict(boxstyle="square,pad=0.3", fc="b", ec="k", lw=2) for jj in range(len(uniqueID)): ax2.text(0.1, (float(jj) + 1.) / (len(uniqueID) + 2), ".", transform=fig.transFigure, ha="right", va="center", size=8, bbox=mrk_props) mrk_props = dict(boxstyle="square,pad=0.3", fc="r", ec="k", lw=2) ax2.text(0.1, (float(ii) + 1.) / (len(uniqueID) + 2), ".", transform=fig.transFigure, ha="right", va="center", size=8, bbox=mrk_props)
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 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 Jvec(self, m, v, f=None): """ Jvec computes the sensitivity times a vector .. math:: \mathbf{J} \mathbf{v} = \\frac{d\mathbf{P}}{d\mathbf{F}} \left( \\frac{d\mathbf{F}}{d\mathbf{u}} \\frac{d\mathbf{u}}{d\mathbf{m}} + \\frac{\partial\mathbf{F}}{\partial\mathbf{m}} \\right) \mathbf{v} where .. math:: \mathbf{A} \\frac{d\mathbf{u}}{d\mathbf{m}} + \\frac{\partial \mathbf{A}(\mathbf{u}, \mathbf{m})} {\partial\mathbf{m}} = \\frac{d \mathbf{RHS}}{d \mathbf{m}} """ if f is None: f = self.fields(m) ftype = self._fieldType + 'Solution' # the thing we solved for self.model = m # mat to store previous time-step's solution deriv times a vector for # each source # size: nu x nSrc # this is a bit silly # if self._fieldType is 'b' or self._fieldType is 'j': # ifields = np.zeros((self.mesh.nF, len(Srcs))) # elif self._fieldType is 'e' or self._fieldType is 'h': # ifields = np.zeros((self.mesh.nE, len(Srcs))) # for i, src in enumerate(self.survey.srcList): dun_dm_v = np.hstack([ Utils.mkvc( self.getInitialFieldsDeriv(src, v), 2 ) for src in self.survey.srcList ]) # can over-write this at each timestep # store the field derivs we need to project to calc full deriv df_dm_v = Fields_Derivs(self.mesh, self.survey) Adiaginv = None for tInd, dt in zip(range(self.nT), self.timeSteps): # keep factors if dt is the same as previous step b/c A will be the # same if Adiaginv is not None and (tInd > 0 and dt != self.timeSteps[tInd - 1]): Adiaginv.clean() Adiaginv = None if Adiaginv is None: A = self.getAdiag(tInd) Adiaginv = self.Solver(A, **self.solverOpts) Asubdiag = self.getAsubdiag(tInd) for i, src in enumerate(self.survey.srcList): # here, we are lagging by a timestep, so filling in as we go for projField in set([rx.projField for rx in src.rxList]): df_dmFun = getattr(f, '_%sDeriv' % projField, None) # df_dm_v is dense, but we only need the times at # (rx.P.T * ones > 0) # This should be called rx.footprint df_dm_v[src, '{}Deriv'.format(projField), tInd] = df_dmFun( tInd, src, dun_dm_v[:, i], v ) un_src = f[src, ftype, tInd+1] # cell centered on time mesh dA_dm_v = self.getAdiagDeriv(tInd, un_src, v) # on nodes of time mesh dRHS_dm_v = self.getRHSDeriv(tInd+1, src, v) dAsubdiag_dm_v = self.getAsubdiagDeriv( tInd, f[src, ftype, tInd], v ) JRHS = dRHS_dm_v - dAsubdiag_dm_v - dA_dm_v # step in time and overwrite if tInd != len(self.timeSteps+1): dun_dm_v[:, i] = Adiaginv * ( JRHS - Asubdiag * dun_dm_v[:, i] ) Jv = [] for src in self.survey.srcList: for rx in src.rxList: Jv.append( rx.evalDeriv(src, self.mesh, self.timeMesh, f, Utils.mkvc( df_dm_v[src, '%sDeriv' % rx.projField, :] ) ) ) Adiaginv.clean() # del df_dm_v, dun_dm_v, Asubdiag # return Utils.mkvc(Jv) return np.hstack(Jv)
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 toRecArray(self, returnType='RealImag'): ''' Function that returns a numpy.recarray for a SimpegMT impedance data object. :param str returnType: Switches between returning a rec array where the impedance is split to real and imaginary ('RealImag') or is a complex ('Complex') ''' # Define the record fields dtRI = [('freq', float), ('x', float), ('y', float), ('z', float), ('zxxr', float), ('zxxi', float), ('zxyr', float), ('zxyi', float), ('zyxr', float), ('zyxi', float), ('zyyr', float), ('zyyi', float), ('tzxr', float), ('tzxi', float), ('tzyr', float), ('tzyi', float)] dtCP = [('freq', float), ('x', float), ('y', float), ('z', float), ('zxx', complex), ('zxy', complex), ('zyx', complex), ('zyy', complex), ('tzx', complex), ('tzy', complex)] impList = [ 'zxxr', 'zxxi', 'zxyr', 'zxyi', 'zyxr', 'zyxi', 'zyyr', 'zyyi' ] for src in self.survey.srcList: # Temp array for all the receivers of the source. # Note: needs to be written more generally, using diffterent rxTypes and not all the data at the locaitons # Assume the same locs for all RX locs = src.rxList[0].locs if locs.shape[1] == 1: locs = np.hstack((np.array([[0.0, 0.0]]), locs)) elif locs.shape[1] == 2: locs = np.hstack((np.array([[0.0]]), locs)) tArrRec = np.concatenate((src.freq * np.ones( (locs.shape[0], 1)), locs, np.nan * np.ones( (locs.shape[0], 12))), axis=1).view(dtRI) # np.array([(src.freq,rx.locs[0,0],rx.locs[0,1],rx.locs[0,2],np.nan ,np.nan ,np.nan ,np.nan ,np.nan ,np.nan ,np.nan ,np.nan ) for rx in src.rxList],dtype=dtRI) # Get the type and the value for the DataMT object as a list typeList = [[rx.rxType.replace('z1d', 'zyx'), self[src, rx]] for rx in src.rxList] # Insert the values to the temp array for nr, (key, val) in enumerate(typeList): tArrRec[key] = mkvc(val, 2) # Masked array mArrRec = np.ma.MaskedArray( rec2ndarr(tArrRec), mask=np.isnan(rec2ndarr(tArrRec))).view(dtype=tArrRec.dtype) # Unique freq and loc of the masked array uniFLmarr = np.unique(mArrRec[['freq', 'x', 'y', 'z']]).copy() try: outTemp = recFunc.stack_arrays((outTemp, mArrRec)) #outTemp = np.concatenate((outTemp,dataBlock),axis=0) except NameError as e: outTemp = mArrRec if 'RealImag' in returnType: outArr = outTemp elif 'Complex' in returnType: # Add the real and imaginary to a complex number outArr = np.empty(outTemp.shape, dtype=dtCP) for comp in ['freq', 'x', 'y', 'z']: outArr[comp] = outTemp[comp].copy() for comp in ['zxx', 'zxy', 'zyx', 'zyy', 'tzx', 'tzy']: outArr[comp] = outTemp[ comp + 'r'].copy() + 1j * outTemp[comp + 'i'].copy() else: raise NotImplementedError( '{:s} is not implemented, as to be RealImag or Complex.') # Return return outArr
def Jvec(self, m, v, f=None): """ Jvec computes the sensitivity times a vector .. math:: \mathbf{J} \mathbf{v} = \\frac{d\mathbf{P}}{d\mathbf{F}} \left( \\frac{d\mathbf{F}}{d\mathbf{u}} \\frac{d\mathbf{u}}{d\mathbf{m}} + \\frac{\partial\mathbf{F}}{\partial\mathbf{m}} \\right) \mathbf{v} where .. math:: \mathbf{A} \\frac{d\mathbf{u}}{d\mathbf{m}} + \\frac{\partial \mathbf{A}(\mathbf{u}, \mathbf{m})} {\partial\mathbf{m}} = \\frac{d \mathbf{RHS}}{d \mathbf{m}} """ if f is None: f = self.fields(m) ftype = self._fieldType + 'Solution' # the thing we solved for self.curModel = m # mat to store previous time-step's solution deriv times a vector for # each source # size: nu x nSrc # this is a bit silly # if self._fieldType is 'b' or self._fieldType is 'j': # ifields = np.zeros((self.mesh.nF, len(Srcs))) # elif self._fieldType is 'e' or self._fieldType is 'h': # ifields = np.zeros((self.mesh.nE, len(Srcs))) # for i, src in enumerate(self.survey.srcList): dun_dm_v = np.hstack([Utils.mkvc(self.getInitialFieldsDeriv(src, v), 2) for src in self.survey.srcList] ) # can over-write this at each timestep # store the field derivs we need to project to calc full deriv df_dm_v = Fields_Derivs(self.mesh, self.survey) Adiaginv = None for tInd, dt in zip(range(self.nT), self.timeSteps): # keep factors if dt is the same as previous step b/c A will be the # same if Adiaginv is not None and (tInd > 0 and dt != self.timeSteps[tInd - 1]): Adiaginv.clean() Adiaginv = None if Adiaginv is None: A = self.getAdiag(tInd) Adiaginv = self.Solver(A, **self.solverOpts) Asubdiag = self.getAsubdiag(tInd) for i, src in enumerate(self.survey.srcList): # here, we are lagging by a timestep, so filling in as we go for projField in set([rx.projField for rx in src.rxList]): # Seogi: df_duFun? df_dmFun = getattr(f, '_%sDeriv' % projField, None) # df_dm_v is dense, but we only need the times at # (rx.P.T * ones > 0) # This should be called rx.footprint df_dm_v[src, '{}Deriv'.format(projField), tInd] = df_dmFun( tInd, src, dun_dm_v[:, i], v ) un_src = f[src, ftype, tInd+1] # cell centered on time mesh dA_dm_v = self.getAdiagDeriv(tInd, un_src, v) # on nodes of time mesh dRHS_dm_v = self.getRHSDeriv(tInd+1, src, v) dAsubdiag_dm_v = self.getAsubdiagDeriv(tInd, f[src, ftype, tInd], v) JRHS = dRHS_dm_v - dAsubdiag_dm_v - dA_dm_v # step in time and overwrite if tInd != len(self.timeSteps+1): dun_dm_v[:, i] = Adiaginv * (JRHS - Asubdiag * dun_dm_v[:, i]) Jv = [] for src in self.survey.srcList: for rx in src.rxList: Jv.append(rx.evalDeriv(src, self.mesh, self.timeMesh, Utils.mkvc(df_dm_v[src, '%sDeriv' % rx.projField, :]) )) Adiaginv.clean() # del df_dm_v, dun_dm_v, Asubdiag # return Utils.mkvc(Jv) return np.hstack(Jv)
def interpFFT(x, y, m): """ Load in a 2D grid and resample OUTPUT: m_out """ from SimPEG import np, sp import scipy.signal as sn # Add padding values by reflection (2**n) lenx = np.round(np.log2(2 * len(x))) npadx = int(np.floor((2**lenx - len(x)) / 2.)) #Create hemming taper if np.mod(npadx * 2 + len(x), 2) != 0: oddx = 1 else: oddx = 0 tap0 = sn.hamming(npadx * 2) tapl = sp.spdiags(tap0[0:npadx], 0, npadx, npadx) tapr = sp.spdiags(tap0[npadx:], 0, npadx, npadx + oddx) # Mirror the 2d data over the half lenght and apply 0-taper mpad = np.hstack( [np.fliplr(m[:, 0:npadx]) * tapl, m, np.fliplr(m[:, -npadx:]) * tapr]) # Repeat along the second dimension leny = np.round(np.log2(2 * len(y))) npady = int(np.floor((2**leny - len(y)) / 2.)) #Create hemming taper if np.mod(npady * 2 + len(y), 2) != 0: oddy = 1 else: oddy = 0 tap0 = sn.hamming(npady * 2) tapu = sp.spdiags(tap0[0:npady], 0, npady, npady) tapd = sp.spdiags(tap0[npady:], 0, npady + oddy, npady) mpad = np.vstack([ tapu * np.flipud(mpad[0:npady, :]), mpad, tapd * np.flipud(mpad[-npady:, :]) ]) # Compute FFT FFTm = np.fft.fft2(mpad) # Do an FFT shift FFTshift = np.fft.fftshift(FFTm) # Pad high frequencies with zeros to increase the sampling rate py = int(FFTm.shape[0] / 2) px = int(FFTm.shape[1] / 2) FFTshift = np.hstack([ np.zeros((FFTshift.shape[0], px)), FFTshift, np.zeros((FFTshift.shape[0], px)) ]) FFTshift = np.vstack([ np.zeros((py, FFTshift.shape[1])), FFTshift, np.zeros((py, FFTshift.shape[1])) ]) # Inverse shift FFTm = np.fft.ifftshift(FFTshift) # Compute inverse FFT IFFTm = np.fft.ifft2(FFTm) * FFTm.size / mpad.size m_out = np.real(IFFTm) # Extract core #m_out = np.real(IFFTm[npady*2:-(npady*2+oddy+1),npadx*2:-(npadx*2+oddx+1)]) m_out = m_out[npady * 2:-(npady + oddy) * 2, npadx * 2:-(npadx + oddx) * 2] if np.mod(m.shape[0], 2) != 0: m_out = m_out[:-1, :] if np.mod(m.shape[1], 2) != 0: m_out = m_out[:, :-1] return m_out
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)))