Example #1
0
    def setUp(self):
        mesh = self.get_mesh()
        params = Richards.Empirical.HaverkampParams().celia1990
        k_fun, theta_fun = Richards.Empirical.haverkamp(mesh, **params)

        self.setup_maps(mesh, k_fun, theta_fun)
        bc, h = self.get_conditions(mesh)

        prob = Richards.RichardsProblem(mesh,
                                        hydraulic_conductivity=k_fun,
                                        water_retention=theta_fun,
                                        root_finder_tol=1e-6,
                                        debug=False,
                                        boundary_conditions=bc,
                                        initial_conditions=h,
                                        do_newton=False,
                                        method='mixed')
        prob.timeSteps = [(40, 3), (60, 3)]
        prob.Solver = Solver

        rx_list = self.get_rx_list(prob)
        survey = Richards.RichardsSurvey(rx_list)

        prob.pair(survey)

        self.h0 = h
        self.mesh = mesh
        self.Ks = params['Ks'] * np.ones(self.mesh.nC)
        self.A = params['A'] * np.ones(self.mesh.nC)
        self.theta_s = params['theta_s'] * np.ones(self.mesh.nC)
        self.prob = prob
        self.survey = survey
        self.setup_model()
Example #2
0
    def setUp(self):
        M = Mesh.TensorMesh([np.ones(20)])
        M.setCellGradBC('dirichlet')

        params = Richards.Empirical.HaverkampParams().celia1990
        params['Ks'] = np.log(params['Ks'])
        E = Richards.Empirical.Haverkamp(M, **params)

        bc = np.array([-61.5, -20.7])
        h = np.zeros(M.nC) + bc[0]

        prob = Richards.RichardsProblem(M,
                                        mapping=E,
                                        timeSteps=[(40, 3), (60, 3)],
                                        tolRootFinder=1e-6,
                                        debug=False,
                                        boundaryConditions=bc,
                                        initialConditions=h,
                                        doNewton=False,
                                        method='mixed')
        prob.Solver = Solver

        locs = np.r_[5., 10, 15]
        times = prob.times[3:5]
        rxSat = Richards.RichardsRx(locs, times, 'saturation')
        rxPre = Richards.RichardsRx(locs, times, 'pressureHead')
        survey = Richards.RichardsSurvey([rxSat, rxPre])

        prob.pair(survey)

        self.h0 = h
        self.M = M
        self.Ks = params['Ks']
        self.prob = prob
        self.survey = survey
Example #3
0
    def setUp(self):
        M = Mesh.TensorMesh([np.ones(8),np.ones(20),np.ones(10)])

        M.setCellGradBC(['neumann','neumann','dirichlet'])

        params = Richards.Empirical.HaverkampParams().celia1990
        params['Ks'] = np.log(params['Ks'])
        E = Richards.Empirical.Haverkamp(M, **params)

        bc = np.array([-61.5,-20.7])
        bc = np.r_[np.zeros(M.nCy*M.nCz*2),np.zeros(M.nCx*M.nCz*2),np.ones(M.nCx*M.nCy)*bc[0],np.ones(M.nCx*M.nCy)*bc[1]]
        h = np.zeros(M.nC) + bc[0]
        prob = Richards.RichardsProblem(M,E, timeSteps=[(40,3),(60,3)], boundaryConditions=bc, initialConditions=h, doNewton=False, method='mixed', tolRootFinder=1e-6, debug=False)
        prob.Solver = Solver

        locs = Utils.ndgrid(np.r_[5,7.],np.r_[5,15.],np.r_[6,8.])
        times = prob.times[3:5]
        rxSat = Richards.RichardsRx(locs, times, 'saturation')
        rxPre = Richards.RichardsRx(locs, times, 'pressureHead')
        survey = Richards.RichardsSurvey([rxSat, rxPre])

        prob.pair(survey)

        self.h0 = h
        self.M = M
        self.Ks = params['Ks']
        self.prob = prob
        self.survey = survey
 def getFields(timeStep, method):
     timeSteps = np.ones(360/timeStep)*timeStep
     prob = Richards.RichardsProblem(
         M, mapping=E, timeSteps=timeSteps,
         boundaryConditions=bc, initialConditions=h,
         doNewton=False, method=method
     )
     return prob.fields(params['Ks'])
Example #5
0
 def getFields(timeStep, method):
     timeSteps = np.ones(int(360 / timeStep)) * timeStep
     prob = Richards.RichardsProblem(M,
                                     hydraulic_conductivity=k_fun,
                                     water_retention=theta_fun,
                                     boundary_conditions=bc,
                                     initial_conditions=h,
                                     do_newton=False,
                                     method=method)
     prob.timeSteps = timeSteps
     return prob.fields(params['Ks'] * np.ones(M.nC))
Example #6
0
 def get_rx_list(self, prob):
     locs = Utils.ndgrid(np.r_[5, 7.], np.r_[5, 15.], np.r_[6, 8.])
     times = prob.times[3:5]
     rxSat = Richards.SaturationRx(locs, times)
     rxPre = Richards.PressureRx(locs, times)
     return [rxSat, rxPre]
Example #7
0
 def get_rx_list(self, prob):
     locs = np.r_[5., 10, 15]
     times = prob.times[3:5]
     rxSat = Richards.SaturationRx(locs, times)
     rxPre = Richards.PressureRx(locs, times)
     return [rxSat, rxPre]
def run(plotIt=True):

    M = Mesh.TensorMesh([np.ones(40)], x0='N')
    M.setCellGradBC('dirichlet')
    # We will use the haverkamp empirical model with parameters from Celia1990
    k_fun, theta_fun = Richards.Empirical.haverkamp(M,
                                                    A=1.1750e+06,
                                                    gamma=4.74,
                                                    alpha=1.6110e+06,
                                                    theta_s=0.287,
                                                    theta_r=0.075,
                                                    beta=3.96)

    # Here we are making saturated hydraulic conductivity
    # an exponential mapping to the model (defined below)
    k_fun.KsMap = Maps.ExpMap(nP=M.nC)

    # Setup the boundary and initial conditions
    bc = np.array([-61.5, -20.7])
    h = np.zeros(M.nC) + bc[0]
    prob = Richards.RichardsProblem(M,
                                    hydraulic_conductivity=k_fun,
                                    water_retention=theta_fun,
                                    boundary_conditions=bc,
                                    initial_conditions=h,
                                    do_newton=False,
                                    method='mixed',
                                    debug=False)
    prob.timeSteps = [(5, 25, 1.1), (60, 40)]

    # Create the survey
    locs = -np.arange(2, 38, 4.)
    times = np.arange(30, prob.timeMesh.vectorCCx[-1], 60)
    rxSat = Richards.SaturationRx(locs, times)
    survey = Richards.RichardsSurvey([rxSat])
    survey.pair(prob)

    # Create a simple model for Ks
    Ks = 1e-3
    mtrue = np.ones(M.nC) * np.log(Ks)
    mtrue[15:20] = np.log(5e-2)
    mtrue[20:35] = np.log(3e-3)
    mtrue[35:40] = np.log(1e-2)

    # Create some synthetic data and fields
    Hs = prob.fields(mtrue)
    data = survey.makeSyntheticData(mtrue, std=0, f=Hs, force=True)

    if plotIt:
        plt.figure(figsize=(14, 9))

        plt.subplot(221)
        plt.plot(np.log10(np.exp(mtrue)), M.gridCC)
        plt.title('(a) True model and data locations')
        plt.ylabel('Depth, cm')
        plt.xlabel('Hydraulic conductivity, $log_{10}(K_s)$')
        plt.plot([-3.25] * len(locs), locs, 'ro')
        plt.legend(('True model', 'Data locations'))

        plt.subplot(222)
        plt.plot(times / 60, data.reshape((-1, len(locs))))
        plt.title('(b) True data over time at all depths')
        plt.xlabel('Time, minutes')
        plt.ylabel('Saturation')

        ax = plt.subplot(212)
        mesh2d = Mesh.TensorMesh([prob.timeMesh.hx / 60, prob.mesh.hx], '0N')
        sats = [theta_fun(_) for _ in Hs]
        clr = mesh2d.plotImage(np.c_[sats][1:, :], ax=ax)
        cmap0 = matplotlib.cm.RdYlBu_r
        clr[0].set_cmap(cmap0)
        c = plt.colorbar(clr[0])
        c.set_label('Saturation $\\theta$')
        plt.xlabel('Time, minutes')
        plt.ylabel('Depth, cm')
        plt.title('(c) Saturation over time')

        plt.tight_layout()
def run(plotIt=True):

    M = Mesh.TensorMesh([np.ones(40)], x0='N')
    M.setCellGradBC('dirichlet')
    # We will use the haverkamp empirical model with parameters from Celia1990
    k_fun, theta_fun = Richards.Empirical.haverkamp(M,
                                                    A=1.1750e+06,
                                                    gamma=4.74,
                                                    alpha=1.6110e+06,
                                                    theta_s=0.287,
                                                    theta_r=0.075,
                                                    beta=3.96)

    # Here we are making saturated hydraulic conductivity
    # an exponential mapping to the model (defined below)
    k_fun.KsMap = Maps.ExpMap(nP=M.nC)

    # Setup the boundary and initial conditions
    bc = np.array([-61.5, -20.7])
    h = np.zeros(M.nC) + bc[0]
    prob = Richards.RichardsProblem(M,
                                    hydraulic_conductivity=k_fun,
                                    water_retention=theta_fun,
                                    boundary_conditions=bc,
                                    initial_conditions=h,
                                    do_newton=False,
                                    method='mixed',
                                    debug=False)
    prob.timeSteps = [(5, 25, 1.1), (60, 40)]

    # Create the survey
    locs = -np.arange(2, 38, 4.)
    times = np.arange(30, prob.timeMesh.vectorCCx[-1], 60)
    rxSat = Richards.SaturationRx(locs, times)
    survey = Richards.RichardsSurvey([rxSat])
    survey.pair(prob)

    # Create a simple model for Ks
    Ks = 1e-3
    mtrue = np.ones(M.nC) * np.log(Ks)
    mtrue[15:20] = np.log(5e-2)
    mtrue[20:35] = np.log(3e-3)
    mtrue[35:40] = np.log(1e-2)
    m0 = np.ones(M.nC) * np.log(Ks)

    # Create some synthetic data and fields
    stdev = 0.02  # The standard deviation for the noise
    Hs = prob.fields(mtrue)
    survey.makeSyntheticData(mtrue, std=stdev, f=Hs, force=True)

    # Setup a pretty standard inversion
    reg = Regularization.Tikhonov(M, alpha_s=1e-1)
    dmis = DataMisfit.l2_DataMisfit(survey)
    opt = Optimization.InexactGaussNewton(maxIter=20, maxIterCG=10)
    invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
    beta = Directives.BetaSchedule(coolingFactor=4)
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e2)
    target = Directives.TargetMisfit()
    dir_list = [beta, betaest, target]
    inv = Inversion.BaseInversion(invProb, directiveList=dir_list)

    mopt = inv.run(m0)

    Hs_opt = prob.fields(mopt)

    if plotIt:
        plt.figure(figsize=(14, 9))

        ax = plt.subplot(121)
        plt.semilogx(np.exp(np.c_[mopt, mtrue]), M.gridCC)
        plt.xlabel('Saturated Hydraulic Conductivity, $K_s$')
        plt.ylabel('Depth, cm')
        plt.semilogx([10**-3.9] * len(locs), locs, 'ro')
        plt.legend(('$m_{rec}$', '$m_{true}$', 'Data locations'), loc=4)

        ax = plt.subplot(222)
        mesh2d = Mesh.TensorMesh([prob.timeMesh.hx / 60, prob.mesh.hx], '0N')
        sats = [theta_fun(_) for _ in Hs]
        clr = mesh2d.plotImage(np.c_[sats][1:, :], ax=ax)
        cmap0 = matplotlib.cm.RdYlBu_r
        clr[0].set_cmap(cmap0)
        c = plt.colorbar(clr[0])
        c.set_label('Saturation $\\theta$')
        plt.xlabel('Time, minutes')
        plt.ylabel('Depth, cm')
        plt.title('True saturation over time')

        ax = plt.subplot(224)
        mesh2d = Mesh.TensorMesh([prob.timeMesh.hx / 60, prob.mesh.hx], '0N')
        sats = [theta_fun(_) for _ in Hs_opt]
        clr = mesh2d.plotImage(np.c_[sats][1:, :], ax=ax)
        cmap0 = matplotlib.cm.RdYlBu_r
        clr[0].set_cmap(cmap0)
        c = plt.colorbar(clr[0])
        c.set_label('Saturation $\\theta$')
        plt.xlabel('Time, minutes')
        plt.ylabel('Depth, cm')
        plt.title('Recovered saturation over time')

        plt.tight_layout()
Example #10
0
def run(plotIt=True):
    """
        FLOW: Richards: 1D: Inversion
        =============================

        The example shows an inversion of Richards equation in 1D with a
        heterogeneous hydraulic conductivity function.

        The haverkamp model is used with the same parameters as Celia1990_
        the boundary and initial conditions are also the same. The simulation
        domain is 40cm deep and is run for an hour with an exponentially
        increasing time step that has a maximum of one minute. The general
        setup of the experiment is an infiltration front that advances
        downward through the model over time.

        The model chosen is the saturated hydraulic conductivity inside
        the hydraulic conductivity function (using haverkamp). The initial
        model is chosen to be the background (1e-3 cm/s). The saturation data
        has 2% random Gaussian noise added.

        The figure shows the recovered saturated hydraulic conductivity
        next to the true model. The other two figures show the saturation
        field for the entire simulation for the true and recovered models.

        Rowan Cockett - 21/12/2016

        .. _Celia1990: http://www.webpages.uidaho.edu/ch/papers/Celia.pdf
    """

    M = Mesh.TensorMesh([np.ones(40)], x0='N')
    M.setCellGradBC('dirichlet')
    # We will use the haverkamp empirical model with parameters from Celia1990
    k_fun, theta_fun = Richards.Empirical.haverkamp(M,
                                                    A=1.1750e+06,
                                                    gamma=4.74,
                                                    alpha=1.6110e+06,
                                                    theta_s=0.287,
                                                    theta_r=0.075,
                                                    beta=3.96)

    # Here we are making saturated hydraulic conductivity
    # an exponential mapping to the model (defined below)
    k_fun.KsMap = Maps.ExpMap(nP=M.nC)

    # Setup the boundary and initial conditions
    bc = np.array([-61.5, -20.7])
    h = np.zeros(M.nC) + bc[0]
    prob = Richards.RichardsProblem(M,
                                    hydraulic_conductivity=k_fun,
                                    water_retention=theta_fun,
                                    boundary_conditions=bc,
                                    initial_conditions=h,
                                    do_newton=False,
                                    method='mixed',
                                    debug=False)
    prob.timeSteps = [(5, 25, 1.1), (60, 40)]

    # Create the survey
    locs = -np.arange(2, 38, 4.)
    times = np.arange(30, prob.timeMesh.vectorCCx[-1], 60)
    rxSat = Richards.SaturationRx(locs, times)
    survey = Richards.RichardsSurvey([rxSat])
    survey.pair(prob)

    # Create a simple model for Ks
    Ks = 1e-3
    mtrue = np.ones(M.nC) * np.log(Ks)
    mtrue[15:20] = np.log(5e-2)
    mtrue[20:35] = np.log(3e-3)
    mtrue[35:40] = np.log(1e-2)
    m0 = np.ones(M.nC) * np.log(Ks)

    # Create some synthetic data and fields
    stdev = 0.02  # The standard deviation for the noise
    Hs = prob.fields(mtrue)
    survey.makeSyntheticData(mtrue, std=stdev, f=Hs, force=True)

    # Setup a pretty standard inversion
    reg = Regularization.Tikhonov(M, alpha_s=1e-1)
    dmis = DataMisfit.l2_DataMisfit(survey)
    opt = Optimization.InexactGaussNewton(maxIter=20, maxIterCG=10)
    invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
    beta = Directives.BetaSchedule(coolingFactor=4)
    betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e2)
    target = Directives.TargetMisfit()
    dir_list = [beta, betaest, target]
    inv = Inversion.BaseInversion(invProb, directiveList=dir_list)

    mopt = inv.run(m0)

    Hs_opt = prob.fields(mopt)

    if plotIt:
        plt.figure(figsize=(14, 9))

        ax = plt.subplot(121)
        plt.semilogx(np.exp(np.c_[mopt, mtrue]), M.gridCC)
        plt.xlabel('Saturated Hydraulic Conductivity, $K_s$')
        plt.ylabel('Depth, cm')
        plt.semilogx([10**-3.9] * len(locs), locs, 'ro')
        plt.legend(('$m_{rec}$', '$m_{true}$', 'Data locations'), loc=4)

        ax = plt.subplot(222)
        mesh2d = Mesh.TensorMesh([prob.timeMesh.hx / 60, prob.mesh.hx], '0N')
        sats = [theta_fun(_) for _ in Hs]
        clr = mesh2d.plotImage(np.c_[sats][1:, :], ax=ax)
        cmap0 = matplotlib.cm.RdYlBu_r
        clr[0].set_cmap(cmap0)
        c = plt.colorbar(clr[0])
        c.set_label('Saturation $\\theta$')
        plt.xlabel('Time, minutes')
        plt.ylabel('Depth, cm')
        plt.title('True saturation over time')

        ax = plt.subplot(224)
        mesh2d = Mesh.TensorMesh([prob.timeMesh.hx / 60, prob.mesh.hx], '0N')
        sats = [theta_fun(_) for _ in Hs_opt]
        clr = mesh2d.plotImage(np.c_[sats][1:, :], ax=ax)
        cmap0 = matplotlib.cm.RdYlBu_r
        clr[0].set_cmap(cmap0)
        c = plt.colorbar(clr[0])
        c.set_label('Saturation $\\theta$')
        plt.xlabel('Time, minutes')
        plt.ylabel('Depth, cm')
        plt.title('Recovered saturation over time')

        plt.tight_layout()
Example #11
0
def run(plotIt=True):
    """
        FLOW: Richards: 1D: Forward Simulation
        ======================================

        The example shows simulation of Richards equation in 1D with a
        heterogeneous hydraulic conductivity function.

        The haverkamp model is used with the same parameters as Celia1990_
        the boundary and initial conditions are also the same. The simulation
        domain is 40cm deep and is run for an hour with an exponentially
        increasing time step that has a maximum of one minute. The general
        setup of the experiment is an infiltration front that advances
        downward through the model over time.

        Figure (a) shows the heterogeneous saturated hydraulic conductivity
        parameter and the location of the data collection, which happens every
        minute from 30 seconds into the simulation. Note that the simulation
        mesh and the data locations are not aligned, and linear interpolation
        is used to collect the data. The points are sampled in pressure head
        and then transformed to saturation using the haverkamp model for
        the water retention curve.

        Figure (b) shows the data collected from the simulation. No noise is
        added to the data at this time. The various data locations register
        the infiltration event through increasing saturation as the front moves
        past the receiver. Notice that the slope of the curves are not equal
        as the hydraulic conductivity function is heterogeneous.

        Figure (c) shows the saturation field over the entire experiment. Here
        you can see that the timestep is not constant over time (5 seconds
        at the start of the simulation, 60 seconds at the end). You can also
        see the effect of the highly conductive layer in the model between
        20 and 25 cm depth. The water drains straight through the conductive
        unit and piles up on the other side - advancing the fluid front
        faster than the other layers.

        Rowan Cockett - 21/12/2016

        .. _Celia1990: http://www.webpages.uidaho.edu/ch/papers/Celia.pdf
    """

    M = Mesh.TensorMesh([np.ones(40)], x0='N')
    M.setCellGradBC('dirichlet')
    # We will use the haverkamp empirical model with parameters from Celia1990
    k_fun, theta_fun = Richards.Empirical.haverkamp(M,
                                                    A=1.1750e+06,
                                                    gamma=4.74,
                                                    alpha=1.6110e+06,
                                                    theta_s=0.287,
                                                    theta_r=0.075,
                                                    beta=3.96)

    # Here we are making saturated hydraulic conductivity
    # an exponential mapping to the model (defined below)
    k_fun.KsMap = Maps.ExpMap(nP=M.nC)

    # Setup the boundary and initial conditions
    bc = np.array([-61.5, -20.7])
    h = np.zeros(M.nC) + bc[0]
    prob = Richards.RichardsProblem(M,
                                    hydraulic_conductivity=k_fun,
                                    water_retention=theta_fun,
                                    boundary_conditions=bc,
                                    initial_conditions=h,
                                    do_newton=False,
                                    method='mixed',
                                    debug=False)
    prob.timeSteps = [(5, 25, 1.1), (60, 40)]

    # Create the survey
    locs = -np.arange(2, 38, 4.)
    times = np.arange(30, prob.timeMesh.vectorCCx[-1], 60)
    rxSat = Richards.SaturationRx(locs, times)
    survey = Richards.RichardsSurvey([rxSat])
    survey.pair(prob)

    # Create a simple model for Ks
    Ks = 1e-3
    mtrue = np.ones(M.nC) * np.log(Ks)
    mtrue[15:20] = np.log(5e-2)
    mtrue[20:35] = np.log(3e-3)
    mtrue[35:40] = np.log(1e-2)

    # Create some synthetic data and fields
    Hs = prob.fields(mtrue)
    data = survey.makeSyntheticData(mtrue, std=0, f=Hs, force=True)

    if plotIt:
        plt.figure(figsize=(14, 9))

        plt.subplot(221)
        plt.plot(np.log10(np.exp(mtrue)), M.gridCC)
        plt.title('(a) True model and data locations')
        plt.ylabel('Depth, cm')
        plt.xlabel('Hydraulic conductivity, $log_{10}(K_s)$')
        plt.plot([-3.25] * len(locs), locs, 'ro')
        plt.legend(('True model', 'Data locations'))

        plt.subplot(222)
        plt.plot(times / 60, data.reshape((-1, len(locs))))
        plt.title('(b) True data over time at all depths')
        plt.xlabel('Time, minutes')
        plt.ylabel('Saturation')

        ax = plt.subplot(212)
        mesh2d = Mesh.TensorMesh([prob.timeMesh.hx / 60, prob.mesh.hx], '0N')
        sats = [theta_fun(_) for _ in Hs]
        clr = mesh2d.plotImage(np.c_[sats][1:, :], ax=ax)
        cmap0 = matplotlib.cm.RdYlBu_r
        clr[0].set_cmap(cmap0)
        c = plt.colorbar(clr[0])
        c.set_label('Saturation $\\theta$')
        plt.xlabel('Time, minutes')
        plt.ylabel('Depth, cm')
        plt.title('(c) Saturation over time')

        plt.tight_layout()