def bPrimary(self, prob): eqLocs = prob._eqLocs if eqLocs is 'FE': gridX = prob.mesh.gridFx gridY = prob.mesh.gridFy gridZ = prob.mesh.gridFz C = prob.mesh.edgeCurl elif eqLocs is 'EF': gridX = prob.mesh.gridEx gridY = prob.mesh.gridEy gridZ = prob.mesh.gridEz C = prob.mesh.edgeCurl.T srcfct = SrcUtils.MagneticDipoleFields if prob.mesh._meshType is 'CYL': if not prob.mesh.isSymmetric: # TODO ? raise NotImplementedError('Non-symmetric cyl mesh not implemented yet!') bx = srcfct(self.loc, gridX, 'x', mu=self.mu, moment=self.moment) bz = srcfct(self.loc, gridZ, 'z', mu=self.mu, moment=self.moment) b = np.concatenate((bx,bz)) else: bx = srcfct(self.loc, gridX, 'x', mu=self.mu, moment=self.moment) by = srcfct(self.loc, gridY, 'y', mu=self.mu, moment=self.moment) bz = srcfct(self.loc, gridZ, 'z', mu=self.mu, moment=self.moment) b = np.concatenate((bx,by,bz)) return b
def _bfromVectorPotential(self, prob): if prob._eqLocs is 'FE': gridX = prob.mesh.gridEx gridY = prob.mesh.gridEy gridZ = prob.mesh.gridEz C = prob.mesh.edgeCurl elif prob._eqLocs is 'EF': gridX = prob.mesh.gridFx gridY = prob.mesh.gridFy gridZ = prob.mesh.gridFz C = prob.mesh.edgeCurl.T if prob.mesh._meshType is 'CYL': if not prob.mesh.isSymmetric: raise NotImplementedError('Non-symmetric cyl mesh not ' 'implemented yet!') a = MagneticLoopVectorPotential(self.loc, gridY, 'y', radius=self.radius, mu=self.mu) else: srcfct = MagneticLoopVectorPotential ax = srcfct(self.loc, gridX, 'x', mu=self.mu, radius=self.radius) ay = srcfct(self.loc, gridY, 'y', mu=self.mu, radius=self.radius) az = srcfct(self.loc, gridZ, 'z', mu=self.mu, radius=self.radius) a = np.concatenate((ax, ay, az)) return C*a
def tovec(self): val = [] for src in self.survey.srcList: for rx in src.rxList: for t in rx.times: val.append(self[src, rx, t]) return np.concatenate(val)
def bPrimary(self, prob): eqLocs = prob._eqLocs if eqLocs is 'FE': gridX = prob.mesh.gridEx gridY = prob.mesh.gridEy gridZ = prob.mesh.gridEz C = prob.mesh.edgeCurl elif eqLocs is 'EF': gridX = prob.mesh.gridFx gridY = prob.mesh.gridFy gridZ = prob.mesh.gridFz C = prob.mesh.edgeCurl.T if prob.mesh._meshType is 'CYL': if not prob.mesh.isSymmetric: # TODO ? raise NotImplementedError('Non-symmetric cyl mesh not implemented yet!') a = SrcUtils.MagneticDipoleVectorPotential(self.loc, gridY, 'y', moment=self.radius, mu=self.mu) else: srcfct = SrcUtils.MagneticDipoleVectorPotential ax = srcfct(self.loc, gridX, 'x', self.radius, mu=self.mu) ay = srcfct(self.loc, gridY, 'y', self.radius, mu=self.mu) az = srcfct(self.loc, gridZ, 'z', self.radius, mu=self.mu) a = np.concatenate((ax, ay, az)) return C*a
def _bfromVectorPotential(self, prob): if prob._eqLocs is 'FE': gridX = prob.mesh.gridEx gridY = prob.mesh.gridEy gridZ = prob.mesh.gridEz C = prob.mesh.edgeCurl elif prob._eqLocs is 'EF': gridX = prob.mesh.gridFx gridY = prob.mesh.gridFy gridZ = prob.mesh.gridFz C = prob.mesh.edgeCurl.T if prob.mesh._meshType is 'CYL': if not prob.mesh.isSymmetric: raise NotImplementedError('Non-symmetric cyl mesh not ' 'implemented yet!') a = MagneticLoopVectorPotential(self.loc, gridY, 'y', radius=self.radius, mu=self.mu) else: srcfct = MagneticLoopVectorPotential ax = srcfct(self.loc, gridX, 'x', mu=self.mu, radius=self.radius) ay = srcfct(self.loc, gridY, 'y', mu=self.mu, radius=self.radius) az = srcfct(self.loc, gridZ, 'z', mu=self.mu, radius=self.radius) a = np.concatenate((ax, ay, az)) return C * a
def __getitem__(self, key): src, rx, t = self._ensureCorrectKey(key) if rx is not None: if rx not in self._dataDict[src]: raise Exception('Data for receiver has not yet been set.') return self._dataDict[src][rx][t] return np.concatenate([self[src, rx, t] for rx in src.rxList])
def __getitem__(self, key): src, rx, t = self._ensureCorrectKey(key) if rx is not None: if rx not in self._dataDict[src]: raise Exception('Data for receiver has not yet been set.') return self._dataDict[src][rx][t] return np.concatenate([self[src,rx, t] for rx in src.rxList])
def gridCC(self): """ Cell-centered grid """ if getattr(self, '_gridCC', None) is None: self._gridCC = np.concatenate([self.aveN2CC*self.gridN[:, i] for i in range(self.dim)]).reshape( (-1, self.dim), order='F') return self._gridCC
def gridCC(self): """ Cell-centered grid """ if getattr(self, '_gridCC', None) is None: self._gridCC = np.concatenate([ self.aveN2CC * self.gridN[:, i] for i in range(self.dim) ]).reshape((-1, self.dim), order='F') return self._gridCC
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 bPrimary(self, prob): """ The primary magnetic flux density from the analytic solution for magnetic fields from a dipole :param Problem prob: FDEM problem :rtype: numpy.ndarray :return: primary magnetic field """ formulation = prob._formulation if formulation is 'EB': gridX = prob.mesh.gridFx gridY = prob.mesh.gridFy gridZ = prob.mesh.gridFz C = prob.mesh.edgeCurl elif formulation is 'HJ': gridX = prob.mesh.gridEx gridY = prob.mesh.gridEy gridZ = prob.mesh.gridEz C = prob.mesh.edgeCurl.T srcfct = MagneticDipoleFields if prob.mesh._meshType is 'CYL': if not prob.mesh.isSymmetric: # TODO ? raise NotImplementedError( 'Non-symmetric cyl mesh not implemented yet!') bx = srcfct(self.loc, gridX, 'x', mu=self.mu, moment=self.moment) bz = srcfct(self.loc, gridZ, 'z', mu=self.mu, moment=self.moment) b = np.concatenate((bx, bz)) else: bx = srcfct(self.loc, gridX, 'x', mu=self.mu, moment=self.moment) by = srcfct(self.loc, gridY, 'y', mu=self.mu, moment=self.moment) bz = srcfct(self.loc, gridZ, 'z', mu=self.mu, moment=self.moment) b = np.concatenate((bx, by, bz)) return b
def bPrimary(self, prob): """ The primary magnetic flux density from the analytic solution for magnetic fields from a dipole :param BaseFDEMProblem prob: FDEM problem :rtype: numpy.ndarray :return: primary magnetic field """ formulation = prob._formulation if formulation is 'EB': gridX = prob.mesh.gridFx gridY = prob.mesh.gridFy gridZ = prob.mesh.gridFz C = prob.mesh.edgeCurl elif formulation is 'HJ': gridX = prob.mesh.gridEx gridY = prob.mesh.gridEy gridZ = prob.mesh.gridEz C = prob.mesh.edgeCurl.T srcfct = MagneticDipoleFields if prob.mesh._meshType is 'CYL': if not prob.mesh.isSymmetric: # TODO ? raise NotImplementedError('Non-symmetric cyl mesh not implemented yet!') bx = srcfct(self.loc, gridX, 'x', mu=self.mu, moment=self.moment) bz = srcfct(self.loc, gridZ, 'z', mu=self.mu, moment=self.moment) b = np.concatenate((bx,bz)) else: bx = srcfct(self.loc, gridX, 'x', mu=self.mu, moment=self.moment) by = srcfct(self.loc, gridY, 'y', mu=self.mu, moment=self.moment) bz = srcfct(self.loc, gridZ, 'z', mu=self.mu, moment=self.moment) b = np.concatenate((bx,by,bz)) return b
def bPrimary(self, prob): """ The primary magnetic flux density from the analytic solution for magnetic fields from a dipole :param BaseFDEMProblem prob: FDEM problem :rtype: numpy.ndarray :return: primary magnetic field """ formulation = prob._formulation if formulation is "EB": gridX = prob.mesh.gridFx gridY = prob.mesh.gridFy gridZ = prob.mesh.gridFz elif formulation is "HJ": gridX = prob.mesh.gridEx gridY = prob.mesh.gridEy gridZ = prob.mesh.gridEz srcfct = MagneticDipoleFields if prob.mesh._meshType is "CYL": if not prob.mesh.isSymmetric: # TODO ? raise NotImplementedError("Non-symmetric cyl mesh not implemented yet!") bx = srcfct(self.loc, gridX, "x", mu=self.mu, moment=self.moment) bz = srcfct(self.loc, gridZ, "z", mu=self.mu, moment=self.moment) b = np.concatenate((bx, bz)) else: bx = srcfct(self.loc, gridX, "x", mu=self.mu, moment=self.moment) by = srcfct(self.loc, gridY, "y", mu=self.mu, moment=self.moment) bz = srcfct(self.loc, gridZ, "z", mu=self.mu, moment=self.moment) b = np.concatenate((bx, by, bz)) return Utils.mkvc(b)
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 bPrimary(self, prob): """ The primary magnetic flux density from a magnetic vector potential :param Problem prob: FDEM problem :rtype: numpy.ndarray :return: primary magnetic field """ formulation = prob._formulation if formulation is 'EB': gridX = prob.mesh.gridEx gridY = prob.mesh.gridEy gridZ = prob.mesh.gridEz C = prob.mesh.edgeCurl elif formulation is 'HJ': gridX = prob.mesh.gridFx gridY = prob.mesh.gridFy gridZ = prob.mesh.gridFz C = prob.mesh.edgeCurl.T if prob.mesh._meshType is 'CYL': if not prob.mesh.isSymmetric: # TODO ? raise NotImplementedError( 'Non-symmetric cyl mesh not implemented yet!') a = MagneticDipoleVectorPotential(self.loc, gridY, 'y', moment=self.radius, mu=self.mu) else: srcfct = MagneticDipoleVectorPotential ax = srcfct(self.loc, gridX, 'x', self.radius, mu=self.mu) ay = srcfct(self.loc, gridY, 'y', self.radius, mu=self.mu) az = srcfct(self.loc, gridZ, 'z', self.radius, mu=self.mu) a = np.concatenate((ax, ay, az)) return C * a
def bPrimary(self, prob): """ The primary magnetic flux density from a magnetic vector potential :param BaseFDEMProblem prob: FDEM problem :rtype: numpy.ndarray :return: primary magnetic field """ formulation = prob._formulation if formulation is 'EB': gridX = prob.mesh.gridEx gridY = prob.mesh.gridEy gridZ = prob.mesh.gridEz C = prob.mesh.edgeCurl elif formulation is 'HJ': gridX = prob.mesh.gridFx gridY = prob.mesh.gridFy gridZ = prob.mesh.gridFz C = prob.mesh.edgeCurl.T if prob.mesh._meshType is 'CYL': if not prob.mesh.isSymmetric: # TODO ? raise NotImplementedError('Non-symmetric cyl mesh not ' 'implemented yet!') assert (np.linalg.norm(self.orientation - np.r_[0., 0., 1.]) < 1e-6), ('for cylindrical symmetry, the dipole must be ' 'oriented in the Z direction') a = self._srcFct(gridY, 'y') else: ax = self._srcFct(gridX, 'x') ay = self._srcFct(gridY, 'y') az = self._srcFct(gridZ, 'z') a = np.concatenate((ax, ay, az)) return C * a
def bPrimary(self, prob): """ The primary magnetic flux density from a magnetic vector potential :param BaseFDEMProblem prob: FDEM problem :rtype: numpy.ndarray :return: primary magnetic field """ formulation = prob._formulation if formulation is "EB": gridX = prob.mesh.gridEx gridY = prob.mesh.gridEy gridZ = prob.mesh.gridEz C = prob.mesh.edgeCurl elif formulation is "HJ": gridX = prob.mesh.gridFx gridY = prob.mesh.gridFy gridZ = prob.mesh.gridFz C = prob.mesh.edgeCurl.T if prob.mesh._meshType is "CYL": if not prob.mesh.isSymmetric: # TODO ? raise NotImplementedError("Non-symmetric cyl mesh not " "implemented yet!") assert np.linalg.norm(self.orientation - np.r_[0.0, 0.0, 1.0]) < 1e-6, ( "for cylindrical symmetry, the dipole must be " "oriented in the Z direction" ) a = self._srcFct(gridY, "y") else: ax = self._srcFct(gridX, "x") ay = self._srcFct(gridY, "y") az = self._srcFct(gridZ, "z") a = np.concatenate((ax, ay, az)) return C * a
def bPrimary(self, prob): """ The primary magnetic flux density from a magnetic vector potential :param BaseFDEMProblem prob: FDEM problem :rtype: numpy.ndarray :return: primary magnetic field """ formulation = prob._formulation if formulation is 'EB': gridX = prob.mesh.gridEx gridY = prob.mesh.gridEy gridZ = prob.mesh.gridEz C = prob.mesh.edgeCurl elif formulation is 'HJ': gridX = prob.mesh.gridFx gridY = prob.mesh.gridFy gridZ = prob.mesh.gridFz C = prob.mesh.edgeCurl.T if prob.mesh._meshType is 'CYL': if not prob.mesh.isSymmetric: # TODO ? raise NotImplementedError('Non-symmetric cyl mesh not implemented yet!') a = MagneticDipoleVectorPotential(self.loc, gridY, 'y', mu=self.mu, moment=self.moment) else: srcfct = MagneticDipoleVectorPotential ax = srcfct(self.loc, gridX, 'x', mu=self.mu, moment=self.moment) ay = srcfct(self.loc, gridY, 'y', mu=self.mu, moment=self.moment) az = srcfct(self.loc, gridZ, 'z', mu=self.mu, moment=self.moment) a = np.concatenate((ax, ay, az)) return C*a
def getSource(self,freq): """ :param float freq: Frequency :rtype: numpy.ndarray (nE, nTx) :return: RHS """ Txs = self.survey.getTransmitters(freq) rhs = range(len(Txs)) solType = self.solType if solType == 'e' or solType == 'b': gridEJx = self.mesh.gridEx gridEJy = self.mesh.gridEy gridEJz = self.mesh.gridEz nEJ = self.mesh.nE gridBHx = self.mesh.gridFx gridBHy = self.mesh.gridFy gridBHz = self.mesh.gridFz nBH = self.mesh.nF C = self.mesh.edgeCurl mui = self.MfMui elif solType == 'h' or solType == 'j': gridEJx = self.mesh.gridFx gridEJy = self.mesh.gridFy gridEJz = self.mesh.gridFz nEJ = self.mesh.nF gridBHx = self.mesh.gridEx gridBHy = self.mesh.gridEy gridBHz = self.mesh.gridEz nBH = self.mesh.nE C = self.mesh.edgeCurl.T mui = self.MeMuI else: NotImplementedError('Only E or F sources') for i, tx in enumerate(Txs): if self.mesh._meshType is 'CYL': if self.mesh.isSymmetric: if tx.txType == 'VMD': SRC = Sources.MagneticDipoleVectorPotential(tx.loc, gridEJy, 'y') elif tx.txType =='CircularLoop': SRC = Sources.MagneticLoopVectorPotential(tx.loc, gridEJy, 'y', tx.radius) else: raise NotImplementedError('Only VMD and CircularLoop') else: raise NotImplementedError('Non-symmetric cyl mesh not implemented yet!') elif self.mesh._meshType is 'TENSOR': if tx.txType == 'VMD': src = Sources.MagneticDipoleVectorPotential SRCx = src(tx.loc, gridEJx, 'x') SRCy = src(tx.loc, gridEJy, 'y') SRCz = src(tx.loc, gridEJz, 'z') elif tx.txType == 'VMD_B': src = Sources.MagneticDipoleFields SRCx = src(tx.loc, gridBHx, 'x') SRCy = src(tx.loc, gridBHy, 'y') SRCz = src(tx.loc, gridBHz, 'z') elif tx.txType == 'CircularLoop': src = Sources.MagneticLoopVectorPotential SRCx = src(tx.loc, gridEJx, 'x', tx.radius) SRCy = src(tx.loc, gridEJy, 'y', tx.radius) SRCz = src(tx.loc, gridEJz, 'z', tx.radius) else: raise NotImplemented('%s txType is not implemented' % tx.txType) SRC = np.concatenate((SRCx, SRCy, SRCz)) else: raise Exception('Unknown mesh for VMD') rhs[i] = SRC # b-forumlation if tx.txType == 'VMD_B': b_0 = np.concatenate(rhs).reshape((nBH, len(Txs)), order='E') else: a = np.concatenate(rhs).reshape((nEJ, len(Txs)), order='F') b_0 = C*a if solType == 'b' or solType == 'h': return b_0 elif solType == 'e' or solType == 'j': return C.T*mui*b_0
def fget(self): if self._gridCC is None: self._gridCC = np.concatenate([self.aveN2CC*self.gridN[:,i] for i in range(self.dim)]).reshape((-1,self.dim), order='F') return self._gridCC
def run(plotIt=True): """ MT: 1D: Inversion ================= Forward model 1D MT data. Setup and run a MT 1D inversion. """ ## Setup the forward modeling # Setting up 1D mesh and conductivity models to forward model data. # Frequency nFreq = 26 freqs = np.logspace(2, -3, nFreq) # Set mesh parameters ct = 10 air = simpeg.Utils.meshTensor([(ct, 25, 1.4)]) core = np.concatenate( (np.kron(simpeg.Utils.meshTensor([(ct, 10, -1.3)]), np.ones( (5, ))), simpeg.Utils.meshTensor([(ct, 5)]))) bot = simpeg.Utils.meshTensor([(core[0], 25, -1.4)]) x0 = -np.array([np.sum(np.concatenate((core, bot)))]) # Make the model m1d = simpeg.Mesh.TensorMesh([np.concatenate((bot, core, air))], x0=x0) # Setup model varibles active = m1d.vectorCCx < 0. layer1 = (m1d.vectorCCx < -500.) & (m1d.vectorCCx >= -800.) layer2 = (m1d.vectorCCx < -3500.) & (m1d.vectorCCx >= -5000.) # Set the conductivity values sig_half = 1e-2 sig_air = 1e-8 sig_layer1 = .2 sig_layer2 = .2 # Make the true model sigma_true = np.ones(m1d.nCx) * sig_air sigma_true[active] = sig_half sigma_true[layer1] = sig_layer1 sigma_true[layer2] = sig_layer2 # Extract the model m_true = np.log(sigma_true[active]) # Make the background model sigma_0 = np.ones(m1d.nCx) * sig_air sigma_0[active] = sig_half m_0 = np.log(sigma_0[active]) # Set the mapping actMap = simpeg.Maps.InjectActiveCells(m1d, active, np.log(1e-8), nC=m1d.nCx) mappingExpAct = simpeg.Maps.ExpMap(m1d) * actMap ## Setup the layout of the survey, set the sources and the connected receivers # Receivers rxList = [] rxList.append( NSEM.Rx.Point_impedance1D(simpeg.mkvc(np.array([-0.5]), 2).T, 'real')) rxList.append( NSEM.Rx.Point_impedance1D(simpeg.mkvc(np.array([-0.5]), 2).T, 'imag')) # Source list srcList = [] for freq in freqs: srcList.append(NSEM.Src.Planewave_xy_1Dprimary(rxList, freq)) # Make the survey survey = NSEM.Survey(srcList) survey.mtrue = m_true ## Set the problem problem = NSEM.Problem1D_ePrimSec(m1d, sigmaPrimary=sigma_0, mapping=mappingExpAct) problem.pair(survey) ## Forward model data # Project the data survey.dtrue = survey.dpred(m_true) survey.dobs = survey.dtrue + 0.01 * abs( survey.dtrue) * np.random.randn(*survey.dtrue.shape) if plotIt: fig = NSEM.Utils.dataUtils.plotMT1DModelData(problem, []) fig.suptitle('Target - smooth true') # Assign uncertainties std = 0.05 # 5% std survey.std = np.abs(survey.dobs * std) # Assign the data weight Wd = 1. / survey.std ## Setup the inversion proceedure # Define a counter C = simpeg.Utils.Counter() # Set the optimization opt = simpeg.Optimization.ProjectedGNCG(maxIter=25) opt.counter = C opt.lower = np.log(1e-4) opt.upper = np.log(5) opt.LSshorten = 0.1 opt.remember('xc') # Data misfit dmis = simpeg.DataMisfit.l2_DataMisfit(survey) dmis.Wd = Wd # Regularization - with a regularization mesh regMesh = simpeg.Mesh.TensorMesh([m1d.hx[active]], m1d.x0) reg = simpeg.Regularization.Tikhonov(regMesh) reg.mrefInSmooth = True reg.alpha_s = 1e-1 reg.alpha_x = 1. # Inversion problem invProb = simpeg.InvProblem.BaseInvProblem(dmis, reg, opt) invProb.counter = C # Beta cooling beta = simpeg.Directives.BetaSchedule() beta.coolingRate = 4. beta.coolingFactor = 4. betaest = simpeg.Directives.BetaEstimate_ByEig(beta0_ratio=100.) betaest.beta0 = 1. targmis = simpeg.Directives.TargetMisfit() targmis.target = survey.nD # Create an inversion object inv = simpeg.Inversion.BaseInversion( invProb, directiveList=[beta, betaest, targmis]) ## Run the inversion mopt = inv.run(m_0) if plotIt: fig = NSEM.Utils.dataUtils.plotMT1DModelData(problem, [mopt]) fig.suptitle('Target - smooth true') fig.axes[0].set_ylim([-10000, 500]) plt.show()
def run(plotIt=True): """ MT: 1D: Inversion ================= Forward model 1D MT data. Setup and run a MT 1D inversion. """ ## Setup the forward modeling # Setting up 1D mesh and conductivity models to forward model data. # Frequency nFreq = 26 freqs = np.logspace(2,-3,nFreq) # Set mesh parameters ct = 10 air = simpeg.Utils.meshTensor([(ct,25,1.4)]) core = np.concatenate( ( np.kron(simpeg.Utils.meshTensor([(ct,10,-1.3)]),np.ones((5,))) , simpeg.Utils.meshTensor([(ct,5)]) ) ) bot = simpeg.Utils.meshTensor([(core[0],25,-1.4)]) x0 = -np.array([np.sum(np.concatenate((core,bot)))]) # Make the model m1d = simpeg.Mesh.TensorMesh([np.concatenate((bot,core,air))], x0=x0) # Setup model varibles active = m1d.vectorCCx<0. layer1 = (m1d.vectorCCx<-500.) & (m1d.vectorCCx>=-800.) layer2 = (m1d.vectorCCx<-3500.) & (m1d.vectorCCx>=-5000.) # Set the conductivity values sig_half = 1e-2 sig_air = 1e-8 sig_layer1 = .2 sig_layer2 = .2 # Make the true model sigma_true = np.ones(m1d.nCx)*sig_air sigma_true[active] = sig_half sigma_true[layer1] = sig_layer1 sigma_true[layer2] = sig_layer2 # Extract the model m_true = np.log(sigma_true[active]) # Make the background model sigma_0 = np.ones(m1d.nCx)*sig_air sigma_0[active] = sig_half m_0 = np.log(sigma_0[active]) # Set the mapping actMap = simpeg.Maps.InjectActiveCells(m1d, active, np.log(1e-8), nC=m1d.nCx) mappingExpAct = simpeg.Maps.ExpMap(m1d) * actMap ## Setup the layout of the survey, set the sources and the connected receivers # Receivers rxList = [] rxList.append(NSEM.Rx.Point_impedance1D(simpeg.mkvc(np.array([-0.5]),2).T,'real')) rxList.append(NSEM.Rx.Point_impedance1D(simpeg.mkvc(np.array([-0.5]),2).T,'imag')) # Source list srcList =[] for freq in freqs: srcList.append(NSEM.Src.Planewave_xy_1Dprimary(rxList,freq)) # Make the survey survey = NSEM.Survey(srcList) survey.mtrue = m_true ## Set the problem problem = NSEM.Problem1D_ePrimSec(m1d,sigmaPrimary=sigma_0,mapping=mappingExpAct) problem.pair(survey) ## Forward model data # Project the data survey.dtrue = survey.dpred(m_true) survey.dobs = survey.dtrue + 0.01*abs(survey.dtrue)*np.random.randn(*survey.dtrue.shape) if plotIt: fig = NSEM.Utils.dataUtils.plotMT1DModelData(problem,[]) fig.suptitle('Target - smooth true') # Assign uncertainties std = 0.05 # 5% std survey.std = np.abs(survey.dobs*std) # Assign the data weight Wd = 1./survey.std ## Setup the inversion proceedure # Define a counter C = simpeg.Utils.Counter() # Set the optimization opt = simpeg.Optimization.ProjectedGNCG(maxIter = 25) opt.counter = C opt.lower = np.log(1e-4) opt.upper = np.log(5) opt.LSshorten = 0.1 opt.remember('xc') # Data misfit dmis = simpeg.DataMisfit.l2_DataMisfit(survey) dmis.Wd = Wd # Regularization - with a regularization mesh regMesh = simpeg.Mesh.TensorMesh([m1d.hx[active]],m1d.x0) reg = simpeg.Regularization.Tikhonov(regMesh) reg.mrefInSmooth = True reg.alpha_s = 1e-1 reg.alpha_x = 1. # Inversion problem invProb = simpeg.InvProblem.BaseInvProblem(dmis, reg, opt) invProb.counter = C # Beta cooling beta = simpeg.Directives.BetaSchedule() beta.coolingRate = 4. beta.coolingFactor = 4. betaest = simpeg.Directives.BetaEstimate_ByEig(beta0_ratio=100.) betaest.beta0 = 1. targmis = simpeg.Directives.TargetMisfit() targmis.target = survey.nD # Create an inversion object inv = simpeg.Inversion.BaseInversion(invProb, directiveList=[beta,betaest,targmis]) ## Run the inversion mopt = inv.run(m_0) if plotIt: fig = NSEM.Utils.dataUtils.plotMT1DModelData(problem,[mopt]) fig.suptitle('Target - smooth true') fig.axes[0].set_ylim([-10000,500]) plt.show()
def MagneticLoopVectorPotential(srcLoc, obsLoc, component, radius, orientation='Z', mu=mu_0): """ Calculate the vector potential of horizontal circular loop at given locations :param numpy.ndarray srcLoc: Location of the source(s) (x, y, z) :param numpy.ndarray,SimPEG.Mesh obsLoc: Where the potentials will be calculated (x, y, z) or a SimPEG Mesh :param str,list component: The component to calculate - 'x', 'y', or 'z' if an array, or grid type if mesh, can be a list :param numpy.ndarray I: Input current of the loop :param numpy.ndarray radius: radius of the loop :rtype: numpy.ndarray :return: The vector potential each dipole at each observation location """ if isinstance(orientation, str): if orientation.upper() != 'Z': raise NotImplementedError('Only Z oriented loops implemented') elif not np.allclose(orientation, np.r_[0., 0., 1.]): raise NotImplementedError('Only Z oriented loops implemented') if type(component) in [list, tuple]: out = list(range(len(component))) for i, comp in enumerate(component): out[i] = MagneticLoopVectorPotential(srcLoc, obsLoc, comp, radius, orientation, mu) return np.concatenate(out) if isinstance(obsLoc, Mesh.BaseMesh): mesh = obsLoc assert component in ['Ex','Ey','Ez','Fx','Fy','Fz'], "Components must be in: ['Ex','Ey','Ez','Fx','Fy','Fz']" return MagneticLoopVectorPotential(srcLoc, getattr(mesh,'grid'+component), component[1], radius, mu) srcLoc = np.atleast_2d(srcLoc) obsLoc = np.atleast_2d(obsLoc) n = obsLoc.shape[0] nSrc = srcLoc.shape[0] if component=='z': A = np.zeros((n, nSrc)) if nSrc ==1: return A.flatten() return A else: A = np.zeros((n, nSrc)) for i in range (nSrc): x = obsLoc[:, 0] - srcLoc[i, 0] y = obsLoc[:, 1] - srcLoc[i, 1] z = obsLoc[:, 2] - srcLoc[i, 2] r = np.sqrt(x**2 + y**2) m = (4 * radius * r) / ((radius + r)**2 + z**2) m[m > 1.] = 1. # m might be slightly larger than 1 due to rounding errors # but ellipke requires 0 <= m <= 1 K = ellipk(m) E = ellipe(m) ind = (r > 0) & (m < 1) # % 1/r singular at r = 0 and K(m) singular at m = 1 Aphi = np.zeros(n) # % Common factor is (mu * I) / pi with I = 1 and mu = 4e-7 * pi. Aphi[ind] = ((mu / (np.pi * np.sqrt(m[ind])) * np.sqrt(radius / r[ind]) *((1. - m[ind] / 2.) * K[ind] - E[ind]))) if component == 'x': A[ind, i] = Aphi[ind] * (-y[ind] / r[ind] ) elif component == 'y': A[ind, i] = Aphi[ind] * ( x[ind] / r[ind] ) else: raise ValueError('Invalid component') if nSrc == 1: return A.flatten() return A
def MagneticDipoleVectorPotential(srcLoc, obsLoc, component, moment=1., orientation=np.r_[0., 0., 1.], mu=mu_0): """ Calculate the vector potential of a set of magnetic dipoles at given locations 'ref. <http://en.wikipedia.org/wiki/Dipole#Magnetic_vector_potential>' :param numpy.ndarray srcLoc: Location of the source(s) (x, y, z) :param numpy.ndarray,SimPEG.Mesh obsLoc: Where the potentials will be calculated (x, y, z) or a SimPEG Mesh :param str,list component: The component to calculate - 'x', 'y', or 'z' if an array, or grid type if mesh, can be a list :param numpy.ndarray orientation: The vector dipole moment :rtype: numpy.ndarray :return: The vector potential each dipole at each observation location """ # TODO: break this out! if isinstance(orientation, str): orientation = orientationDict[orientation] assert np.linalg.norm(np.array(orientation), 2) == 1., ("orientation must " "be a unit vector") if type(component) in [list, tuple]: out = list(range(len(component))) for i, comp in enumerate(component): out[i] = MagneticDipoleVectorPotential(srcLoc, obsLoc, comp, orientation=orientation, mu=mu) return np.concatenate(out) if isinstance(obsLoc, Mesh.BaseMesh): mesh = obsLoc assert component in ['Ex', 'Ey', 'Ez', 'Fx', 'Fy', 'Fz'], ("Components" "must be in: ['Ex','Ey','Ez','Fx','Fy','Fz']") return MagneticDipoleVectorPotential(srcLoc, getattr(mesh, 'grid' + component), component[1], orientation=orientation) if component == 'x': dimInd = 0 elif component == 'y': dimInd = 1 elif component == 'z': dimInd = 2 else: raise ValueError('Invalid component') srcLoc = np.atleast_2d(srcLoc) obsLoc = np.atleast_2d(obsLoc) orientation = np.atleast_2d(orientation) nObs = obsLoc.shape[0] nSrc = srcLoc.shape[0] m = moment*np.array(orientation).repeat(nObs, axis=0) A = np.empty((nObs, nSrc)) for i in range(nSrc): dR = obsLoc - srcLoc[i, np.newaxis].repeat(nObs, axis=0) mCr = np.cross(m, dR) r = np.sqrt((dR**2).sum(axis=1)) A[:, i] = +(mu/(4*np.pi)) * mCr[:, dimInd]/(r**3) if nSrc == 1: return A.flatten() return A
def MagneticDipoleVectorPotential(srcLoc, obsLoc, component, moment=1., orientation=np.r_[0., 0., 1.], mu=mu_0): """ Calculate the vector potential of a set of magnetic dipoles at given locations 'ref. <http://en.wikipedia.org/wiki/Dipole#Magnetic_vector_potential>' :param numpy.ndarray srcLoc: Location of the source(s) (x, y, z) :param numpy.ndarray,SimPEG.Mesh obsLoc: Where the potentials will be calculated (x, y, z) or a SimPEG Mesh :param str,list component: The component to calculate - 'x', 'y', or 'z' if an array, or grid type if mesh, can be a list :param numpy.ndarray orientation: The vector dipole moment :rtype: numpy.ndarray :return: The vector potential each dipole at each observation location """ # TODO: break this out! if isinstance(orientation, str): orientation = orientationDict[orientation] assert np.linalg.norm(np.array(orientation), 2) == 1., ("orientation must " "be a unit vector") if type(component) in [list, tuple]: out = range(len(component)) for i, comp in enumerate(component): out[i] = MagneticDipoleVectorPotential(srcLoc, obsLoc, comp, orientation=orientation, mu=mu) return np.concatenate(out) if isinstance(obsLoc, Mesh.BaseMesh): mesh = obsLoc assert component in ['Ex', 'Ey', 'Ez', 'Fx', 'Fy', 'Fz'], ("Components" "must be in: ['Ex','Ey','Ez','Fx','Fy','Fz']") return MagneticDipoleVectorPotential(srcLoc, getattr(mesh, 'grid' + component), component[1], orientation=orientation) if component == 'x': dimInd = 0 elif component == 'y': dimInd = 1 elif component == 'z': dimInd = 2 else: raise ValueError('Invalid component') srcLoc = np.atleast_2d(srcLoc) obsLoc = np.atleast_2d(obsLoc) orientation = np.atleast_2d(orientation) nObs = obsLoc.shape[0] nSrc = srcLoc.shape[0] m = moment*np.array(orientation).repeat(nObs, axis=0) A = np.empty((nObs, nSrc)) for i in range(nSrc): dR = obsLoc - srcLoc[i, np.newaxis].repeat(nObs, axis=0) mCr = np.cross(m, dR) r = np.sqrt((dR**2).sum(axis=1)) A[:, i] = +(mu/(4*np.pi)) * mCr[:, dimInd]/(r**3) if nSrc == 1: return A.flatten() return A
def MagneticLoopVectorPotential(srcLoc, obsLoc, component, radius, orientation='Z', mu=mu_0): """ Calculate the vector potential of horizontal circular loop at given locations :param numpy.ndarray srcLoc: Location of the source(s) (x, y, z) :param numpy.ndarray,SimPEG.Mesh obsLoc: Where the potentials will be calculated (x, y, z) or a SimPEG Mesh :param str,list component: The component to calculate - 'x', 'y', or 'z' if an array, or grid type if mesh, can be a list :param numpy.ndarray I: Input current of the loop :param numpy.ndarray radius: radius of the loop :rtype: numpy.ndarray :return: The vector potential each dipole at each observation location """ if isinstance(orientation, str): if orientation.upper() != 'Z': raise NotImplementedError, 'Only Z oriented loops implemented' elif not np.allclose(orientation, np.r_[0., 0., 1.]): raise NotImplementedError, 'Only Z oriented loops implemented' if type(component) in [list, tuple]: out = range(len(component)) for i, comp in enumerate(component): out[i] = MagneticLoopVectorPotential(srcLoc, obsLoc, comp, radius, orientation, mu) return np.concatenate(out) if isinstance(obsLoc, Mesh.BaseMesh): mesh = obsLoc assert component in ['Ex','Ey','Ez','Fx','Fy','Fz'], "Components must be in: ['Ex','Ey','Ez','Fx','Fy','Fz']" return MagneticLoopVectorPotential(srcLoc, getattr(mesh,'grid'+component), component[1], radius, mu) srcLoc = np.atleast_2d(srcLoc) obsLoc = np.atleast_2d(obsLoc) n = obsLoc.shape[0] nSrc = srcLoc.shape[0] if component=='z': A = np.zeros((n, nSrc)) if nSrc ==1: return A.flatten() return A else: A = np.zeros((n, nSrc)) for i in range (nSrc): x = obsLoc[:, 0] - srcLoc[i, 0] y = obsLoc[:, 1] - srcLoc[i, 1] z = obsLoc[:, 2] - srcLoc[i, 2] r = np.sqrt(x**2 + y**2) m = (4 * radius * r) / ((radius + r)**2 + z**2) m[m > 1.] = 1. # m might be slightly larger than 1 due to rounding errors # but ellipke requires 0 <= m <= 1 K = ellipk(m) E = ellipe(m) ind = (r > 0) & (m < 1) # % 1/r singular at r = 0 and K(m) singular at m = 1 Aphi = np.zeros(n) # % Common factor is (mu * I) / pi with I = 1 and mu = 4e-7 * pi. Aphi[ind] = ((mu / (np.pi * np.sqrt(m[ind])) * np.sqrt(radius / r[ind]) *((1. - m[ind] / 2.) * K[ind] - E[ind]))) if component == 'x': A[ind, i] = Aphi[ind] * (-y[ind] / r[ind] ) elif component == 'y': A[ind, i] = Aphi[ind] * ( x[ind] / r[ind] ) else: raise ValueError('Invalid component') if nSrc == 1: return A.flatten() return A