Beispiel #1
0
    def __init__(self, state, V, direction=[1,2], params=None):
        super(InteriorPenalty, self).__init__(state)

        dt = state.timestepping.dt
        kappa = params['kappa']
        mu = params['mu']
        gamma = TestFunction(V)
        phi = TrialFunction(V)
        self.phi1 = Function(V)
        n = FacetNormal(state.mesh)
        a = inner(gamma,phi)*dx + dt*inner(grad(gamma), grad(phi)*kappa)*dx

        def get_flux_form(dS, M):

            fluxes = (-inner(2*avg(outer(phi, n)), avg(grad(gamma)*M))
                      - inner(avg(grad(phi)*M), 2*avg(outer(gamma, n)))
                      + mu*inner(2*avg(outer(phi, n)), 2*avg(outer(gamma, n)*kappa)))*dS
            return fluxes

        if 1 in direction:
            a += dt*get_flux_form(dS_v, kappa)
        if 2 in direction:
            a += dt*get_flux_form(dS_h, kappa)
        L = inner(gamma,phi)*dx
        problem = LinearVariationalProblem(a, action(L,self.phi1), self.phi1)
        self.solver = LinearVariationalSolver(problem)
    def _setup_solver(self):

        state = self.state
        H = state.parameters.H
        g = state.parameters.g
        beta = state.timestepping.dt*state.timestepping.alpha

        # Split up the rhs vector (symbolically)
        u_in, D_in = split(state.xrhs)

        W = state.W
        w, phi = TestFunctions(W)
        u, D = TrialFunctions(W)

        eqn = (
            inner(w, u) - beta*g*div(w)*D
            - inner(w, u_in)
            + phi*D + beta*H*phi*div(u)
            - phi*D_in
        )*dx

        aeqn = lhs(eqn)
        Leqn = rhs(eqn)

        # Place to put result of u rho solver
        self.uD = Function(W)

        # Solver for u, D
        uD_problem = LinearVariationalProblem(
            aeqn, Leqn, self.state.dy)

        self.uD_solver = LinearVariationalSolver(uD_problem,
                                                 solver_parameters=self.params,
                                                 options_prefix='SWimplicit')
Beispiel #3
0
    def __init__(self, state, linear=False):
        self.state = state

        g = state.parameters.g
        f = state.f

        Vu = state.V[0]
        W = state.W

        self.x0 = Function(W)  # copy x to here

        u0, D0 = split(self.x0)
        n = FacetNormal(state.mesh)
        un = 0.5 * (dot(u0, n) + abs(dot(u0, n)))

        F = TrialFunction(Vu)
        w = TestFunction(Vu)
        self.uF = Function(Vu)

        outward_normals = CellNormal(state.mesh)
        perp = lambda u: cross(outward_normals, u)
        a = inner(w, F) * dx
        L = (-f * inner(w, perp(u0)) + g * div(w) * D0) * dx - g * inner(
            jump(w, n), un("+") * D0("+") - un("-") * D0("-")
        ) * dS

        if not linear:
            L -= 0.5 * div(w) * inner(u0, u0) * dx

        u_forcing_problem = LinearVariationalProblem(a, L, self.uF)

        self.u_forcing_solver = LinearVariationalSolver(u_forcing_problem)
Beispiel #4
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
Beispiel #5
0
 def V_approx_inv_mass(self, V, DG):
     """
     Approximate inverse mass.  Computes (cellwise) (V, V)^{-1} (V, DG).
     :arg V: a function space
     :arg DG: the DG space
     :returns: A PETSc Mat mapping from V -> DG.
     """
     key = V.dim()
     try:
         return self._V_approx_inv_mass[key]
     except KeyError:
         a = firedrake.Tensor(firedrake.inner(firedrake.TestFunction(V),
                                              firedrake.TrialFunction(V))*firedrake.dx)
         b = firedrake.Tensor(firedrake.inner(firedrake.TestFunction(V),
                                              firedrake.TrialFunction(DG))*firedrake.dx)
         M = firedrake.assemble(a.inv * b)
         M.force_evaluation()
         return self._V_approx_inv_mass.setdefault(key, M.petscmat)
 def A(self):
     u = firedrake.TrialFunction(self.target.function_space())
     v = firedrake.TestFunction(self.target.function_space())
     a = firedrake.inner(u, v)*firedrake.dx
     if self.use_slate_for_inverse:
         a = firedrake.Tensor(a).inv
     A = firedrake.assemble(a, bcs=self.bcs,
                            form_compiler_parameters=self.form_compiler_parameters)
     return A
Beispiel #7
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)
Beispiel #8
0
    def __init__(self, state, V, continuity=False):

        super(DGAdvection, self).__init__(state)

        element = V.fiat_element
        assert element.entity_dofs() == element.entity_closure_dofs(), "Provided space is not discontinuous"
        dt = state.timestepping.dt

        if V.extruded:
            surface_measure = (dS_h + dS_v)
        else:
            surface_measure = dS

        phi = TestFunction(V)
        D = TrialFunction(V)
        self.D1 = Function(V)
        self.dD = Function(V)

        n = FacetNormal(state.mesh)
        # ( dot(v, n) + |dot(v, n)| )/2.0
        un = 0.5*(dot(self.ubar, n) + abs(dot(self.ubar, n)))

        a_mass = inner(phi,D)*dx

        if continuity:
            a_int = -inner(grad(phi), outer(D, self.ubar))*dx
        else:
            a_int = -inner(div(outer(phi,self.ubar)),D)*dx

        a_flux = (dot(jump(phi), un('+')*D('+') - un('-')*D('-')))*surface_measure
        arhs = a_mass - dt*(a_int + a_flux)

        DGproblem = LinearVariationalProblem(a_mass, action(arhs,self.D1),
                                             self.dD)
        self.DGsolver = LinearVariationalSolver(DGproblem,
                                                solver_parameters={
                                                    'ksp_type':'preonly',
                                                    'pc_type':'bjacobi',
                                                    'sub_pc_type': 'ilu'},
                                                options_prefix='DGAdvection')
Beispiel #9
0
 def DG_inv_mass(self, DG):
     """
     Inverse DG mass matrix
     :arg DG: the DG space
     :returns: A PETSc Mat.
     """
     key = DG.dim()
     try:
         return self._DG_inv_mass[key]
     except KeyError:
         M = firedrake.assemble(firedrake.Tensor(firedrake.inner(firedrake.TestFunction(DG),
                                                                 firedrake.TrialFunction(DG))*firedrake.dx).inv)
         M.force_evaluation()
         return self._DG_inv_mass.setdefault(key, M.petscmat)
Beispiel #10
0
 def V_DG_mass(self, V, DG):
     """
     Mass matrix from between V and DG spaces.
     :arg V: a function space
     :arg DG: the DG space
     :returns: A PETSc Mat mapping from V -> DG
     """
     key = V.dim()
     try:
         return self._V_DG_mass[key]
     except KeyError:
         M = firedrake.assemble(firedrake.inner(firedrake.TestFunction(DG),
                                                firedrake.TrialFunction(V))*firedrake.dx)
         M.force_evaluation()
         return self._V_DG_mass.setdefault(key, M.petscmat)
Beispiel #11
0
    def _build_forcing_solver(self, linear):
        """
        Only put forcing terms into the u equation.
        """

        state = self.state
        self.scaling = Constant(1.0)
        Vu = state.V[0]
        W = state.W

        self.x0 = Function(W)  # copy x to here

        u0, rho0, theta0 = split(self.x0)

        F = TrialFunction(Vu)
        w = TestFunction(Vu)
        self.uF = Function(Vu)

        Omega = state.Omega
        cp = state.parameters.cp
        mu = state.mu

        n = FacetNormal(state.mesh)

        pi = exner(theta0, rho0, state)

        a = inner(w, F) * dx
        L = self.scaling * (
            +cp * div(theta0 * w) * pi * dx  # pressure gradient [volume]
            - cp * jump(w * theta0, n) * avg(pi) * dS_v  # pressure gradient [surface]
        )

        if state.parameters.geopotential:
            Phi = state.Phi
            L += self.scaling * div(w) * Phi * dx  # gravity term
        else:
            g = state.parameters.g
            L -= self.scaling * g * inner(w, state.k) * dx  # gravity term

        if not linear:
            L -= self.scaling * 0.5 * div(w) * inner(u0, u0) * dx

        if Omega is not None:
            L -= self.scaling * inner(w, cross(2 * Omega, u0)) * dx  # Coriolis term

        if mu is not None:
            self.mu_scaling = Constant(1.0)
            L -= self.mu_scaling * mu * inner(w, state.k) * inner(u0, state.k) * dx

        bcs = [DirichletBC(Vu, 0.0, "bottom"), DirichletBC(Vu, 0.0, "top")]

        u_forcing_problem = LinearVariationalProblem(a, L, self.uF, bcs=bcs)

        self.u_forcing_solver = LinearVariationalSolver(u_forcing_problem)
Beispiel #12
0
    def _build_forcing_solver(self, linear):
        """
        Only put forcing terms into the u equation.
        """

        state = self.state
        self.scaling = Constant(1.0)
        Vu = state.V[0]
        W = state.W

        self.x0 = Function(W)  # copy x to here

        u0, p0, b0 = split(self.x0)

        F = TrialFunction(Vu)
        w = TestFunction(Vu)
        self.uF = Function(Vu)

        Omega = state.Omega
        mu = state.mu

        a = inner(w, F) * dx
        L = (
            self.scaling * div(w) * p0 * dx  # pressure gradient
            + self.scaling * b0 * inner(w, state.k) * dx  # gravity term
        )

        if not linear:
            L -= self.scaling * 0.5 * div(w) * inner(u0, u0) * dx

        if Omega is not None:
            L -= self.scaling * inner(w, cross(2 * Omega, u0)) * dx  # Coriolis term

        if mu is not None:
            self.mu_scaling = Constant(1.0)
            L -= self.mu_scaling * mu * inner(w, state.k) * inner(u0, state.k) * dx

        bcs = [DirichletBC(Vu, 0.0, "bottom"), DirichletBC(Vu, 0.0, "top")]

        u_forcing_problem = LinearVariationalProblem(a, L, self.uF, bcs=bcs)

        self.u_forcing_solver = LinearVariationalSolver(u_forcing_problem)

        Vp = state.V[1]
        p = TrialFunction(Vp)
        q = TestFunction(Vp)
        self.divu = Function(Vp)

        a = p * q * dx
        L = q * div(u0) * dx

        divergence_problem = LinearVariationalProblem(a, L, self.divu)

        self.divergence_solver = LinearVariationalSolver(divergence_problem)
Beispiel #13
0
    def initialize(self, pc):
        from firedrake import TrialFunction, TestFunction, dx, assemble, inner, parameters
        prefix = pc.getOptionsPrefix()
        options_prefix = prefix + "Mp_"
        # we assume P has things stuffed inside of it
        _, P = pc.getOperators()
        context = P.getPythonContext()

        test, trial = context.a.arguments()

        if test.function_space() != trial.function_space():
            raise ValueError("MassInvPC only makes sense if test and trial space are the same")

        V = test.function_space()

        mu = context.appctx.get("mu", 1.0)

        u = TrialFunction(V)
        v = TestFunction(V)
        # Handle vector and tensor-valued spaces.

        # 1/mu goes into the inner product in case it varies spatially.
        a = inner(1/mu * u, v)*dx

        opts = PETSc.Options()
        mat_type = opts.getString(options_prefix + "mat_type",
                                  parameters["default_matrix_type"])

        A = assemble(a, form_compiler_parameters=context.fc_params,
                     mat_type=mat_type, options_prefix=options_prefix)
        A.force_evaluation()

        Pmat = A.petscmat
        Pmat.setNullSpace(P.getNullSpace())
        tnullsp = P.getTransposeNullSpace()
        if tnullsp.handle != 0:
            Pmat.setTransposeNullSpace(tnullsp)

        ksp = PETSc.KSP().create(comm=pc.comm)
        ksp.incrementTabLevel(1, parent=pc)
        ksp.setOperators(Pmat)
        ksp.setOptionsPrefix(options_prefix)
        ksp.setFromOptions()
        ksp.setUp()
        self.ksp = ksp
Beispiel #14
0
 def V_inv_mass_ksp(self, V):
     """
     A KSP inverting a mass matrix
     :arg V: a function space.
     :returns: A PETSc KSP for inverting (V, V).
     """
     key = V.dim()
     try:
         return self._V_inv_mass_ksp[key]
     except KeyError:
         M = firedrake.assemble(firedrake.inner(firedrake.TestFunction(V),
                                                firedrake.TrialFunction(V))*firedrake.dx)
         M.force_evaluation()
         ksp = PETSc.KSP().create(comm=V.comm)
         ksp.setOperators(M.petscmat)
         ksp.setOptionsPrefix("{}_prolongation_mass_".format(V.ufl_element()._short_name))
         ksp.setType("preonly")
         ksp.pc.setType("cholesky")
         ksp.setFromOptions()
         ksp.setUp()
         return self._V_inv_mass_ksp.setdefault(key, ksp)
Beispiel #15
0
 def momentum_term():
     return inner(rho * hh * (u1 - u0), p) * dx
Beispiel #16
0
 def advection_term(self, q):
     L = super().advection_term(q)
     L -= 0.5 * div(self.test) * inner(q, self.ubar) * dx
     return L
Beispiel #17
0
 def mass_term(self, q):
     return inner(self.test, q) * dx
Beispiel #18
0
    def _setup_solver(self):
        state = self.state      # just cutting down line length a bit
        Dt = state.timestepping.dt
        beta_ = Dt*state.timestepping.alpha
        mu = state.mu
        Vu = state.spaces("HDiv")
        Vb = state.spaces("HDiv_v")
        Vp = state.spaces("DG")

        # Store time-stepping coefficients as UFL Constants
        dt = Constant(Dt)
        beta = Constant(beta_)

        # Split up the rhs vector (symbolically)
        u_in, p_in, b_in = split(state.xrhs)

        # Build the reduced function space for u,p
        M = MixedFunctionSpace((Vu, Vp))
        w, phi = TestFunctions(M)
        u, p = TrialFunctions(M)

        # Get background fields
        bbar = state.fields("bbar")

        # Analytical (approximate) elimination of theta
        k = state.k             # Upward pointing unit vector
        b = -dot(k, u)*dot(k, grad(bbar))*beta + b_in

        # vertical projection
        def V(u):
            return k*inner(u, k)

        eqn = (
            inner(w, (u - u_in))*dx
            - beta*div(w)*p*dx
            - beta*inner(w, k)*b*dx
            + phi*div(u)*dx
        )

        if mu is not None:
            eqn += dt*mu*inner(w, k)*inner(u, k)*dx
        aeqn = lhs(eqn)
        Leqn = rhs(eqn)

        # Place to put result of u p solver
        self.up = Function(M)

        # Boundary conditions (assumes extruded mesh)
        bcs = None if len(self.state.bcs) == 0 else self.state.bcs

        # Solver for u, p
        up_problem = LinearVariationalProblem(aeqn, Leqn, self.up, bcs=bcs)

        # Provide callback for the nullspace of the trace system
        def trace_nullsp(T):
            return VectorSpaceBasis(constant=True)

        appctx = {"trace_nullspace": trace_nullsp}
        self.up_solver = LinearVariationalSolver(up_problem,
                                                 solver_parameters=self.solver_parameters,
                                                 appctx=appctx)

        # Reconstruction of b
        b = TrialFunction(Vb)
        gamma = TestFunction(Vb)

        u, p = self.up.split()
        self.b = Function(Vb)

        b_eqn = gamma*(b - b_in
                       + dot(k, u)*dot(k, grad(bbar))*beta)*dx

        b_problem = LinearVariationalProblem(lhs(b_eqn),
                                             rhs(b_eqn),
                                             self.b)
        self.b_solver = LinearVariationalSolver(b_problem)
Beispiel #19
0
def compliance_optimization(n_iters=200):

    output_dir = "cantilever/"

    path = os.path.abspath(__file__)
    dir_path = os.path.dirname(path)
    m = fd.Mesh(f"{dir_path}/mesh_cantilever.msh")
    mesh = fd.MeshHierarchy(m, 0)[-1]

    # Perturb the mesh coordinates. Necessary to calculate shape derivatives
    S = fd.VectorFunctionSpace(mesh, "CG", 1)
    s = fd.Function(S, name="deform")
    mesh.coordinates.assign(mesh.coordinates + s)

    # Initial level set function
    x, y = fd.SpatialCoordinate(mesh)
    PHI = fd.FunctionSpace(mesh, "CG", 1)
    lx = 2.0
    ly = 1.0
    phi_expr = (
        -cos(6.0 / lx * pi * x) * cos(4.0 * pi * y)
        - 0.6
        + max_value(200.0 * (0.01 - x ** 2 - (y - ly / 2) ** 2), 0.0)
        + max_value(100.0 * (x + y - lx - ly + 0.1), 0.0)
        + max_value(100.0 * (x - y - lx + 0.1), 0.0)
    )
    # Avoid recording the operation interpolate into the tape.
    # Otherwise, the shape derivatives will not be correct
    with fda.stop_annotating():
        phi = fd.interpolate(phi_expr, PHI)
        phi.rename("LevelSet")
        fd.File(output_dir + "phi_initial.pvd").write(phi)

    # Physics. Elasticity
    rho_min = 1e-5
    beta = fd.Constant(200.0)

    def hs(phi, beta):
        return fd.Constant(1.0) / (
            fd.Constant(1.0) + exp(-beta * phi)
        ) + fd.Constant(rho_min)

    H1_elem = fd.VectorElement("CG", mesh.ufl_cell(), 1)
    W = fd.FunctionSpace(mesh, H1_elem)

    u = fd.TrialFunction(W)
    v = fd.TestFunction(W)

    # Elasticity parameters
    E, nu = 1.0, 0.3
    mu, lmbda = fd.Constant(E / (2 * (1 + nu))), fd.Constant(
        E * nu / ((1 + nu) * (1 - 2 * nu))
    )

    def epsilon(u):
        return sym(nabla_grad(u))

    def sigma(v):
        return 2.0 * mu * epsilon(v) + lmbda * tr(epsilon(v)) * Identity(2)

    a = inner(hs(-phi, beta) * sigma(u), nabla_grad(v)) * dx
    t = fd.Constant((0.0, -75.0))
    L = inner(t, v) * ds(2)

    bc = fd.DirichletBC(W, fd.Constant((0.0, 0.0)), 1)
    parameters = {
        "ksp_type": "preonly",
        "pc_type": "lu",
        "mat_type": "aij",
        "ksp_converged_reason": None,
        "pc_factor_mat_solver_type": "mumps",
    }
    u_sol = fd.Function(W)
    F = fd.action(a, u_sol) - L
    problem = fd.NonlinearVariationalProblem(F, u_sol, bcs=bc)
    solver = fd.NonlinearVariationalSolver(
        problem, solver_parameters=parameters
    )
    solver.solve()
    # fd.solve(
    #    a == L, u_sol, bcs=[bc], solver_parameters=parameters
    # )  # , nullspace=nullspace)
    with fda.stop_annotating():
        fd.File("u_sol.pvd").write(u_sol)

    # Cost function: Compliance
    J = fd.assemble(
        fd.Constant(1e-2)
        * inner(hs(-phi, beta) * sigma(u_sol), epsilon(u_sol))
        * dx
    )

    # Constraint: Volume
    with fda.stop_annotating():
        total_volume = fd.assemble(fd.Constant(1.0) * dx(domain=mesh))
    VolPen = fd.assemble(hs(-phi, beta) * dx)
    # Needed to track the value of the volume
    VolControl = fda.Control(VolPen)
    Vval = total_volume / 2.0

    phi_pvd = fd.File("phi_evolution.pvd", target_continuity=fd.H1)

    def deriv_cb(phi):
        with fda.stop_annotating():
            phi_pvd.write(phi[0])

    c = fda.Control(s)
    Jhat = LevelSetFunctional(J, c, phi, derivative_cb_pre=deriv_cb)
    Vhat = LevelSetFunctional(VolPen, c, phi)
    beta_param = 0.1
    # Boundary conditions for the shape derivatives.
    # They must be zero at the boundary conditions.
    bcs_vel = fd.DirichletBC(S, fd.Constant((0.0, 0.0)), (1, 2))
    # Regularize the shape derivatives
    reg_solver = RegularizationSolver(
        S,
        mesh,
        beta=beta_param,
        gamma=1.0e5,
        dx=dx,
        bcs=bcs_vel,
        output_dir=None,
    )
    # Hamilton-Jacobi equation to advect the level set
    dt = 0.05
    tol = 1e-5

    # Optimization problem
    vol_constraint = Constraint(Vhat, Vval, VolControl)
    problem = InfDimProblem(Jhat, reg_solver, ineqconstraints=vol_constraint)

    parameters = {
        "ksp_type": "preonly",
        "pc_type": "lu",
        "mat_type": "aij",
        "ksp_converged_reason": None,
        "pc_factor_mat_solver_type": "mumps",
    }

    params = {
        "alphaC": 3.0,
        "K": 0.1,
        "debug": 5,
        "alphaJ": 1.0,
        "dt": dt,
        "maxtrials": 10,
        "maxit": n_iters,
        "itnormalisation": 50,
        "tol": tol,
    }
    results = nlspace_solve(problem, params)

    return results
Beispiel #20
0
    h_undamaged = firedrake.Function(Q)
    u_undamaged = firedrake.Function(V)
    chk.load(h_undamaged, name='h')
    chk.load(u_undamaged, name='u')

with firedrake.DumbCheckpoint(args.damaged, mode=firedrake.FILE_READ) as chk:
    h_damaged = firedrake.Function(Q)
    u_damaged = firedrake.Function(V)
    D = firedrake.Function(Δ)
    chk.load(h_damaged, name='h')
    chk.load(u_damaged, name='u')
    chk.load(D, name='D')

δh = firedrake.interpolate(h_damaged - h_undamaged, Q)

speed = sqrt(inner(u_undamaged, u_undamaged))
v = u_undamaged / speed
δu = firedrake.interpolate(inner(u_damaged - u_undamaged, v), Q)

fig, axes = icepack.plot.subplots(nrows=2, ncols=2, sharex=True, sharey=True)
axes[0, 0].set_ylabel('distance (m)')

umax = icepack.norm(u_undamaged, norm_type='Linfty')
umax = (int(umax // 50) + 1) * 50
streamlines = icepack.plot.streamplot(u_undamaged, precision=1e3, density=5e3, axes=axes[0, 0])
colorbar(fig, axes[0, 0], streamlines, label='velocity (m/a)')

dumax = icepack.norm(δu, norm_type='Linfty')
dumax = int(dumax) + 1
levels = np.linspace(-dumax, +dumax, 2 * dumax + 1)
contours = icepack.plot.tricontourf(δu, levels=levels, cmap='twilight', axes=axes[0, 1])
Beispiel #21
0
 def rhs_form(self):
     v = firedrake.TestFunction(self.target.function_space())
     form = firedrake.inner(self.source, v) * firedrake.dx
     return form
Beispiel #22
0
 def delta(self, u):
     return sqrt(self.params.Delta_min ** 2 + 2 * self.params.e ** (-2) * inner(dev(self.strain(grad(u))),
                                                                                dev(self.strain(grad(u)))) + tr(
         self.strain(grad(u))) ** 2)
Beispiel #23
0
 def rheology_term():
     return inner(sigma, grad(p)) * dx
Beispiel #24
0
    def compute_basis(self, n_basis, inner_product="L2", time_scaling=False, delta_t=None):
        """

        :arg n_basis: Number of basis.
        :arg inner_product: Type of inner product (L2 or H1).
        :arg time_scaling: Use time scaling.
        :arg delta_t: :class:`numpy.ndarray` with used timesteps to scale.
        :return: Estimated error.
        """
        # Build inner product matrix
        V = self.snaps[-1].function_space()
        if inner_product == "L2":
            ip_form = inner(TrialFunction(V), TestFunction(V)) * dx
        elif inner_product == "H1":
            ip_form = inner(TrialFunction(V), TestFunction(V)) * dx + inner(grad(TrialFunction(V)),
                                                                            grad(TestFunction(V))) * dx

        ip_mat = assemble(ip_form, mat_type="aij").M.handle

        M = self.snapshots_to_matrix()

        # This matrix is symmetric positive semidefinite
        corr_mat = np.matmul(self.snap_mat.transpose(), petsc2sp(ip_mat).dot(self.snap_mat))

        # Build time scaling diagonal matrix
        if time_scaling is True and delta_t is not None:
            D = np.zeros((len(self.snaps), len(self.snaps)))
            for i in range(len(self.snaps)):
                D[i, i] = np.sqrt(delta_t[i])
            D[0, 0] = np.sqrt(delta_t[0] / 2.0)
            D[-1, -1] = np.sqrt(delta_t[-1] / 2.0)

            # D'MD
            corr_mat = np.matmul(D.transpose(), np.matmul(corr_mat, D))

        self.n_basis = n_basis

        # Compute eigenvalues, all real and non negative
        w, v = np.linalg.eigh(corr_mat)

        idx = np.argsort(w)[::-1]
        w = w[idx]
        v = v[:, idx]

        # Skip negative entries
        idx_neg = np.argwhere(w < 0)
        if len(idx_neg) > 0:
            # Reduce number of basis to min(n_basis, first_negative_eigenvalue)
            n_basis = np.minimum(n_basis, idx_neg[0][0])

        psi_mat = np.zeros((self.snaps[-1].function_space().dof_count, n_basis))

        for i in range(n_basis):
            psi_mat[:, i] = self.snap_mat.dot(v[:, i]) / np.sqrt(w[i])

        ratio = np.sum(w[:n_basis]) / np.sum(w[:M])

        self.basis_mat = PETSc.Mat().create(PETSc.COMM_WORLD)
        self.basis_mat.setType('dense')
        self.basis_mat.setSizes([self.snap_mat.shape[0], n_basis])
        self.basis_mat.setUp()

        self.basis_mat.setValues(range(self.snap_mat.shape[0]),
                                 range(n_basis),
                                 psi_mat.reshape((self.snap_mat.shape[0], n_basis)))

        self.basis_mat.assemble()

        return ratio
Beispiel #25
0
    def advection_term(self, q):

        if self.state.mesh.topological_dimension() == 3:
            # <w,curl(u) cross ubar + grad( u.ubar)>
            # =<curl(u),ubar cross w> - <div(w), u.ubar>
            # =<u,curl(ubar cross w)> -
            #      <<u_upwind, [[n cross(ubar cross w)cross]]>>

            both = lambda u: 2 * avg(u)

            L = (inner(q, curl(cross(self.ubar, self.test))) * dx -
                 inner(both(self.Upwind * q),
                       both(cross(self.n, cross(self.ubar, self.test)))) *
                 self.dS)

        else:

            if self.ibp == "once":
                L = (-inner(
                    self.gradperp(inner(self.test, self.perp(self.ubar))), q) *
                     dx - inner(
                         jump(inner(self.test, self.perp(self.ubar)), self.n),
                         self.perp_u_upwind(q)) * self.dS)
            else:
                L = (
                    (-inner(self.test,
                            div(self.perp(q)) * self.perp(self.ubar))) * dx -
                    inner(jump(inner(self.test, self.perp(self.ubar)), self.n),
                          self.perp_u_upwind(q)) * self.dS + jump(
                              inner(self.test, self.perp(self.ubar)) *
                              self.perp(q), self.n) * self.dS)

        L -= 0.5 * div(self.test) * inner(q, self.ubar) * dx

        return L
Beispiel #26
0
def _effective_strain_rate(ε, ε_min):
    return sqrt((inner(ε, ε) + trace(ε) ** 2 + ε_min ** 2) / 2)
Beispiel #27
0
 def forcing_term():
     return inner(rho * hh * cor * perp(ocean_curr - uh), p) * dx
Beispiel #28
0
 def inner_product(self, x, y):
     return fd.assemble(inner(x, y) * dx)
Beispiel #29
0
 def stress_term(density, drag, func):
     return inner(density * drag * sqrt(dot(func, func)) * func, p) * dx(degree=3)
Beispiel #30
0
    def initialize(self, pc):
        from firedrake import TrialFunction, TestFunction, dx, \
            assemble, inner, grad, split, Constant, parameters
        from firedrake.assemble import allocate_matrix, create_assembly_callable
        prefix = pc.getOptionsPrefix() + "pcd_"

        # we assume P has things stuffed inside of it
        _, P = pc.getOperators()
        context = P.getPythonContext()

        test, trial = context.a.arguments()
        if test.function_space() != trial.function_space():
            raise ValueError("Pressure space test and trial space differ")

        Q = test.function_space()

        p = TrialFunction(Q)
        q = TestFunction(Q)

        mass = p*q*dx

        # Regularisation to avoid having to think about nullspaces.
        stiffness = inner(grad(p), grad(q))*dx + Constant(1e-6)*p*q*dx

        opts = PETSc.Options()
        # we're inverting Mp and Kp, so default them to assembled.
        # Fp only needs its action, so default it to mat-free.
        # These can of course be overridden.
        # only Fp is referred to in update, so that's the only
        # one we stash.
        default = parameters["default_matrix_type"]
        Mp_mat_type = opts.getString(prefix+"Mp_mat_type", default)
        Kp_mat_type = opts.getString(prefix+"Kp_mat_type", default)
        self.Fp_mat_type = opts.getString(prefix+"Fp_mat_type", "matfree")

        Mp = assemble(mass, form_compiler_parameters=context.fc_params,
                      mat_type=Mp_mat_type)
        Kp = assemble(stiffness, form_compiler_parameters=context.fc_params,
                      mat_type=Kp_mat_type)

        Mp.force_evaluation()
        Kp.force_evaluation()

        # FIXME: Should we transfer nullspaces over.  I think not.

        Mksp = PETSc.KSP().create()
        Mksp.setOptionsPrefix(prefix + "Mp_")
        Mksp.setOperators(Mp.petscmat)
        Mksp.setUp()
        Mksp.setFromOptions()
        self.Mksp = Mksp

        Kksp = PETSc.KSP().create()
        Kksp.setOptionsPrefix(prefix + "Kp_")
        Kksp.setOperators(Kp.petscmat)
        Kksp.setUp()
        Kksp.setFromOptions()
        self.Kksp = Kksp

        state = context.appctx["state"]

        Re = context.appctx.get("Re", 1.0)

        velid = context.appctx["velocity_space"]

        u0 = split(state)[velid]
        fp = 1.0/Re * inner(grad(p), grad(q))*dx + inner(u0, grad(p))*q*dx

        self.Re = Re
        self.Fp = allocate_matrix(fp, form_compiler_parameters=context.fc_params,
                                  mat_type=self.Fp_mat_type)
        self._assemble_Fp = create_assembly_callable(fp, tensor=self.Fp,
                                                     form_compiler_parameters=context.fc_params,
                                                     mat_type=self.Fp_mat_type)
        self._assemble_Fp()
        self.Fp.force_evaluation()
        Fpmat = self.Fp.petscmat
        self.workspace = [Fpmat.createVecLeft() for i in (0, 1)]
Beispiel #31
0
    inlet_angles = π * np.array([-3/4, -1/2, -1/3, -1/6])
    inlet_widths = π * np.array([1/8, 1/12, 1/24, 1/12])

    x = firedrake.SpatialCoordinate(mesh)

    R = 200e3
    u_in = 300
    h_in = 350
    hb = 100
    dh, du = 400, 250

    hs, us = [], []
    for θ, ϕ in zip(inlet_angles, inlet_widths):
        x0 = R * as_vector((np.cos(θ), np.sin(θ)))
        v = -as_vector((np.cos(θ), np.sin(θ)))
        L = inner(x - x0, v)
        W = x - x0 - L * v
        Rn = 2 * ϕ / π * R
        q = firedrake.max_value(1 - (W / Rn)**2, 0)
        hs.append(hb + q * ((h_in - hb) - dh * L /R))
        us.append(firedrake.exp(-4 * (W/R)**2) * (u_in + du * L / R) * v)

    h_expr = firedrake.Constant(hb)
    for h in hs:
        h_expr = firedrake.max_value(h, h_expr)

    u_expr = sum(us)

    # Interpolate the initial data to finite element spaces
    h0 = firedrake.interpolate(h_expr, Q)
    u0 = firedrake.interpolate(u_expr, V)
Beispiel #32
0
    def _setup_solver(self):
        import numpy as np

        state = self.state
        Dt = state.timestepping.dt
        beta_ = Dt*state.timestepping.alpha
        cp = state.parameters.cp
        mu = state.mu
        Vu = state.spaces("HDiv")
        Vu_broken = FunctionSpace(state.mesh, BrokenElement(Vu.ufl_element()))
        Vtheta = state.spaces("HDiv_v")
        Vrho = state.spaces("DG")

        # Store time-stepping coefficients as UFL Constants
        dt = Constant(Dt)
        beta = Constant(beta_)
        beta_cp = Constant(beta_ * cp)

        h_deg = state.horizontal_degree
        v_deg = state.vertical_degree
        Vtrace = FunctionSpace(state.mesh, "HDiv Trace", degree=(h_deg, v_deg))

        # Split up the rhs vector (symbolically)
        u_in, rho_in, theta_in = split(state.xrhs)

        # Build the function space for "broken" u, rho, and pressure trace
        M = MixedFunctionSpace((Vu_broken, Vrho, Vtrace))
        w, phi, dl = TestFunctions(M)
        u, rho, l0 = TrialFunctions(M)

        n = FacetNormal(state.mesh)

        # Get background fields
        thetabar = state.fields("thetabar")
        rhobar = state.fields("rhobar")
        pibar = thermodynamics.pi(state.parameters, rhobar, thetabar)
        pibar_rho = thermodynamics.pi_rho(state.parameters, rhobar, thetabar)
        pibar_theta = thermodynamics.pi_theta(state.parameters, rhobar, thetabar)

        # Analytical (approximate) elimination of theta
        k = state.k             # Upward pointing unit vector
        theta = -dot(k, u)*dot(k, grad(thetabar))*beta + theta_in

        # Only include theta' (rather than pi') in the vertical
        # component of the gradient

        # The pi prime term (here, bars are for mean and no bars are
        # for linear perturbations)
        pi = pibar_theta*theta + pibar_rho*rho

        # Vertical projection
        def V(u):
            return k*inner(u, k)

        # Specify degree for some terms as estimated degree is too large
        dxp = dx(degree=(self.quadrature_degree))
        dS_vp = dS_v(degree=(self.quadrature_degree))
        dS_hp = dS_h(degree=(self.quadrature_degree))
        ds_vp = ds_v(degree=(self.quadrature_degree))
        ds_tbp = (ds_t(degree=(self.quadrature_degree))
                  + ds_b(degree=(self.quadrature_degree)))

        # Add effect of density of water upon theta
        if self.moisture is not None:
            water_t = Function(Vtheta).assign(0.0)
            for water in self.moisture:
                water_t += self.state.fields(water)
            theta_w = theta / (1 + water_t)
            thetabar_w = thetabar / (1 + water_t)
        else:
            theta_w = theta
            thetabar_w = thetabar

        _l0 = TrialFunction(Vtrace)
        _dl = TestFunction(Vtrace)
        a_tr = _dl('+')*_l0('+')*(dS_vp + dS_hp) + _dl*_l0*ds_vp + _dl*_l0*ds_tbp

        def L_tr(f):
            return _dl('+')*avg(f)*(dS_vp + dS_hp) + _dl*f*ds_vp + _dl*f*ds_tbp

        cg_ilu_parameters = {'ksp_type': 'cg',
                             'pc_type': 'bjacobi',
                             'sub_pc_type': 'ilu'}

        # Project field averages into functions on the trace space
        rhobar_avg = Function(Vtrace)
        pibar_avg = Function(Vtrace)

        rho_avg_prb = LinearVariationalProblem(a_tr, L_tr(rhobar), rhobar_avg)
        pi_avg_prb = LinearVariationalProblem(a_tr, L_tr(pibar), pibar_avg)

        rho_avg_solver = LinearVariationalSolver(rho_avg_prb,
                                                 solver_parameters=cg_ilu_parameters,
                                                 options_prefix='rhobar_avg_solver')
        pi_avg_solver = LinearVariationalSolver(pi_avg_prb,
                                                solver_parameters=cg_ilu_parameters,
                                                options_prefix='pibar_avg_solver')

        with timed_region("Gusto:HybridProjectRhobar"):
            rho_avg_solver.solve()

        with timed_region("Gusto:HybridProjectPibar"):
            pi_avg_solver.solve()

        # "broken" u, rho, and trace system
        # NOTE: no ds_v integrals since equations are defined on
        # a periodic (or sphere) base mesh.
        eqn = (
            # momentum equation
            inner(w, (state.h_project(u) - u_in))*dx
            - beta_cp*div(theta_w*V(w))*pibar*dxp
            # following does nothing but is preserved in the comments
            # to remind us why (because V(w) is purely vertical).
            # + beta_cp*jump(theta_w*V(w), n=n)*pibar_avg('+')*dS_vp
            + beta_cp*jump(theta_w*V(w), n=n)*pibar_avg('+')*dS_hp
            + beta_cp*dot(theta_w*V(w), n)*pibar_avg*ds_tbp
            - beta_cp*div(thetabar_w*w)*pi*dxp
            # trace terms appearing after integrating momentum equation
            + beta_cp*jump(thetabar_w*w, n=n)*l0('+')*(dS_vp + dS_hp)
            + beta_cp*dot(thetabar_w*w, n)*l0*(ds_tbp + ds_vp)
            # mass continuity equation
            + (phi*(rho - rho_in) - beta*inner(grad(phi), u)*rhobar)*dx
            + beta*jump(phi*u, n=n)*rhobar_avg('+')*(dS_v + dS_h)
            # term added because u.n=0 is enforced weakly via the traces
            + beta*phi*dot(u, n)*rhobar_avg*(ds_tb + ds_v)
            # constraint equation to enforce continuity of the velocity
            # through the interior facets and weakly impose the no-slip
            # condition
            + dl('+')*jump(u, n=n)*(dS_vp + dS_hp)
            + dl*dot(u, n)*(ds_tbp + ds_vp)
        )

        # contribution of the sponge term
        if mu is not None:
            eqn += dt*mu*inner(w, k)*inner(u, k)*dx

        aeqn = lhs(eqn)
        Leqn = rhs(eqn)

        # Function for the hybridized solutions
        self.urhol0 = Function(M)

        hybridized_prb = LinearVariationalProblem(aeqn, Leqn, self.urhol0)
        hybridized_solver = LinearVariationalSolver(hybridized_prb,
                                                    solver_parameters=self.solver_parameters,
                                                    options_prefix='ImplicitSolver')
        self.hybridized_solver = hybridized_solver

        # Project broken u into the HDiv space using facet averaging.
        # Weight function counting the dofs of the HDiv element:
        shapes = {"i": Vu.finat_element.space_dimension(),
                  "j": np.prod(Vu.shape, dtype=int)}
        weight_kernel = """
        for (int i=0; i<{i}; ++i)
            for (int j=0; j<{j}; ++j)
                w[i*{j} + j] += 1.0;
        """.format(**shapes)

        self._weight = Function(Vu)
        par_loop(weight_kernel, dx, {"w": (self._weight, INC)})

        # Averaging kernel
        self._average_kernel = """
        for (int i=0; i<{i}; ++i)
            for (int j=0; j<{j}; ++j)
                vec_out[i*{j} + j] += vec_in[i*{j} + j]/w[i*{j} + j];
        """.format(**shapes)

        # HDiv-conforming velocity
        self.u_hdiv = Function(Vu)

        # Reconstruction of theta
        theta = TrialFunction(Vtheta)
        gamma = TestFunction(Vtheta)

        self.theta = Function(Vtheta)
        theta_eqn = gamma*(theta - theta_in
                           + dot(k, self.u_hdiv)*dot(k, grad(thetabar))*beta)*dx

        theta_problem = LinearVariationalProblem(lhs(theta_eqn), rhs(theta_eqn), self.theta)
        self.theta_solver = LinearVariationalSolver(theta_problem,
                                                    solver_parameters=cg_ilu_parameters,
                                                    options_prefix='thetabacksubstitution')

        # Store boundary conditions for the div-conforming velocity to apply
        # post-solve
        self.bcs = self.state.bcs
u_exact = x * y * (1 - fd.exp(c[0] *
                              (x - 1))) * (1 - fd.exp(c[1] * (y - 1))) / (
                                  (1 - fd.exp(-c[0])) * (1 - fd.exp(-c[1])))
source = fd.div(velocity * u_exact) - fd.div(Dm * fd.grad(u_exact))

# stability
tau_d = fd.Constant(max([Dm, tau_e])) / h
tau_a = abs(fd.dot(velocity, n))
# tau = fd.Constant(1.0) / h + vn

# numerical flux
qhat = qh + tau_d * (ch - lmbd_h) * n
fhat = velocity * lmbd_h + tau_a * (ch - lmbd_h) * n

a_u = (
    fd.inner(fd.inv(Dm) * qh, vh) * fd.dx - ch * fd.div(vh) * fd.dx +
    # internal faces
    fd.jump(lmbd_h * vh, n) * fd.dS +
    # other faces
    lmbd_h * fd.inner(vh, n) * fd.ds)

# Dirichlet faces
L_u = 0

a_c = (-fd.inner(fd.grad(wh), qh + ch * velocity) * fd.dx +
       wh('+') * fd.jump(qhat + fhat, n) * fd.dS +
       wh * fd.inner(qhat + fhat, n) * fd.ds - wh * source * fd.dx)

L_c = 0

# transmission boundary condition
Beispiel #34
0
 def V(u):
     return k*inner(u, k)
 def rhs_form(self):
     v = firedrake.TestFunction(self.target.function_space())
     form = firedrake.inner(self.source, v)*firedrake.dx
     return form
Beispiel #36
0
    def advection_term(self, q):

        n = FacetNormal(self.state.mesh)
        Upwind = 0.5 * (sign(dot(self.ubar, n)) + 1)

        if self.state.mesh.topological_dimension() == 3:
            # <w,curl(u) cross ubar + grad( u.ubar)>
            # =<curl(u),ubar cross w> - <div(w), u.ubar>
            # =<u,curl(ubar cross w)> -
            #      <<u_upwind, [[n cross(ubar cross w)cross]]>>

            both = lambda u: 2 * avg(u)

            L = (inner(q, curl(cross(self.ubar, self.test))) * dx -
                 inner(both(Upwind * q),
                       both(cross(n, cross(self.ubar, self.test)))) * self.dS)

        else:

            perp = self.state.perp
            if self.state.on_sphere:
                outward_normals = CellNormal(self.state.mesh)
                perp_u_upwind = lambda q: Upwind('+') * cross(
                    outward_normals('+'), q('+')) + Upwind('-') * cross(
                        outward_normals('-'), q('-'))
            else:
                perp_u_upwind = lambda q: Upwind('+') * perp(q('+')) + Upwind(
                    '-') * perp(q('-'))

            if self.ibp == IntegrateByParts.ONCE:
                L = (-inner(perp(grad(inner(self.test, perp(self.ubar)))), q) *
                     dx - inner(jump(inner(self.test, perp(self.ubar)), n),
                                perp_u_upwind(q)) * self.dS)
            else:
                L = ((-inner(self.test,
                             div(perp(q)) * perp(self.ubar))) * dx -
                     inner(jump(inner(self.test, perp(self.ubar)), n),
                           perp_u_upwind(q)) * self.dS +
                     jump(inner(self.test, perp(self.ubar)) * perp(q), n) *
                     self.dS)

        L -= 0.5 * div(self.test) * inner(q, self.ubar) * dx

        return L
Beispiel #37
0
 def mass_term(self, test, trial):
     r"""Return the UFL for the mass term \int test * trial * dx typically used in the time term."""
     return firedrake.inner(test, trial) * self.dx
Beispiel #38
0
def mass(mesh, degree):
    V = FunctionSpace(mesh, 'CG', degree)
    u = TrialFunction(V)
    v = TestFunction(V)
    return inner(u, v) * dx
    def _setup_solver(self):
        state = self.state      # just cutting down line length a bit
        dt = state.timestepping.dt
        beta = dt*state.timestepping.alpha
        mu = state.mu

        # Split up the rhs vector (symbolically)
        u_in, p_in, b_in = split(state.xrhs)

        # Build the reduced function space for u,p
        M = MixedFunctionSpace((state.V[0], state.V[1]))
        w, phi = TestFunctions(M)
        u, p = TrialFunctions(M)

        # Get background fields
        bbar = state.bbar

        # Analytical (approximate) elimination of theta
        k = state.k             # Upward pointing unit vector
        b = -dot(k,u)*dot(k,grad(bbar))*beta + b_in

        # vertical projection
        def V(u):
            return k*inner(u,k)

        eqn = (
            inner(w, (u - u_in))*dx
            - beta*div(w)*p*dx
            - beta*inner(w,k)*b*dx
            + phi*div(u)*dx
        )

        if mu is not None:
            eqn += dt*mu*inner(w,k)*inner(u,k)*dx
        aeqn = lhs(eqn)
        Leqn = rhs(eqn)

        # Place to put result of u p solver
        self.up = Function(M)

        # Boundary conditions (assumes extruded mesh)
        dim = M.sub(0).ufl_element().value_shape()[0]
        bc = ("0.0",)*dim
        bcs = [DirichletBC(M.sub(0), Expression(bc), "bottom"),
               DirichletBC(M.sub(0), Expression(bc), "top")]

        # preconditioner equation
        L = self.L
        Ap = (
            inner(w,u) + L*L*div(w)*div(u) +
            phi*p/L/L
        )*dx

        # Solver for u, p
        up_problem = LinearVariationalProblem(
            aeqn, Leqn, self.up, bcs=bcs, aP=Ap)

        nullspace = MixedVectorSpaceBasis(M,
                                          [M.sub(0),
                                           VectorSpaceBasis(constant=True)])

        self.up_solver = LinearVariationalSolver(up_problem,
                                                 solver_parameters=self.params,
                                                 nullspace=nullspace)

        # Reconstruction of b
        b = TrialFunction(state.V[2])
        gamma = TestFunction(state.V[2])

        u, p = self.up.split()
        self.b = Function(state.V[2])

        b_eqn = gamma*(b - b_in +
                       dot(k,u)*dot(k,grad(bbar))*beta)*dx

        b_problem = LinearVariationalProblem(lhs(b_eqn),
                                             rhs(b_eqn),
                                             self.b)
        self.b_solver = LinearVariationalSolver(b_problem)
Beispiel #40
0
    timesteps, indices = chk.get_timesteps()
    chk.set_timestep(timesteps[-1], idx=indices[-1])

    chk.load(h, name='h')
    chk.load(u, name='u')

x, y, ζ = firedrake.SpatialCoordinate(mesh)

P_0 = 1
P_1 = np.sqrt(3) * (2 * ζ - 1)
P_2 = np.sqrt(5) * (6 * ζ**2 - 6 * ζ + 1)

weight = P_0 - np.sqrt(3) * P_1 + np.sqrt(5) * P_2
u_b = icepack.depth_average(u, weight=weight)

weight = P_0 + np.sqrt(3) * P_1 + np.sqrt(5) * P_2
u_s = icepack.depth_average(u, weight=weight)

U_b = sqrt(inner(u_b, u_b))
U_s = sqrt(inner(u_s, u_s))
Q2d = firedrake.FunctionSpace(mesh2d, 'CG', 1)
ratio = firedrake.project(U_b / U_s, Q2d)

fig, axes = icepack.plot.subplots()
axes.set_xlim(0, 640e3)
axes.set_ylim(0, 80e3)
axes.get_yaxis().set_visible(False)
colors = icepack.plot.tripcolor(ratio, vmin=0.8, vmax=1.0, axes=axes)
fig.colorbar(colors, ax=axes, fraction=0.0075, pad=0.04)
fig.savefig(args.output, dpi=300, bbox_inches='tight')
Beispiel #41
0
def exact_u(h_expr, Q):
    h = interpolate(h_expr,Q)
    u_exact = -A0 * h**(n + 1) * inner(grad(h), grad(h)) * grad(h)
    return u_exact
Beispiel #42
0
    def initialize(self, pc):
        from firedrake import TrialFunction, TestFunction, Function, DirichletBC, dx, \
             assemble, Mesh, inner, grad, split, Constant, parameters
        from firedrake.assemble import allocate_matrix, create_assembly_callable

        prefix = pc.getOptionsPrefix() + "pcd_"

        _, P = pc.getOperators()
        context = P.getPythonContext()

        test, trial = context.a.arguments()

        Q = test.function_space()

        p = TrialFunction(Q)
        q = TestFunction(Q)

        nu = context.appctx["nu"]
        dt = context.appctx["dt"]

        mass = (1.0 / nu) * p * q * dx

        stiffness = inner(grad(p), grad(q)) * dx

        velid = context.appctx["velocity_space"]

        self.bcs = context.appctx["PCDbc"]

        opts = PETSc.Options()

        default = parameters["default_matrix_type"]
        Mp_mat_type = opts.getString(prefix + "Mp_mat_type", default)
        Kp_mat_type = opts.getString(prefix + "Kp_mat_type", default)
        Fp_mat_type = opts.getString(prefix + "Fp_mat_type", "matfree")

        Mp = assemble(mass,
                      form_compiler_parameters=context.fc_params,
                      mat_type=Mp_mat_type,
                      options_prefix=prefix + "Mp_")

        Kp = assemble(stiffness,
                      bcs=self.bcs,
                      form_compiler_parameters=context.fc_params,
                      mat_type=Kp_mat_type,
                      options_prefix=prefix + "Kp_")

        Mksp = PETSc.KSP().create(comm=pc.comm)
        Mksp.incrementTabLevel(1, parent=pc)
        Mksp.setOptionsPrefix(prefix + "Mp_")
        Mksp.setOperators(Mp.petscmat)
        Mksp.setUp()
        Mksp.setFromOptions()
        self.Mksp = Mksp

        Kksp = PETSc.KSP().create(comm=pc.comm)
        Kksp.incrementTabLevel(1, parent=pc)
        Kksp.setOptionsPrefix(prefix + "Kp_")
        Kksp.setOperators(Kp.petscmat)
        Kksp.setUp()
        Kksp.setFromOptions()
        self.Kksp = Kksp

        u = context.appctx["u"]
        fp = (1.0 / nu) * ((1.0 / dt) * p + dot(u, grad(p))) * q * dx

        Fp = allocate_matrix(fp,
                             form_compiler_parameters=context.fc_params,
                             mat_type=Fp_mat_type,
                             options_prefix=prefix + "Fp_")

        self._assemble_Fp = create_assembly_callable(
            fp,
            tensor=Fp,
            form_compiler_parameters=context.fc_params,
            mat_type=Fp_mat_type)

        self.Fp = Fp
        self._assemble_Fp()
        self.workspace = [Fp.petscmat.createVecLeft() for i in (0, 1)]

        self.tmp = Function(Q)
# tau_a = vn

# numerical flux
chat = lmbd_h
###########################################
qhat = qh + tau_d * (ch - chat) * n + velocity * chat + tau_a * (ch - chat) * n
# qhat = qh + tau*(ch - chat)*n + velocity * cupw
# qhat_n = fd.dot(qh, n) + tau*(ch - chat) + chat*vn

# ###########################################
# # Lax-Friedrichs/Roe form
# ch_a = 0.5*(ch('+') + ch('-'))
# qhat = qh + tau_d*(ch - chat)*n + velocity * ch_a + tau_a*(ch - ch_a)*n

a_u = (
    fd.inner(fd.inv(Diff) * qh, vh) * fd.dx - ch * fd.div(vh) * fd.dx +
    # internal faces
    fd.jump(lmbd_h * vh, n) * fd.dS +
    # other faces
    lmbd_h * fd.inner(vh, n) * fd.ds(outflow) +
    lmbd_h * fd.inner(vh, n) * fd.ds(TOP) +
    lmbd_h * fd.inner(vh, n) * fd.ds(BOTTOM))

# Dirichlet faces
L_u = -fd.Constant(cIn) * fd.inner(vh, n) * fd.ds(inlet)

a_c = (wh * (ch - c0) / dtc * fd.dx -
       fd.inner(fd.grad(wh), qh + ch * velocity) * fd.dx +
       wh("+") * fd.jump(qhat, n) * fd.dS + wh * fd.inner(qhat, n) * fd.ds)

L_c = 0
def compressible_hydrostatic_balance(state, theta0, rho0, pi0=None,
                                     top=False, pi_boundary=Constant(1.0),
                                     solve_for_rho=False,
                                     params=None):
    """
    Compute a hydrostatically balanced density given a potential temperature
    profile.

    :arg state: The :class:`State` object.
    :arg theta0: :class:`.Function`containing the potential temperature.
    :arg rho0: :class:`.Function` to write the initial density into.
    :arg top: If True, set a boundary condition at the top. Otherwise, set
    it at the bottom.
    :arg pi_boundary: a field or expression to use as boundary data for pi on
    the top or bottom as specified.
    """

    # Calculate hydrostatic Pi
    W = MixedFunctionSpace((state.Vv,state.V[1]))
    v, pi = TrialFunctions(W)
    dv, dpi = TestFunctions(W)

    n = FacetNormal(state.mesh)

    cp = state.parameters.cp

    alhs = (
        (cp*inner(v,dv) - cp*div(dv*theta0)*pi)*dx
        + dpi*div(theta0*v)*dx
    )

    if top:
        bmeasure = ds_t
        bstring = "bottom"
    else:
        bmeasure = ds_b
        bstring = "top"

    arhs = -cp*inner(dv,n)*theta0*pi_boundary*bmeasure
    if state.parameters.geopotential:
        Phi = state.Phi
        arhs += div(dv)*Phi*dx - inner(dv,n)*Phi*bmeasure
    else:
        g = state.parameters.g
        arhs -= g*inner(dv,state.k)*dx

    if(state.mesh.geometric_dimension() == 2):
        bcs = [DirichletBC(W.sub(0), Expression(("0.", "0.")), bstring)]
    elif(state.mesh.geometric_dimension() == 3):
        bcs = [DirichletBC(W.sub(0), Expression(("0.", "0.", "0.")), bstring)]
    w = Function(W)
    PiProblem = LinearVariationalProblem(alhs, arhs, w, bcs=bcs)

    if(params is None):
        params = {'pc_type': 'fieldsplit',
                  'pc_fieldsplit_type': 'schur',
                  'ksp_type': 'gmres',
                  'ksp_monitor_true_residual': True,
                  'ksp_max_it': 100,
                  'ksp_gmres_restart': 50,
                  'pc_fieldsplit_schur_fact_type': 'FULL',
                  'pc_fieldsplit_schur_precondition': 'selfp',
                  'fieldsplit_0_ksp_type': 'richardson',
                  'fieldsplit_0_ksp_max_it': 5,
                  'fieldsplit_0_pc_type': 'gamg',
                  'fieldsplit_1_pc_gamg_sym_graph': True,
                  'fieldsplit_1_mg_levels_ksp_type': 'chebyshev',
                  'fieldsplit_1_mg_levels_ksp_chebyshev_estimate_eigenvalues': True,
                  'fieldsplit_1_mg_levels_ksp_chebyshev_estimate_eigenvalues_random': True,
                  'fieldsplit_1_mg_levels_ksp_max_it': 5,
                  'fieldsplit_1_mg_levels_pc_type': 'bjacobi',
                  'fieldsplit_1_mg_levels_sub_pc_type': 'ilu'}

    PiSolver = LinearVariationalSolver(PiProblem,
                                       solver_parameters=params)

    PiSolver.solve()
    v, Pi = w.split()
    if pi0 is not None:
        pi0.assign(Pi)

    kappa = state.parameters.kappa
    R_d = state.parameters.R_d
    p_0 = state.parameters.p_0

    if solve_for_rho:
        w1 = Function(W)
        v, rho = w1.split()
        rho.interpolate(p_0*(Pi**((1-kappa)/kappa))/R_d/theta0)
        v, rho = split(w1)
        dv, dpi = TestFunctions(W)
        pi = ((R_d/p_0)*rho*theta0)**(kappa/(1.-kappa))
        F = (
            (cp*inner(v,dv) - cp*div(dv*theta0)*pi)*dx
            + dpi*div(theta0*v)*dx
            + cp*inner(dv,n)*theta0*pi_boundary*bmeasure
        )
        if state.parameters.geopotential:
            F += - div(dv)*Phi*dx + inner(dv,n)*Phi*bmeasure
        else:
            F += g*inner(dv,state.k)*dx
        rhoproblem = NonlinearVariationalProblem(F, w1, bcs=bcs)
        rhosolver = NonlinearVariationalSolver(rhoproblem, solver_parameters=params)
        rhosolver.solve()
        v, rho_ = w1.split()
        rho0.assign(rho_)
    else:
        rho0.interpolate(p_0*(Pi**((1-kappa)/kappa))/R_d/theta0)
Beispiel #45
0
 def norm(u):
     return fd.inner(u, u) * fd.dx
Beispiel #46
0
        def get_flux_form(dS, M):

            fluxes = (-inner(2*avg(outer(phi, n)), avg(grad(gamma)*M))
                      - inner(avg(grad(phi)*M), 2*avg(outer(gamma, n)))
                      + mu*inner(2*avg(outer(phi, n)), 2*avg(outer(gamma, n)*kappa)))*dS
            return fluxes
Beispiel #47
0
    def __init__(self, state, V):
        super(EulerPoincareForm, self).__init__(state)

        dt = state.timestepping.dt
        w = TestFunction(V)
        u = TrialFunction(V)
        self.u0 = Function(V)
        ustar = 0.5*(self.u0 + u)
        n = FacetNormal(state.mesh)
        Upwind = 0.5*(sign(dot(self.ubar, n))+1)

        if state.mesh.geometric_dimension() == 3:

            if V.extruded:
                surface_measure = (dS_h + dS_v)
            else:
                surface_measure = dS

            # <w,curl(u) cross ubar + grad( u.ubar)>
            # =<curl(u),ubar cross w> - <div(w), u.ubar>
            # =<u,curl(ubar cross w)> -
            #      <<u_upwind, [[n cross(ubar cross w)cross]]>>

            both = lambda u: 2*avg(u)

            Eqn = (
                inner(w, u-self.u0)*dx
                + dt*inner(ustar, curl(cross(self.ubar, w)))*dx
                - dt*inner(both(Upwind*ustar),
                           both(cross(n, cross(self.ubar, w))))*surface_measure
                - dt*div(w)*inner(ustar, self.ubar)*dx
            )

        # define surface measure and terms involving perp differently
        # for slice (i.e. if V.extruded is True) and shallow water
        # (V.extruded is False)
        else:
            if V.extruded:
                surface_measure = (dS_h + dS_v)
                perp = lambda u: as_vector([-u[1], u[0]])
                perp_u_upwind = Upwind('+')*perp(ustar('+')) + Upwind('-')*perp(ustar('-'))
            else:
                surface_measure = dS
                outward_normals = CellNormal(state.mesh)
                perp = lambda u: cross(outward_normals, u)
                perp_u_upwind = Upwind('+')*cross(outward_normals('+'),ustar('+')) + Upwind('-')*cross(outward_normals('-'),ustar('-'))

            Eqn = (
                (inner(w, u-self.u0)
                 - dt*inner(w, div(perp(ustar))*perp(self.ubar))
                 - dt*div(w)*inner(ustar, self.ubar))*dx
                - dt*inner(jump(inner(w, perp(self.ubar)), n),
                           perp_u_upwind)*surface_measure
                + dt*jump(inner(w,
                                perp(self.ubar))*perp(ustar), n)*surface_measure
            )

        a = lhs(Eqn)
        L = rhs(Eqn)
        self.u1 = Function(V)
        uproblem = LinearVariationalProblem(a, L, self.u1)
        self.usolver = LinearVariationalSolver(uproblem,
                                               options_prefix='EPAdvection')
 def V(u):
     return k*inner(u,k)
Beispiel #49
0
                                        Q,
                                        fixed_bids=fixed_bids,
                                        direct_solve=True)

# import IPython; IPython.embed()

res = [0, 1, 10, 50, 100, 150, 200, 250, 300, 400, 499, 625, 750, 875, 999]
res = [r for r in res if r <= optre - 1]
if res[-1] != optre - 1:
    res.append(optre - 1)
results = run_solver(solver, res, args)
# import sys; sys.exit()

u, _ = fd.split(solver.z)
nu = solver.nu
objective_form = nu * fd.inner(fd.sym(fd.grad(u)), fd.sym(fd.grad(u))) * fd.dx
solver.setup_adjoint(objective_form)
solver.solver_adjoint.solve()

# import sys; sys.exit()


class Constraint(fs.PdeConstraint):
    def solve(self):
        super().solve()
        solver.solve(optre)


class Objective(fs.ShapeObjective):
    def __init__(self, *args_, **kwargs_):
        super().__init__(*args_, **kwargs_)
    def _setup_solver(self):
        state = self.state      # just cutting down line length a bit
        dt = state.timestepping.dt
        beta = dt*state.timestepping.alpha
        cp = state.parameters.cp
        mu = state.mu

        # Split up the rhs vector (symbolically)
        u_in, rho_in, theta_in = split(state.xrhs)

        # Build the reduced function space for u,rho
        M = MixedFunctionSpace((state.V[0], state.V[1]))
        w, phi = TestFunctions(M)
        u, rho = TrialFunctions(M)

        n = FacetNormal(state.mesh)

        # Get background fields
        thetabar = state.thetabar
        rhobar = state.rhobar
        pibar = exner(thetabar, rhobar, state)
        pibar_rho = exner_rho(thetabar, rhobar, state)
        pibar_theta = exner_theta(thetabar, rhobar, state)

        # Analytical (approximate) elimination of theta
        k = state.k             # Upward pointing unit vector
        theta = -dot(k,u)*dot(k,grad(thetabar))*beta + theta_in

        # Only include theta' (rather than pi') in the vertical
        # component of the gradient

        # the pi prime term (here, bars are for mean and no bars are
        # for linear perturbations)

        pi = pibar_theta*theta + pibar_rho*rho

        # vertical projection
        def V(u):
            return k*inner(u,k)

        eqn = (
            inner(w, (u - u_in))*dx
            - beta*cp*div(theta*V(w))*pibar*dx
            # following does nothing but is preserved in the comments
            # to remind us why (because V(w) is purely vertical.
            # + beta*cp*jump(theta*V(w),n)*avg(pibar)*dS_v
            - beta*cp*div(thetabar*w)*pi*dx
            + beta*cp*jump(thetabar*w,n)*avg(pi)*dS_v
            + (phi*(rho - rho_in) - beta*inner(grad(phi), u)*rhobar)*dx
            + beta*jump(phi*u, n)*avg(rhobar)*(dS_v + dS_h)
        )

        if mu is not None:
            eqn += dt*mu*inner(w,k)*inner(u,k)*dx
        aeqn = lhs(eqn)
        Leqn = rhs(eqn)

        # Place to put result of u rho solver
        self.urho = Function(M)

        # Boundary conditions (assumes extruded mesh)
        dim = M.sub(0).ufl_element().value_shape()[0]
        bc = ("0.0",)*dim
        bcs = [DirichletBC(M.sub(0), Expression(bc), "bottom"),
               DirichletBC(M.sub(0), Expression(bc), "top")]

        # Solver for u, rho
        urho_problem = LinearVariationalProblem(
            aeqn, Leqn, self.urho, bcs=bcs)

        self.urho_solver = LinearVariationalSolver(urho_problem,
                                                   solver_parameters=self.params,
                                                   options_prefix='ImplicitSolver')

        # Reconstruction of theta
        theta = TrialFunction(state.V[2])
        gamma = TestFunction(state.V[2])

        u, rho = self.urho.split()
        self.theta = Function(state.V[2])

        theta_eqn = gamma*(theta - theta_in +
                           dot(k,u)*dot(k,grad(thetabar))*beta)*dx

        theta_problem = LinearVariationalProblem(lhs(theta_eqn),
                                                 rhs(theta_eqn),
                                                 self.theta)
        self.theta_solver = LinearVariationalSolver(theta_problem,
                                                    options_prefix='thetabacksubstitution')
Beispiel #51
0
 def value_form(self):
     """Evaluate misfit functional."""
     u = fd.split(self.pde_solver.solution)[0]
     nu = self.pde_solver.nu
     return 0.5 * nu * fd.inner(fd.grad(u), fd.grad(u)) * fd.dx