示例#1
0
文件: fm3d.py 项目: JKutt/PyDev
def run(plotIt=True, survey_type="pole-dipole"):
    np.random.seed(1)
    # Initiate I/O class for DC
    IO = DC.IO()
    # Obtain ABMN locations

    fileName1 = "C:/Users/johnk/Projects/Seabridge/fmdataDC.con"   # output mod
    fileName1_ = "C:/Users/johnk/Projects/Seabridge/fmdataIP.chg"  # output mod
    fileName2 = "C:/Users/johnk/Projects/Seabridge/forwardmodel.msh"  # in mesh
    mesh = Mesh.TensorMesh._readUBC_3DMesh(fileName2)     # Read in/create mesh

    print("Starting forward modeling")
    start = clock()
    # Define model Background
    rx = getRxData()                                     # rx locations
    tx = getTxData()                                     # tx locations
    survey_dc = generateSurvey(rx, tx, 45, 65)         # create survey object
    survey_dc.getABMN_locations()                           # get locations
    # survey_dc = IO.from_ambn_locations_to_survey(
    #     survey_dc.a_locations, survey_dc.b_locations,
    #     survey_dc.m_locations, survey_dc.n_locations,
    #     survey_type, data_dc_type='volt', data_ip_type='volt'
    # )
    uniq = Utils.uniqueRows(np.vstack((survey_dc.a_locations,
                                       survey_dc.b_locations,
                                       survey_dc.m_locations,
                                       survey_dc.n_locations)))
    electrode_locations = uniq[0]                            # assign
    actinds = Utils.surface2ind_topo(mesh,
                                     electrode_locations,
                                     method='cubic')      # active indicies
    survey_dc.drapeTopo(mesh, actinds)                       # drape topo
# =============================================================================
    # create sphere for ice representation
    x0 = (np.max(mesh.gridCC[:, 0]) +
          np.min(mesh.gridCC[:, 0])) / 2. + 50      # x0 center point of sphere
    y0 = (np.max(mesh.gridCC[:, 1]) +
          np.min(mesh.gridCC[:, 1])) / 2. - 50      # y0 center point of sphere
    z0 = 2350                                       # x0 center point of sphere
    # (np.max(mesh.gridCC[:, 2]) + np.min(mesh.gridCC[:, 2])) / 2.
    r0 = 500                                           # radius of sphere
    print(x0, y0, z0)
    csph = (np.sqrt((mesh.gridCC[:, 0] - x0)**2. +
                    (mesh.gridCC[:, 1] - y0)**2. +
                    (mesh.gridCC[:, 2] - z0)**2.)) < r0  # indicies of sphere
# sphere done =================================================================

# ============================================================================
# Create model
    mx = np.ones(mesh.nC) * 0.020                         # chargeability
    sigma = np.ones(mesh.nC) * 1. / 15000.

# create dipping structure parameters
    theta = 45. * np.pi / 180.                            # dipping angle
    x0_d = 374700.
    x1_d = 375000.
    y0_d = 6275850.
    y0_1d = 500. * np.sin(theta) + y0_d
    y1_d = 6275900.
    y1_1d = 500. * np.sin(theta) + y1_d
    z0_d = 1860.
    z1_d = z0_d - (500. * np.cos(theta))
    m_ = (z0_d - z1_d) / (y0_1d - y0_d)                   # slope of dip

    # loop through mesh and assign dipping structure conductivity
    for idx in range(mesh.nC):
        if z1_d <= mesh.gridCC[idx, 2] <= z0_d:
            if (x0_d <= mesh.gridCC[idx, 0] <= x1_d):
                yslope1 = y0_d + (1. / m_) * (mesh.gridCC[idx, 2] - z0_d)
                yslope2 = y1_d + (1. / m_) * (mesh.gridCC[idx, 2] - z0_d)
                if yslope1 <= mesh.gridCC[idx, 1] <= yslope2:
                    mx[idx] = 0.03
                    sigma[idx] = 1. / 300.

    # mx[csph] = ((0.025) *
    #             np.ones_like(mx[csph]))             # set sphere values
    mx[~actinds] = 1. / 1e8                             # flag air values
    # sigma[csph] = ((5000.) *
    #                np.ones_like(sigma[csph]))             # set sphere values
    sigma[~actinds] = 1. / 1e8                              # flag air values
    rho = 1. / sigma
    stop = clock()
    print(stop)
    # plot results
    # Show the true conductivity model
    if plotIt:
        ncy = mesh.nCy
        ncz = mesh.nCz
        ncx = mesh.nCx
        mtrue = mx
        print(mtrue.min(), mtrue.max())
        clim = [0, 0.04]
        fig, ax = plt.subplots(2, 2, figsize=(12, 6))
        ax = Utils.mkvc(ax)
        dat = mesh.plotSlice(((mx)), ax=ax[0], normal='Z', clim=clim,
                             ind=int(ncz / 2), pcolorOpts={"cmap": "jet"})
        ax[0].plot(rx[:, 0], rx[:, 1], 'or')
        ax[0].plot(tx[:, 0], tx[:, 1], 'dk')
        mesh.plotSlice(((mx)), ax=ax[1], normal='Y', clim=clim,
                       ind=int(ncy / 2 + 2), pcolorOpts={"cmap": "jet"})
        mesh.plotSlice(((mx)), ax=ax[2], normal='X', clim=clim,
                       ind=int(ncx / 2 + 4), pcolorOpts={"cmap": "jet"})
        mesh.plotSlice(((mx)), ax=ax[3], normal='X', clim=clim,
                       ind=int(ncx / 2 + 8), pcolorOpts={"cmap": "jet"})
        cbar_ax = fig.add_axes([0.82, 0.15, 0.05, 0.7])
        cb = plt.colorbar(dat[0], ax=cbar_ax)
        fig.subplots_adjust(right=0.85)
        cb.set_label('V/V')
        cbar_ax.axis('off')
        plt.show()

        mtrue = 1. / sigma
        print(mtrue.min(), mtrue.max())
        clim = [0, 20000]
        fig, ax = plt.subplots(2, 2, figsize=(12, 6))
        ax = Utils.mkvc(ax)
        dat = mesh.plotSlice(((mtrue)), ax=ax[0], normal='Z', clim=clim,
                             ind=int(ncz / 2 - 4), pcolorOpts={"cmap": "jet"})
        ax[0].plot(rx[:, 0], rx[:, 1], 'or')
        ax[0].plot(tx[:, 0], tx[:, 1], 'dk')
        mesh.plotSlice(((mtrue)), ax=ax[1], normal='Y', clim=clim,
                       ind=int(ncy / 2), pcolorOpts={"cmap": "jet"})
        mesh.plotSlice(((mtrue)), ax=ax[2], normal='X', clim=clim,
                       ind=int(ncx / 2 + 4), pcolorOpts={"cmap": "jet"})
        mesh.plotSlice(((mtrue)), ax=ax[3], normal='X', clim=clim,
                       ind=int(ncx / 2 + 8), pcolorOpts={"cmap": "jet"})
        cbar_ax = fig.add_axes([0.82, 0.15, 0.05, 0.7])
        cb = plt.colorbar(dat[0], ax=cbar_ax)
        fig.subplots_adjust(right=0.85)
        cb.set_label('rho')
        cbar_ax.axis('off')
        plt.show()

    # Use Exponential Map: m = log(rho)
    actmap = Maps.InjectActiveCells(
        mesh, indActive=actinds, valInactive=np.log(1e8)
    )
    mapping = Maps.ExpMap(mesh) * actmap

    # Generate mtrue_dc for resistivity
    mtrue_dc = np.log(rho[actinds])

    # Generate 3D DC problem
    # "CC" means potential is defined at center
    prb = DC.Problem3D_CC(
        mesh, rhoMap=mapping, storeJ=False,
        Solver=Solver
    )
    # Pair problem with survey
    try:
        prb.pair(survey_dc)
    except:
        survey_dc.unpair()
        prb.pair(survey_dc)

    # Make synthetic DC data with 5% Gaussian noise
    dtrue_dc = survey_dc.makeSyntheticData(mtrue_dc, std=0.05, force=True)
    IO.data_dc = dtrue_dc
    # Generate mtrue_ip for chargability
    mtrue_ip = mx[actinds]
    # Generate 3D DC problem
    # "CC" means potential is defined at center
    prb_ip = IP.Problem3D_CC(
        mesh, etaMap=actmap, storeJ=False, rho=rho,
        Solver=Solver
    )
    survey_ip = IP.from_dc_to_ip_survey(survey_dc, dim="3D")
    prb_ip.pair(survey_ip)
    dtrue_ip = survey_ip.makeSyntheticData(mtrue_ip, std=0.05)
    IO.data_ip = dtrue_ip

    # Show apparent resisitivty histogram
    # if plotIt:
    #     fig = plt.figure(figsize=(10, 4))
    #     ax1 = plt.subplot(121)
    #     out = hist(np.log10(abs(IO.voltages)), bins=20)
    #     ax1.set_xlabel("log10 DC voltage (V)")
    #     ax2 = plt.subplot(122)
    #     out = hist(IO.apparent_resistivity, bins=20)
    #     ax2.set_xlabel("Apparent Resistivity ($\Omega$m)")
    #     plt.tight_layout()
    #     plt.show()

    # Set initial model based upon histogram
    m0_dc = np.ones(actmap.nP) * np.log(10000.)
    # Set uncertainty
    # floor
    eps_dc = 10**(-3.2)
    # percentage
    std_dc = 0.05

    mopt_dc, pred_dc = DC.run_inversion(
        m0_dc, survey_dc, actinds, mesh, std_dc, eps_dc,
        use_sensitivity_weight=False)

    # Convert obtained inversion model to resistivity
    # rho = M(m), where M(.) is a mapping
    rho_est = mapping * mopt_dc
    # rho_est[~actinds] = np.nan
    rho_true = rho.copy()
    rho_true[~actinds] = np.nan

    # write data to file
    out_file = open(fileName1, "w")
    for i in range(rho_est.size):
        out_file.write("%0.5e\n" % rho_est[i])

    # Set initial model based upon histogram
    m0_ip = np.ones(actmap.nP) * 1e-10
    # Set uncertainty
    # floor
    eps_ip = 10**(-4)
    # percentage
    std_ip = 0.05
    # Clean sensitivity function formed with true resistivity
    prb_ip._Jmatrix = None
    # Input obtained resistivity to form sensitivity
    prb_ip.rho = mapping * mopt_dc
    mopt_ip, _ = IP.run_inversion(
        m0_ip, survey_ip, actinds, mesh, std_ip, eps_ip,
        upper=np.Inf, lower=0.,
        use_sensitivity_weight=False)

    # Convert obtained inversion model to chargeability
    # charg = M(m), where M(.) is a mapping for cells below topography
    charg_est = actmap * mopt_ip
    # charg_est[~actinds] = np.nan
    charg_true = charg.copy()
    charg_true[~actinds] = np.nan

    # write IP data to file
    out_file = open(fileName1_, "w")
    for i in range(charg_est.size):
        out_file.write("%0.5e\n" % charg_est[i])
示例#2
0
def run(plotIt=True, survey_type="dipole-dipole"):
    np.random.seed(1)
    # Initiate I/O class for DC
    IO = DC.IO()
    # Obtain ABMN locations

    xmin, xmax = 0., 200.
    ymin, ymax = 0., 0.
    zmin, zmax = 0, 0
    endl = np.array([[xmin, ymin, zmin], [xmax, ymax, zmax]])
    # Generate DC survey object
    survey_dc = DC.Utils.gen_DCIPsurvey(endl,
                                        survey_type=survey_type,
                                        dim=2,
                                        a=10,
                                        b=10,
                                        n=10)
    survey_dc.getABMN_locations()
    survey_dc = IO.from_ambn_locations_to_survey(survey_dc.a_locations,
                                                 survey_dc.b_locations,
                                                 survey_dc.m_locations,
                                                 survey_dc.n_locations,
                                                 survey_type,
                                                 data_dc_type='volt',
                                                 data_ip_type='volt')

    # Obtain 2D TensorMesh
    mesh, actind = IO.set_mesh()
    topo, mesh1D = DC.Utils.genTopography(mesh, -10, 0, its=100)
    actind = Utils.surface2ind_topo(mesh, np.c_[mesh1D.vectorCCx, topo])
    survey_dc.drapeTopo(mesh, actind, option="top")

    # Build conductivity and chargeability model
    blk_inds_c = Utils.ModelBuilder.getIndicesSphere(np.r_[60., -25.], 12.5,
                                                     mesh.gridCC)
    blk_inds_r = Utils.ModelBuilder.getIndicesSphere(np.r_[140., -25.], 12.5,
                                                     mesh.gridCC)
    blk_inds_charg = Utils.ModelBuilder.getIndicesSphere(
        np.r_[100., -25], 12.5, mesh.gridCC)
    sigma = np.ones(mesh.nC) * 1. / 100.
    sigma[blk_inds_c] = 1. / 10.
    sigma[blk_inds_r] = 1. / 1000.
    sigma[~actind] = 1. / 1e8
    rho = 1. / sigma
    charg = np.zeros(mesh.nC)
    charg[blk_inds_charg] = 0.1

    # Show the true conductivity model
    if plotIt:
        fig, axs = plt.subplots(2, 1, figsize=(12, 6))
        temp_rho = rho.copy()
        temp_rho[~actind] = np.nan
        temp_charg = charg.copy()
        temp_charg[~actind] = np.nan

        out1 = mesh.plotImage(temp_rho,
                              grid=True,
                              ax=axs[0],
                              gridOpts={'alpha': 0.2},
                              clim=(10, 1000),
                              pcolorOpts={
                                  "cmap": "viridis",
                                  "norm": colors.LogNorm()
                              })
        out2 = mesh.plotImage(temp_charg,
                              grid=True,
                              ax=axs[1],
                              gridOpts={'alpha': 0.2},
                              clim=(0, 0.1),
                              pcolorOpts={"cmap": "magma"})
        for i in range(2):
            axs[i].plot(survey_dc.electrode_locations[:, 0],
                        survey_dc.electrode_locations[:, 1], 'kv')
            axs[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max())
            axs[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min())
            axs[i].set_aspect('equal')
        cb = plt.colorbar(out1[0], ax=axs[0])
        cb.set_label("Resistivity (ohm-m)")
        cb = plt.colorbar(out2[0], ax=axs[1])
        cb.set_label("Chargeability")

        plt.show()

    # Use Exponential Map: m = log(rho)
    actmap = Maps.InjectActiveCells(mesh,
                                    indActive=actind,
                                    valInactive=np.log(1e8))
    mapping = Maps.ExpMap(mesh) * actmap

    # Generate mtrue_dc for resistivity
    mtrue_dc = np.log(rho[actind])

    # Generate 2.5D DC problem
    # "N" means potential is defined at nodes
    prb = DC.Problem2D_N(mesh, rhoMap=mapping, storeJ=True, Solver=Solver)
    # Pair problem with survey
    try:
        prb.pair(survey_dc)
    except:
        survey_dc.unpair()
        prb.pair(survey_dc)

    # Make synthetic DC data with 5% Gaussian noise
    dtrue_dc = survey_dc.makeSyntheticData(mtrue_dc, std=0.05, force=True)
    IO.data_dc = dtrue_dc

    # Generate mtrue_ip for chargability
    mtrue_ip = charg[actind]
    # Generate 2.5D DC problem
    # "N" means potential is defined at nodes
    prb_ip = IP.Problem2D_N(mesh,
                            etaMap=actmap,
                            storeJ=True,
                            rho=rho,
                            Solver=Solver)
    survey_ip = IP.from_dc_to_ip_survey(survey_dc, dim="2.5D")
    prb_ip.pair(survey_ip)

    dtrue_ip = survey_ip.makeSyntheticData(mtrue_ip, std=0.05)

    IO.data_ip = dtrue_ip

    # Show apparent resisitivty pseudo-section
    if plotIt:
        IO.plotPseudoSection(data_type='apparent_resistivity',
                             scale='log',
                             cmap='viridis')
        plt.show()

    # Show apparent chargeability pseudo-section
    if plotIt:
        IO.plotPseudoSection(data_type='apparent_chargeability',
                             scale='linear',
                             cmap='magma')
        plt.show()

    # Show apparent resisitivty histogram
    if plotIt:
        fig = plt.figure(figsize=(10, 4))
        ax1 = plt.subplot(121)
        out = hist(np.log10(abs(IO.voltages)), bins=20)
        ax1.set_xlabel("log10 DC voltage (V)")
        ax2 = plt.subplot(122)
        out = hist(IO.apparent_resistivity, bins=20)
        ax2.set_xlabel("Apparent Resistivity ($\Omega$m)")
        plt.tight_layout()
        plt.show()

    # Set initial model based upon histogram
    m0_dc = np.ones(actmap.nP) * np.log(100.)
    # Set uncertainty
    # floor
    eps_dc = 10**(-3.2)
    # percentage
    std_dc = 0.05

    mopt_dc, pred_dc = DC.run_inversion(m0_dc,
                                        survey_dc,
                                        actind,
                                        mesh,
                                        std_dc,
                                        eps_dc,
                                        beta0_ratio=1e0,
                                        use_sensitivity_weight=True)

    # Convert obtained inversion model to resistivity
    # rho = M(m), where M(.) is a mapping

    rho_est = mapping * mopt_dc
    rho_est[~actind] = np.nan
    rho_true = rho.copy()
    rho_true[~actind] = np.nan

    # show recovered conductivity
    if plotIt:
        vmin, vmax = rho.min(), rho.max()
        fig, ax = plt.subplots(2, 1, figsize=(20, 6))
        out1 = mesh.plotImage(rho_true,
                              clim=(10, 1000),
                              pcolorOpts={
                                  "cmap": "viridis",
                                  "norm": colors.LogNorm()
                              },
                              ax=ax[0])
        out2 = mesh.plotImage(rho_est,
                              clim=(10, 1000),
                              pcolorOpts={
                                  "cmap": "viridis",
                                  "norm": colors.LogNorm()
                              },
                              ax=ax[1])
        out = [out1, out2]
        for i in range(2):
            ax[i].plot(survey_dc.electrode_locations[:, 0],
                       survey_dc.electrode_locations[:, 1], 'kv')
            ax[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max())
            ax[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min())
            cb = plt.colorbar(out[i][0], ax=ax[i])
            cb.set_label("Resistivity ($\Omega$m)")
            ax[i].set_xlabel("Northing (m)")
            ax[i].set_ylabel("Elevation (m)")
            ax[i].set_aspect('equal')
        plt.tight_layout()
        plt.show()

    # Show apparent resisitivty histogram
    if plotIt:
        fig = plt.figure(figsize=(10, 4))
        ax1 = plt.subplot(121)
        out = hist(np.log10(abs(IO.voltages_ip)), bins=20)
        ax1.set_xlabel("log10 IP voltage (V)")
        ax2 = plt.subplot(122)
        out = hist(IO.apparent_chargeability, bins=20)
        ax2.set_xlabel("Apparent Chargeability (V/V)")
        plt.tight_layout()
        plt.show()

    # Set initial model based upon histogram
    m0_ip = np.ones(actmap.nP) * 1e-10
    # Set uncertainty
    # floor
    eps_ip = 10**(-4)
    # percentage
    std_ip = 0.05
    # Clean sensitivity function formed with true resistivity
    prb_ip._Jmatrix = None
    # Input obtained resistivity to form sensitivity
    prb_ip.rho = mapping * mopt_dc
    mopt_ip, _ = IP.run_inversion(m0_ip,
                                  survey_ip,
                                  actind,
                                  mesh,
                                  std_ip,
                                  eps_ip,
                                  upper=np.Inf,
                                  lower=0.,
                                  beta0_ratio=1e0,
                                  use_sensitivity_weight=True)

    # Convert obtained inversion model to chargeability
    # charg = M(m), where M(.) is a mapping for cells below topography

    charg_est = actmap * mopt_ip
    charg_est[~actind] = np.nan
    charg_true = charg.copy()
    charg_true[~actind] = np.nan

    # show recovered chargeability
    if plotIt:
        fig, ax = plt.subplots(2, 1, figsize=(20, 6))
        out1 = mesh.plotImage(charg_true,
                              clim=(0, 0.1),
                              pcolorOpts={"cmap": "magma"},
                              ax=ax[0])
        out2 = mesh.plotImage(charg_est,
                              clim=(0, 0.1),
                              pcolorOpts={"cmap": "magma"},
                              ax=ax[1])
        out = [out1, out2]
        for i in range(2):
            ax[i].plot(survey_dc.electrode_locations[:, 0],
                       survey_dc.electrode_locations[:, 1], 'rv')
            ax[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max())
            ax[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min())
            cb = plt.colorbar(out[i][0], ax=ax[i])
            cb.set_label("Resistivity ($\Omega$m)")
            ax[i].set_xlabel("Northing (m)")
            ax[i].set_ylabel("Elevation (m)")
            ax[i].set_aspect('equal')
        plt.tight_layout()
        plt.show()
示例#3
0
def run(plotIt=True, survey_type="dipole-dipole"):
    np.random.seed(1)
    # Initiate I/O class for DC
    IO = DC.IO()
    # Obtain ABMN locations

    xmin, xmax = 0., 200.
    ymin, ymax = 0., 0.
    zmin, zmax = 0, 0
    endl = np.array([[xmin, ymin, zmin], [xmax, ymax, zmax]])
    # Generate DC survey object
    survey_dc = DC.Utils.gen_DCIPsurvey(endl, survey_type=survey_type, dim=2,
                                     a=10, b=10, n=10)
    survey_dc.getABMN_locations()
    survey_dc = IO.from_ambn_locations_to_survey(
        survey_dc.a_locations, survey_dc.b_locations,
        survey_dc.m_locations, survey_dc.n_locations,
        survey_type, data_dc_type='volt', data_ip_type='volt'
    )

    # Obtain 2D TensorMesh
    mesh, actind = IO.set_mesh()
    topo, mesh1D = DC.Utils.genTopography(mesh, -10, 0, its=100)
    actind = Utils.surface2ind_topo(mesh, np.c_[mesh1D.vectorCCx, topo])
    survey_dc.drapeTopo(mesh, actind, option="top")

    # Build conductivity and chargeability model
    blk_inds_c = Utils.ModelBuilder.getIndicesSphere(
        np.r_[60., -25.], 12.5, mesh.gridCC
    )
    blk_inds_r = Utils.ModelBuilder.getIndicesSphere(
        np.r_[140., -25.], 12.5, mesh.gridCC
    )
    blk_inds_charg = Utils.ModelBuilder.getIndicesSphere(
        np.r_[100., -25], 12.5, mesh.gridCC
    )
    sigma = np.ones(mesh.nC)*1./100.
    sigma[blk_inds_c] = 1./10.
    sigma[blk_inds_r] = 1./1000.
    sigma[~actind] = 1./1e8
    rho = 1./sigma
    charg = np.zeros(mesh.nC)
    charg[blk_inds_charg] = 0.1

    # Show the true conductivity model
    if plotIt:
        fig, axs = plt.subplots(2,1, figsize=(12, 6))
        temp_rho = rho.copy()
        temp_rho[~actind] = np.nan
        temp_charg = charg.copy()
        temp_charg[~actind] = np.nan

        out1 = mesh.plotImage(
            temp_rho, grid=True, ax=axs[0], gridOpts={'alpha': 0.2},
            clim=(10, 1000),
            pcolorOpts={"cmap": "viridis", "norm": colors.LogNorm()}
        )
        out2 = mesh.plotImage(
            temp_charg, grid=True, ax=axs[1], gridOpts={'alpha': 0.2},
            clim=(0, 0.1),
            pcolorOpts={"cmap": "magma"}
        )
        for i in range(2):
            axs[i].plot(
                survey_dc.electrode_locations[:, 0],
                survey_dc.electrode_locations[:, 1], 'kv'
            )
            axs[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max())
            axs[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min())
            axs[i].set_aspect('equal')
        cb = plt.colorbar(out1[0], ax=axs[0])
        cb.set_label("Resistivity (ohm-m)")
        cb = plt.colorbar(out2[0], ax=axs[1])
        cb.set_label("Chargeability")

        plt.show()

    # Use Exponential Map: m = log(rho)
    actmap = Maps.InjectActiveCells(
        mesh, indActive=actind, valInactive=np.log(1e8)
    )
    mapping = Maps.ExpMap(mesh) * actmap

    # Generate mtrue_dc for resistivity
    mtrue_dc = np.log(rho[actind])

    # Generate 2.5D DC problem
    # "N" means potential is defined at nodes
    prb = DC.Problem2D_N(
        mesh, rhoMap=mapping, storeJ=True,
        Solver=Solver
    )
    # Pair problem with survey
    try:
        prb.pair(survey_dc)
    except:
        survey_dc.unpair()
        prb.pair(survey_dc)

    # Make synthetic DC data with 5% Gaussian noise
    dtrue_dc = survey_dc.makeSyntheticData(mtrue_dc, std=0.05, force=True)
    IO.data_dc = dtrue_dc

    # Generate mtrue_ip for chargability
    mtrue_ip = charg[actind]
    # Generate 2.5D DC problem
    # "N" means potential is defined at nodes
    prb_ip = IP.Problem2D_N(
        mesh, etaMap=actmap, storeJ=True, rho=rho,
        Solver=Solver
    )
    survey_ip = IP.from_dc_to_ip_survey(survey_dc, dim="2.5D")
    prb_ip.pair(survey_ip)
    dtrue_ip = survey_ip.makeSyntheticData(mtrue_ip, std=0.05)

    IO.data_ip = dtrue_ip

    # Show apparent resisitivty pseudo-section
    if plotIt:
        IO.plotPseudoSection(
            data_type='apparent_resistivity', scale='log',
            cmap='viridis'
        )
        plt.show()

    # Show apparent chargeability pseudo-section
    if plotIt:
        IO.plotPseudoSection(
            data_type='apparent_chargeability', scale='linear',
            cmap='magma'
        )
        plt.show()

    # Show apparent resisitivty histogram
    if plotIt:
        fig = plt.figure(figsize=(10, 4))
        ax1 = plt.subplot(121)
        out = hist(np.log10(abs(IO.voltages)), bins=20)
        ax1.set_xlabel("log10 DC voltage (V)")
        ax2 = plt.subplot(122)
        out = hist(IO.apparent_resistivity, bins=20)
        ax2.set_xlabel("Apparent Resistivity ($\Omega$m)")
        plt.tight_layout()
        plt.show()

    # Set initial model based upon histogram
    m0_dc = np.ones(actmap.nP)*np.log(100.)
    # Set uncertainty
    # floor
    eps_dc = 10**(-3.2)
    # percentage
    std_dc = 0.05

    mopt_dc, pred_dc = DC.run_inversion(
        m0_dc, survey_dc, actind, mesh, std_dc, eps_dc,
        beta0_ratio=1e0,
        use_sensitivity_weight=True
        )

    # Convert obtained inversion model to resistivity
    # rho = M(m), where M(.) is a mapping

    rho_est = mapping*mopt_dc
    rho_est[~actind] = np.nan
    rho_true = rho.copy()
    rho_true[~actind] = np.nan

    # show recovered conductivity
    if plotIt:
        vmin, vmax = rho.min(), rho.max()
        fig, ax = plt.subplots(2, 1, figsize=(20, 6))
        out1 = mesh.plotImage(
                rho_true, clim=(10, 1000),
                pcolorOpts={"cmap": "viridis", "norm": colors.LogNorm()},
                ax=ax[0]
        )
        out2 = mesh.plotImage(
            rho_est, clim=(10, 1000),
            pcolorOpts={"cmap": "viridis", "norm": colors.LogNorm()},
            ax=ax[1]
        )
        out = [out1, out2]
        for i in range(2):
            ax[i].plot(
                survey_dc.electrode_locations[:, 0],
                survey_dc.electrode_locations[:, 1], 'kv'
            )
            ax[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max())
            ax[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min())
            cb = plt.colorbar(out[i][0], ax=ax[i])
            cb.set_label("Resistivity ($\Omega$m)")
            ax[i].set_xlabel("Northing (m)")
            ax[i].set_ylabel("Elevation (m)")
            ax[i].set_aspect('equal')
        plt.tight_layout()
        plt.show()

    # Show apparent resisitivty histogram
    if plotIt:
        fig = plt.figure(figsize=(10, 4))
        ax1 = plt.subplot(121)
        out = hist(np.log10(abs(IO.voltages_ip)), bins=20)
        ax1.set_xlabel("log10 IP voltage (V)")
        ax2 = plt.subplot(122)
        out = hist(IO.apparent_chargeability, bins=20)
        ax2.set_xlabel("Apparent Chargeability (V/V)")
        plt.tight_layout()
        plt.show()


    # Set initial model based upon histogram
    m0_ip = np.ones(actmap.nP)*1e-10
    # Set uncertainty
    # floor
    eps_ip = 10**(-4)
    # percentage
    std_ip = 0.05
    # Clean sensitivity function formed with true resistivity
    prb_ip._Jmatrix = None
    # Input obtained resistivity to form sensitivity
    prb_ip.rho = mapping*mopt_dc
    mopt_ip, _ = IP.run_inversion(
        m0_ip, survey_ip, actind, mesh, std_ip, eps_ip,
        upper=np.Inf, lower=0.,
        beta0_ratio=1e0,
        use_sensitivity_weight=True
    )

    # Convert obtained inversion model to chargeability
    # charg = M(m), where M(.) is a mapping for cells below topography

    charg_est = actmap*mopt_ip
    charg_est[~actind] = np.nan
    charg_true = charg.copy()
    charg_true[~actind] = np.nan

    # show recovered chargeability
    if plotIt:
        fig, ax = plt.subplots(2, 1, figsize=(20, 6))
        out1 = mesh.plotImage(
                charg_true, clim=(0, 0.1),
                pcolorOpts={"cmap": "magma"},
                ax=ax[0]
        )
        out2 = mesh.plotImage(
            charg_est, clim=(0, 0.1),
            pcolorOpts={"cmap": "magma"},
            ax=ax[1]
        )
        out = [out1, out2]
        for i in range(2):
            ax[i].plot(
                survey_dc.electrode_locations[:, 0],
                survey_dc.electrode_locations[:, 1], 'rv'
            )
            ax[i].set_xlim(IO.grids[:, 0].min(), IO.grids[:, 0].max())
            ax[i].set_ylim(-IO.grids[:, 1].max(), IO.grids[:, 1].min())
            cb = plt.colorbar(out[i][0], ax=ax[i])
            cb.set_label("Resistivity ($\Omega$m)")
            ax[i].set_xlabel("Northing (m)")
            ax[i].set_ylabel("Elevation (m)")
            ax[i].set_aspect('equal')
        plt.tight_layout()
        plt.show()