示例#1
0
def DerivProjfieldsTest(inputSetup, comp="All", freq=False):

    survey, simulation = nsem.utils.test_utils.setupSimpegNSEM_ePrimSec(
        inputSetup, comp, freq)
    print(
        "Derivative test of data projection for eFormulation primary/secondary\n"
    )
    # simulation.mapping = maps.ExpMap(simulation.mesh)
    # Initate things for the derivs Test
    src = survey.source_list[0]
    np.random.seed(1983)
    u0x = np.random.randn(
        survey.mesh.nE) + np.random.randn(survey.mesh.nE) * 1j
    u0y = np.random.randn(
        survey.mesh.nE) + np.random.randn(survey.mesh.nE) * 1j
    u0 = np.vstack((mkvc(u0x, 2), mkvc(u0y, 2)))
    f0 = simulation.fieldsPair(survey.mesh, survey)
    # u0 = np.hstack((mkvc(u0_px,2),mkvc(u0_py,2)))
    f0[src, "e_pxSolution"] = u0[:len(u0) / 2]  # u0x
    f0[src, "e_pySolution"] = u0[len(u0) / 2::]  # u0y

    def fun(u):
        f = simulation.fieldsPair(survey.mesh, survey)
        f[src, "e_pxSolution"] = u[:len(u) / 2]
        f[src, "e_pySolution"] = u[len(u) / 2::]
        return (
            rx.eval(src, survey.mesh, f),
            lambda t: rx.evalDeriv(src, survey.mesh, f0, mkvc(t, 2)),
        )

    return tests.checkDerivative(fun, u0, num=4, plotIt=False, eps=FLR)
示例#2
0
    def test_ana_forward(self):

        # Compute 3-component mag data
        self.survey.pair(self.prob_xyz)
        d = self.prob_xyz.fields(self.model)

        ndata = self.locXyz.shape[0]
        dbx = d[0:ndata]
        dby = d[ndata:2 * ndata]
        dbz = d[2 * ndata:]

        # Compute tmi mag data
        self.survey.pair(self.prob_tmi)
        dtmi = self.prob_tmi.fields(self.model)

        # Compute analytical response from a magnetized sphere
        bxa, bya, bza = PF.MagAnalytics.MagSphereFreeSpace(
            self.locXyz[:, 0], self.locXyz[:, 1], self.locXyz[:, 2], self.rad,
            0, 0, 0, self.chi, self.b0)

        # Projection matrix
        Ptmi = mkvc(self.b0) / np.sqrt(np.sum(self.b0**2.))

        btmi = mkvc(Ptmi.dot(np.vstack((bxa, bya, bza))))

        err_xyz = (np.linalg.norm(d - np.r_[bxa, bya, bza]) /
                   np.linalg.norm(np.r_[bxa, bya, bza]))

        err_tmi = np.linalg.norm(dtmi - btmi) / np.linalg.norm(btmi)
        self.assertTrue(err_xyz < 0.005 and err_tmi < 0.005)
示例#3
0
    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
            ePri = self.ePrimary(problem)[:, 1]
            MsigmaDeriv = (
                problem.mesh.getFaceInnerProductDeriv(problem.sigma)(ePri) *
                problem.sigmaDeriv)
            # MsigmaDeriv = ( MsigmaDeriv * MsigmaDeriv.T)**2

            if adjoint:
                #
                return MsigmaDeriv.T * v
            else:
                # v should be nC size
                return MsigmaDeriv * v
        if problem.mesh.dim == 2:
            raise NotImplementedError('The NSEM 2D problem is not implemented')
        if problem.mesh.dim == 3:
            # Need to take the derivative of both u_px and u_py
            # And stack them to be of the correct size
            e_p = self.ePrimary(problem)
            if adjoint:
                return sp.hstack((
                    problem.MeSigmaDeriv(e_p[:, 0]).T,
                    problem.MeSigmaDeriv(e_p[:, 1]).T)) * v
            else:
                return np.hstack((
                    mkvc(problem.MeSigmaDeriv(e_p[:, 0]) * v, 2),
                    mkvc(problem.MeSigmaDeriv(e_p[:, 1]) * v, 2)))
示例#4
0
 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
示例#5
0
    def getADeriv(self, freq, u, v, adjoint=False):
        """
        Calculate the derivative of A wrt m.

        :param float freq: Frequency
        :param SimPEG.EM.NSEM.FieldsNSEM u: NSEM Fields object
        :param numpy.ndarray v: vector of size (nU,) (adjoint=False)
            and size (nP,) (adjoint=True)
        :rtype: numpy.ndarray
        :return: Calculated derivative (nP,) (adjoint=False) and (nU,)[NOTE return as a (nU/2,2)
            columnwise polarizations] (adjoint=True) for both polarizations

        """
        # Fix u to be a matrix nE,2
        # This considers both polarizations and returns a nE,2 matrix for each polarization
        # The solution types
        sol0, sol1 = self._solutionType

        if adjoint:
            dMe_dsigV = (
                self.MeSigmaDeriv(u[sol0], v[:self.mesh.nE], adjoint) +
                self.MeSigmaDeriv(u[sol1], v[self.mesh.nE:], adjoint)
            )
        else:
            # Need a nE,2 matrix to be returned
            dMe_dsigV = np.hstack(
                (
                    mkvc(self.MeSigmaDeriv(u[sol0], v, adjoint), 2),
                    mkvc(self.MeSigmaDeriv(u[sol1], v, adjoint), 2)
                )
            )
        return 1j * omega(freq) * dMe_dsigV
示例#6
0
    def test_ana_forward(self):

        # Compute 3-component mag data
        self.survey.pair(self.prob_xyz)
        d = self.prob_xyz.fields(self.model)

        ndata = self.locXyz.shape[0]
        dbx = d[0:ndata]
        dby = d[ndata:2*ndata]
        dbz = d[2*ndata:]

        # Compute tmi mag data
        self.survey.pair(self.prob_tmi)
        dtmi = self.prob_tmi.fields(self.model)

        # Compute analytical response from a magnetized sphere
        bxa, bya, bza = PF.MagAnalytics.MagSphereFreeSpace(self.locXyz[:, 0],
                                                           self.locXyz[:, 1],
                                                           self.locXyz[:, 2],
                                                           self.rad, 0, 0, 0,
                                                           self.chi, self.b0)

        # Projection matrix
        Ptmi = mkvc(self.b0)/np.sqrt(np.sum(self.b0**2.))

        btmi = mkvc(Ptmi.dot(np.vstack((bxa, bya, bza))))

        err_xyz = (np.linalg.norm(d-np.r_[bxa, bya, bza]) /
                   np.linalg.norm(np.r_[bxa, bya, bza]))

        err_tmi = np.linalg.norm(dtmi-btmi)/np.linalg.norm(btmi)
        self.assertTrue(err_xyz < 0.005 and err_tmi < 0.005)
示例#7
0
    def test_basic_inversion(self):
        """
        Test to see if inversion recovers model
        """

        h = [(2, 30)]
        meshObj = Mesh.TensorMesh((h, h, [(2, 10)]), x0='CCN')

        mod = 0.00025 * np.ones(meshObj.nC)
        mod[(meshObj.gridCC[:, 0] > -4.) & (meshObj.gridCC[:, 1] > -4.) &
            (meshObj.gridCC[:, 0] < 4.) & (meshObj.gridCC[:, 1] < 4.)] = 0.001

        times = np.logspace(-4, -2, 5)
        waveObj = VRM.WaveformVRM.SquarePulse(0.02)

        x, y = np.meshgrid(np.linspace(-17, 17, 16), np.linspace(-17, 17, 16))
        x, y, z = mkvc(x), mkvc(y), 0.5 * np.ones(np.size(x))
        rxList = [VRM.Rx.Point(np.c_[x, y, z], times, 'dbdt', 'z')]

        txNodes = np.array([[-20, -20, 0.001], [20, -20,
                                                0.001], [20, 20, 0.001],
                            [-20, 20, 0.01], [-20, -20, 0.001]])
        txList = [VRM.Src.LineCurrent(rxList, txNodes, 1., waveObj)]

        Survey = VRM.Survey(txList)
        Problem = VRM.Problem_Linear(meshObj, refFact=2)
        Problem.pair(Survey)
        Survey.makeSyntheticData(mod)
        Survey.eps = 1e-11

        dmis = DataMisfit.l2_DataMisfit(Survey)
        W = mkvc((np.sum(np.array(Problem.A)**2, axis=0)))**0.25
        reg = Regularization.Simple(meshObj,
                                    alpha_s=0.01,
                                    alpha_x=1.,
                                    alpha_y=1.,
                                    alpha_z=1.,
                                    cell_weights=W)
        opt = Optimization.ProjectedGNCG(maxIter=20,
                                         lower=0.,
                                         upper=1e-2,
                                         maxIterLS=20,
                                         tolCG=1e-4)
        invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
        directives = [
            Directives.BetaSchedule(coolingFactor=2, coolingRate=1),
            Directives.TargetMisfit()
        ]
        inv = Inversion.BaseInversion(invProb, directiveList=directives)

        m0 = 1e-6 * np.ones(len(mod))
        mrec = inv.run(m0)

        dmis_final = np.sum(
            (dmis.W.diagonal() * (Survey.dobs - Problem.fields(mrec)))**2)
        mod_err_2 = np.sqrt(np.sum((mrec - mod)**2)) / np.size(mod)
        mod_err_inf = np.max(np.abs(mrec - mod))

        self.assertTrue(dmis_final < Survey.nD and mod_err_2 < 5e-6
                        and mod_err_inf < np.max(mod))
示例#8
0
    def test_basic_inversion(self):

        """
        Test to see if inversion recovers model
        """

        h = [(2, 30)]
        meshObj = Mesh.TensorMesh((h, h, [(2, 10)]), x0='CCN')

        mod = 0.00025*np.ones(meshObj.nC)
        mod[(meshObj.gridCC[:, 0] > -4.) &
            (meshObj.gridCC[:, 1] > -4.) &
            (meshObj.gridCC[:, 0] < 4.) &
            (meshObj.gridCC[:, 1] < 4.)] = 0.001

        times = np.logspace(-4, -2, 5)
        waveObj = VRM.WaveformVRM.SquarePulse(delt=0.02)

        x, y = np.meshgrid(np.linspace(-17, 17, 16), np.linspace(-17, 17, 16))
        x, y, z = mkvc(x), mkvc(y), 0.5*np.ones(np.size(x))
        rxList = [VRM.Rx.Point(np.c_[x, y, z], times=times, fieldType='dbdt', fieldComp='z')]

        txNodes = np.array([[-20, -20, 0.001],
                            [20, -20, 0.001],
                            [20, 20, 0.001],
                            [-20, 20, 0.01],
                            [-20, -20, 0.001]])
        txList = [VRM.Src.LineCurrent(rxList, txNodes, 1., waveObj)]

        Survey = VRM.Survey(txList)
        Survey.t_active = np.zeros(Survey.nD, dtype=bool)
        Survey.set_active_interval(-1e6, 1e6)
        Problem = VRM.Problem_Linear(meshObj, ref_factor=2)
        Problem.pair(Survey)
        Survey.makeSyntheticData(mod)
        Survey.eps = 1e-11

        dmis = DataMisfit.l2_DataMisfit(Survey)
        W = mkvc((np.sum(np.array(Problem.A)**2, axis=0)))**0.25
        reg = Regularization.Simple(
            meshObj, alpha_s=0.01, alpha_x=1., alpha_y=1., alpha_z=1., cell_weights=W
            )
        opt = Optimization.ProjectedGNCG(
            maxIter=20, lower=0., upper=1e-2, maxIterLS=20, tolCG=1e-4
            )
        invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
        directives = [
            Directives.BetaSchedule(coolingFactor=2, coolingRate=1),
            Directives.TargetMisfit()
        ]
        inv = Inversion.BaseInversion(invProb, directiveList=directives)

        m0 = 1e-6*np.ones(len(mod))
        mrec = inv.run(m0)

        dmis_final = np.sum((dmis.W.diagonal()*(Survey.dobs - Problem.fields(mrec)))**2)
        mod_err_2 = np.sqrt(np.sum((mrec-mod)**2))/np.size(mod)
        mod_err_inf = np.max(np.abs(mrec-mod))

        self.assertTrue(dmis_final < Survey.nD and mod_err_2 < 5e-6 and mod_err_inf < np.max(mod))
示例#9
0
    def getADeriv(self, freq, u, v, adjoint=False):
        """
        Calculate the derivative of A wrt m.

        :param float freq: Frequency
        :param SimPEG.EM.NSEM.FieldsNSEM u: NSEM Fields object
        :param numpy.ndarray v: vector of size (nU,) (adjoint=False)
            and size (nP,) (adjoint=True)
        :rtype: numpy.ndarray
        :return: Calculated derivative (nP,) (adjoint=False) and (nU,)[NOTE return as a (nU/2,2)
            columnwise polarizations] (adjoint=True) for both polarizations

        """
        # Fix u to be a matrix nE,2
        # This considers both polarizations and returns a nE,2 matrix for each polarization
        # The solution types
        sol0, sol1 = self._solutionType

        if adjoint:
            dMe_dsigV = sp.hstack((self.MeSigmaDeriv(
                u[sol0]).T, self.MeSigmaDeriv(u[sol1]).T)) * v
        else:
            # Need a nE,2 matrix to be returned
            dMe_dsigV = np.hstack(
                (mkvc(self.MeSigmaDeriv(u[sol0]) * v,
                      2), mkvc(self.MeSigmaDeriv(u[sol1]) * v, 2)))
        return 1j * omega(freq) * dMe_dsigV
示例#10
0
def getInputs():
    """
    Function that returns Mesh, freqs, rx_loc, elev.
    """
    # Make a mesh
    M = discretize.TensorMesh(
        [
            [(200, 6, -1.5), (200.0, 4), (200, 6, 1.5)],
            [(200, 6, -1.5), (200.0, 4), (200, 6, 1.5)],
            [(200, 8, -1.5), (200.0, 8), (200, 8, 1.5)],
        ],
        x0=["C", "C", "C"],
    )  # Setup the model
    # Set the frequencies
    freqs = np.logspace(1, -3, 5)
    elev = 0

    # Setup the the survey object
    # Receiver locations
    rx_x, rx_y = np.meshgrid(np.arange(-350, 350, 200),
                             np.arange(-350, 350, 200))
    rx_loc = np.hstack((mkvc(rx_x, 2), mkvc(rx_y, 2), elev + np.zeros(
        (np.prod(rx_x.shape), 1))))

    return M, freqs, rx_loc, elev
示例#11
0
 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.sigma)(self.ePrimary(problem)[:, 1]) *
             problem.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)
         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
示例#12
0
文件: SrcNSEM.py 项目: jsc1129/simpeg
    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
            ePri = self.ePrimary(problem)[:,1]
            MsigmaDeriv = problem.mesh.getFaceInnerProductDeriv(problem.sigma)(ePri) * problem.sigmaDeriv
            # MsigmaDeriv = ( MsigmaDeriv * MsigmaDeriv.T)**2

            if adjoint:
                #
                return MsigmaDeriv.T * v
            else:
                # v should be nC size
                return MsigmaDeriv * v
        if problem.mesh.dim == 2:
            raise NotImplementedError('The NSEM 2D problem is not implemented')
        if problem.mesh.dim == 3:
            # Need to take the derivative of both u_px and u_py
            # And stack them to be of the correct size
            e_p = self.ePrimary(problem)
            if adjoint:
                return sp.hstack(( problem.MeSigmaDeriv(e_p[:,0]).T, problem.MeSigmaDeriv(e_p[:,1]).T ))*v
            else:
                return np.hstack(( mkvc(problem.MeSigmaDeriv(e_p[:,0]) * v,2), mkvc(problem.MeSigmaDeriv(e_p[:,1])*v,2) ))
示例#13
0
    def importFiles(self):
        """
        Function to import EDI files into a object.


        """

        # Constants that are needed for convertion of units

        # Temp lists
        tmpStaList = []

        tmpCompList = ['freq','x','y','z']
        tmpCompList.extend(self.comps)
        # Make the outarray
        dtRI = [(compS.lower().replace('.',''),float) for compS in tmpCompList]
        # Loop through all the files
        for nrEDI, EDIfile in enumerate(self.filesList):
            # Read the file into a list of the lines
            with open(EDIfile,'r') as fid:
                EDIlines = fid.readlines()
            # Find the location
            latD, longD, elevM = _findLatLong(EDIlines)
            # Transfrom coordinates
            transCoord = self._transfromPoints(longD,latD)
            # Extract the name of the file (station)
            EDIname = EDIfile.split(os.sep)[-1].split('.')[0]
            # Arrange the data
            staList = [EDIname, EDIfile, transCoord[0], transCoord[1], elevM[0]]
            # Add to the station list
            tmpStaList.extend(staList)

            # Read the frequency data
            freq = _findEDIcomp('>FREQ',EDIlines)
            # Make the temporary rec array.
            tArrRec = ( np.nan*np.ones( (len(freq),len(dtRI)) ) ).view(dtRI)     #np.concatenate((freq*np.ones((locs.shape[0],1)),locs,np.nan*np.ones((locs.shape[0],8))),axis=1).view(dtRI)
            # Add data to the array
            tArrRec['freq'] = mkvc(freq,2)
            tArrRec['x'] = mkvc(np.ones((len(freq),1))*transCoord[0],2)
            tArrRec['y'] = mkvc(np.ones((len(freq),1))*transCoord[1],2)
            tArrRec['z'] = mkvc(np.ones((len(freq),1))*elevM[0],2)
            for comp in self.comps:
                # Deal with converting units of the impedance tensor
                if 'Z' in comp:
                    unitConvert = self._impUnitEDI2SI
                else:
                    unitConvert = 1
                # Rotate the data since EDI x is *north, y *east but Simpeg uses x *east, y *north (* means internal reference frame)
                key = [comp.lower().replace('.','').replace(s,t) for s,t in [['xx','yy'],['xy','yx'],['yx','xy'],['yy','xx']] if s in comp.lower()][0]
                tArrRec[key] = mkvc(unitConvert*_findEDIcomp('>'+comp,EDIlines),2)
            # Make a masked array
            mArrRec = np.ma.MaskedArray(rec2ndarr(tArrRec),mask=np.isnan(rec2ndarr(tArrRec))).view(dtype=tArrRec.dtype)
            try:
                outTemp = recFunc.stack_arrays((outTemp,mArrRec))
            except NameError as e:
                outTemp = mArrRec

        # Assign the data
        self._data = outTemp
示例#14
0
    def importFiles(self):
        """
        Function to import EDI files into a object.


        """

        # Constants that are needed for convertion of units

        # Temp lists
        tmpStaList = []

        tmpCompList = ['freq','x','y','z']
        tmpCompList.extend(self.comps)
        # Make the outarray
        dtRI = [(compS.lower().replace('.',''),float) for compS in tmpCompList]
        # Loop through all the files
        for nrEDI, EDIfile in enumerate(self.filesList):
            # Read the file into a list of the lines
            with open(EDIfile,'r') as fid:
                EDIlines = fid.readlines()
            # Find the location
            latD, longD, elevM = _findLatLong(EDIlines)
            # Transfrom coordinates
            transCoord = self._transfromPoints(longD,latD)
            # Extract the name of the file (station)
            EDIname = EDIfile.split(os.sep)[-1].split('.')[0]
            # Arrange the data
            staList = [EDIname, EDIfile, transCoord[0], transCoord[1], elevM[0]]
            # Add to the station list
            tmpStaList.extend(staList)

            # Read the frequency data
            freq = _findEDIcomp('>FREQ',EDIlines)
            # Make the temporary rec array.
            tArrRec = ( np.nan*np.ones( (len(freq),len(dtRI)) ) ).view(dtRI)     #np.concatenate((freq*np.ones((locs.shape[0],1)),locs,np.nan*np.ones((locs.shape[0],8))),axis=1).view(dtRI)
            # Add data to the array
            tArrRec['freq'] = mkvc(freq,2)
            tArrRec['x'] = mkvc(np.ones((len(freq),1))*transCoord[0],2)
            tArrRec['y'] = mkvc(np.ones((len(freq),1))*transCoord[1],2)
            tArrRec['z'] = mkvc(np.ones((len(freq),1))*elevM[0],2)
            for comp in self.comps:
                # Deal with converting units of the impedance tensor
                if 'Z' in comp:
                    unitConvert = self._impUnitEDI2SI
                else:
                    unitConvert = 1
                # Rotate the data since EDI x is *north, y *east but Simpeg uses x *east, y *north (* means internal reference frame)
                key = [comp.lower().replace('.','').replace(s,t) for s,t in [['xx','yy'],['xy','yx'],['yx','xy'],['yy','xx']] if s in comp.lower()][0]
                tArrRec[key] = mkvc(unitConvert*_findEDIcomp('>'+comp,EDIlines),2)
            # Make a masked array
            mArrRec = np.ma.MaskedArray(rec2ndarr(tArrRec),mask=np.isnan(rec2ndarr(tArrRec))).view(dtype=tArrRec.dtype)
            try:
                outTemp = recFunc.stack_arrays((outTemp,mArrRec))
            except NameError as e:
                outTemp = mArrRec

        # Assign the data
        self._data = outTemp
示例#15
0
    def Jtvec(self, m, v, u=None):
        """
        Function to calculate the transpose of the data sensitivities (dD/dm)^T times a vector.

            :param numpy.ndarray m (nC, 1) - conductive model
            :param numpy.ndarray v (nD, 1) - vector
            :param MTfields object u (optional) - MT fields object, if not given it is calculated
            :rtype: MTdata object
            :return: Data sensitivities wrt m
        """

        if u is None:
            u = self.fields(m)

        self.curModel = m

        # Ensure v is a data object.
        if not isinstance(v, self.dataPair):
            v = self.dataPair(self.survey, v)

        Jtv = np.zeros(m.size)

        for freq in self.survey.freqs:
            AT = self.getA(freq).T

            ATinv = self.Solver(AT, **self.solverOpts)

            for src in self.survey.getSrcByFreq(freq):
                ftype = self._fieldType + 'Solution'
                u_src = u[src, :]

                for rx in src.rxList:
                    # Get the adjoint evalDeriv
                    # PTv needs to be nE,
                    PTv = rx.evalDeriv(src, self.mesh, u, mkvc(v[src, rx],2), adjoint=True) # wrt u, need possibility wrt m
                    # Get the
                    dA_duIT = ATinv * PTv
                    dA_dmT = self.getADeriv_m(freq, u_src, mkvc(dA_duIT), adjoint=True)
                    dRHS_dmT = self.getRHSDeriv_m(freq, mkvc(dA_duIT), adjoint=True)
                    # Make du_dmT
                    if dRHS_dmT is None:
                        du_dmT = -dA_dmT
                    else:
                        du_dmT = -dA_dmT + dRHS_dmT
                    # Select the correct component
                    # du_dmT needs to be of size nC,
                    real_or_imag = rx.projComp
                    if real_or_imag == 'real':
                        Jtv +=  du_dmT.real
                    elif real_or_imag == 'imag':
                        Jtv +=  -du_dmT.real
                    else:
                        raise Exception('Must be real or imag')
            # Clean the factorization, clear memory.
            ATinv.clean()
        return Jtv
示例#16
0
    def Jtvec(self, m, v, f=None):
        """
        Function to calculate the transpose of the data sensitivities (dD/dm)^T times a vector.

        :param numpy.ndarray m: inversion model (nP,)
        :param numpy.ndarray v: vector which we take adjoint product with (nP,)
        :param SimPEG.EM.NSEM.FieldsNSEM f (optional): NSEM fields object, if not given it is calculated
        :rtype: numpy.ndarray
        :return: Jtv (nP,) Data sensitivities wrt m
        """

        if f is None:
            f = self.fields(m)

        self.model = m

        # Ensure v is a data object.
        if not isinstance(v, self.dataPair):
            v = self.dataPair(self.survey, v)

        Jtv = np.zeros(m.size)

        for freq in self.survey.freqs:
            AT = self.getA(freq).T

            ATinv = self.Solver(AT, **self.solverOpts)

            for src in self.survey.getSrcByFreq(freq):
                # u_src needs to have both polarizations
                u_src = f[src, :]

                for rx in src.rxList:
                    # Get the adjoint evalDeriv
                    # PTv needs to be nE,2
                    PTv = rx.evalDeriv(
                        src, self.mesh, f, mkvc(v[src, rx]),
                        adjoint=True)  # wrt f, need possibility wrt m
                    # Get the
                    dA_duIT = mkvc(ATinv * PTv)  # Force (nU,) shape
                    dA_dmT = self.getADeriv(freq, u_src, dA_duIT, adjoint=True)
                    dRHS_dmT = self.getRHSDeriv(freq, dA_duIT, adjoint=True)
                    # Make du_dmT
                    du_dmT = -dA_dmT + dRHS_dmT
                    # Select the correct component
                    # du_dmT needs to be of size (nP,) number of model parameters
                    real_or_imag = rx.component
                    if real_or_imag == 'real':
                        Jtv += np.array(du_dmT, dtype=complex).real
                    elif real_or_imag == 'imag':
                        Jtv += -np.array(du_dmT, dtype=complex).real
                    else:
                        raise Exception('Must be real or imag')
            # Clean the factorization, clear memory.
            ATinv.clean()
        return Jtv
示例#17
0
    def getADeriv(self, freq, u, v, adjoint=False):
        """
        The derivative of A wrt sigma
        """

        u_src = u['e_1dSolution']
        dMfSigma_dm = self.MfSigmaDeriv(u_src)
        if adjoint:
            return 1j * omega(freq) * mkvc(dMfSigma_dm.T * v, )
        # Note: output has to be nN/nF, not nC/nE.
        # v should be nC
        return 1j * omega(freq) * mkvc(dMfSigma_dm * v, )
示例#18
0
    def getADeriv(self, freq, u, v, adjoint=False):
        """
        The derivative of A wrt sigma
        """

        u_src = u['e_1dSolution']
        dMfSigma_dm = self.MfSigmaDeriv(u_src)
        if adjoint:
            return 1j * omega(freq) * mkvc(dMfSigma_dm.T * v,)
        # Note: output has to be nN/nF, not nC/nE.
        # v should be nC
        return 1j * omega(freq) * mkvc(dMfSigma_dm * v,)
示例#19
0
    def Jtvec(self, m, v, f=None):
        """
        Function to calculate the transpose of the data sensitivities (dD/dm)^T times a vector.

        :param numpy.ndarray m: inversion model (nP,)
        :param numpy.ndarray v: vector which we take adjoint product with (nP,)
        :param SimPEG.EM.NSEM.FieldsNSEM f (optional): NSEM fields object, if not given it is calculated
        :rtype: numpy.ndarray
        :return: Jtv (nP,) Data sensitivities wrt m
        """

        if f is None:
            f = self.fields(m)

        self.model = m

        # Ensure v is a data object.
        if not isinstance(v, self.dataPair):
            v = self.dataPair(self.survey, v)

        Jtv = np.zeros(m.size)

        for freq in self.survey.freqs:
            AT = self.getA(freq).T

            ATinv = self.Solver(AT, **self.solverOpts)

            for src in self.survey.getSrcByFreq(freq):
                # u_src needs to have both polarizations
                u_src = f[src, :]

                for rx in src.rxList:
                    # Get the adjoint evalDeriv
                    # PTv needs to be nE,2
                    PTv = rx.evalDeriv(src, self.mesh, f, mkvc(v[src, rx]), adjoint=True) # wrt f, need possibility wrt m
                    # Get the
                    dA_duIT = mkvc(ATinv * PTv) # Force (nU,) shape
                    dA_dmT = self.getADeriv(freq, u_src, dA_duIT, adjoint=True)
                    dRHS_dmT = self.getRHSDeriv(freq, dA_duIT, adjoint=True)
                    # Make du_dmT
                    du_dmT = -dA_dmT + dRHS_dmT
                    # Select the correct component
                    # du_dmT needs to be of size (nP,) number of model parameters
                    real_or_imag = rx.component
                    if real_or_imag == 'real':
                        Jtv +=  np.array(du_dmT, dtype=complex).real
                    elif real_or_imag == 'imag':
                        Jtv +=  -np.array(du_dmT, dtype=complex).real
                    else:
                        raise Exception('Must be real or imag')
            # Clean the factorization, clear memory.
            ATinv.clean()
        return Jtv
示例#20
0
    def Jtvec(self, m, v, u=None):
        if u is None:
            u = self.fields(m)

        self.curModel = m

        # Ensure v is a data object.
        if not isinstance(v, self.dataPair):
            v = self.dataPair(self.survey, v)

        Jtv = np.zeros(m.size)

        for freq in self.survey.freqs:
            AT = self.getA(freq).T

            ATinv = self.Solver(AT, **self.solverOpts)

            for src in self.survey.getSrcByFreq(freq):
                ftype = self._fieldType + 'Solution'
                u_src = u[src, :]

                for rx in src.rxList:
                    # Get the adjoint projectFieldsDeriv
                    # PTv needs to be nE,
                    PTv = rx.projectFieldsDeriv(
                        src, self.mesh, u, mkvc(v[src, rx], 2),
                        adjoint=True)  # wrt u, need possibility wrt m
                    # Get the
                    dA_duIT = ATinv * PTv
                    dA_dmT = self.getADeriv_m(freq,
                                              u_src,
                                              mkvc(dA_duIT),
                                              adjoint=True)
                    dRHS_dmT = self.getRHSDeriv_m(freq,
                                                  mkvc(dA_duIT),
                                                  adjoint=True)
                    # Make du_dmT
                    if dRHS_dmT is None:
                        du_dmT = -dA_dmT
                    else:
                        du_dmT = -dA_dmT + dRHS_dmT
                    # Select the correct component
                    # du_dmT needs to be of size nC,
                    real_or_imag = rx.projComp
                    if real_or_imag == 'real':
                        Jtv += du_dmT.real
                    elif real_or_imag == 'imag':
                        Jtv += -du_dmT.real
                    else:
                        raise Exception('Must be real or imag')

        return Jtv
示例#21
0
    def _getSubsetAcolumns(self, xyzc, xyzh, pp, qq, refFlag):
        """
        This method returns the refined sensitivities for columns that will be
        replaced in the A matrix for source pp and refinement factor qq.
..
..        INPUTS:
..
..        xyzc -- Cell centers of topo mesh cells N X 3 array
..
..        xyzh -- Cell widths of topo mesh cells N X 3 array
..
..        pp -- Source ID
..
..        qq -- Mesh refinement factor
..
..        refFlag -- refinement factors for all topo mesh cells
..
..        OUTPUTS:
..
..        Acols -- Columns containing replacement sensitivities

        """

        # GET SUBMESH GRID
        n = 2**qq
        [nx, ny, nz] = np.meshgrid(
            np.linspace(1, n, n) - 0.5,
            np.linspace(1, n, n) - 0.5,
            np.linspace(1, n, n) - 0.5)
        nxyz_sub = np.c_[mkvc(nx), mkvc(ny), mkvc(nz)]

        xyzh_sub = xyzh[refFlag == qq, :]  # Get widths of cells to be refined
        xyzc_sub = xyzc[refFlag == qq, :] - xyzh[
            refFlag ==
            qq, :] / 2  # Get bottom southwest corners of cells to be refined
        m = np.shape(xyzc_sub)[0]
        xyzc_sub = np.kron(xyzc_sub, np.ones(
            (n**3, 1)))  # Kron for n**3 refined cells
        xyzh_sub = np.kron(xyzh_sub / n, np.ones(
            (n**3, 1)))  # Kron for n**3 refined cells with widths h/n
        nxyz_sub = np.kron(np.ones((m, 1)),
                           nxyz_sub)  # Kron for n**3 refined cells
        xyzc_sub = xyzc_sub + xyzh_sub * nxyz_sub

        # GET SUBMESH A MATRIX AND COLLAPSE TO COLUMNS
        G = self._getGeometryMatrix(xyzc_sub, xyzh_sub, pp)
        H0 = self._getH0matrix(xyzc_sub, pp)
        Acols = (G * H0) * sp.kron(sp.diags(np.ones(m)), np.ones((n**3, 1)))

        return Acols
示例#22
0
    def Jvec(self, m, v, f=None):
        """
        Function to calculate the data sensitivities dD/dm times a vector.

        :param numpy.ndarray m: conductivity model (nP,)
        :param numpy.ndarray v: vector which we take sensitivity product with (nP,)
        :param SimPEG.EM.NSEM.FieldsNSEM (optional) u: NSEM fields object, if not given
            it is calculated
        :rtype: numpy.ndarray
        :return: Jv (nData,) Data sensitivities wrt m
        """

        # Calculate the fields if not given as input
        if f is None:
            f = self.fields(m)
        # Set current model
        self.curModel = m
        # Initiate the Jv object
        Jv = self.dataPair(self.survey)

        # Loop all the frequenies
        for freq in self.survey.freqs:
            # Get the system
            A = self.getA(freq)
            # Factor
            Ainv = self.Solver(A, **self.solverOpts)

            for src in self.survey.getSrcByFreq(freq):
                # We need fDeriv_m = df/du*du/dm + df/dm
                # Construct du/dm, it requires a solve
                # NOTE: need to account for the 2 polarizations in the derivatives.
                u_src = f[
                    src, :]  # u should be a vector by definition. Need to fix this...
                # dA_dm and dRHS_dm should be of size nE,2, so that we can multiply by Ainv.
                # The 2 columns are each of the polarizations.
                dA_dm_v = self.getADeriv(
                    freq, u_src, v)  # Size: nE,2 (u_px,u_py) in the columns.
                dRHS_dm_v = self.getRHSDeriv(
                    freq, v)  # Size: nE,2 (u_px,u_py) in the columns.
                # Calculate du/dm*v
                du_dm_v = Ainv * (-dA_dm_v + dRHS_dm_v)
                # Calculate the projection derivatives
                for rx in src.rxList:
                    # Calculate dP/du*du/dm*v
                    Jv[src, rx] = rx.evalDeriv(
                        src, self.mesh, f,
                        mkvc(du_dm_v))  # wrt uPDeriv_u(mkvc(du_dm))
            Ainv.clean()
        # Return the vectorized sensitivities
        return mkvc(Jv)
示例#23
0
    def Jvec(self, m, v, u=None):
        """
        Function to calculate the data sensitivities dD/dm times a vector.

            :param numpy.ndarray (nC, 1) - conductive model
            :param numpy.ndarray (nC, 1) - random vector
            :param MTfields object (optional) - MT fields object, if not given it is calculated
            :rtype: MTdata object
            :return: Data sensitivities wrt m
        """

        # Calculate the fields
        if u is None:
            u = self.fields(m)
        # Set current model
        self.curModel = m
        # Initiate the Jv object
        Jv = self.dataPair(self.survey)

        # Loop all the frequenies
        for freq in self.survey.freqs:
            dA_du = self.getA(freq)  #

            dA_duI = self.Solver(dA_du, **self.solverOpts)

            for src in self.survey.getSrcByFreq(freq):
                # We need fDeriv_m = df/du*du/dm + df/dm
                # Construct du/dm, it requires a solve
                # NOTE: need to account for the 2 polarizations in the derivatives.
                u_src = u[src, :]
                # dA_dm and dRHS_dm should be of size nE,2, so that we can multiply by dA_duI. The 2 columns are each of the polarizations.
                dA_dm = self.getADeriv_m(
                    freq, u_src, v)  # Size: nE,2 (u_px,u_py) in the columns.
                dRHS_dm = self.getRHSDeriv_m(
                    freq, v)  # Size: nE,2 (u_px,u_py) in the columns.
                if dRHS_dm is None:
                    du_dm = dA_duI * (-dA_dm)
                else:
                    du_dm = dA_duI * (-dA_dm + dRHS_dm)
                # Calculate the projection derivatives
                for rx in src.rxList:
                    # Get the projection derivative
                    # v should be of size 2*nE (for 2 polarizations)
                    PDeriv_u = lambda t: rx.projectFieldsDeriv(
                        src, self.mesh, u, t
                    )  # wrt u, we don't have have PDeriv wrt m
                    Jv[src, rx] = PDeriv_u(mkvc(du_dm))
        # Return the vectorized sensitivities
        return mkvc(Jv)
示例#24
0
def writeUBC_DCobs(fileName,Tx,Rx,d,wd, dtype):
    
    from SimPEG import np, mkvc
    import re
    """
        Read UBC GIF DCIP 3D observation file and generate arrays for tx-rx location
    
        Input:
        :param fileName, path to the UBC GIF 3D obs file
    
        Output:
        :param rx, tx, d, wd
        :return
        
        Created on Mon December 7th, 2015
    
        @author: dominiquef
    
    """
    fid = open(fileName,'w')
    fid.write('! GENERAL FORMAT\n')  
    
    for ii in range(len(Tx)):
        
        tx = np.asarray(Tx[ii])
        rx = np.asarray(Rx[ii])
        nrx = rx.shape[0]
        
        fid.write('\n')
        
        if re.match(dtype,'2D'):
            
            for jj in range(nrx):
                
                fid.writelines("%e " % ii for ii in mkvc(tx))
                fid.writelines("%e " % ii for ii in mkvc(rx[jj]))
                fid.write('%e %e\n'% (d[ii][jj],wd[ii][jj]))
                #np.savetxt(fid, np.c_[ rx ,np.asarray(d[ii]), np.asarray(wd[ii]) ], fmt='%e',delimiter=' ',newline='\n') 
        
        elif re.match(dtype,'3D'):
                                
            fid.write('\n')
            fid.writelines("%e " % ii for ii in mkvc(tx))
            fid.write('%i\n'% nrx)
            np.savetxt(fid, np.c_[ rx ,np.asarray(d[ii]), np.asarray(wd[ii]) ], fmt='%e',delimiter=' ',newline='\n') 
        
        
    fid.close()  
示例#25
0
    def fields(self, m=None):

        """Computes the fields at every time d(t) = G*M(t)"""

        if self.ispaired is False:
            AssertionError("Problem must be paired with survey to generate A matrix")

        # Fields from each source
        srcList = self.survey.srcList
        nSrc = len(srcList)
        f = []

        for pp in range(0, nSrc):

            rxList = srcList[pp].rxList
            nRx = len(rxList)
            waveObj = srcList[pp].waveform

            for qq in range(0, nRx):

                times = rxList[qq].times
                eta = waveObj.getLogUniformDecay(
                    rxList[qq].fieldType, times, self.chi0, self.dchi, self.tau1, self.tau2
                )

                f.append(mkvc((self.A[qq] * np.matrix(eta)).T))

        return np.array(np.hstack(f))
示例#26
0
    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
示例#27
0
    def fields(self, m=None):
        """Computes the fields at every time d(t) = G*M(t)"""

        if self.ispaired is False:
            AssertionError(
                "Problem must be paired with survey to generate A matrix")

        # Fields from each source
        srcList = self.survey.srcList
        nSrc = len(srcList)
        f = []

        for pp in range(0, nSrc):

            rxList = srcList[pp].rxList
            nRx = len(rxList)
            waveObj = srcList[pp].waveform

            for qq in range(0, nRx):

                times = rxList[qq].times
                eta = waveObj.getLogUniformDecay(rxList[qq].fieldType, times,
                                                 self.chi0, self.dchi,
                                                 self.tau1, self.tau2)

                f.append(mkvc((self.A[qq] * np.matrix(eta)).T))

        return np.array(np.hstack(f))
示例#28
0
 def _aey_py_u(self, vec):
     """
     """
     # vec is (nD,) and returns a (nU,)
     return self.f._e_pyDeriv_u(self.src,
                                self.Pey.T * mkvc(vec, ),
                                adjoint=True)
示例#29
0
    def fields(self, m):
        '''
        Function to calculate all the fields for the model m.

        :param np.ndarray (nC,) m: Conductivity model
        :param np.ndarray (nC,) m_back: Background conductivity model
        '''
        self.curModel = m
        # RHS, CalcFields = self.getRHS(freq,m_back), self.calcFields

        F = Fields1D_e(self.mesh, self.survey)
        for freq in self.survey.freqs:
            if self.verbose:
                startTime = time.time()
                print 'Starting work for {:.3e}'.format(freq)
                sys.stdout.flush()
            A = self.getA(freq)
            rhs, e_o = self.getRHS(freq)
            Ainv = self.Solver(A, **self.solverOpts)
            e_i = Ainv * rhs
            e = mkvc(np.r_[e_o[0], e_i, e_o[1]], 2)
            # Store the fields
            Src = self.survey.getSrcByFreq(freq)
            # NOTE: only store e fields
            F[Src, 'e_1dSolution'] = e[:, 0]
            if self.verbose:
                print 'Ran for {:f} seconds'.format(time.time() - startTime)
                sys.stdout.flush()
        return F
示例#30
0
    def fields(self, m):
        '''
        Function to calculate all the fields for the model m.

        :param np.ndarray (nC,) m: Conductivity model
        :param np.ndarray (nC,) m_back: Background conductivity model
        '''
        self.curModel = m
        # RHS, CalcFields = self.getRHS(freq,m_back), self.calcFields

        F = FieldsMT_1D(self.mesh, self.survey)
        for freq in self.survey.freqs:
            if self.verbose:
                startTime = time.time()
                print 'Starting work for {:.3e}'.format(freq)
                sys.stdout.flush()
            A = self.getA(freq)
            rhs, e_o = self.getRHS(freq)
            Ainv = self.Solver(A, **self.solverOpts)
            e_i = Ainv * rhs
            e = mkvc(np.r_[e_o[0], e_i, e_o[1]],2)
            # Store the fields
            Src = self.survey.getSrcByFreq(freq)
            # NOTE: only store e fields
            F[Src, 'e_1dSolution'] = e[:,0]
            if self.verbose:
                print 'Ran for {:f} seconds'.format(time.time()-startTime)
                sys.stdout.flush()
        return F
示例#31
0
    def Jvec(self, m, v, u=None):
        """
        Function to calculate the data sensitivities dD/dm times a vector.

            :param numpy.ndarray m (nC, 1) - conductive model
            :param numpy.ndarray v (nC, 1) - random vector
            :param MTfields object (optional) - MT fields object, if not given it is calculated
            :rtype: MTdata object
            :return: Data sensitivities wrt m
        """

        # Calculate the fields
        if u is None:
           u = self.fields(m)
        # Set current model
        self.curModel = m
        # Initiate the Jv object
        Jv = self.dataPair(self.survey)

        # Loop all the frequenies
        for freq in self.survey.freqs:
            dA_du = self.getA(freq) #

            dA_duI = self.Solver(dA_du, **self.solverOpts)

            for src in self.survey.getSrcByFreq(freq):
                # We need fDeriv_m = df/du*du/dm + df/dm
                # Construct du/dm, it requires a solve
                # NOTE: need to account for the 2 polarizations in the derivatives.
                u_src = u[src,:]
                # dA_dm and dRHS_dm should be of size nE,2, so that we can multiply by dA_duI. The 2 columns are each of the polarizations.
                dA_dm = self.getADeriv_m(freq, u_src, v) # Size: nE,2 (u_px,u_py) in the columns.
                dRHS_dm = self.getRHSDeriv_m(freq, v) # Size: nE,2 (u_px,u_py) in the columns.
                if dRHS_dm is None:
                    du_dm = dA_duI * ( -dA_dm )
                else:
                    du_dm = dA_duI * ( -dA_dm + dRHS_dm )
                # Calculate the projection derivatives
                for rx in src.rxList:
                    # Get the projection derivative
                    # v should be of size 2*nE (for 2 polarizations)
                    PDeriv_u = lambda t: rx.evalDeriv(src, self.mesh, u, t) # wrt u, we don't have have PDeriv wrt m
                    Jv[src, rx] = PDeriv_u(mkvc(du_dm))
            dA_duI.clean()
        # Return the vectorized sensitivities
        return mkvc(Jv)
示例#32
0
 def fun(u):
     f = simulation.fieldsPair(survey.mesh, survey)
     f[src, "e_pxSolution"] = u[:len(u) / 2]
     f[src, "e_pySolution"] = u[len(u) / 2::]
     return (
         rx.eval(src, survey.mesh, f),
         lambda t: rx.evalDeriv(src, survey.mesh, f0, mkvc(t, 2)),
     )
示例#33
0
文件: BaseMT.py 项目: simpeg/simpegmt
    def Jtvec(self, m, v, u=None):
        if u is None:
            u = self.fields(m)

        self.curModel = m

        # Ensure v is a data object.
        if not isinstance(v, self.dataPair):
            v = self.dataPair(self.survey, v)

        Jtv = np.zeros(m.size)

        for freq in self.survey.freqs:
            AT = self.getA(freq).T

            ATinv = self.Solver(AT, **self.solverOpts)

            for src in self.survey.getSrcByFreq(freq):
                ftype = self._fieldType + 'Solution'
                u_src = u[src, :]

                for rx in src.rxList:
                    # Get the adjoint projectFieldsDeriv
                    # PTv needs to be nE,
                    PTv = rx.projectFieldsDeriv(src, self.mesh, u, mkvc(v[src, rx],2), adjoint=True) # wrt u, need possibility wrt m
                    # Get the
                    dA_duIT = ATinv * PTv
                    dA_dmT = self.getADeriv_m(freq, u_src, mkvc(dA_duIT), adjoint=True)
                    dRHS_dmT = self.getRHSDeriv_m(freq, mkvc(dA_duIT), adjoint=True)
                    # Make du_dmT
                    if dRHS_dmT is None:
                        du_dmT = -dA_dmT
                    else:
                        du_dmT = -dA_dmT + dRHS_dmT
                    # Select the correct component
                    # du_dmT needs to be of size nC,
                    real_or_imag = rx.projComp
                    if real_or_imag == 'real':
                        Jtv +=  du_dmT.real
                    elif real_or_imag == 'imag':
                        Jtv +=  -du_dmT.real
                    else:
                        raise Exception('Must be real or imag')

        return Jtv
示例#34
0
    def Jvec(self, m, v, f=None):
        """
        Function to calculate the data sensitivities dD/dm times a vector.

        :param numpy.ndarray m: conductivity model (nP,)
        :param numpy.ndarray v: vector which we take sensitivity product with (nP,)
        :param SimPEG.EM.NSEM.FieldsNSEM (optional) u: NSEM fields object, if not given
            it is calculated
        :rtype: numpy.ndarray
        :return: Jv (nData,) Data sensitivities wrt m
        """

        # Calculate the fields if not given as input
        if f is None:
           f = self.fields(m)
        # Set current model
        self.model = m
        # Initiate the Jv object
        Jv = self.dataPair(self.survey)

        # Loop all the frequenies
        for freq in self.survey.freqs:
            # Get the system
            A = self.getA(freq)
            # Factor
            Ainv = self.Solver(A, **self.solverOpts)

            for src in self.survey.getSrcByFreq(freq):
                # We need fDeriv_m = df/du*du/dm + df/dm
                # Construct du/dm, it requires a solve
                # NOTE: need to account for the 2 polarizations in the derivatives.
                u_src = f[src,:] # u should be a vector by definition. Need to fix this...
                # dA_dm and dRHS_dm should be of size nE,2, so that we can multiply by Ainv.
                # The 2 columns are each of the polarizations.
                dA_dm_v = self.getADeriv(freq, u_src, v) # Size: nE,2 (u_px,u_py) in the columns.
                dRHS_dm_v = self.getRHSDeriv(freq, v) # Size: nE,2 (u_px,u_py) in the columns.
                # Calculate du/dm*v
                du_dm_v = Ainv * ( - dA_dm_v + dRHS_dm_v)
                # Calculate the projection derivatives
                for rx in src.rxList:
                    # Calculate dP/du*du/dm*v
                    Jv[src, rx] = rx.evalDeriv(src, self.mesh, f, mkvc(du_dm_v)) # wrt uPDeriv_u(mkvc(du_dm))
            Ainv.clean()
        # Return the vectorized sensitivities
        return mkvc(Jv)
示例#35
0
    def getRHSDeriv(self, freq, v, adjoint=False):
        """
        The derivative of the RHS wrt sigma
        """

        Src = self.survey.getSrcByFreq(freq)[0]

        S_eDeriv = mkvc(Src.S_eDeriv_m(self, v, adjoint), )
        return -1j * omega(freq) * S_eDeriv
示例#36
0
    def getRHSDeriv(self, freq, v, adjoint=False):
        """
        The derivative of the RHS wrt sigma
        """

        Src = self.survey.getSrcByFreq(freq)[0]

        S_eDeriv = mkvc(Src.S_eDeriv_m(self, v, adjoint),)
        return -1j * omega(freq) * S_eDeriv
示例#37
0
    def projectFields(self, u):
        """
            Predicted data.

            .. math::
                d_\\text{pred} = Pu(m)
        """
        P = self.getP(self.prob.mesh)
        return P*mkvc(u[self.srcList, 'phi_sol'])
示例#38
0
    def _getSubsetAcolumns(self, xyzc, xyzh, pp, qq, refFlag):

        """
        This method returns the refined sensitivities for columns that will be
        replaced in the A matrix for source pp and refinement factor qq.
..
..        INPUTS:
..
..        xyzc -- Cell centers of topo mesh cells N X 3 array
..
..        xyzh -- Cell widths of topo mesh cells N X 3 array
..
..        pp -- Source ID
..
..        qq -- Mesh refinement factor
..
..        refFlag -- refinement factors for all topo mesh cells
..
..        OUTPUTS:
..
..        Acols -- Columns containing replacement sensitivities

        """

        # GET SUBMESH GRID
        n = 2**qq
        [nx, ny, nz] = np.meshgrid(
            np.linspace(1, n, n)-0.5, np.linspace(1, n, n)-0.5, np.linspace(1, n, n)-0.5)
        nxyz_sub = np.c_[mkvc(nx), mkvc(ny), mkvc(nz)]

        xyzh_sub = xyzh[refFlag == qq, :]     # Get widths of cells to be refined
        xyzc_sub = xyzc[refFlag == qq, :] - xyzh[refFlag == qq, :]/2   # Get bottom southwest corners of cells to be refined
        m = np.shape(xyzc_sub)[0]
        xyzc_sub = np.kron(xyzc_sub, np.ones((n**3, 1)))     # Kron for n**3 refined cells
        xyzh_sub = np.kron(xyzh_sub/n, np.ones((n**3, 1)))   # Kron for n**3 refined cells with widths h/n
        nxyz_sub = np.kron(np.ones((m, 1)), nxyz_sub)        # Kron for n**3 refined cells
        xyzc_sub = xyzc_sub + xyzh_sub*nxyz_sub

        # GET SUBMESH A MATRIX AND COLLAPSE TO COLUMNS
        G = self._getGeometryMatrix(xyzc_sub, xyzh_sub, pp)
        H0 = self._getH0matrix(xyzc_sub, pp)
        Acols = (G*H0)*sp.kron(sp.diags(np.ones(m)), np.ones((n**3, 1)))

        return Acols
示例#39
0
def setup1DSurvey(sigmaHalf, tD=False, structure=False):

    # Frequency
    num_frequencies = 33
    freqs = np.logspace(3, -3, num_frequencies)
    # Make the mesh
    ct = 5
    air = meshTensor([(ct, 25, 1.3)])
    # coreT0 = meshTensor([(ct,15,1.2)])
    # coreT1 = np.kron(meshTensor([(coreT0[-1],15,1.3)]),np.ones((7,)))
    core = np.concatenate((np.kron(meshTensor([(ct, 15, -1.2)]), np.ones(
        (10, ))), meshTensor([(ct, 20)])))
    bot = meshTensor([(core[0], 20, -1.3)])
    x0 = -np.array([np.sum(np.concatenate((core, bot)))])
    m1d = discretize.TensorMesh([np.concatenate((bot, core, air))], x0=x0)
    # Make the model
    sigma = np.zeros(m1d.nC) + sigmaHalf
    sigma[m1d.gridCC > 0] = 1e-8
    sigmaBack = sigma.copy()
    # Add structure
    if structure:
        shallow = (m1d.gridCC < -200) * (m1d.gridCC > -600)
        deep = (m1d.gridCC < -3000) * (m1d.gridCC > -5000)
        sigma[shallow] = 1
        sigma[deep] = 0.1

    receiver_list = []
    for rxType in ["z1d", "z1d"]:
        receiver_list.append(
            Point1DImpedance(mkvc(np.array([0.0]), 2).T, "real"))
        receiver_list.append(
            Point1DImpedance(mkvc(np.array([0.0]), 2).T, "imag"))
    # Source list
    source_list = []
    if tD:
        for freq in freqs:
            source_list.append(Planewave_xy_1DhomotD(receiver_list, freq))
    else:
        for freq in freqs:
            source_list.append(Planewave_xy_1Dprimary(receiver_list, freq))

    survey = Survey(source_list)
    return (survey, sigma, sigmaBack, m1d)
示例#40
0
    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
示例#41
0
    def Jvec(self, m, v, u=None):
        """
            :param numpy.array m: model
            :param numpy.array v: vector to multiply
            :param numpy.array u: fields
            :rtype: numpy.array
            :return: Jv

            .. math::
                c(m,u) = A(m)u - q = G\\text{sdiag}(M(mT(m)))Du - q = 0

                \\nabla_u (A(m)u - q) = A(m)

                \\nabla_m (A(m)u - q) = G\\text{sdiag}(Du)\\nabla_m(M(mT(m)))

            Where M() is the mass matrix and mT is the model transform.

            .. math::
                J = - P \left( \\nabla_u c(m, u) \\right)^{-1} \\nabla_m c(m, u)

                J(v) = - P ( A(m)^{-1} ( G\\text{sdiag}(Du)\\nabla_m(M(mT(m))) v ) )
        """
        # Set current model; clear dependent property $\mathbf{A(m)}$
        self.curModel = m
        sigma = self.curModel.transform # $\sigma = \mathcal{M}(\m)$
        if u is None:
            # Run forward simulation if $u$ not provided
            u = self.fields(self.curModel)[self.survey.srcList, 'phi_sol']
        else:
            u = u[self.survey.srcList, 'phi_sol']

        D = self.mesh.faceDiv
        G = self.mesh.cellGrad
        # Derivative of model transform, $\deriv{\sigma}{\m}$
        dsigdm_x_v = self.curModel.transformDeriv * v

        # Take derivative of $C(m,u)$ w.r.t. $m$
        dCdm_x_v = np.empty_like(u)
        # loop over fields for each source
        for i in range(self.survey.nSrc):
            # Derivative of inner product, $\left(\mathbf{M}_{1/\sigma}^f\right)^{-1}$
            dAdsig         = D * self.dMdsig( G * u[:,i] )
            dCdm_x_v[:, i] = dAdsig *  dsigdm_x_v

        # Take derivative of $C(m,u)$ w.r.t. $u$
        dA_du = self.A
        # Solve for $\deriv{u}{m}$
        # dCdu_inv = self.Solver(dCdu, **self.solverOpts)
        if self.Ainv is None:
            self.Ainv = self.Solver(dA_du, **self.solverOpts)

        P        = self.survey.getP(self.mesh)
        Jv    = - P * mkvc( self.Ainv * dCdm_x_v )
        return Jv
示例#42
0
def readUBC_DC2DModel(fileName):

    from SimPEG import np, mkvc
    """
        Read UBC GIF 2DTensor model and generate 2D Tensor model in simpeg

        Input:
        :param fileName, path to the UBC GIF 2D model file

        Output:
        :param SimPEG TensorMesh 2D object
        :return
        
        Created on Thu Nov 12 13:14:10 2015

        @author: dominiquef

    """
    
    # Open fileand skip header... assume that we know the mesh already

    obsfile = np.genfromtxt(fileName,delimiter=' \n',dtype=np.str,comments='!')
    
    dim = np.array(obsfile[0].split(),dtype=float)
    
    temp = np.array(obsfile[1].split(),dtype=float)
    
    if len(temp) > 1:
        model = np.zeros(dim)
        
        for ii in range(len(obsfile)-1):
            mm = np.array(obsfile[ii+1].split(),dtype=float)
            model[:,ii] = mm
            
        model = model[:,::-1]
        
    else:
        
        if len(obsfile[1:])==1:
            mm = np.array(obsfile[1:].split(),dtype=float)
            
        else:
            mm = np.array(obsfile[1:],dtype=float)
            
        # Permute the second dimension to flip the order
        model = mm.reshape(dim[1],dim[0])
    
        model = model[::-1,:]
        model = np.transpose(model, (1, 0))
        
    model = mkvc(model)


    return model
示例#43
0
文件: SrcNSEM.py 项目: simpeg/simpeg
 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.sigma)(self.ePrimary(problem)[:, 1]) *
             problem.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)
         if adjoint:
             return (
                 problem.MeSigmaDeriv(
                     ePri[:, 0], v[:int(v.shape[0]/2)], adjoint
                 ) +
                 problem.MeSigmaDeriv(
                     ePri[:, 1], v[int(v.shape[0]/2):], 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, adjoint), 2),
                 mkvc(problem.MeSigmaDeriv(ePri[:, 1], v, adjoint), 2)
             ))
     if adjoint:
         #
         return MsigmaDeriv.T * v
     else:
         # v should be nC size
         return MsigmaDeriv * v
示例#44
0
def readUBC_DC2DModel(fileName):
    """
        Read UBC GIF 2DTensor model and generate 2D Tensor model in simpeg

        Input:
        :param fileName, path to the UBC GIF 2D model file

        Output:
        :param SimPEG TensorMesh 2D object
        :return

        Created on Thu Nov 12 13:14:10 2015

        @author: dominiquef

    """
    from SimPEG import np, mkvc

    # Open fileand skip header... assume that we know the mesh already
    obsfile = np.genfromtxt(fileName,delimiter=' \n',dtype=np.str,comments='!')

    dim = np.array(obsfile[0].split(),dtype=float)

    temp = np.array(obsfile[1].split(),dtype=float)

    if len(temp) > 1:
        model = np.zeros(dim)

        for ii in range(len(obsfile)-1):
            mm = np.array(obsfile[ii+1].split(),dtype=float)
            model[:,ii] = mm

        model = model[:,::-1]

    else:

        if len(obsfile[1:])==1:
            mm = np.array(obsfile[1:].split(),dtype=float)

        else:
            mm = np.array(obsfile[1:],dtype=float)

        # Permute the second dimension to flip the order
        model = mm.reshape(dim[1],dim[0])

        model = model[::-1,:]
        model = np.transpose(model, (1, 0))

    model = mkvc(model)


    return model
示例#45
0
    def getRHS(self, freq):
        """
            Function to return the right hand side for the system.
            :param float freq: Frequency
            :rtype: numpy.ndarray
            :return: RHS for 1 polarizations, primary fields (nF, 1)
        """

        # Get sources for the frequncy(polarizations)
        Src = self.survey.getSrcByFreq(freq)[0]
        # Only select the yx polarization
        S_e = mkvc(Src.S_e(self)[:, 1], 2)
        return -1j * omega(freq) * S_e
示例#46
0
    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
示例#47
0
    def getRHS(self, freq):
        """
            Function to return the right hand side for the system.
            :param float freq: Frequency
            :rtype: numpy.ndarray
            :return: RHS for 1 polarizations, primary fields (nF, 1)
        """

        # Get sources for the frequncy(polarizations)
        Src = self.survey.getSrcByFreq(freq)[0]
        # Only select the yx polarization
        S_e = mkvc(Src.S_e(self)[:, 1], 2)
        return -1j * omega(freq) * S_e
示例#48
0
文件: Probs.py 项目: dakentod/simpeg
    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
示例#49
0
    def fields(self, m):
        """Computes the fields d = T*A*m"""

        assert self.ispaired, "Problem must be paired with survey to predict data"

        self.model = m  # Initiates/updates model and initiates mapping

        # Project to active mesh cells
        # m = np.matrix(self.xiMap * m).T
        m = np.matrix(self.xiMap * m).T

        # Must return as a numpy array
        return mkvc(sp.coo_matrix.dot(self.T, np.dot(self.A, m)))
示例#50
0
def grid_survey(spacing,width, x0 = (0,0,0), topo=None):
    """
        grid_survey(spacing,width)
        Generate concentric grid surveys centered at the origin
        :grid: List of grid spacing
        :width: Grid width
        
        return: rxLoc an n-by-3 receiver locations
        
    """
    rxLoc = []
    
    if len(spacing)!=len(width):
        raise 'Number of elements in spacing different than grid width'
    
    ii = -1
    for dx in spacing:

        ii += 1

        # Define survey grids centered at [0,0]
        
        # Number of grid points that fits in the width
        nC = int(width[ii]/dx)
        
        rxVec = -width[ii]/2. + dx/2. + np.asarray(range(nC))*dx
        
        rxGridx, rxGridy = np.meshgrid(rxVec,rxVec)
        
        rxGridx += x0[0]
        rxGridy += x0[1]
    
        if topo is not None:
            
            rxGridz = scipy.interpolate.griddata(topo[:,:2], topo[:,2], (rxGridx, rxGridy),
                                              method='linear') + x0[2]
                                             
        else:
            rxGridz = np.zeros_like(rxGridx) + x0[2]
            
        # Remove points if already inside inner grid
        if ii > 0:
            indx = np.logical_and(np.logical_and(rxGridy<rxLoc[:,1].max(), rxGridy>rxLoc[:,1].min()),np.logical_and(rxGridx>rxLoc[:,0].min(), rxGridx<rxLoc[:,0].max()))
        
            indx = indx.reshape(rxGridx.shape)
            rxGridx = rxGridx[indx==0]
            rxGridy = rxGridy[indx==0]
            rxGridz = rxGridz[indx==0]
            
            rxLoc = np.vstack([rxLoc, np.c_[mkvc(rxGridx),mkvc(rxGridy),mkvc(rxGridz)]])
            
        else:
            rxLoc = np.c_[mkvc(rxGridx),mkvc(rxGridy),mkvc(rxGridz)]
        

        
    return rxGridx, rxGridy, rxGridz
示例#51
0
    def fields(self, m):
        """Computes the fields d = T*A*m"""

        if self.ispaired is False:
            AssertionError(
                "Problem must be paired with survey to generate A matrix")

        self.model = m  # Initiates/updates model and initiates mapping

        # Project to active mesh cells
        # m = np.matrix(self.xiMap * m).T
        m = np.matrix(self.xiMap * m).T

        # Must return as a numpy array
        return mkvc(sp.coo_matrix.dot(self.T, np.dot(self.A, m)))
示例#52
0
    def fields(self, m):

        """Computes the fields d = T*A*m"""

        if self.ispaired is False:
            AssertionError("Problem must be paired with survey to generate A matrix")

        self.model = m   # Initiates/updates model and initiates mapping

        # Project to active mesh cells
        # m = np.matrix(self.xiMap * m).T
        m = np.matrix(self.xiMap * m).T

        # Must return as a numpy array
        return mkvc(sp.coo_matrix.dot(self.T, np.dot(self.A, m)))
def dataMis_AnalyticPrimarySecondary(sigmaHalf):

    # Make the survey
    # Primary secondary
    survey, sig, sigBG, mesh = nsem.utils.test_utils.setup1DSurvey(
        sigmaHalf, False, structure=True)
    # Analytic data
    simulation = nsem.Simulation1DPrimarySecondary(mesh,
                                                   sigmaPrimary=sig,
                                                   sigma=sig,
                                                   survey=survey)

    dataAnaObj = calculateAnalyticSolution(survey.source_list, mesh, sig)

    data = simulation.dpred()
    dataAna = mkvc(dataAnaObj)
    return np.all((data - dataAna) / dataAna < 2.0)
示例#54
0
    def Jvec(self, m, v, f=None):

        """Compute Pd*T*A*dxidm*v"""

        if self.ispaired is False:
            AssertionError("Problem must be paired with survey to generate A matrix")

        # Jacobian of xi wrt model
        dxidm = self.xiMap.deriv(m)

        # dxidm*v
        v = np.matrix(dxidm*v).T

        # Dot product with A
        v = self.A*v

        # Get active time rows of T
        T = self.T.tocsr()[self.survey.t_active, :]

        # Must return an array
        return mkvc(sp.csr_matrix.dot(T, v))
示例#55
0
    def Jtvec(self, m, v, f=None):

        """Compute (Pd*T*A*dxidm)^T * v"""

        if self.ispaired is False:
            AssertionError("Problem must be paired with survey to generate A matrix")

        # Define v as a column vector
        v = np.matrix(v).T

        # Get T'*Pd'*v
        T = self.T.tocsr()[self.survey.t_active, :]
        v = sp.csc_matrix.dot(T.transpose(), v)

        # Multiply by A'
        v = (np.dot(v.T, self.A)).T

        # Jacobian of xi wrt model
        dxidm = self.xiMap.deriv(m)

        # Must return an array
        return mkvc(dxidm.T*v)
示例#56
0
文件: RxNSEM.py 项目: jsc1129/simpeg
 def _hx(self):
     return self.Pbx * mkvc(self.f[self.src, 'b_1d'], 2) / mu_0
示例#57
0
    def eval(self, src, mesh, f):
        '''
        Project the fields to natural source data.

            :param SrcMT src: The source of the fields to project
            :param SimPEG.Mesh mesh:
            :param FieldsMT f: Natural source fields object to project
        '''

        ## NOTE: Assumes that e is on t
        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
            # Note: Has a minus sign in front, to comply with quadrant calculations.
            # Can be derived from zyx case for the 3D case.
            f_part_complex = -ex/bx
        # elif self.projType is 'Z2D':
        elif self.projType is 'Z3D':
            ## NOTE: Assumes that e is on edges and b on the faces. Need to generalize that or use a prop of fields to determine that.
            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
            # Make the complex data
            if 'zxx' in self.rxType:
                f_part_complex = ( ex_px*hy_py - ex_py*hy_px)/(hx_px*hy_py - hx_py*hy_px)
            elif 'zxy' in self.rxType:
                f_part_complex = (-ex_px*hx_py + ex_py*hx_px)/(hx_px*hy_py - hx_py*hy_px)
            elif 'zyx' in self.rxType:
                f_part_complex = ( ey_px*hy_py - ey_py*hy_px)/(hx_px*hy_py - hx_py*hy_px)
            elif 'zyy' in self.rxType:
                f_part_complex = (-ey_px*hx_py + ey_py*hx_px)/(hx_px*hy_py - hx_py*hy_px)
        elif self.projType is 'T3D':
            if self.locs.ndim == 3:
                horLoc = self.locs[:,:,0]
                vertLoc = self.locs[:,:,1]
            else:
                horLoc = self.locs
                vertLoc = self.locs
            Pbx = mesh.getInterpolationMat(horLoc,'Fx')
            Pby = mesh.getInterpolationMat(horLoc,'Fy')
            Pbz = mesh.getInterpolationMat(vertLoc,'Fz')
            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']
            if 'tzx' in self.rxType:
                f_part_complex = (- by_px*bz_py + by_py*bz_px)/(bx_px*by_py - bx_py*by_px)
            if 'tzy' in self.rxType:
                f_part_complex = (  bx_px*bz_py - bx_py*bz_px)/(bx_px*by_py - bx_py*by_px)

        else:
            NotImplementedError('Projection of {:s} receiver type is not implemented.'.format(self.rxType))
        # Get the real or imag component
        real_or_imag = self.projComp
        f_part = getattr(f_part_complex, real_or_imag)
        # print f_part
        return f_part
示例#58
0
    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