Beispiel #1
0
    def test_updateMultipliers(self):
        nP = 10

        m = np.random.rand(nP)

        W1 = utils.sdiag(np.random.rand(nP))
        W2 = utils.sdiag(np.random.rand(nP))

        phi1 = objective_function.L2ObjectiveFunction(W=W1)
        phi2 = objective_function.L2ObjectiveFunction(W=W2)

        phi = phi1 + phi2

        self.assertTrue(phi(m) == phi1(m) + phi2(m))

        phi.multipliers[0] = utils.Zero()
        self.assertTrue(phi(m) == phi2(m))

        phi.multipliers[0] = 1.0
        phi.multipliers[1] = utils.Zero()

        self.assertTrue(len(phi.objfcts) == 2)
        self.assertTrue(len(phi.multipliers) == 2)
        self.assertTrue(len(phi) == 2)

        self.assertTrue(phi(m) == phi1(m))
Beispiel #2
0
def solve_2D_J(rho1, rho2, h, A, B):

    ex, ez, V = solve_2D_E(rho1, rho2, h, A, B)
    sigma = 1.0 / rho2 * np.ones(mesh.nC)
    sigma[mesh.gridCC[:, 1] >= -h] = 1.0 / rho1  # since the model is 2D

    return utils.sdiag(sigma) * ex, utils.sdiag(sigma) * ez, V
Beispiel #3
0
    def M(self):
        """
        M: ndarray
            Magnetization matrix
        """
        if getattr(self, "_M", None) is None:

            if self.modelType == "vector":
                self._M = sp.identity(self.nC) * self.survey.source_field.parameters[0]

            else:
                mag = mat_utils.dip_azimuth2cartesian(
                    np.ones(self.nC) * self.survey.source_field.parameters[1],
                    np.ones(self.nC) * self.survey.source_field.parameters[2],
                )

                self._M = sp.vstack(
                    (
                        sdiag(mag[:, 0] * self.survey.source_field.parameters[0]),
                        sdiag(mag[:, 1] * self.survey.source_field.parameters[0]),
                        sdiag(mag[:, 2] * self.survey.source_field.parameters[0]),
                    )
                )

        return self._M
def solve_2D_potentials(rho1, rho2, h, A, B):
    """
    Here we solve the 2D DC problem for potentials (using SimPEG Mesh Class)
    """
    sigma = 1.0 / rho2 * np.ones(mesh.nC)
    sigma[mesh.gridCC[:, 1] >= -h] = 1.0 / rho1  # since the model is 2D

    q = np.zeros(mesh.nC)
    a = utils.closestPoints(mesh, A[:2])
    q[a] = 1.0 / mesh.vol[a]
    if B is not None:
        b = utils.closestPoints(mesh, B[:2])
        q[b] = -1.0 / mesh.vol[b]

    # Use a Neumann Boundary Condition (so pole source is reasonable)
    fxm, fxp, fym, fyp = mesh.faceBoundaryInd

    n_xm = fxm.sum()
    n_xp = fxp.sum()
    n_ym = fym.sum()
    n_yp = fyp.sum()

    xBC_xm = np.zeros(n_xm)  # 0.5*a_xm
    xBC_xp = np.zeros(n_xp)  # 0.5*a_xp/b_xp
    yBC_xm = np.ones(n_xm)  # 0.5*(1.-b_xm)
    yBC_xp = np.ones(n_xp)  # 0.5*(1.-1./b_xp)
    xBC_ym = np.zeros(n_ym)  # 0.5*a_ym
    xBC_yp = np.zeros(n_yp)  # 0.5*a_yp/b_yp
    yBC_ym = np.ones(n_ym)  # 0.5*(1.-b_ym)
    yBC_yp = np.ones(n_yp)  # 0.5*(1.-1./b_yp)

    sortindsfx = np.argsort(np.r_[np.arange(mesh.nFx)[fxm],
                                  np.arange(mesh.nFx)[fxp]])
    sortindsfy = np.argsort(np.r_[np.arange(mesh.nFy)[fym],
                                  np.arange(mesh.nFy)[fyp]])
    xBC_x = np.r_[xBC_xm, xBC_xp][sortindsfx]
    xBC_y = np.r_[xBC_ym, xBC_yp][sortindsfy]
    yBC_x = np.r_[yBC_xm, yBC_xp][sortindsfx]
    yBC_y = np.r_[yBC_ym, yBC_yp][sortindsfy]
    x_BC = np.r_[xBC_x, xBC_y]
    y_BC = np.r_[yBC_x, yBC_y]

    V = utils.sdiag(mesh.vol)
    Div = V * mesh.faceDiv
    P_BC, B = mesh.getBCProjWF_simple()
    M = B * mesh.aveCC2F
    Grad = Div.T - P_BC * utils.sdiag(y_BC) * M

    A = (Div * utils.sdiag(1.0 / (mesh.dim * mesh.aveF2CC.T * (1.0 / sigma))) *
         Grad)

    A[0, 0] = A[0, 0] + 1.  # Because Neumann
    Ainv = Pardiso(A)

    V = Ainv * q
    return V
Beispiel #5
0
 def M(self, M):
     """
     Create magnetization matrix from unit vector orientation
     :parameter
     M: array (3*nC,) or (nC, 3)
     """
     if self.modelType == "vector":
         self._M = sdiag(mkvc(M) * self.survey.source_field.parameters[0])
     else:
         M = M.reshape((-1, 3))
         self._M = sp.vstack((
             sdiag(M[:, 0] * self.survey.source_field.parameters[0]),
             sdiag(M[:, 1] * self.survey.source_field.parameters[0]),
             sdiag(M[:, 2] * self.survey.source_field.parameters[0]),
         ))
def BiotSavartFun(mesh, r_pts, component="z"):
    """
        Compute systematrix G using Biot-Savart Law


        G = np.vstack((G1,G2,G3..,Gnpts)

        .. math::

    """
    if r_pts.ndim == 1:
        npts = 1
    else:
        npts = r_pts.shape[0]
    e = np.ones((mesh.nC, 1))
    o = np.zeros((mesh.nC, 1))
    const = mu_0 / 4 / np.pi
    G = np.zeros((npts, mesh.nC * 3))

    for i in range(npts):
        if npts == 1:
            r_rx = np.repeat(utils.mkvc(r_pts).reshape([1, -1]),
                             mesh.nC,
                             axis=0)
        else:
            r_rx = np.repeat(r_pts[i, :].reshape([1, -1]), mesh.nC, axis=0)
        r_CC = mesh.gridCC
        r = r_rx - r_CC
        r_abs = np.sqrt((r**2).sum(axis=1))
        rxind = r_abs == 0.0
        # r_abs[rxind] = mesh.vol.min()**(1./3.)*0.5
        r_abs[rxind] = 1e20
        Sx = const * utils.sdiag(mesh.vol * r[:, 0] / r_abs**3)
        Sy = const * utils.sdiag(mesh.vol * r[:, 1] / r_abs**3)
        Sz = const * utils.sdiag(mesh.vol * r[:, 2] / r_abs**3)

        # G_temp = sp.vstack((sp.hstack(( o.T,     e.T*Sz, -e.T*Sy)), \
        #                       sp.hstack((-e.T*Sz,  o.T,     e.T*Sx)), \
        #                       sp.hstack((-e.T*Sy,  e.T*Sx,  o.T   ))))
        if component == "x":
            G_temp = np.hstack((o.T, e.T * Sz, -e.T * Sy))
        elif component == "y":
            G_temp = np.hstack((-e.T * Sz, o.T, e.T * Sx))
        elif component == "z":
            G_temp = np.hstack((e.T * Sy, -e.T * Sx, o.T))
        G[i, :] = G_temp

    return G
Beispiel #7
0
def solve_2D_potentials(rho1, rho2, h, A, B):
    """
    Here we solve the 2D DC problem for potentials (using SimPEG Mesg Class)
    """
    sigma = 1.0 / rho2 * np.ones(mesh.nC)
    sigma[mesh.gridCC[:, 1] >= -h] = 1.0 / rho1  # since the model is 2D

    q = np.zeros(mesh.nC)
    a = utils.closestPoints(mesh, A[:2])
    b = utils.closestPoints(mesh, B[:2])

    q[a] = 1.0 / mesh.vol[a]
    q[b] = -1.0 / mesh.vol[b]

    # q = q * 1./mesh.vol

    A = (
        mesh.cellGrad.T
        * utils.sdiag(1.0 / (mesh.dim * mesh.aveF2CC.T * (1.0 / sigma)))
        * mesh.cellGrad
    )
    Ainv = Pardiso(A)

    V = Ainv * q
    return V
Beispiel #8
0
    def test_basic(self):
        expMap = maps.ExpMap(discretize.TensorMesh((3,)))
        assert expMap.nP == 3

        for Example in [SimpleExample, ShortcutExample]:

            PM = Example(sigmaMap=expMap)
            assert PM.sigmaMap is not None
            assert PM.sigmaMap is expMap

            # There is currently no model, so sigma, which is mapped, fails
            self.assertRaises(AttributeError, getattr, PM, "sigma")

            PM.model = np.r_[1.0, 2.0, 3.0]
            assert np.all(PM.sigma == np.exp(np.r_[1.0, 2.0, 3.0]))
            # PM = pickle.loads(pickle.dumps(PM))
            # PM = maps.ExpMap.deserialize(PM.serialize())

            assert np.all(
                PM.sigmaDeriv.todense()
                == utils.sdiag(np.exp(np.r_[1.0, 2.0, 3.0])).todense()
            )

            # If we set sigma, we should delete the mapping
            PM.sigma = np.r_[1.0, 2.0, 3.0]
            assert np.all(PM.sigma == np.r_[1.0, 2.0, 3.0])
            # PM = pickle.loads(pickle.dumps(PM))
            assert PM.sigmaMap is None
            assert PM.sigmaDeriv == 0

            del PM.model
            # sigma is not changed
            assert np.all(PM.sigma == np.r_[1.0, 2.0, 3.0])
Beispiel #9
0
    def getJtJdiag(self, m, W=None):
        """
        Return the diagonal of JtJ
        """
        self.model = m

        if W is None:
            W = np.ones(self.survey.nD)
        else:
            W = W.diagonal() ** 2
        if getattr(self, "_gtg_diagonal", None) is None:
            diag = np.zeros(self.G.shape[1])
            if not self.is_amplitude_data:
                for i in range(len(W)):
                    diag += W[i] * (self.G[i] * self.G[i])
            else:
                fieldDeriv = self.fieldDeriv
                Gx = self.G[::3]
                Gy = self.G[1::3]
                Gz = self.G[2::3]
                for i in range(len(W)):
                    row = (
                        fieldDeriv[0, i] * Gx[i]
                        + fieldDeriv[1, i] * Gy[i]
                        + fieldDeriv[2, i] * Gz[i]
                    )
                    diag += W[i] * (row * row)
            self._gtg_diagonal = diag
        else:
            diag = self._gtg_diagonal
        return mkvc((sdiag(np.sqrt(diag)) @ self.chiDeriv).power(2).sum(axis=0))
Beispiel #10
0
 def makeMassMatrices(self, m):
     mu = self.muMap * m
     self._MfMui = self.mesh.getFaceInnerProduct(1.0 / mu) / self.mesh.dim
     # self._MfMui = self.mesh.getFaceInnerProduct(1./mu)
     # TODO: this will break if tensor mu
     self._MfMuI = sdiag(1.0 / self._MfMui.diagonal())
     self._MfMu0 = self.mesh.getFaceInnerProduct(1.0 / mu_0) / self.mesh.dim
Beispiel #11
0
    def test_early_exits(self):
        nP = 10

        m = np.random.rand(nP)
        v = np.random.rand(nP)

        W1 = utils.sdiag(np.random.rand(nP))
        phi1 = objective_function.L2ObjectiveFunction(W=W1)

        phi2 = Error_if_Hit_ObjFct()

        objfct = phi1 + 0 * phi2

        self.assertTrue(len(objfct) == 2)
        self.assertTrue(np.all(objfct.multipliers == np.r_[1, 0]))
        self.assertTrue(objfct(m) == phi1(m))
        self.assertTrue(np.all(objfct.deriv(m) == phi1.deriv(m)))
        self.assertTrue(np.all(objfct.deriv2(m, v) == phi1.deriv2(m, v)))

        objfct.multipliers[1] = utils.Zero()

        self.assertTrue(len(objfct) == 2)
        self.assertTrue(np.all(objfct.multipliers == np.r_[1, 0]))
        self.assertTrue(objfct(m) == phi1(m))
        self.assertTrue(np.all(objfct.deriv(m) == phi1.deriv(m)))
        self.assertTrue(np.all(objfct.deriv2(m, v) == phi1.deriv2(m, v)))
Beispiel #12
0
    def __init__(self, mesh, **kwargs):
        super().__init__(mesh, **kwargs)

        Pbc, Pin, self._Pout = self.mesh.getBCProjWF("neumann", discretization="CC")

        Dface = self.mesh.faceDiv
        Mc = sdiag(self.mesh.vol)
        self._Div = Mc * Dface * Pin.T * Pin
Beispiel #13
0
    def test_sum_fail(self):
        nP1 = 10
        nP2 = 30

        phi1 = objective_function.L2ObjectiveFunction(
            W=utils.sdiag(np.random.rand(nP1))
        )

        phi2 = objective_function.L2ObjectiveFunction(
            W=utils.sdiag(np.random.rand(nP2))
        )

        with self.assertRaises(Exception):
            phi = phi1 + phi2

        with self.assertRaises(Exception):
            phi = phi1 + 100 * phi2
Beispiel #14
0
    def getRHS(self, m):
        """"""

        Mc = utils.sdiag(self.mesh.vol)

        self.model = m
        rho = self.rho

        return Mc * rho
Beispiel #15
0
def CasingMagDipoleDeriv_z(z):
    obsloc = np.vstack([xobs, yobs, z]).T

    f = Casing._getCasingHertzMagDipole(srcloc, obsloc, freq, sigma, a, b, mu)
    g = utils.sdiag(
        Casing._getCasingHertzMagDipoleDeriv_z(srcloc, obsloc, freq, sigma, a,
                                               b, mu))

    return f, g
Beispiel #16
0
 def test_NewtonRoot(self):
     fun = (lambda x, return_g=True: np.sin(x)
            if not return_g else (np.sin(x), sdiag(np.cos(x))))
     x = np.array([np.pi - 0.3, np.pi + 0.1, 0])
     xopt = optimization.NewtonRoot(comments=False).root(fun, x)
     x_true = np.array([np.pi, np.pi, 0])
     print("Newton Root Finding")
     print("xopt: ", xopt)
     print("x_true: ", x_true)
     self.assertTrue(np.linalg.norm(xopt - x_true, 2) < TOL, True)
Beispiel #17
0
    def getFields(self, bType="b", ifreq=0):
        src = self.srcList[ifreq]
        Pfx = self.mesh.getInterpolationMat(self.mesh.gridCC[self.activeCC, :],
                                            locType="Fx")
        Pfz = self.mesh.getInterpolationMat(self.mesh.gridCC[self.activeCC, :],
                                            locType="Fz")
        Ey = self.mesh.aveE2CC * self.f[src, "e"]
        Jy = utils.sdiag(self.sim.sigma) * Ey

        self.Ey = utils.mkvc(self.mirrorArray(Ey[self.activeCC],
                                              direction="y"))
        self.Jy = utils.mkvc(self.mirrorArray(Jy[self.activeCC],
                                              direction="y"))
        self.Bx = utils.mkvc(
            self.mirrorArray(Pfx * self.f[src, bType], direction="x"))
        self.Bz = utils.mkvc(
            self.mirrorArray(Pfz * self.f[src, bType], direction="z"))
Beispiel #18
0
    def test_scalarmul(self):
        scalar = 10.0
        nP = 100
        objfct_a = objective_function.L2ObjectiveFunction(
            W=utils.sdiag(np.random.randn(nP))
        )
        objfct_b = scalar * objfct_a
        m = np.random.rand(nP)

        objfct_c = objfct_a + objfct_b

        self.assertTrue(scalar * objfct_a(m) == objfct_b(m))
        self.assertTrue(objfct_b.test())
        self.assertTrue(objfct_c(m) == objfct_a(m) + objfct_b(m))

        self.assertTrue(len(objfct_c.objfcts) == 2)
        self.assertTrue(len(objfct_c.multipliers) == 2)
        self.assertTrue(len(objfct_c) == 2)
Beispiel #19
0
    def getJtJdiag(self, m, W=None):
        """
            Return the diagonal of JtJ
        """
        self.model = m

        if W is None:
            W = np.ones(self.survey.nD)
        else:
            W = W.diagonal() ** 2
        if getattr(self, "_gtg_diagonal", None) is None:

            diag = np.zeros(self.G.shape[1])
            for i in range(len(W)):
                diag += W[i] * (self.G[i] * self.G[i])
            self._gtg_diagonal = diag
        else:
            diag = self._gtg_diagonal
        return mkvc((sdiag(np.sqrt(diag)) @ self.rhoDeriv).power(2).sum(axis=0))
Beispiel #20
0
    def test_mappings_and_cell_weights(self):
        mesh = discretize.TensorMesh([8, 7, 6])
        m = np.random.rand(2 * mesh.nC)
        v = np.random.rand(2 * mesh.nC)

        cell_weights = np.random.rand(mesh.nC)

        wires = maps.Wires(("sigma", mesh.nC), ("mu", mesh.nC))

        reg = regularization.SimpleSmall(mesh,
                                         mapping=wires.sigma,
                                         cell_weights=cell_weights)

        objfct = objective_function.L2ObjectiveFunction(W=utils.sdiag(
            np.sqrt(cell_weights)),
                                                        mapping=wires.sigma)

        self.assertTrue(reg(m) == objfct(m))
        self.assertTrue(np.all(reg.deriv(m) == objfct.deriv(m)))
        self.assertTrue(np.all(reg.deriv2(m, v=v) == objfct.deriv2(m, v=v)))
Beispiel #21
0
    def test_2sum(self):
        nP = 80
        alpha1 = 100
        alpha2 = 200

        phi1 = (
            objective_function.L2ObjectiveFunction(W=utils.sdiag(np.random.rand(nP)))
            + alpha1 * objective_function.L2ObjectiveFunction()
        )
        phi2 = objective_function.L2ObjectiveFunction() + alpha2 * phi1
        self.assertTrue(phi2.test(eps=EPS))

        self.assertTrue(len(phi1.multipliers) == 2)
        self.assertTrue(len(phi2.multipliers) == 2)

        self.assertTrue(len(phi1.objfcts) == 2)
        self.assertTrue(len(phi2.objfcts) == 2)
        self.assertTrue(len(phi2) == 2)

        self.assertTrue(len(phi1) == 2)
        self.assertTrue(len(phi2) == 2)

        self.assertTrue(np.all(phi1.multipliers == np.r_[1.0, alpha1]))
        self.assertTrue(np.all(phi2.multipliers == np.r_[1.0, alpha2]))
    def getFields(self, itime):
        src = self.srcList[0]

        Ey = self.mesh.aveE2CC * self.f[src, "e", itime]
        Jy = utils.sdiag(self.sim.sigma) * Ey

        self.Ey = utils.mkvc(self.mirrorArray(Ey[self.activeCC],
                                              direction="y"))
        self.Jy = utils.mkvc(self.mirrorArray(Jy[self.activeCC],
                                              direction="y"))
        self.Bx = utils.mkvc(
            self.mirrorArray(self.Pfx * self.f[src, "b", itime],
                             direction="x"))
        self.Bz = utils.mkvc(
            self.mirrorArray(self.Pfz * self.f[src, "b", itime],
                             direction="z"))
        self.dBxdt = utils.mkvc(
            self.mirrorArray(-self.Pfx * self.mesh.edgeCurl *
                             self.f[src, "e", itime],
                             direction="x"))
        self.dBzdt = utils.mkvc(
            self.mirrorArray(-self.Pfz * self.mesh.edgeCurl *
                             self.f[src, "e", itime],
                             direction="z"))
Beispiel #23
0
# Define the Inverse Problem
# --------------------------
#
# The inverse problem is defined by 3 things:
#
#     1) Data Misfit: a measure of how well our recovered model explains the field data
#     2) Regularization: constraints placed on the recovered model and a priori information
#     3) Optimization: the numerical approach used to solve the inverse problem
#

# Define the data misfit. Here the data misfit is the L2 norm of the weighted
# residual between the observed data and the data predicted for a given model.
# Within the data misfit, the residual between predicted and observed data are
# normalized by the data's standard deviation.
dmis = data_misfit.L2DataMisfit(data=data_object, simulation=simulation)
dmis.W = utils.sdiag(1 / uncertainties)

# Define the regularization (model objective function).
reg = regularization.Sparse(mesh, indActive=ind_active, mapping=model_map)
reg.norms = np.c_[0, 2, 2, 2]

# Define how the optimization problem is solved. Here we will use a projected
# Gauss-Newton approach that employs the conjugate gradient solver.
opt = optimization.ProjectedGNCG(maxIter=100,
                                 lower=-1.0,
                                 upper=1.0,
                                 maxIterLS=20,
                                 maxIterCG=10,
                                 tolCG=1e-3)

# Here we define the inverse problem that is to be solved
Beispiel #24
0
    def Jtvec(self, m, v, u=None):
        """
            Computing Jacobian^T multiplied by vector.

        .. math ::

            (\\frac{\delta \mathbf{P}\mathbf{B}} {\delta \mathbf{m}})^{T} = \left[ \mathbf{P}_{deriv}\\frac{\partial \mathbf{\mu} } {\partial \mathbf{m} }
            \left[
            \diag(\M^f_{\mu_{0}^{-1} } \mathbf{B}_0) \dMfMuI  \\
             -  \diag (\Div^T\mathbf{u})\dMfMuI
            \\right ]\\right]^{T}

             -  \left[\mathbf{P}_{deriv}(\MfMui)^{-1}\Div^T\\frac{\delta\mathbf{u}}{\delta \mathbf{m}} \\right]^{T}

        where

        .. math ::

            \mathbf{P}_{derv} = \\frac{\partial \mathbf{P}}{\partial\mathbf{B}}

        .. note ::

            Here we only want to compute

            .. math ::

                \mathbf{J}^{T}\mathbf{v} = (\\frac{\delta \mathbf{P}\mathbf{B}} {\delta \mathbf{m}})^{T} \mathbf{v}

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

        B, u = u["B"], u["u"]
        mu = self.mapping * (m)
        dmu_dm = self.mapping.deriv(m)
        # dchidmu = sdiag(1 / mu_0 * np.ones(self.mesh.nC))

        vol = self.mesh.vol
        Div = self._Div
        Dface = self.mesh.faceDiv
        P = self.survey.projectFieldsDeriv(B)  # Projection matrix
        B0 = self.getB0()

        MfMuIvec = 1 / self.MfMui.diagonal()
        dMfMuI = sdiag(MfMuIvec ** 2) * self.mesh.aveF2CC.T * sdiag(vol * 1.0 / mu ** 2)

        # A = self._Div*self.MfMuI*self._Div.T
        # RHS = Div*MfMuI*MfMu0*B0 - Div*B0 + Mc*Dface*Pout.T*Bbc
        # C(m,u) = A*m-rhs
        # dudm = -(dCdu)^(-1)dCdm

        dCdu = self.getA(m)
        s = Div * (self.MfMuI.T * (P.T * v))

        Ainv = self.solver(dCdu.T, **self.solver_opts)
        sol = Ainv * s

        Ainv.clean()

        # dCdm_A = Div * ( sdiag( Div.T * u )* dMfMuI *dmu_dm  )
        # dCdm_Atsol = ( dMfMuI.T*( sdiag( Div.T * u ) * (Div.T * dmu_dm)) ) * sol
        dCdm_Atsol = (dmu_dm.T * dMfMuI.T * (sdiag(Div.T * u) * Div.T)) * sol

        # dCdm_RHS1 = Div * (sdiag( self.MfMu0*B0  ) * dMfMuI)
        # dCdm_RHS1tsol = (dMfMuI.T*( sdiag( self.MfMu0*B0  ) ) * Div.T * dmu_dm) * sol
        dCdm_RHS1tsol = (dmu_dm.T * dMfMuI.T * (sdiag(self.MfMu0 * B0)) * Div.T) * sol

        # temp1 = (Dface*(self._Pout.T*self.Bbc_const*self.Bbc))
        # temp1sol = (Dface.T * (sdiag(vol) * sol))
        # temp2 = self.Bbc_const * (self._Pout.T * self.Bbc).T
        # dCdm_RHS2v  = (sdiag(vol)*temp1)*np.inner(vol, dchidmu*dmu_dm*v)
        # dCdm_RHS2tsol = (dmu_dm.T * dchidmu.T * vol) * np.inner(temp2, temp1sol)

        # dCdm_RHSv =  dCdm_RHS1*(dmu_dm*v) +  dCdm_RHS2v

        # temporary fix
        # dCdm_RHStsol = dCdm_RHS1tsol - dCdm_RHS2tsol
        dCdm_RHStsol = dCdm_RHS1tsol

        # dCdm_RHSv =  dCdm_RHS1*(dmu_dm*v) +  dCdm_RHS2v
        # dCdm_v = dCdm_A*v - dCdm_RHSv

        Ctv = dCdm_Atsol - dCdm_RHStsol

        # B = self.MfMuI*self.MfMu0*B0-B0-self.MfMuI*self._Div.T*u
        # dBdm = d\mudm*dBd\mu
        # dPBdm^T*v = Atemp^T*P^T*v - Btemp^T*P^T*v - Ctv

        Atemp = sdiag(self.MfMu0 * B0) * (dMfMuI * (dmu_dm))
        Btemp = sdiag(Div.T * u) * (dMfMuI * (dmu_dm))
        Jtv = Atemp.T * (P.T * v) - Btemp.T * (P.T * v) - Ctv

        return mkvc(Jtv)
Beispiel #25
0
    def Jvec(self, m, v, u=None):
        """
            Computing Jacobian multiplied by vector

            By setting our problem as

            .. math ::

                \mathbf{C}(\mathbf{m}, \mathbf{u}) = \mathbf{A}\mathbf{u} - \mathbf{rhs} = 0

            And taking derivative w.r.t m

            .. math ::

                \\nabla \mathbf{C}(\mathbf{m}, \mathbf{u}) = \\nabla_m \mathbf{C}(\mathbf{m}) \delta \mathbf{m} +
                                                             \\nabla_u \mathbf{C}(\mathbf{u}) \delta \mathbf{u} = 0

                \\frac{\delta \mathbf{u}}{\delta \mathbf{m}} = - [\\nabla_u \mathbf{C}(\mathbf{u})]^{-1}\\nabla_m \mathbf{C}(\mathbf{m})

            With some linear algebra we can have

            .. math ::

                \\nabla_u \mathbf{C}(\mathbf{u}) = \mathbf{A}

                \\nabla_m \mathbf{C}(\mathbf{m}) =
                \\frac{\partial \mathbf{A}}{\partial \mathbf{m}}(\mathbf{m})\mathbf{u} - \\frac{\partial \mathbf{rhs}(\mathbf{m})}{\partial \mathbf{m}}

            .. math ::

                \\frac{\partial \mathbf{A}}{\partial \mathbf{m}}(\mathbf{m})\mathbf{u} =
                \\frac{\partial \mathbf{\mu}}{\partial \mathbf{m}} \left[\Div \diag (\Div^T \mathbf{u}) \dMfMuI \\right]

                \dMfMuI = \diag(\MfMui)^{-1}_{vec} \mathbf{Av}_{F2CC}^T\diag(\mathbf{v})\diag(\\frac{1}{\mu^2})

                \\frac{\partial \mathbf{rhs}(\mathbf{m})}{\partial \mathbf{m}} =  \\frac{\partial \mathbf{\mu}}{\partial \mathbf{m}} \left[
                \Div \diag(\M^f_{\mu_{0}^{-1}}\mathbf{B}_0) \dMfMuI \\right] - \diag(\mathbf{v})\mathbf{D} \mathbf{P}_{out}^T\\frac{\partial B_{sBC}}{\partial \mathbf{m}}

            In the end,

            .. math ::

                \\frac{\delta \mathbf{u}}{\delta \mathbf{m}} =
                - [ \mathbf{A} ]^{-1}\left[ \\frac{\partial \mathbf{A}}{\partial \mathbf{m}}(\mathbf{m})\mathbf{u}
                - \\frac{\partial \mathbf{rhs}(\mathbf{m})}{\partial \mathbf{m}} \\right]

            A little tricky point here is we are not interested in potential (u), but interested in magnetic flux (B).
            Thus, we need sensitivity for B. Now we take derivative of B w.r.t m and have

            .. math ::

                \\frac{\delta \mathbf{B}} {\delta \mathbf{m}} = \\frac{\partial \mathbf{\mu} } {\partial \mathbf{m} }
                \left[
                \diag(\M^f_{\mu_{0}^{-1} } \mathbf{B}_0) \dMfMuI  \\
                 -  \diag (\Div^T\mathbf{u})\dMfMuI
                \\right ]

                 -  (\MfMui)^{-1}\Div^T\\frac{\delta\mathbf{u}}{\delta \mathbf{m}}

            Finally we evaluate the above, but we should remember that

            .. note ::

                We only want to evalute

                .. math ::

                    \mathbf{J}\mathbf{v} = \\frac{\delta \mathbf{P}\mathbf{B}} {\delta \mathbf{m}}\mathbf{v}

                Since forming sensitivity matrix is very expensive in that this monster is "big" and "dense" matrix!!


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

        B, u = u["B"], u["u"]
        mu = self.muMap * (m)
        dmu_dm = self.muDeriv
        # dchidmu = sdiag(1 / mu_0 * np.ones(self.mesh.nC))

        vol = self.mesh.vol
        Div = self._Div
        P = self.survey.projectFieldsDeriv(B)  # Projection matrix
        B0 = self.getB0()

        MfMuIvec = 1 / self.MfMui.diagonal()
        dMfMuI = sdiag(MfMuIvec ** 2) * self.mesh.aveF2CC.T * sdiag(vol * 1.0 / mu ** 2)

        # A = self._Div*self.MfMuI*self._Div.T
        # RHS = Div*MfMuI*MfMu0*B0 - Div*B0 + Mc*Dface*Pout.T*Bbc
        # C(m,u) = A*m-rhs
        # dudm = -(dCdu)^(-1)dCdm

        dCdu = self.getA(m)  # = A
        dCdm_A = Div * (sdiag(Div.T * u) * dMfMuI * dmu_dm)
        dCdm_RHS1 = Div * (sdiag(self.MfMu0 * B0) * dMfMuI)
        # temp1 = (Dface * (self._Pout.T * self.Bbc_const * self.Bbc))
        # dCdm_RHS2v = (sdiag(vol) * temp1) * \
        #    np.inner(vol, dchidmu * dmu_dm * v)

        # dCdm_RHSv =  dCdm_RHS1*(dmu_dm*v) +  dCdm_RHS2v
        dCdm_RHSv = dCdm_RHS1 * (dmu_dm * v)
        dCdm_v = dCdm_A * v - dCdm_RHSv

        Ainv = self.solver(dCdu, **self.solver_opts)
        sol = Ainv * dCdm_v

        dudm = -sol
        dBdmv = (
            sdiag(self.MfMu0 * B0) * (dMfMuI * (dmu_dm * v))
            - sdiag(Div.T * u) * (dMfMuI * (dmu_dm * v))
            - self.MfMuI * (Div.T * (dudm))
        )

        Ainv.clean()

        return mkvc(P * dBdmv)
def run(runIt=False, plotIt=True, saveIt=False, saveFig=False, cleanup=True):
    """
    Run the bookpurnong 1D stitched RESOLVE inversions.

    :param bool runIt: re-run the inversions? Default downloads and plots saved results
    :param bool plotIt: show the plots?
    :param bool saveIt: save the re-inverted results?
    :param bool saveFig: save the figure
    :param bool cleanup: remove the downloaded results
    """

    # download the data
    downloads, directory = download_and_unzip_data()

    # Load resolve data
    resolve = h5py.File(os.path.sep.join([directory, "booky_resolve.hdf5"]),
                        "r")

    river_path = resolve["river_path"][()]  # River path
    nSounding = resolve["data"].shape[0]  # the # of soundings

    # Bird height from surface
    b_height_resolve = resolve["src_elevation"][()]

    # fetch the frequencies we are considering
    cpi_inds = [0, 2, 6, 8, 10]  # Indices for HCP in-phase
    cpq_inds = [1, 3, 7, 9, 11]  # Indices for HCP quadrature
    frequency_cp = resolve["frequency_cp"][()]

    # build a mesh
    cs, ncx, ncz, npad = 1.0, 10.0, 10.0, 20
    hx = [(cs, ncx), (cs, npad, 1.3)]
    npad = 12
    temp = np.logspace(np.log10(1.0), np.log10(12.0), 19)
    temp_pad = temp[-1] * 1.3**np.arange(npad)
    hz = np.r_[temp_pad[::-1], temp[::-1], temp, temp_pad]
    mesh = discretize.CylMesh([hx, 1, hz], "00C")
    active = mesh.vectorCCz < 0.0

    # survey parameters
    rxOffset = 7.86  # tx-rx separation
    bp = -mu_0 / (4 * np.pi * rxOffset**3)  # primary magnetic field

    # re-run the inversion
    if runIt:

        # set up the mappings - we are inverting for 1D log conductivity
        # below the earth's surface.
        actMap = maps.InjectActiveCells(mesh,
                                        active,
                                        np.log(1e-8),
                                        nC=mesh.nCz)
        mapping = maps.ExpMap(mesh) * maps.SurjectVertical1D(mesh) * actMap

        # build starting and reference model
        sig_half = 1e-1
        sig_air = 1e-8
        sigma = np.ones(mesh.nCz) * sig_air
        sigma[active] = sig_half
        m0 = np.log(1e-1) * np.ones(active.sum())  # starting model
        mref = np.log(1e-1) * np.ones(active.sum())  # reference model

        # initalize empty lists for storing inversion results
        mopt_re = []  # recovered model
        dpred_re = []  # predicted data
        dobs_re = []  # observed data

        # downsample the data for the inversion
        nskip = 40

        # set up a noise model
        # 10% for the 3 lowest frequencies, 15% for the two highest
        relative = np.repeat(np.r_[np.ones(3) * 0.1, np.ones(2) * 0.15], 2)
        floor = abs(20 * bp * 1e-6)  # floor of 20ppm

        # loop over the soundings and invert each
        for rxind in range(nSounding):

            # convert data from ppm to magnetic field (A/m^2)
            dobs = (np.c_[resolve["data"][rxind, :][cpi_inds].astype(float),
                          resolve["data"][
                              rxind, :][cpq_inds].astype(float), ].flatten() *
                    bp * 1e-6)

            # perform the inversion
            src_height = b_height_resolve[rxind].astype(float)
            mopt, dpred, dobs = resolve_1Dinversions(
                mesh,
                dobs,
                src_height,
                frequency_cp,
                m0,
                mref,
                mapping,
                relative=relative,
                floor=floor,
            )

            # add results to our list
            mopt_re.append(mopt)
            dpred_re.append(dpred)
            dobs_re.append(dobs)

        # save results
        mopt_re = np.vstack(mopt_re)
        dpred_re = np.vstack(dpred_re)
        dobs_re = np.vstack(dobs_re)

        if saveIt:
            np.save("mopt_re_final", mopt_re)
            np.save("dobs_re_final", dobs_re)
            np.save("dpred_re_final", dpred_re)

    mopt_re = resolve["mopt"][()]
    dobs_re = resolve["dobs"][()]
    dpred_re = resolve["dpred"][()]

    sigma = np.exp(mopt_re)
    indz = -7  # depth index

    # so that we can visually compare with literature (eg Viezzoli, 2010)
    cmap = "jet"

    # dummy figure for colobar
    fig = plt.figure()
    out = plt.scatter(np.ones(3),
                      np.ones(3),
                      c=np.linspace(-2, 1, 3),
                      cmap=cmap)
    plt.close(fig)

    # plot from the paper
    fs = 13  # fontsize
    # matplotlib.rcParams['font.size'] = fs
    plt.figure(figsize=(13, 7))
    ax0 = plt.subplot2grid((2, 3), (0, 0), rowspan=2, colspan=2)
    ax1 = plt.subplot2grid((2, 3), (0, 2))
    ax2 = plt.subplot2grid((2, 3), (1, 2))

    # titles of plots
    title = [
        ("(a) Recovered model, %.1f m depth") %
        (-mesh.vectorCCz[active][indz]),
        "(b) Obs (Real 400 Hz)",
        "(c) Pred (Real 400 Hz)",
    ]

    temp = sigma[:, indz]
    tree = cKDTree(list(zip(resolve["xy"][:, 0], resolve["xy"][:, 1])))
    d, d_inds = tree.query(list(zip(resolve["xy"][:, 0], resolve["xy"][:, 1])),
                           k=20)
    w = 1.0 / (d + 100.0)**2.0
    w = utils.sdiag(1.0 / np.sum(w, axis=1)) * (w)
    xy = resolve["xy"]
    temp = (temp.flatten()[d_inds] * w).sum(axis=1)
    utils.plot2Ddata(
        xy,
        temp,
        ncontour=100,
        scale="log",
        dataloc=False,
        contourOpts={
            "cmap": cmap,
            "vmin": 1e-2,
            "vmax": 1e1
        },
        ax=ax0,
    )
    ax0.plot(resolve["xy"][:, 0], resolve["xy"][:, 1], "k.", alpha=0.02, ms=1)

    cb = plt.colorbar(out,
                      ax=ax0,
                      ticks=np.linspace(-2, 1, 4),
                      format="$10^{%.1f}$")
    cb.set_ticklabels(["0.01", "0.1", "1", "10"])
    cb.set_label("Conductivity (S/m)")
    ax0.plot(river_path[:, 0], river_path[:, 1], "k-", lw=0.5)

    # plot observed and predicted data
    freq_ind = 0
    axs = [ax1, ax2]
    temp_dobs = dobs_re[:, freq_ind].copy()
    ax1.plot(river_path[:, 0], river_path[:, 1], "k-", lw=0.5)
    inf = temp_dobs / abs(bp) * 1e6
    print(inf.min(), inf.max())
    out = utils.plot2Ddata(
        resolve["xy"][()],
        temp_dobs / abs(bp) * 1e6,
        ncontour=100,
        scale="log",
        dataloc=False,
        ax=ax1,
        contourOpts={"cmap": "viridis"},
    )
    vmin, vmax = out[0].get_clim()
    print(vmin, vmax)
    cb = plt.colorbar(
        out[0],
        ticks=np.logspace(np.log10(vmin), np.log10(vmax), 3),
        ax=ax1,
        format="%.1e",
        fraction=0.046,
        pad=0.04,
    )
    cb.set_label("Bz (ppm)")
    temp_dpred = dpred_re[:, freq_ind].copy()
    # temp_dpred[mask_:_data] = np.nan
    ax2.plot(river_path[:, 0], river_path[:, 1], "k-", lw=0.5)
    utils.plot2Ddata(
        resolve["xy"][()],
        temp_dpred / abs(bp) * 1e6,
        ncontour=100,
        scale="log",
        dataloc=False,
        contourOpts={
            "vmin": vmin,
            "vmax": vmax,
            "cmap": "viridis"
        },
        ax=ax2,
    )
    cb = plt.colorbar(
        out[0],
        ticks=np.logspace(np.log10(vmin), np.log10(vmax), 3),
        ax=ax2,
        format="%.1e",
        fraction=0.046,
        pad=0.04,
    )
    cb.set_label("Bz (ppm)")

    for i, ax in enumerate([ax0, ax1, ax2]):
        xticks = [460000, 463000]
        yticks = [6195000, 6198000, 6201000]
        xloc, yloc = 462100.0, 6196500.0
        ax.set_xticks(xticks)
        ax.set_yticks(yticks)
        # ax.plot(xloc, yloc, 'wo')
        ax.plot(river_path[:, 0], river_path[:, 1], "k", lw=0.5)

        ax.set_aspect("equal")
        ax.plot(resolve["xy"][:, 0],
                resolve["xy"][:, 1],
                "k.",
                alpha=0.02,
                ms=1)

        ax.set_yticklabels([str(f) for f in yticks])
        ax.set_ylabel("Northing (m)")
        ax.set_xlabel("Easting (m)")
        ax.set_title(title[i])

    plt.tight_layout()

    if plotIt:
        plt.show()

    if saveFig is True:
        fig.savefig("obspred_resolve.png", dpi=200)

    resolve.close()
    if cleanup:
        os.remove(downloads)
        shutil.rmtree(directory)
Beispiel #27
0
    def test_CylMeshEBDipoles(self, plotIt=plotIt):
        print("Testing CylMesh Electric and Magnetic Dipoles in a wholespace-"
              " Analytic: J-formulation")
        sigmaback = 1.0
        mur = 2.0
        freq = 1.0
        skdpth = 500.0 / np.sqrt(sigmaback * freq)

        csx, ncx, npadx = 5, 50, 25
        csz, ncz, npadz = 5, 50, 25

        hx = utils.meshTensor([(csx, ncx), (csx, npadx, 1.3)])
        hz = utils.meshTensor([(csz, npadz, -1.3), (csz, ncz),
                               (csz, npadz, 1.3)])

        # define the cylindrical mesh
        mesh = discretize.CylMesh([hx, 1, hz], [0.0, 0.0, -hz.sum() / 2])

        if plotIt:
            mesh.plotGrid()

        # make sure mesh is big enough
        self.assertTrue(mesh.hz.sum() > skdpth * 2.0)
        self.assertTrue(mesh.hx.sum() > skdpth * 2.0)

        # set up source
        # test electric dipole
        src_loc = np.r_[0.0, 0.0, 0.0]
        s_ind = utils.closestPoints(mesh, src_loc, "Fz") + mesh.nFx

        de = np.zeros(mesh.nF, dtype=complex)
        de[s_ind] = 1.0 / csz
        de_p = [fdem.Src.RawVec_e([], freq, de / mesh.area)]

        dm_p = [fdem.Src.MagDipole([], freq, src_loc)]

        # Pair the problem and survey
        surveye = fdem.Survey(de_p)
        surveym = fdem.Survey(dm_p)

        prbe = fdem.Simulation3DMagneticField(mesh,
                                              survey=surveye,
                                              sigma=sigmaback,
                                              mu=mur * mu_0)
        prbm = fdem.Simulation3DElectricField(mesh,
                                              survey=surveym,
                                              sigma=sigmaback,
                                              mu=mur * mu_0)

        # solve
        fieldsBackE = prbe.fields()
        fieldsBackM = prbm.fields()

        rlim = [20.0, 500.0]
        # lookAtTx = de_p
        r = mesh.vectorCCx[np.argmin(np.abs(mesh.vectorCCx - rlim[0])):np.
                           argmin(np.abs(mesh.vectorCCx - rlim[1]))]
        z = 100.0

        # where we choose to measure
        XYZ = utils.ndgrid(r, np.r_[0.0], np.r_[z])

        Pf = mesh.getInterpolationMat(XYZ, "CC")
        Zero = sp.csr_matrix(Pf.shape)
        Pfx, Pfz = sp.hstack([Pf, Zero]), sp.hstack([Zero, Pf])

        jn = fieldsBackE[de_p, "j"]
        bn = fieldsBackM[dm_p, "b"]

        SigmaBack = sigmaback * np.ones((mesh.nC))
        Rho = utils.sdiag(1.0 / SigmaBack)
        Rho = sp.block_diag([Rho, Rho])

        en = Rho * mesh.aveF2CCV * jn
        bn = mesh.aveF2CCV * bn

        ex, ez = Pfx * en, Pfz * en
        bx, bz = Pfx * bn, Pfz * bn

        # get analytic solution
        exa, eya, eza = analytics.FDEM.ElectricDipoleWholeSpace(XYZ,
                                                                src_loc,
                                                                sigmaback,
                                                                freq,
                                                                "Z",
                                                                mu_r=mur)

        exa = utils.mkvc(exa, 2)
        eya = utils.mkvc(eya, 2)
        eza = utils.mkvc(eza, 2)

        bxa, bya, bza = analytics.FDEM.MagneticDipoleWholeSpace(XYZ,
                                                                src_loc,
                                                                sigmaback,
                                                                freq,
                                                                "Z",
                                                                mu_r=mur)
        bxa = utils.mkvc(bxa, 2)
        bya = utils.mkvc(bya, 2)
        bza = utils.mkvc(bza, 2)

        print(
            " comp,       anayltic,       numeric,       num - ana,       (num - ana)/ana"
        )
        print(
            "  ex:",
            np.linalg.norm(exa),
            np.linalg.norm(ex),
            np.linalg.norm(exa - ex),
            np.linalg.norm(exa - ex) / np.linalg.norm(exa),
        )
        print(
            "  ez:",
            np.linalg.norm(eza),
            np.linalg.norm(ez),
            np.linalg.norm(eza - ez),
            np.linalg.norm(eza - ez) / np.linalg.norm(eza),
        )

        print(
            "  bx:",
            np.linalg.norm(bxa),
            np.linalg.norm(bx),
            np.linalg.norm(bxa - bx),
            np.linalg.norm(bxa - bx) / np.linalg.norm(bxa),
        )
        print(
            "  bz:",
            np.linalg.norm(bza),
            np.linalg.norm(bz),
            np.linalg.norm(bza - bz),
            np.linalg.norm(bza - bz) / np.linalg.norm(bza),
        )

        if plotIt is True:
            # Edipole
            plt.subplot(221)
            plt.plot(r, ex.real, "o", r, exa.real, linewidth=2)
            plt.grid(which="both")
            plt.title("Ex Real")
            plt.xlabel("r (m)")

            plt.subplot(222)
            plt.plot(r, ex.imag, "o", r, exa.imag, linewidth=2)
            plt.grid(which="both")
            plt.title("Ex Imag")
            plt.legend(["Num", "Ana"], bbox_to_anchor=(1.5, 0.5))
            plt.xlabel("r (m)")

            plt.subplot(223)
            plt.plot(r, ez.real, "o", r, eza.real, linewidth=2)
            plt.grid(which="both")
            plt.title("Ez Real")
            plt.xlabel("r (m)")

            plt.subplot(224)
            plt.plot(r, ez.imag, "o", r, eza.imag, linewidth=2)
            plt.grid(which="both")
            plt.title("Ez Imag")
            plt.xlabel("r (m)")

            plt.tight_layout()

            # Bdipole
            plt.subplot(221)
            plt.plot(r, bx.real, "o", r, bxa.real, linewidth=2)
            plt.grid(which="both")
            plt.title("Bx Real")
            plt.xlabel("r (m)")

            plt.subplot(222)
            plt.plot(r, bx.imag, "o", r, bxa.imag, linewidth=2)
            plt.grid(which="both")
            plt.title("Bx Imag")
            plt.legend(["Num", "Ana"], bbox_to_anchor=(1.5, 0.5))
            plt.xlabel("r (m)")

            plt.subplot(223)
            plt.plot(r, bz.real, "o", r, bza.real, linewidth=2)
            plt.grid(which="both")
            plt.title("Bz Real")
            plt.xlabel("r (m)")

            plt.subplot(224)
            plt.plot(r, bz.imag, "o", r, bza.imag, linewidth=2)
            plt.grid(which="both")
            plt.title("Bz Imag")
            plt.xlabel("r (m)")

            plt.tight_layout()

        self.assertTrue(
            np.linalg.norm(exa - ex) / np.linalg.norm(exa) < tol_EBdipole)
        self.assertTrue(
            np.linalg.norm(eza - ez) / np.linalg.norm(eza) < tol_EBdipole)

        self.assertTrue(
            np.linalg.norm(bxa - bx) / np.linalg.norm(bxa) < tol_EBdipole)
        self.assertTrue(
            np.linalg.norm(bza - bz) / np.linalg.norm(bza) < tol_EBdipole)
Beispiel #28
0
 def getEBJcore(src0):
     B0 = np.r_[Pfx * f[src0, "b"], Pfy * f[src0, "b"], Pfz * f[src0, "b"]]
     E0 = np.r_[Pex * f[src0, "e"], Pey * f[src0, "e"], Pez * f[src0, "e"]]
     J0 = utils.sdiag(np.r_[sigma_core, sigma_core, sigma_core]) * E0
     return E0, B0, J0
Beispiel #29
0
 def simpleFail(x):
     return np.sin(x), -sdiag(np.cos(x))
Beispiel #30
0
 def simpleFunction(x):
     return np.sin(x), lambda xi: sdiag(np.cos(x)) * xi