Example #1
0
def get_facet_areas(mesh):
    """
    Compute area of each facet of `mesh`.

    The facet areas are stored as a HDiv
    trace field.

    Note that the plus sign is arbitrary
    and could equally well be chosen as minus.

    :arg mesh: the input mesh to do computations on

    :rtype: firedrake.function.Function facet_areas with
        facet area data
    """
    HDivTrace = firedrake.FunctionSpace(mesh, "HDiv Trace", 0)
    v = firedrake.TestFunction(HDivTrace)
    u = firedrake.TrialFunction(HDivTrace)
    facet_areas = firedrake.Function(HDivTrace, name="Facet areas")
    mass_term = v("+") * u("+") * ufl.dS + v * u * ufl.ds
    rhs = v("+") * ufl.FacetArea(mesh) * ufl.dS + v * ufl.FacetArea(mesh) * ufl.ds
    sp = {
        "snes_type": "ksponly",
        "ksp_type": "preonly",
        "pc_type": "jacobi",
    }
    firedrake.solve(mass_term == rhs, facet_areas, solver_parameters=sp)
    return facet_areas
Example #2
0
def compressible_eady_initial_v(state, theta0, rho0, v):
    f = state.parameters.f
    cp = state.parameters.cp

    # exner function
    Vr = rho0.function_space()
    Pi = Function(Vr).interpolate(thermodynamics.pi(state.parameters, rho0, theta0))

    # get Pi gradient
    Vu = state.spaces("HDiv")
    g = TrialFunction(Vu)
    wg = TestFunction(Vu)

    n = FacetNormal(state.mesh)

    a = inner(wg, g)*dx
    L = -div(wg)*Pi*dx + inner(wg, n)*Pi*ds_tb
    pgrad = Function(Vu)
    solve(a == L, pgrad)

    # get initial v
    m = TrialFunction(Vr)
    phi = TestFunction(Vr)

    a = phi*f*m*dx
    L = phi*cp*theta0*pgrad[0]*dx
    solve(a == L, v)

    return v
Example #3
0
def _newton_solve(z, E, scale, tolerance=1e-6, armijo=1e-4, max_iterations=50):
    F = derivative(E, z)
    H = derivative(F, z)

    Q = z.function_space()
    bc = firedrake.DirichletBC(Q, 0, 'on_boundary')
    p = firedrake.Function(Q)
    for iteration in range(max_iterations):
        firedrake.solve(H == -F, p, bc,
            solver_parameters={'ksp_type': 'preonly', 'pc_type': 'lu'})

        dE_dp = assemble(action(F, p))
        α = 1.0
        E0 = assemble(E)
        Ez = assemble(replace(E, {z: z + firedrake.Constant(α) * p}))
        while (Ez > E0 + armijo * α * dE_dp) or np.isnan(Ez):
            α /= 2
            Ez = assemble(replace(E, {z: z + firedrake.Constant(α) * p}))

        z.assign(z + firedrake.Constant(α) * p)
        if abs(dE_dp) < tolerance * assemble(scale):
            return z

    raise ValueError("Newton solver failed to converge after {0} iterations"
                     .format(max_iterations))
def test_LinearSolver_solve_prior_generating(fs, A, b, fc, od, params, interp,
                                             A_numpy, cov, K, ls):
    "test the function to solve the prior of the generating process"

    ls.set_params(params)
    m_eta, C_eta = ls.solve_prior_generating()

    m_eta2, C_eta2 = solve_prior_generating(A, b, fc, od, params)

    rho = np.exp(params[0])

    C_expected = np.linalg.solve(A_numpy, interp)
    C_expected = np.dot(cov, C_expected)
    C_expected = np.linalg.solve(A_numpy, C_expected)
    C_expected = rho**2 * np.dot(interp.T, C_expected) + K

    u = Function(fs)
    solve(A, u, b)
    m_expected = rho * np.dot(interp.T, u.vector().gather())

    if COMM_WORLD.rank == 0:
        assert_allclose(m_expected, m_eta, atol=1.e-10)
        assert_allclose(C_expected, C_eta, atol=1.e-10)
        assert_allclose(m_expected, m_eta2, atol=1.e-10)
        assert_allclose(C_expected, C_eta2, atol=1.e-10)
    else:
        assert m_eta.shape == (0, )
        assert C_eta.shape == (0, 0)
        assert m_eta2.shape == (0, )
        assert C_eta2.shape == (0, 0)

    fc.destroy()
Example #5
0
    def gauss_newton_energy_norm(self, q):
        r"""Compute the energy norm of a field w.r.t. the Gauss-Newton operator

        The energy norm of a field :math:`q` w.r.t. the Gauss-Newton operator
        :math:`H` can be computed using one fewer linear solve than if we were
        to calculate the action of :math:`H\cdot q` on :math:`q`. This saves
        computation when using the conjugate gradient method to solve for the
        search direction.
        """
        u, p = self.state, self.parameter

        dE = derivative(self._E, u)
        dR = derivative(self._R, p)
        dF_du, dF_dp = self._dF_du, derivative(self._F, p)

        v = firedrake.Function(u.function_space())
        firedrake.solve(dF_du == action(dF_dp, q),
                        v,
                        self._bc,
                        solver_parameters=self._solver_params,
                        form_compiler_parameters=self._fc_params)

        return self._assemble(
            firedrake.energy_norm(derivative(dE, u), v) +
            firedrake.energy_norm(derivative(dR, p), q))
def test_LinearSolver_solve_prior(fs, A, b, fc, od, interp, cov, A_numpy, ls):
    "test solve_conditioned_FEM"

    mu, Cu = ls.solve_prior()

    mu2, Cu2 = solve_prior(A, b, fc, od)

    C_expected = np.linalg.solve(A_numpy, interp)
    C_expected = np.dot(cov, C_expected)
    C_expected = np.linalg.solve(A_numpy, C_expected)
    C_expected = np.dot(interp.T, C_expected)

    u = Function(fs)
    solve(A, u, b)
    m_expected = np.dot(interp.T, u.vector().gather())

    if COMM_WORLD.rank == 0:
        assert_allclose(m_expected, mu, atol=1.e-10)
        assert_allclose(C_expected, Cu, atol=1.e-10)
        assert_allclose(m_expected, mu2, atol=1.e-10)
        assert_allclose(C_expected, Cu2, atol=1.e-10)
    else:
        assert mu.shape == (0, )
        assert Cu.shape == (0, 0)
        assert mu2.shape == (0, )
        assert Cu2.shape == (0, 0)

    fc.destroy()
Example #7
0
    def _ad_convert_type(self, value, options=None):
        from firedrake import Function, TrialFunction, TestFunction, assemble

        options = {} if options is None else options
        riesz_representation = options.get("riesz_representation", "l2")

        if riesz_representation == "l2":
            return Function(self.function_space(), val=value)

        elif riesz_representation == "L2":
            ret = Function(self.function_space())
            u = TrialFunction(self.function_space())
            v = TestFunction(self.function_space())
            M = assemble(firedrake.inner(u, v) * firedrake.dx)
            firedrake.solve(M, ret, value)
            return ret

        elif riesz_representation == "H1":
            ret = Function(self.function_space())
            u = TrialFunction(self.function_space())
            v = TestFunction(self.function_space())
            M = assemble(
                firedrake.inner(u, v) * firedrake.dx +
                firedrake.inner(firedrake.grad(u), firedrake.grad(v)) *
                firedrake.dx)
            firedrake.solve(M, ret, value)
            return ret

        elif callable(riesz_representation):
            return riesz_representation(value)

        else:
            raise NotImplementedError("Unknown Riesz representation %s" %
                                      riesz_representation)
Example #8
0
def eady_initial_v(state, p0, v):
    f = state.parameters.f
    x, y, z = SpatialCoordinate(state.mesh)

    # get pressure gradient
    Vu = state.spaces("HDiv")
    g = TrialFunction(Vu)
    wg = TestFunction(Vu)

    n = FacetNormal(state.mesh)

    a = inner(wg, g)*dx
    L = -div(wg)*p0*dx + inner(wg, n)*p0*ds_tb
    pgrad = Function(Vu)
    solve(a == L, pgrad)

    # get initial v
    Vp = p0.function_space()
    phi = TestFunction(Vp)
    m = TrialFunction(Vp)

    a = f*phi*m*dx
    L = phi*pgrad[0]*dx
    solve(a == L, v)

    return v
Example #9
0
    def _advect(self, dt, E, u, w, h, s, E_inflow, E_surface):
        Q = E.function_space()
        φ, ψ = firedrake.TrialFunction(Q), firedrake.TestFunction(Q)

        U = firedrake.as_vector((u[0], u[1], w))
        flux_cells = -φ * inner(U, grad(ψ)) * h * dx

        mesh = Q.mesh()
        ν = facet_normal_2(mesh)
        outflow = firedrake.max_value(inner(u, ν), 0)
        inflow = firedrake.min_value(inner(u, ν), 0)

        flux_outflow = φ * ψ * outflow * h * ds_v + \
                       φ * ψ * firedrake.max_value(-w, 0) * h * ds_b + \
                       φ * ψ * firedrake.max_value(+w, 0) * h * ds_t
        F = φ * ψ * h * dx + dt * (flux_cells + flux_outflow)

        flux_inflow = -E_inflow * ψ * inflow * h * ds_v \
                      -E_surface * ψ * firedrake.min_value(-w, 0) * h * ds_b \
                      -E_surface * ψ * firedrake.min_value(+w, 0) * h * ds_t
        A = E * ψ * h * dx + dt * flux_inflow

        solver_parameters = {'ksp_type': 'preonly', 'pc_type': 'lu'}
        degree_E = E.ufl_element().degree()
        degree_u = u.ufl_element().degree()
        degree = (3 * degree_E[0] + degree_u[0], 2 * degree_E[1] + degree_u[1])
        form_compiler_parameters = {'quadrature_degree': degree}
        firedrake.solve(F == A,
                        E,
                        solver_parameters=solver_parameters,
                        form_compiler_parameters=form_compiler_parameters)
Example #10
0
 def solve(self):
     super().solve()
     # self.solver.solve()
     fd.solve(self.F == 0,
              self.solution,
              bcs=self.bcs,
              solver_parameters=self.params,
              nullspace=self.nsp)
Example #11
0
def solve_something(mesh):
    V = fd.FunctionSpace(mesh, "CG", 1)
    u = fd.Function(V)
    v = fd.TestFunction(V)

    x, y = fd.SpatialCoordinate(mesh)
    # f = fd.sin(x) * fd.sin(y) + x**2 + y**2
    # uex = x**4 * y**4
    uex = fd.sin(x) * fd.sin(y)  #*(x*y)**3
    # def source(xs, ys):
    #     return 1/((x-xs)**2+(y-ys)**2 + 0.1)
    # uex = source(0, 0)
    uex = uex - fd.assemble(uex * fd.dx) / fd.assemble(1 * fd.dx(domain=mesh))
    # f = fd.conditional(fd.ge(abs(x)-abs(y), 0), 1, 0)
    from firedrake import inner, grad, dx, ds, div, sym
    eps = fd.Constant(0.0)
    f = uex - div(grad(uex)) + eps * div(grad(div(grad(uex))))
    n = fd.FacetNormal(mesh)
    g = inner(grad(uex), n)
    g1 = inner(grad(div(grad(uex))), n)
    g2 = div(grad(uex))
    # F = 0.1 * inner(u, v) * dx + inner(grad(u), grad(v)) * dx + inner(grad(grad(u)), grad(grad(v))) * dx - f * v * dx - g * v * ds
    F = inner(u, v) * dx + inner(grad(u),
                                 grad(v)) * dx - f * v * dx - g * v * ds
    F += eps * inner(div(grad(u)), div(grad(v))) * dx
    F += eps * g1 * v * ds
    F -= eps * g2 * inner(grad(v), n) * ds
    # f = -div(grad(uex))
    # F = inner(grad(u), grad(v)) * dx - f * v * dx

    # bc = fd.DirichletBC(V, uex, "on_boundary")
    bc = None
    fd.solve(F == 0,
             u,
             bcs=bc,
             solver_parameters={
                 "ksp_type": "cg",
                 "ksp_atol": 1e-13,
                 "ksp_rtol": 1e-13,
                 "ksp_dtol": 1e-13,
                 "ksp_stol": 1e-13,
                 "pc_type": "jacobi",
                 "pc_factor_mat_solver_type": "mumps",
                 "snes_type": "ksponly",
                 "ksp_converged_reason": None
             })
    print("||u-uex||             =", fd.norm(u - uex))
    print("||grad(u-uex)||       =", fd.norm(grad(u - uex)))
    print("||grad(grad(u-uex))|| =", fd.norm(grad(grad(u - uex))))
    err = fd.Function(
        fd.TensorFunctionSpace(mesh, "DG",
                               V.ufl_element().degree() - 2)).interpolate(
                                   grad(grad(u - uex)))
    # err = fd.Function(fd.FunctionSpace(mesh, "DG", V.ufl_element().degree())).interpolate(u-uex)
    fd.File(outdir + "sln.pvd").write(u)
    fd.File(outdir + "err.pvd").write(err)
Example #12
0
def incompressible_hydrostatic_balance(state, b0, p0, top=False, params=None):

    # get F
    Vu = state.spaces("HDiv")
    Vv = FunctionSpace(state.mesh, Vu.ufl_element()._elements[-1])
    v = TrialFunction(Vv)
    w = TestFunction(Vv)

    if top:
        bstring = "top"
    else:
        bstring = "bottom"

    bcs = [DirichletBC(Vv, 0.0, bstring)]

    a = inner(w, v) * dx
    L = inner(state.k, w) * b0 * dx
    F = Function(Vv)

    solve(a == L, F, bcs=bcs)

    # define mixed function space
    VDG = state.spaces("DG")
    WV = (Vv) * (VDG)

    # get pprime
    v, pprime = TrialFunctions(WV)
    w, phi = TestFunctions(WV)

    bcs = [DirichletBC(WV[0], zero(), bstring)]

    a = (inner(w, v) + div(w) * pprime + div(v) * phi) * dx
    L = phi * div(F) * dx
    w1 = Function(WV)

    if params is None:
        params = {
            'ksp_type': 'gmres',
            'pc_type': 'fieldsplit',
            'pc_fieldsplit_type': 'schur',
            'pc_fieldsplit_schur_fact_type': 'full',
            'pc_fieldsplit_schur_precondition': 'selfp',
            'fieldsplit_1_ksp_type': 'preonly',
            'fieldsplit_1_pc_type': 'gamg',
            'fieldsplit_1_mg_levels_pc_type': 'bjacobi',
            'fieldsplit_1_mg_levels_sub_pc_type': 'ilu',
            'fieldsplit_0_ksp_type': 'richardson',
            'fieldsplit_0_ksp_max_it': 4,
            'ksp_atol': 1.e-08,
            'ksp_rtol': 1.e-08
        }

    solve(a == L, w1, bcs=bcs, solver_parameters=params)

    v, pprime = w1.split()
    p0.project(pprime)
Example #13
0
 def update_search_direction(self):
     r"""Set the search direction to be the inverse of the mass matrix times
     the gradient of the objective"""
     q, dJ = self.search_direction, self.gradient
     Q = q.function_space()
     M = firedrake.TrialFunction(Q) * firedrake.TestFunction(Q) * dx
     firedrake.solve(M == -dJ,
                     q,
                     solver_parameters=self._solver_params,
                     form_compiler_parameters=self._fc_params)
Example #14
0
 def update_adjoint_state(self):
     r"""Update the adjoint state for new values of the observable state and
     parameters so that we can calculate derivatives"""
     λ = self.adjoint_state
     L = adjoint(self._dF_du)
     firedrake.solve(L == -self._dE,
                     λ,
                     self._bc,
                     solver_parameters=self._solver_params,
                     form_compiler_parameters=self._fc_params)
Example #15
0
def solvevdisp(mesh,bdryids,deltah):
    P1 = FunctionSpace(mesh, "CG", 1)
    r = TrialFunction(P1)
    s = TestFunction(P1)
    a = inner(grad(r), grad(s)) * dx   # note natural b.c. on outflow
    L = inner(Constant(0.0), s) * dx
    # WARNING: top must go *first* so closed top gets zero; is this documented behavior?
    bcs = [ DirichletBC(P1, deltah, bdryids['top']),
            DirichletBC(P1, Constant(0.0), (bdryids['base'],bdryids['inflow'])) ]
    rsoln = Function(P1)
    solve(a == L, rsoln, bcs=bcs, options_prefix='vd', solver_parameters={})
    return rsoln
Example #16
0
 def solve(self):
     super().solve()
     self.failed_to_solve = False
     u_old = self.solution.copy(deepcopy=True)
     try:
         fd.solve(self.F == 0,
                  self.solution,
                  bcs=self.bcs,
                  solver_parameters=self.params)
     except fd.ConvergenceError:
         self.failed_to_solve = True
         self.solution.assign(u_old)
Example #17
0
    def solve(self, dt, h0, a, u, h_inflow=None):
        r"""Propagate the thickness forward by one timestep

        This function uses the implicit Euler timestepping scheme to avoid
        the stability issues associated to using continuous finite elements
        for advection-type equations. The implicit Euler scheme is stable
        for any timestep; you do not need to ensure that the CFL condition
        is satisfied in order to get an answer. Nonetheless, keeping the
        timestep within the CFL bound is a good idea for accuracy.

        Parameters
        ----------
        dt : float
            Timestep
        h0 : firedrake.Function
            Initial ice thickness
        a : firedrake.Function
            Sum of accumulation and melt rates
        u : firedrake.Function
            Ice velocity
        h_inflow : firedrake.Function
            Thickness of the upstream ice that advects into the domain

        Returns
        -------
        h : firedrake.Function
            Ice thickness at `t + dt`
        """
        grad, ds = self.grad, self.ds

        h_inflow = h_inflow if h_inflow is not None else h0

        Q = h0.function_space()
        h, φ = firedrake.TrialFunction(Q), firedrake.TestFunction(Q)

        n = self.facet_normal(Q.mesh())
        outflow = firedrake.max_value(inner(u, n), 0)
        inflow = firedrake.min_value(inner(u, n), 0)

        flux_cells = -h * inner(u, grad(φ)) * dx
        flux_out = h * φ * outflow * ds
        F = h * φ * dx + dt * (flux_cells + flux_out)

        accumulation = a * φ * dx
        flux_in = -h_inflow * φ * inflow * ds
        A = h0 * φ * dx + dt * (accumulation + flux_in)

        h = h0.copy(deepcopy=True)
        solver_parameters = {'ksp_type': 'preonly', 'pc_type': 'lu'}
        firedrake.solve(F == A, h, solver_parameters=solver_parameters)

        return h
Example #18
0
    def solvePDE(self):
        """Solve the heat equation and evaluate the objective function."""
        self.J = 0
        t = 0
        self.u.assign(self.u0)
        self.J += fd.assemble(self.dt * (self.u - self.u_t(t))**2 * self.dx)

        for ii in range(10):
            self.u_old.assign(self.u)
            fd.solve(self.F(t, self.u, self.u_old) == 0, self.u, bcs=self.bcs)
            t += self.dt
            self.J += fd.assemble(self.dt * (self.u - self.u_t(t))**2 *
                                  self.dx)
Example #19
0
    def solve(self, dt, h0, a, u, h_inflow=None):
        r"""Propagate the thickness forward by one timestep

        This function uses an implicit second-order Taylor-Galerkin (also
        known as Lax-Wendroff) scheme to solve the conservative advection
        equation for ice thickness.

        Parameters
        ----------
        dt : float
            Timestep
        h0 : firedrake.Function
            Initial ice thickness
        a : firedrake.Function
            Sum of accumulation and melt rates
        u : firedrake.Function
            Ice velocity
        h_inflow : firedrake.Function
            Thickness of the upstream ice that advects into the domain

        Returns
        -------
        h : firedrake.Function
            Ice thickness at `t + dt`
        """
        grad, div, ds = self.grad, self.div, self.ds

        h_inflow = h_inflow if h_inflow is not None else h0

        Q = h0.function_space()
        h, φ = firedrake.TrialFunction(Q), firedrake.TestFunction(Q)

        n = self.facet_normal(Q.mesh())
        outflow = firedrake.max_value(inner(u, n), 0)
        inflow = firedrake.min_value(inner(u, n), 0)

        flux_cells = -h * inner(u, grad(φ)) * dx
        flux_cells_lax = 0.5 * dt * div(h * u) * inner(u, grad(φ)) * dx
        flux_out = (h - 0.5 * dt * div(h * u)) * φ * outflow * ds
        F = h * φ * dx + dt * (flux_cells + flux_cells_lax + flux_out)

        accumulation = a * φ * dx
        flux_in = -(h_inflow - 0.5 * dt * div(h0 * u)) * φ * inflow * ds
        A = h0 * φ * dx + dt * (accumulation + flux_in)

        h = h0.copy(deepcopy=True)
        solver_parameters = {'ksp_type': 'preonly', 'pc_type': 'lu'}
        firedrake.solve(F == A, h, solver_parameters=solver_parameters)

        return h
Example #20
0
 def solve(self, q, f, dirichlet_ids=[], **kwargs):
     u = firedrake.Function(f.function_space())
     L = self.action(q, u, f)
     F = firedrake.derivative(L, u)
     V = u.function_space()
     bc = firedrake.DirichletBC(V, firedrake.Constant(0), dirichlet_ids)
     firedrake.solve(F == 0,
                     u,
                     bc,
                     solver_parameters={
                         'ksp_type': 'preonly',
                         'pc_type': 'lu'
                     })
     return u
Example #21
0
    def update_search_direction(self):
        r"""Solve the Gauss-Newton system for the new search direction using
        the preconditioned conjugate gradient method"""
        p, q, dJ = self.parameter, self.search_direction, self.gradient

        dR = derivative(self.regularization, self.parameter)
        Q = q.function_space()
        M = firedrake.TrialFunction(Q) * firedrake.TestFunction(Q) * dx + \
            derivative(dR, p)

        # Compute the preconditioned residual
        z = firedrake.Function(Q)
        firedrake.solve(M == -dJ,
                        z,
                        solver_parameters=self._solver_params,
                        form_compiler_parameters=self._fc_params)

        # This variable is a search direction for a search direction, which
        # is definitely not confusing at all.
        s = z.copy(deepcopy=True)
        q *= 0.0

        old_cost = np.inf
        while True:
            z_mnorm = self._assemble(firedrake.energy_norm(M, z))
            s_hnorm = self.gauss_newton_energy_norm(s)
            α = z_mnorm / s_hnorm

            δz = firedrake.Function(Q)
            g = self.gauss_newton_mult(s)
            firedrake.solve(M == g,
                            δz,
                            solver_parameters=self._solver_params,
                            form_compiler_parameters=self._fc_params)

            q += α * s
            z -= α * δz

            β = self._assemble(firedrake.energy_norm(M, z)) / z_mnorm
            s *= β
            s += z

            energy_norm = self.gauss_newton_energy_norm(q)
            cost = 0.5 * energy_norm + self._assemble(action(dJ, q))

            if (abs(old_cost - cost) /
                (0.5 * energy_norm) < self._search_tolerance):
                return

            old_cost = cost
def solve_firedrake(q, kappa0, kappa1):

    x = firedrake.SpatialCoordinate(mesh)
    f = x[0]

    u = firedrake.Function(V)
    bcs = [firedrake.DirichletBC(V, firedrake.Constant(0.0), "on_boundary")]

    inner, grad, dx = ufl.inner, ufl.grad, ufl.dx
    JJ = 0.5 * inner(kappa0 * grad(u), grad(u)) * dx - q * kappa1 * f * u * dx
    v = firedrake.TestFunction(V)
    F = firedrake.derivative(JJ, u, v)
    firedrake.solve(F == 0, u, bcs=bcs)
    return u
Example #23
0
    def step(self, dt):

        self.dt.assign(dt)

        try:

            # Solve for potential
            firedrake.solve(
                self.F == 0,
                self.model.phi,
                self.model.d_bcs,
                J=self.J,
                solver_parameters={
                    "snes_monitor": None,
                    "snes_view": None,
                    "ksp_monitor_true_residual": None,
                    "snes_converged_reason": None,
                    "ksp_converged_reason": None,
                },
            )  # , solver_parameters = self.model.newton_params)

            # Derive values from the new potential
            self.model.update_phi()
        except:

            # Try the solve again with a lower relaxation param
            firedrake.solve(
                self.F == 0,
                self.model.phi,
                self.model.d_bcs,
                J=self.J,
                solver_parameters={
                    "snes_type": "newtonls",
                    "snes_rtol": 5e-11,
                    "snes_atol": 5e-10,
                    "pc_type": "lu",
                    "snes_max_it": 50,
                    "mat_type": "aij",
                },
            )  # , solver_parameters = self.model.newton_params)

            # Derive values from potential
            self.model.update_phi()

            # Didn't converge with standard params
            return False

        # Did converge with standard params
        return True
Example #24
0
def distance_function(mesh,
                      boundary_ids="on_boundary",
                      order=1,
                      eps=fd.Constant(0.1)):
    V = fd.FunctionSpace(mesh, "CG", order)
    u = fd.Function(V)
    v = fd.TestFunction(V)
    a = eps * fd.inner(fd.grad(u), fd.grad(v)) * fd.dx \
        + fd.inner(fd.grad(u), fd.grad(u)) * v * fd.dx \
        - v * fd.dx
    fd.solve(a == 0, u, bcs=fd.DirichletBC(V, 0, boundary_ids))
    return u

    def get_nullspace(self, V):
        return self.inner.get_nullspace(V)
Example #25
0
def form2indicator(F):
    """
    Multiply throughout in a form and
    assemble as a cellwise error
    indicator.

    :arg F: the form
    """
    mesh = F.ufl_domain()
    P0 = firedrake.FunctionSpace(mesh, "DG", 0)
    p0test = firedrake.TestFunction(P0)
    indicator = firedrake.Function(P0)

    # Contributions from surface integrals
    flux_terms = 0
    integrals = F.integrals_by_type("exterior_facet")
    if len(integrals) > 0:
        for integral in integrals:
            ds = firedrake.ds(integral.subdomain_id())
            flux_terms += p0test * integral.integrand() * ds
    integrals = F.integrals_by_type("interior_facet")
    if len(integrals) > 0:
        for integral in integrals:
            dS = firedrake.dS(integral.subdomain_id())
            flux_terms += p0test("+") * integral.integrand() * dS
            flux_terms += p0test("-") * integral.integrand() * dS
    if flux_terms != 0:
        dx = firedrake.dx
        mass_term = firedrake.TrialFunction(P0) * p0test * dx
        sp = {
            "snes_type": "ksponly",
            "ksp_type": "preonly",
            "pc_type": "jacobi",
        }
        firedrake.solve(mass_term == flux_terms,
                        indicator,
                        solver_parameters=sp)

    # Contributions from volume integrals
    cell_terms = 0
    integrals = F.integrals_by_type("cell")
    if len(integrals) > 0:
        for integral in integrals:
            dx = firedrake.dx(integral.subdomain_id())
            cell_terms += p0test * integral.integrand() * dx
    indicator += firedrake.assemble(cell_terms)

    return indicator
Example #26
0
 def get_mu(self, V):
     W = fd.FunctionSpace(V.mesh(), "CG", 1)
     bcs = []
     if len(self.fixed_bids):
         bcs.append(fd.DirichletBC(W, 1, self.fixed_bids))
     if len(self.free_bids):
         bcs.append(fd.DirichletBC(W, 10, self.free_bids))
     if len(bcs) == 0:
         bcs = None
     u = fd.TrialFunction(W)
     v = fd.TestFunction(W)
     a = fd.inner(fd.grad(u), fd.grad(v)) * fd.dx
     b = fd.inner(fd.Constant(0.), v) * fd.dx
     mu = fd.Function(W)
     fd.solve(a == b, mu, bcs=bcs)
     return mu
Example #27
0
    def eval_ddJdw(self):
        u = self.u
        v = self.v
        J = self.J
        F = self.F
        X = self.X
        w = self.w
        V = self.V
        L = self.L
        bil_form = self.bil_form
        params = self.params

        s = w
        y_s = Function(V)
        # follow p 65 of Hinze, Pinnau, Ulbrich, Ulbrich
        # Step 1:
        solve(
            assemble(derivative(F, u)),
            y_s,
            assemble(derivative(-F, X, s)),
            solver_parameters=params,
            bcs=self.bc,
        )
        # Step 2:
        Lyy_y_s = assemble(derivative(derivative(L, u), u, y_s))
        Lyu_s = assemble(derivative(derivative(L, u), X, s))

        h1 = Lyy_y_s
        h1 += Lyu_s

        Luy_y_s = assemble(derivative(derivative(L, X), u, y_s))
        Luu_s = assemble(derivative(derivative(L, X), X, s))
        h2 = Luy_y_s
        h2 += Luu_s
        h3_temp = Function(V)
        # Step 3:
        solve(assemble(bil_form),
              h3_temp,
              h1,
              bcs=self.bc,
              solver_parameters=params)
        F_h3_temp = replace(F, {v: h3_temp})
        h3 = assemble(derivative(-F_h3_temp, X))
        res = h2
        res += h3
        return res.vector().inner(w.vector())
Example #28
0
    def solve(self, velocity, dJ):
        """Solve the problem

        Args:
            velocity ([type]): Solution. velocity means regularized shape derivatives
            dJ ([type]): Shape derivatives to be regularized
        """
        for bc in self.bcs:
            bc.apply(dJ)

        solve(
            self.Av,
            velocity.vector(),
            dJ,
            options_prefix="reg_solver",
            solver_parameters=self.solver_parameters,
        )
Example #29
0
    def _diffuse(self, dt, E, h, q, q_bed, E_surface):
        Q = E.function_space()
        degree = Q.ufl_element().degree()[1]
        φ, ψ = firedrake.TrialFunction(Q), firedrake.TestFunction(Q)

        a = (h * φ * ψ + dt * α * φ.dx(2) * ψ.dx(2) / h) * dx \
            + degree**2 * dt * α * φ * ψ / h * ds_t
        f = E * ψ * h * dx \
            + dt * q * ψ * h * dx \
            + dt * q_bed * ψ * ds_b \
            + degree**2 * dt * α * E_surface * ψ / h * ds_t

        degree_E = E.ufl_element().degree()
        degree = (3 * degree_E[0], 2 * degree_E[1])
        form_compiler_parameters = {'quadrature_degree': degree}
        firedrake.solve(a == f,
                        E,
                        form_compiler_parameters=form_compiler_parameters)
Example #30
0
    def update_search_direction(self):
        r"""Apply the low-rank approximation of the Hessian inverse

        This procedure implements the two-loop recursion algorithm to apply the
        low-rank approximation of the Hessian inverse to the derivative of the
        objective functional. See Nocedal and Wright, Numerical Optimization,
        2nd ed., algorithm 7.4."""
        p, q, dJ = self.parameter, self.search_direction, self.gradient
        Q = q.function_space()
        M = firedrake.TrialFunction(Q) * firedrake.TestFunction(Q) * dx
        f = firedrake.Function(Q)
        firedrake.solve(M == dJ,
                        f,
                        solver_parameters=self._solver_params,
                        form_compiler_parameters=self._fc_params)

        # Append the latest values of the parameters and the objective gradient
        # and compute the curvature factor
        ps, fs, ρ = self._ps, self._fs, self._rho
        ρ.append(1 / self._assemble((p - ps[-1]) * (f - fs[-1]) * dx))
        ps.append(p.copy(deepcopy=True))
        fs.append(f.copy(deepcopy=True))

        # Forget any old values of the parameters and objective gradient
        ps = ps[-(self.memory + 1):]
        fs = fs[-(self.memory + 1):]
        ρ = ρ[-self.memory:]

        g = f.copy(deepcopy=True)
        m = len(ρ)
        α = np.zeros(m)
        for i in range(m - 1, -1, -1):
            α[i] = ρ[i] * self._assemble(f * (ps[i + 1] - ps[i]) * dx)
            g -= α[i] * (fs[i + 1] - fs[i])

        r = g.copy(deepcopy=True)
        dp, df = ps[-1] - ps[-2], fs[-1] - fs[-2]
        r *= self._assemble(dp * df * dx) / self._assemble(df * df * dx)

        for i in range(m):
            β = ρ[i] * self._assemble((fs[i + 1] - fs[i]) * r * dx)
            r += (α[i] - β) * (ps[i + 1] - ps[i])

        q.assign(-r)
Example #31
0
def compute_space_accuracy_via_mms(
        grid_sizes, element_degree, quadrature_degree, smoothing):
    
    dx = fe.dx(degree = quadrature_degree)
    
    parameters["smoothing"].assign(smoothing)
    
    h, e, order = [], [], []
    
    for gridsize in grid_sizes:
    
        mesh = fe.UnitIntervalMesh(gridsize)
        
        element = fe.FiniteElement("P", mesh.ufl_cell(), element_degree)
        
        V = fe.FunctionSpace(mesh, element)
        
        u_m = manufactured_solution(mesh)
        
        bc = fe.DirichletBC(V, u_m, "on_boundary")
        
        u = fe.TrialFunction(V)
        
        v = fe.TestFunction(V)
        
        u_h = fe.Function(V)
        
        fe.solve(F(u, v)*dx == v*R(u_m)*dx, u_h, bcs = bc)

        e.append(math.sqrt(fe.assemble(fe.inner(u_h - u_m, u_h - u_m)*dx)))
        
        h.append(1./float(gridsize))
        
        if len(e) > 1:
    
            r = h[-2]/h[-1] 
            
            log = math.log
            
            order = log(e[-2]/e[-1])/log(r)
            
            print("{0: <4}, {1: .3f}, {2: .5f}, {3: .3f}, {4: .3f}".format(
                str(quadrature_degree), smoothing, h[-1], e[-1], order))
Example #32
0
    def __init__(self, mesh, vertical_degree=1, horizontal_degree=1,
                 family="RT", z=None, k=None, Omega=None, mu=None,
                 timestepping=None,
                 output=None,
                 parameters=None,
                 diagnostics=None,
                 fieldlist=None,
                 diagnostic_fields=[],
                 on_sphere=False):

        super(BaroclinicState, self).__init__(mesh=mesh,
                                              vertical_degree=vertical_degree,
                                              horizontal_degree=horizontal_degree,
                                              family=family,
                                              z=z, k=k, Omega=Omega, mu=mu,
                                              timestepping=timestepping,
                                              output=output,
                                              parameters=parameters,
                                              diagnostics=diagnostics,
                                              fieldlist=fieldlist,
                                              diagnostic_fields=diagnostic_fields)

        #  build the geopotential
        if parameters.geopotential:
            V = FunctionSpace(mesh, "CG", 1)
            if on_sphere:
                self.Phi = Function(V).interpolate(Expression("pow(x[0]*x[0]+x[1]*x[1]+x[2]*x[2],0.5)"))
            else:
                self.Phi = Function(V).interpolate(Expression("x[1]"))
            self.Phi *= parameters.g

        if self.k is None:
            # build the vertical normal
            w = TestFunction(self.Vv)
            u = TrialFunction(self.Vv)
            self.k = Function(self.Vv)
            n = FacetNormal(self.mesh)
            krhs = -div(w)*self.z*dx + inner(w,n)*self.z*ds_tb
            klhs = inner(w,u)*dx
            solve(klhs == krhs, self.k)