def _hPrimary(self, hSolution, srcList): hPrimary = np.zeros_like(hSolution,dtype = complex) for i, src in enumerate(srcList): hp = src.hPrimary(self.prob) if hp is not None: hPrimary[:,i] += hp return hPrimary
def _jPrimary(self, jSolution, srcList): jPrimary = np.zeros_like(jSolution,dtype = complex) for i, src in enumerate(srcList): jp = src.jPrimary(self.prob) if jp is not None: jPrimary[:,i] += jp return jPrimary
def _ePrimary(self, eSolution, srcList): ePrimary = np.zeros_like(eSolution) for i, src in enumerate(srcList): ep = src.ePrimary(self.prob) if ep is not None: ePrimary[:,i] = ep return ePrimary
def _e_pyPrimary(self, e_pySolution, srcList): e_pyPrimary = np.zeros_like(e_pySolution) for i, src in enumerate(srcList): ep = src.ePrimary(self.survey.prob) if ep is not None: e_pyPrimary[:, i] = ep[:, 1] return e_pyPrimary
def _bPrimary(self, bSolution, srcList): bPrimary = np.zeros_like(bSolution) for i, src in enumerate(srcList): bp = src.bPrimary(self.prob) if bp is not None: bPrimary[:,i] = bp return bPrimary
def _ePrimary(self, eSolution, srcList): ePrimary = np.zeros_like(eSolution) for i, src in enumerate(srcList): ep = src.ePrimary(self.survey.prob) if ep is not None: ePrimary[:,i] = ep[:,-1] return ePrimary
def _e_pyDeriv_u(self, src, v, adjoint=False): """ Takes the derivative of e_py wrt u """ if adjoint: # adjoint: returns a 2*nE long vector with zero's for px return np.vstack((np.zeros_like(v), v)) # Not adjoint: return only the px part of the vector return v[len(v) / 2 : :]
def _e_pyDeriv_u(self, src, v, adjoint = False): ''' Takes the derivative of e_py wrt u ''' if adjoint: # adjoint: returns a 2*nE long vector with zero's for px return np.vstack((np.zeros_like(v),v)) # Not adjoint: return only the px part of the vector return v[len(v)/2::]
def _e_pxDeriv_u(self, src, v, adjoint = False): ''' Takes the derivative of e_px wrt u ''' if adjoint: # adjoint: returns a 2*nE long vector with zero's for py return np.vstack((v,np.zeros_like(v))) # Not adjoint: return only the px part of the vector return v[:len(v)/2]
def halfSpaceProblemAnaVMDDiff(showIt=False, waveformType="STEPOFF"): cs, ncx, ncz, npad = 20., 25, 25, 15 hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hz], '00C') sighalf = 1e-2 siginf = np.ones(mesh.nC) * 1e-8 siginf[mesh.gridCC[:, -1] < 0.] = sighalf eta = np.ones(mesh.nC) * 0.2 tau = np.ones(mesh.nC) * 0.005 c = np.ones(mesh.nC) * 0.7 m = np.r_[siginf, eta, tau, c] iMap = Maps.IdentityMap(nP=int(mesh.nC)) maps = [('sigmaInf', iMap), ('eta', iMap), ('tau', iMap), ('c', iMap)] prb = ProblemATEMIP_b(mesh, mapping=maps) if waveformType == "GENERAL": # timeon = np.cumsum(np.r_[np.ones(10)*1e-3, np.ones(10)*5e-4, np.ones(10)*1e-4]) timeon = np.cumsum(np.r_[np.ones(10) * 1e-3, np.ones(10) * 5e-4, np.ones(10) * 1e-4]) timeon -= timeon.max() timeoff = np.cumsum(np.r_[np.ones(20) * 1e-5, np.ones(20) * 1e-4, np.ones(20) * 1e-3]) time = np.r_[timeon, timeoff] current_on = np.ones_like(timeon) current_on[[0, -1]] = 0. current = np.r_[current_on, np.zeros_like(timeoff)] wave = np.c_[time, current] prb.waveformType = "GENERAL" prb.currentwaveform(wave) prb.t0 = time.min() elif waveformType == "STEPOFF": prb.timeSteps = [(1e-5, 20), (1e-4, 20), (1e-3, 10)] offset = 20. tobs = np.logspace(-4, -2, 21) rx = EM.TDEM.RxTDEM(np.array([[offset, 0., 0.]]), tobs, "bz") src = EM.TDEM.SrcTDEM_VMD_MVP([rx], np.array([[0., 0., 0.]]), waveformType=waveformType) survey = EM.TDEM.SurveyTDEM([src]) prb.Solver = MumpsSolver prb.pair(survey) out = survey.dpred(m) bz_ana = mu_0 * hzAnalyticDipoleT_CC( offset, rx.times, sigmaInf=sighalf, eta=eta[0], tau=tau[0], c=c[0]) err = np.linalg.norm(bz_ana - out) / np.linalg.norm(bz_ana) print '>> Relative error = ', err if showIt: plt.loglog(rx.times, abs(bz_ana), 'k') plt.loglog(rx.times, abs(out), 'b.') plt.show() return err
def halfSpaceProblemAnaVMDDiff(showIt=False, waveformType="STEPOFF"): cs, ncx, ncz, npad = 20., 25, 25, 15 hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] mesh = Mesh.CylMesh([hx, 1, hz], '00C') prb = ProblemATEM_b(mesh) if waveformType == "GENERAL": timeon = np.cumsum(np.r_[np.ones(10) * 1e-3, np.ones(10) * 5e-4, np.ones(10) * 1e-4]) timeon -= timeon.max() timeoff = np.cumsum(np.r_[np.ones(10) * 5e-5, np.ones(10) * 1e-4, np.ones(10) * 5e-4, np.ones(10) * 1e-3, np.ones(10) * 5e-3]) time = np.r_[timeon, timeoff] current_on = np.ones_like(timeon) current_on[[0, -1]] = 0. current = np.r_[current_on, np.zeros_like(timeoff)] wave = np.c_[time, current] prb.waveformType = "GENERAL" prb.currentwaveform(wave) prb.t0 = time.min() elif waveformType == "STEPOFF": prb.timeSteps = [(1e-5, 10), (5e-5, 10), (1e-4, 10), (5e-4, 10), (1e-3, 10), (5e-3, 10)] offset = 20. tobs = np.logspace(-4, -2, 21) rx = EM.TDEM.RxTDEM(np.array([[offset, 0., 0.]]), tobs, "bz") src = EM.TDEM.SrcTDEM_VMD_MVP([rx], np.array([[0., 0., 0.]]), waveformType=waveformType) survey = EM.TDEM.SurveyTDEM([src]) prb.Solver = MumpsSolver sigma = np.ones(mesh.nC) * 1e-8 active = mesh.gridCC[:, 2] < 0. sig_half = 1e-2 sigma[active] = sig_half prb.pair(survey) out = survey.dpred(sigma) bz_ana = mu_0 * hzAnalyticDipoleT(offset, rx.times, sig_half) err = np.linalg.norm(bz_ana - out) / np.linalg.norm(bz_ana) print '>> Relative error = ', err if showIt: plt.loglog(rx.times, bz_ana, 'k') plt.loglog(rx.times, out, 'b.') plt.show() return err
def halfSpaceProblemAnaVMDDiff(showIt=False, waveformType="STEPOFF"): cs, ncx, ncz, npad = 20., 25, 25, 15 hx = [(cs,ncx), (cs,npad,1.3)] hz = [(cs,npad,-1.3), (cs,ncz), (cs,npad,1.3)] mesh = Mesh.CylMesh([hx,1,hz], '00C') sighalf = 1e-2 siginf = np.ones(mesh.nC)*1e-8 siginf[mesh.gridCC[:,-1]<0.] = sighalf eta = np.ones(mesh.nC)*0.2 tau = np.ones(mesh.nC)*0.005 c = np.ones(mesh.nC)*0.7 m = np.r_[siginf, eta, tau, c] iMap = Maps.IdentityMap(nP=int(mesh.nC)) maps = [('sigmaInf', iMap), ('eta', iMap), ('tau', iMap), ('c', iMap)] prb = ProblemATEMIP_b(mesh, mapping = maps) if waveformType =="GENERAL": # timeon = np.cumsum(np.r_[np.ones(10)*1e-3, np.ones(10)*5e-4, np.ones(10)*1e-4]) timeon = np.cumsum(np.r_[np.ones(10)*1e-3, np.ones(10)*5e-4, np.ones(10)*1e-4]) timeon -= timeon.max() timeoff = np.cumsum(np.r_[np.ones(20)*1e-5, np.ones(20)*1e-4, np.ones(20)*1e-3]) time = np.r_[timeon, timeoff] current_on = np.ones_like(timeon) current_on[[0,-1]] = 0. current = np.r_[current_on, np.zeros_like(timeoff)] wave = np.c_[time, current] prb.waveformType = "GENERAL" prb.currentwaveform(wave) prb.t0 = time.min() elif waveformType =="STEPOFF": prb.timeSteps = [(1e-5, 20), (1e-4, 20), (1e-3, 10)] offset = 20. tobs = np.logspace(-4, -2, 21) rx = EM.TDEM.RxTDEM(np.array([[offset, 0., 0.]]), tobs, "bz") src = EM.TDEM.SrcTDEM_VMD_MVP([rx], np.array([[0., 0., 0.]]), waveformType=waveformType) survey = EM.TDEM.SurveyTDEM([src]) prb.Solver = MumpsSolver prb.pair(survey) out = survey.dpred(m) bz_ana = mu_0*hzAnalyticDipoleT_CC(offset, rx.times, sigmaInf=sighalf, eta=eta[0], tau=tau[0], c=c[0]) err = np.linalg.norm(bz_ana-out)/np.linalg.norm(bz_ana) print '>> Relative error = ', err if showIt: plt.loglog(rx.times, abs(bz_ana), 'k') plt.loglog(rx.times, abs(out), 'b.') plt.show() return err
def halfSpaceProblemAnaVMDDiff(showIt=False, waveformType="STEPOFF"): cs, ncx, ncz, npad = 20., 25, 25, 15 hx = [(cs,ncx), (cs,npad,1.3)] hz = [(cs,npad,-1.3), (cs,ncz), (cs,npad,1.3)] mesh = Mesh.CylMesh([hx,1,hz], '00C') prb = ProblemATEM_b(mesh) if waveformType =="GENERAL": timeon = np.cumsum(np.r_[np.ones(10)*1e-3, np.ones(10)*5e-4, np.ones(10)*1e-4]) timeon -= timeon.max() timeoff = np.cumsum(np.r_[np.ones(10)*5e-5, np.ones(10)*1e-4, np.ones(10)*5e-4, np.ones(10)*1e-3, np.ones(10)*5e-3]) time = np.r_[timeon, timeoff] current_on = np.ones_like(timeon) current_on[[0,-1]] = 0. current = np.r_[current_on, np.zeros_like(timeoff)] wave = np.c_[time, current] prb.waveformType = "GENERAL" prb.currentwaveform(wave) prb.t0 = time.min() elif waveformType =="STEPOFF": prb.timeSteps = [(1e-5, 10), (5e-5, 10), (1e-4, 10), (5e-4, 10), (1e-3, 10),(5e-3, 10)] offset = 20. tobs = np.logspace(-4, -2, 21) rx = EM.TDEM.RxTDEM(np.array([[offset, 0., 0.]]), tobs, "bz") src = EM.TDEM.SrcTDEM_VMD_MVP([rx], np.array([[0., 0., 0.]]), waveformType=waveformType) survey = EM.TDEM.SurveyTDEM([src]) prb.Solver = MumpsSolver sigma = np.ones(mesh.nC)*1e-8 active = mesh.gridCC[:,2]<0. sig_half = 1e-2 sigma[active] = sig_half prb.pair(survey) out = survey.dpred(sigma) bz_ana = mu_0*hzAnalyticDipoleT(offset, rx.times, sig_half) err = np.linalg.norm(bz_ana-out)/np.linalg.norm(bz_ana) print '>> Relative error = ', err if showIt: plt.loglog(rx.times, bz_ana, 'k') plt.loglog(rx.times, out, 'b.') plt.show() return err
def Jtvec(self, m, v, f=None): """ Jvec computes the adjoint of the sensitivity times a vector .. math:: \mathbf{J}^\\top \mathbf{v} = \left( \\frac{d\mathbf{u}}{d\mathbf{m}} ^ \\top \\frac{d\mathbf{F}}{d\mathbf{u}} ^ \\top + \\frac{\partial\mathbf{F}}{\partial\mathbf{m}} ^ \\top \\right) \\frac{d\mathbf{P}}{d\mathbf{F}} ^ \\top \mathbf{v} where .. math:: \\frac{d\mathbf{u}}{d\mathbf{m}} ^\\top \mathbf{A}^\\top + \\frac{d\mathbf{A}(\mathbf{u})}{d\mathbf{m}} ^ \\top = \\frac{d \mathbf{RHS}}{d \mathbf{m}} ^ \\top """ if f is None: f = self.fields(m) self.model = m ftype = self._fieldType + 'Solution' # the thing we solved for # Ensure v is a data object. if not isinstance(v, self.dataPair): v = self.dataPair(self.survey, v) df_duT_v = Fields_Derivs(self.mesh, self.survey) # same size as fields at a single timestep ATinv_df_duT_v = np.zeros( ( len(self.survey.srcList), len(f[self.survey.srcList[0], ftype, 0]) ), dtype=float ) JTv = np.zeros(m.shape, dtype=float) # Loop over sources and receivers to create a fields object: # PT_v, df_duT_v, df_dmT_v # initialize storage for PT_v (don't need to preserve over sources) PT_v = Fields_Derivs(self.mesh, self.survey) for src in self.survey.srcList: # Looping over initializing field class is appending memory! # PT_v = Fields_Derivs(self.mesh, self.survey) # initialize storage # #for PT_v (don't need to preserve over sources) # initialize size df_duT_v[src, '{}Deriv'.format(self._fieldType), :] = ( np.zeros_like(f[src, self._fieldType, :]) ) for rx in src.rxList: PT_v[src, '{}Deriv'.format(rx.projField), :] = rx.evalDeriv( src, self.mesh, self.timeMesh, f, Utils.mkvc(v[src, rx]), adjoint=True ) # this is += # PT_v = np.reshape(curPT_v,(len(curPT_v)/self.timeMesh.nN, # self.timeMesh.nN), order='F') df_duTFun = getattr(f, '_{}Deriv'.format(rx.projField), None) for tInd in range(self.nT+1): cur = df_duTFun( tInd, src, None, Utils.mkvc( PT_v[src, '{}Deriv'.format(rx.projField), tInd] ), adjoint=True ) df_duT_v[src, '{}Deriv'.format(self._fieldType), tInd] = ( df_duT_v[src, '{}Deriv'.format(self._fieldType), tInd] + Utils.mkvc(cur[0], 2)) JTv = cur[1] + JTv del PT_v # no longer need this AdiagTinv = None # Do the back-solve through time # if the previous timestep is the same: no need to refactor the matrix # for tInd, dt in zip(range(self.nT), self.timeSteps): for tInd in reversed(range(self.nT)): # tInd = tIndP - 1 if AdiagTinv is not None and ( tInd <= self.nT and self.timeSteps[tInd] != self.timeSteps[tInd+1] ): AdiagTinv.clean() AdiagTinv = None # refactor if we need to if AdiagTinv is None: # and tInd > -1: Adiag = self.getAdiag(tInd) AdiagTinv = self.Solver(Adiag.T, **self.solverOpts) if tInd < self.nT - 1: Asubdiag = self.getAsubdiag(tInd+1) for isrc, src in enumerate(self.survey.srcList): # solve against df_duT_v if tInd >= self.nT-1: # last timestep (first to be solved) ATinv_df_duT_v[isrc, :] = AdiagTinv * df_duT_v[ src, '{}Deriv'.format(self._fieldType), tInd+1] elif tInd > -1: ATinv_df_duT_v[isrc, :] = AdiagTinv * ( Utils.mkvc(df_duT_v[ src, '{}Deriv'.format(self._fieldType), tInd+1 ] ) - Asubdiag.T * Utils.mkvc(ATinv_df_duT_v[isrc, :])) if tInd < self.nT: dAsubdiagT_dm_v = self.getAsubdiagDeriv( tInd, f[src, ftype, tInd], ATinv_df_duT_v[isrc, :], adjoint=True) else: dAsubdiagT_dm_v = Utils.Zero() dRHST_dm_v = self.getRHSDeriv( tInd+1, src, ATinv_df_duT_v[isrc, :], adjoint=True ) # on nodes of time mesh un_src = f[src, ftype, tInd+1] # cell centered on time mesh dAT_dm_v = self.getAdiagDeriv( tInd, un_src, ATinv_df_duT_v[isrc, :], adjoint=True ) JTv = JTv + Utils.mkvc( -dAT_dm_v - dAsubdiagT_dm_v + dRHST_dm_v ) # del df_duT_v, ATinv_df_duT_v, A, Asubdiag if AdiagTinv is not None: AdiagTinv.clean() return Utils.mkvc(JTv).astype(float)
def Jtvec(self, m, v, f=None): """ Jvec computes the adjoint of the sensitivity times a vector .. math:: \mathbf{J}^\\top \mathbf{v} = \left( \\frac{d\mathbf{u}}{d\mathbf{m}} ^ \\top \\frac{d\mathbf{F}}{d\mathbf{u}} ^ \\top + \\frac{\partial\mathbf{F}}{\partial\mathbf{m}} ^ \\top \\right) \\frac{d\mathbf{P}}{d\mathbf{F}} ^ \\top \mathbf{v} where .. math:: \\frac{d\mathbf{u}}{d\mathbf{m}} ^\\top \mathbf{A}^\\top + \\frac{d\mathbf{A}(\mathbf{u})}{d\mathbf{m}} ^ \\top = \\frac{d \mathbf{RHS}}{d \mathbf{m}} ^ \\top """ if f is None: f = self.fields(m) self.curModel = m ftype = self._fieldType + 'Solution' # the thing we solved for # Ensure v is a data object. if not isinstance(v, self.dataPair): v = self.dataPair(self.survey, v) df_duT_v = Fields_Derivs(self.mesh, self.survey) # same size as fields at a single timestep ATinv_df_duT_v = np.zeros((len(self.survey.srcList), len(f[self.survey.srcList[0], ftype, 0])), dtype=float) JTv = np.zeros(m.shape, dtype=float) # Loop over sources and receivers to create a fields object: # PT_v, df_duT_v, df_dmT_v # initialize storage for PT_v (don't need to preserve over sources) PT_v = Fields_Derivs(self.mesh, self.survey) for src in self.survey.srcList: # Looping over initializing field class is appending memory! # PT_v = Fields_Derivs(self.mesh, self.survey) # initialize storage # #for PT_v (don't need to preserve over sources) # initialize size df_duT_v[src, '{}Deriv'.format(self._fieldType), :] = np.zeros_like( f[src, self._fieldType, :]) for rx in src.rxList: PT_v[src, '{}Deriv'.format(rx.projField), :] = rx.evalDeriv( src, self.mesh, self.timeMesh, Utils.mkvc(v[src, rx]), adjoint=True) # this is += # PT_v = np.reshape(curPT_v,(len(curPT_v)/self.timeMesh.nN, # self.timeMesh.nN), order='F') df_duTFun = getattr(f, '_{}Deriv'.format(rx.projField), None) for tInd in range(self.nT+1): cur = df_duTFun( tInd, src, None, Utils.mkvc(PT_v[ src, '{}Deriv'.format(rx.projField), tInd]), adjoint=True) df_duT_v[src, '{}Deriv'.format(self._fieldType), tInd] = ( df_duT_v[src, '{}Deriv'.format(self._fieldType), tInd] + Utils.mkvc(cur[0], 2)) JTv = cur[1] + JTv del PT_v # no longer need this AdiagTinv = None # Do the back-solve through time # if the previous timestep is the same: no need to refactor the matrix # for tInd, dt in zip(range(self.nT), self.timeSteps): for tInd in reversed(range(self.nT)): # tInd = tIndP - 1 if AdiagTinv is not None and ( tInd <= self.nT and self.timeSteps[tInd] != self.timeSteps[tInd+1] ): AdiagTinv.clean() AdiagTinv = None # refactor if we need to if AdiagTinv is None: # and tInd > -1: Adiag = self.getAdiag(tInd) AdiagTinv = self.Solver(Adiag.T, **self.solverOpts) if tInd < self.nT - 1: Asubdiag = self.getAsubdiag(tInd+1) for isrc, src in enumerate(self.survey.srcList): # solve against df_duT_v if tInd >= self.nT-1: # last timestep (first to be solved) ATinv_df_duT_v[isrc, :] = AdiagTinv * df_duT_v[ src, '{}Deriv'.format(self._fieldType), tInd+1] elif tInd > -1: ATinv_df_duT_v[isrc, :] = AdiagTinv * (Utils.mkvc(df_duT_v[ src, '{}Deriv'.format(self._fieldType), tInd+1]) - Asubdiag.T * Utils.mkvc(ATinv_df_duT_v[isrc, :])) if tInd < self.nT: dAsubdiagT_dm_v = self.getAsubdiagDeriv( tInd, f[src, ftype, tInd], ATinv_df_duT_v[isrc, :], adjoint=True) else: dAsubdiagT_dm_v = Utils.Zero() dRHST_dm_v = self.getRHSDeriv( tInd+1, src, ATinv_df_duT_v[isrc, :], adjoint=True ) # on nodes of time mesh un_src = f[src, ftype, tInd+1] # cell centered on time mesh dAT_dm_v = self.getAdiagDeriv(tInd, un_src, ATinv_df_duT_v[isrc, :], adjoint=True) JTv = JTv + Utils.mkvc(-dAT_dm_v - dAsubdiagT_dm_v + dRHST_dm_v) # del df_duT_v, ATinv_df_duT_v, A, Asubdiag if AdiagTinv is not None: AdiagTinv.clean() return Utils.mkvc(JTv).astype(float)