Ejemplo n.º 1
0
def plot_subsurface_01():
    """
    Create a basic graben geology using recursive procedural API
    :return: nothing (but plot the result)
    """
    z0, L, NL = 0.0, 10000.0, 30
    h = L / NL
    print("z0, L, nL, h =", z0, L, NL, h)
    mesh = baseline_tensor_mesh(NL, h, centering='CCN')
    survey = survey_gridded_locations(L, L, 20, 20, z0)
    history = [Basement()]
    history.append(StratigraphicLayer(history[-1]))
    history.append(StratigraphicLayer(history[-1]))
    history.append(PlanarFault(history[-1]))
    history.append(PlanarFault(history[-1]))
    # Basic stratigraphy
    histpars = [3.0, 1900.0, 2.5, 2500.0, 2.0]
    # Fault #1
    histpars.extend([-4000.0, 0.0, 0.0, 0.940, 0.0, 0.342, -4200.0])
    # Fault #2
    histpars.extend([+4000.0, 0.0, 0.0, 0.940, 0.0, -0.342, 4200.0])
    fwdmodel = DiscreteGravity(mesh, survey, history[0])
    fwdmodel.gfunc = Basement()
    fwdmodel.edgemask = profile_timer(fwdmodel.calc_gravity, h, [1.0])
    for m, part_history in enumerate(history):
        fwdmodel.gfunc = part_history
        npars = np.sum([e.npars for e in history[:m + 1]])
        profile_timer(fwdmodel.calc_gravity, h, histpars[:npars])
        fwdmodel.fwd_data -= fwdmodel.edgemask * fwdmodel.voxmodel.mean()
        fig = plt.figure(figsize=(12, 4))
        ax1 = plt.subplot(121)
        fwdmodel.plot_model_slice(ax=ax1)
        ax2 = plt.subplot(122)
        fwdmodel.plot_gravity(ax=ax2)
        plt.show()
Ejemplo n.º 2
0
def initialize_geomodel(gconf):  # pars, L, NL, foldhistory=False):
    """
    Initialize a GeoModel instance and get it ready for sampling
    :param pars: parameter vector (see top of file)
    :return: GeoModel instance ready for sampling with riemann
    """
    # Initialize a mesh for forward gravity calculation
    L, NL = gconf.L, gconf.NL
    z0, h = 0.0, L / NL
    print("z0, L, nL, h =", z0, L, NL, h)
    mesh = baseline_tensor_mesh(NL, h, centering='CCN')
    survey = survey_gridded_locations(L, L, 20, 20, z0)

    # Initialize a GeoHistory based on the parameters passed in
    history = gconf.geohist()

    # Initialize a DiscreteGravity forward model instance
    fwdmodel = DiscreteGravity(mesh, survey, history.rockprops)

    # Make some synthetic data based on this history and mesh
    data0 = fwdmodel.calc_gravity(h)
    np.random.seed(413)
    sigdata = 0.05 * np.std(data0)
    epsilon = sigdata * np.random.normal(size=data0.shape)
    dsynth = data0 + epsilon

    # Construct and return a GeoModel
    mymodel = GeoModel(history, fwdmodel, dsynth, sigdata, alpha=2.5)
    mymodel.stepsizes = gconf.stepsizes
    return mymodel
Ejemplo n.º 3
0
def plot_subsurface_02():
    """
    Create a basic graben geology using object-oriented API
    :return: nothing (but plot the result)
    """
    # Initialize basic grid parameters
    z0, L, NL = 0.0, 10000.0, 30
    h = L / NL
    print("z0, L, nL, h =", z0, L, NL, h)
    mesh = baseline_tensor_mesh(NL, h, centering='CCN')
    survey = survey_gridded_locations(L, L, 20, 20, z0)
    # Create the history
    history = gen_two_fault_model_demo([
        3.0, 1900.0, 2.5, 2500.0, 2.0, -4000.0, 0.0, +20.0, 0.0, -4200.0,
        +4000.0, 0.0, -20.0, 0.0, +4200.0
    ])
    # Add a final Fold event just for laughs
    history.add_event(
        FoldEvent([('nth', 'nph', vMFDist(th0=+0.0, ph0=0.0, kappa=100)),
                   ('pitch', UniGaussianDist(mean=0.0, std=30.0)),
                   ('phase', UniformDist(mean=0.0, width=360.0)),
                   ('wavelength', UniGaussianDist(mean=3000.0, std=300.0)),
                   ('amplitude', UniGaussianDist(mean=300.0, std=50.0))]))
    print("history.pars =", history.serialize())
    # Can also set parameters all at once -- good for running MCMC
    history.set_to_prior_draw()
    history.deserialize([
        3.0, 1900.0, 2.5, 2500.0, 2.0, -4000.0, 0.0, +20.0, 0.0, -4200.0,
        +4000.0, 0.0, -20.0, 0.0, +4200.0, -0.0, 0.0, 0.0, 0.0, 3000.0, 300.0
    ])
    print("history.pars =", history.serialize())
    print("history.prior =", history.logprior())
    # Plot a cross-section
    fwdmodel = DiscreteGravity(mesh, survey, history.event_list[0])
    fwdmodel.gfunc = history.event_list[0].rockprops
    fwdmodel.edgemask = profile_timer(fwdmodel.calc_gravity, h)
    for m, event in enumerate(history.event_list):
        print("current event:", event)
        fwdmodel.gfunc = lambda r, h: np.array(event.rockprops(r, h))
        profile_timer(fwdmodel.calc_gravity, h)
        fwdmodel.fwd_data -= fwdmodel.edgemask * fwdmodel.voxmodel.mean()
        fig = plt.figure(figsize=(12, 4))
        ax1 = plt.subplot(121)
        fwdmodel.plot_model_slice(ax=ax1)
        ax2 = plt.subplot(122)
        fwdmodel.plot_gravity(ax=ax2)
        plt.show()
Ejemplo n.º 4
0
def plot_subsurface_02():
    """
    Create a basic graben geology using object-oriented API
    :return: nothing (but plot the result)
    """
    # Initialize basic grid parameters
    z0, L, NL = 0.0, 10000.0, 30
    h = L / NL
    print("z0, L, nL, h =", z0, L, NL, h)
    mesh = baseline_tensor_mesh(NL, h, centering='CCN')
    survey = survey_gridded_locations(L, L, 20, 20, z0)
    # Create the history
    history = GeoHistory()
    history.add_event(BasementEvent(3.0))
    history.add_event(StratLayerEvent(1900.0, 2.5))
    history.add_event(StratLayerEvent(2500.0, 2.0))
    history.add_event(PlanarFaultEvent(-4000.0, 0.0, +20.0, 0.0, -4200.0))
    history.add_event(PlanarFaultEvent(+4000.0, 0.0, -20.0, 0.0, +4200.0))
    print("history.pars =", history.serialize())
    # Can also set parameters all at once -- good for running MCMC
    history = GeoHistory()
    history.add_event(BasementEvent())
    history.add_event(StratLayerEvent())
    history.add_event(StratLayerEvent())
    history.add_event(PlanarFaultEvent())
    history.add_event(PlanarFaultEvent())
    history.deserialize([
        3.0, 1900.0, 2.5, 2500.0, 2.0, -4000.0, 0.0, +20.0, 0.0, -4200.0,
        +4000.0, 0.0, -20.0, 0.0, +4200.0
    ])
    print("history.pars =", history.serialize())
    # Plot a cross-section
    fwdmodel = DiscreteGravity(mesh, survey, history.event_list[0])
    fwdmodel.gfunc = BasementEvent(1.0).rockprops
    fwdmodel.edgemask = profile_timer(fwdmodel.calc_gravity, h)
    for m, event in enumerate(history.event_list):
        print("current event:", event)
        fwdmodel.gfunc = lambda r, h: np.array(event.rockprops(r, h))
        profile_timer(fwdmodel.calc_gravity, h)
        fwdmodel.fwd_data -= fwdmodel.edgemask * fwdmodel.voxmodel.mean()
        fig = plt.figure(figsize=(12, 4))
        ax1 = plt.subplot(121)
        fwdmodel.plot_model_slice(ax=ax1)
        ax2 = plt.subplot(122)
        fwdmodel.plot_gravity(ax=ax2)
        plt.show()
Ejemplo n.º 5
0
def gradtest():
    """
    Testing ground for adding automatic gradients to GeoFuncs
    :return: nothing (yet)
    """
    # All the same setup as before
    z0, L, NL = 0.0, 10000.0, 15
    h = L / NL
    print("z0, L, nL, h =", z0, L, NL, h)
    mesh = baseline_tensor_mesh(NL, h, centering='CCN')
    survey = survey_gridded_locations(L, L, 20, 20, z0)
    history = [Basement()]
    history.append(StratigraphicLayer(history[-1]))
    history.append(StratigraphicLayer(history[-1]))
    history.append(PlanarFault(history[-1]))
    history.append(PlanarFault(history[-1]))
    # Basic stratigraphy
    histpars = [3.0, 1900.0, 2.5, 2500.0, 2.0]
    # Fault #1
    histpars.extend([-4000.0, 0.0, 0.0, 0.940, 0.0, 0.342, -4200.0])
    # Fault #2
    histpars.extend([+4000.0, 0.0, 0.0, 0.940, 0.0, -0.342, 4200.0])
    # Forward model stuff
    fwdmodel = DiscreteGravity(mesh, survey, history[0])
    fwdmodel.gfunc = Basement()
    fwdmodel.edgemask = profile_timer(fwdmodel.calc_gravity, h, [1.0])

    # Test gradient of anti-aliasing function
    x = np.linspace(-1, 1, 4001)
    t0 = time.time()
    g = [soft_if_then_piecewise_ifthen(xi, 0.0, 1.0, 1.0) for xi in x]
    t1 = time.time()
    g = soft_if_then_piecewise(x, np.zeros(x.shape), np.ones(x.shape), 1.0)
    t2 = time.time()
    g = soft_if_then_logjit(x, np.zeros(x.shape), np.ones(x.shape), 1.0)
    t3 = time.time()
    print("looped:    {:.2e} sec".format(t1 - t0))
    print("vector:    {:.2e} sec".format(t2 - t1))
    print("logistic:  {:.2e} sec".format(t3 - t2))
    # a vectorized way to take the 1-D derivative
    logistic_jac = jacobian(soft_if_then_logjit)
    dg = np.sum(logistic_jac(x, 0.0, 1.0, 1.0), axis=0)
    fig = plt.figure()
    plt.plot(x, g)
    plt.plot(x, dg, ls='--')
    plt.show()

    # Go through the history event by event
    for m, part_history in enumerate(history):
        fwdmodel.gfunc = part_history
        npars = np.sum([e.npars for e in history[:m + 1]])
        profile_timer(fwdmodel.calc_gravity, h, histpars[:npars])
        fwdmodel.fwd_data -= fwdmodel.edgemask * fwdmodel.voxmodel.mean()
        fig = plt.figure(figsize=(12, 4))
        ax1 = plt.subplot(121)
        fwdmodel.plot_model_slice(ax=ax1)
        ax2 = plt.subplot(122)
        fwdmodel.plot_gravity(ax=ax2)
        plt.show()

    # Finite differences, hrngh
    t0 = time.time()
    dgfd = []
    for i in range(len(histpars)):
        hp1, hp2 = np.array(histpars), np.array(histpars)
        dth = 1e-7 * max(1, histpars[i])
        hp1[i] -= dth
        vox1 = history[-1](fwdmodel.mesh.gridCC, h, hp1)
        hp2[i] += dth
        vox2 = history[-1](fwdmodel.mesh.gridCC, h, hp2)
        dgfd.append((vox2 - vox1) / (2 * dth))
    dgfd = np.array(dgfd).T
    t1 = time.time()
    print("dgfd ran in {:.3f} seconds".format(t1 - t0))

    # Demonstrate an end-to-end derivative w/rt parameters
    gfuncjac = profile_timer(jacobian, history[-1], 2)
    gfuncjac = jit(gfuncjac)
    jhistpars = jnp.array(histpars)
    dg = profile_timer(gfuncjac, fwdmodel.mesh.gridCC, h, jhistpars)
    print("dg.shape =", dg.shape)
    for i in range(3):
        dg = profile_timer(gfuncjac, fwdmodel.mesh.gridCC, h, jhistpars)
    for dgi in dg.T:
        fwdmodel.voxmodel = np.array(dgi)
        print("voxmodel.mean, voxmodel.std =", fwdmodel.voxmodel.mean(),
              fwdmodel.voxmodel.std())
        print("voxmodel.isnan.sum() =", np.sum(np.isnan(fwdmodel.voxmodel)))
        # fwdmodel.plot_model_slice()
        # plt.show()

    idx = (np.abs(dgfd) > 1e-9)
    resids = 0.5 * (dgfd[idx] - dg[idx]) / (np.abs(dg[idx] + dgfd[idx]))
    print("mean fractional derivative error: {:.3g} +/- {:.3g}".format(
        resids.mean(), resids.std()))