Ejemplo n.º 1
0
def AdvectionDiffusionGLS(
    V: fd.FunctionSpace,
    theta: fd.Function,
    phi: fd.Function,
    PeInv: float = 1e-4,
    phi_t: fd.Function = None,
):
    PeInv_ct = fd.Constant(PeInv)
    rho = fd.TestFunction(V)
    F = (inner(theta, grad(phi)) * rho +
         PeInv_ct * inner(grad(phi), grad(rho))) * dx

    if phi_t:
        F += phi_t * rho * dx

    h = fd.CellDiameter(V.ufl_domain())
    R_U = dot(theta, grad(phi)) - PeInv_ct * div(grad(phi))

    if phi_t:
        R_U += phi_t

    beta_gls = 0.9
    tau_gls = beta_gls * ((4.0 * dot(theta, theta) / h**2) + 9.0 *
                          (4.0 * PeInv_ct / h**2)**2)**(-0.5)

    theta_U = dot(theta, grad(rho)) - PeInv_ct * div(grad(rho))
    F += tau_gls * inner(R_U, theta_U) * dx()

    return F
Ejemplo n.º 2
0
    def residual(self, test, trial, trial_lagged, fields, bcs):
        u_adv = trial_lagged
        phi = test
        n = self.n
        u = trial

        F = -dot(u, div(outer(phi, u_adv)))*self.dx

        for id, bc in bcs.items():
            if 'u' in bc:
                u_in = bc['u']
            elif 'un' in bc:
                u_in = bc['un'] * n  # this implies u_t=0 on the inflow
            else:
                u_in = zero(self.dim)
            F += conditional(dot(u_adv, n) < 0,
                             dot(phi, u_in)*dot(u_adv, n),
                             dot(phi, u)*dot(u_adv, n)) * self.ds(id)

        if not (is_continuous(self.trial_space) and normal_is_continuous(u_adv)):
            # s=0: u.n(-)<0  =>  flow goes from '+' to '-' => '+' is upwind
            # s=1: u.n(-)>0  =>  flow goes from '-' to '+' => '-' is upwind
            s = 0.5*(sign(dot(avg(u), n('-'))) + 1.0)
            u_up = u('-')*s + u('+')*(1-s)
            F += dot(u_up, (dot(u_adv('+'), n('+'))*phi('+') + dot(u_adv('-'), n('-'))*phi('-'))) * self.dS

        return -F
Ejemplo n.º 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)
    def setup_solver(self, up_init=None):
        """ Setup the solvers
        """
        self.up0 = Function(self.W)
        if up_init is not None:
            chk_in = checkpointing.HDF5File(up_init, file_mode='r')
            chk_in.read(self.up0, "/up")
            chk_in.close()
        self.u0, self.p0 = split(self.up0)

        self.up = Function(self.W)
        if up_init is not None:
            chk_in = checkpointing.HDF5File(up_init, file_mode='r')
            chk_in.read(self.up, "/up")
            chk_in.close()
        self.u1, self.p1 = split(self.up)

        self.up.sub(0).rename("velocity")
        self.up.sub(1).rename("pressure")

        v, q = TestFunctions(self.W)

        h = CellVolume(self.mesh)
        u_norm = sqrt(dot(self.u0, self.u0))

        if self.has_nullspace:
            nullspace = MixedVectorSpaceBasis(
                self.W,
                [self.W.sub(0), VectorSpaceBasis(constant=True)])
        else:
            nullspace = None

        tau = ((2.0 / self.dt)**2 + (2.0 * u_norm / h)**2 +
               (4.0 * self.nu / h**2)**2)**(-0.5)

        # temporal discretization
        F = (1.0 / self.dt) * inner(self.u1 - self.u0, v) * dx

        # weak form
        F += (+inner(dot(self.u0, nabla_grad(self.u1)), v) * dx +
              self.nu * inner(grad(self.u1), grad(v)) * dx -
              (1.0 / self.rho) * self.p1 * div(v) * dx +
              div(self.u1) * q * dx - inner(self.forcing, v) * dx)

        # residual form
        R = (+(1.0 / self.dt) * (self.u1 - self.u0) +
             dot(self.u0, nabla_grad(self.u1)) - self.nu * div(grad(self.u1)) +
             (1.0 / self.rho) * grad(self.p1) - self.forcing)

        # GLS
        F += tau * inner(
            +dot(self.u0, nabla_grad(v)) - self.nu * div(grad(v)) +
            (1.0 / self.rho) * grad(q), R) * dx

        self.problem = NonlinearVariationalProblem(F, self.up, self.bcs)
        self.solver = NonlinearVariationalSolver(
            self.problem,
            nullspace=nullspace,
            solver_parameters=self.solver_parameters)
Ejemplo n.º 5
0
 def kinetic(self, u, factor=None):
     """
     Computes 0.5*dot(u, u) with an option to multiply rho
     """
     if factor is not None:
         energy = 0.5*factor*dot(u, u)
     else:
         energy = 0.5*dot(u, u)
     return energy
Ejemplo n.º 6
0
def linear_advection_form(state, test, qbar):

    ubar = Function(state.spaces("HDiv"))

    L = test * dot(ubar, state.k) * dot(state.k, grad(qbar)) * dx

    form = transporting_velocity(L, ubar)

    return transport(form, TransportEquationType.advective)
Ejemplo n.º 7
0
    def advection_term(self, q):

        if self.continuity:
            n = FacetNormal(self.state.mesh)
            L = (-dot(grad(self.test), self.ubar) * self.qbar * dx +
                 jump(self.ubar * self.test, n) * avg(self.qbar) * self.dS)
        else:
            L = self.test * dot(self.ubar, self.state.k) * dot(
                self.state.k, grad(self.qbar)) * dx
        return L
Ejemplo n.º 8
0
    def topography_term(self):
        g = self.state.parameters.g
        u0, _ = split(self.x0)
        b = self.state.fields("topography")
        n = FacetNormal(self.state.mesh)
        un = 0.5 * (dot(u0, n) + abs(dot(u0, n)))

        L = g * div(self.test) * b * dx - g * inner(
            jump(self.test, n),
            un('+') * b('+') - un('-') * b('-')) * dS
        return L
Ejemplo n.º 9
0
    def pressure_gradient_term(self):

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

        L = g * (div(self.test) * D0 * dx -
                 inner(jump(self.test, n),
                       un('+') * D0('+') - un('-') * D0('-')) * dS)
        return L
Ejemplo n.º 10
0
    def dgls_form(self, problem, mesh, bcs_p):
        rho = problem.rho
        mu = problem.mu
        k = problem.k
        f = problem.f

        q, p = fire.TrialFunctions(self._W)
        w, v = fire.TestFunctions(self._W)

        n = fire.FacetNormal(mesh)
        h = fire.CellDiameter(mesh)

        # Stabilizing parameters
        has_mesh_characteristic_length = True
        delta_0 = fire.Constant(1)
        delta_1 = fire.Constant(-1 / 2)
        delta_2 = fire.Constant(1 / 2)
        delta_3 = fire.Constant(1 / 2)
        eta_p = fire.Constant(100)
        eta_q = fire.Constant(100)
        h_avg = (h("+") + h("-")) / 2.0
        if has_mesh_characteristic_length:
            delta_2 = delta_2 * h * h
            delta_3 = delta_3 * h * h

        kappa = rho * k / mu
        inv_kappa = 1.0 / kappa

        # Classical mixed terms
        a = (dot(inv_kappa * q, w) - div(w) * p - delta_0 * v * div(q)) * dx
        L = -delta_0 * f * v * dx

        # DG terms
        a += jump(w, n) * avg(p) * dS - avg(v) * jump(q, n) * dS

        # Edge stabilizing terms
        a += (eta_q * h_avg) * avg(inv_kappa) * (
            jump(q, n) * jump(w, n)) * dS + (eta_p / h_avg) * avg(kappa) * dot(
                jump(v, n), jump(p, n)) * dS

        # Add the contributions of the pressure boundary conditions to L
        for pboundary, iboundary in bcs_p:
            L -= pboundary * dot(w, n) * ds(iboundary)

        # Stabilizing terms
        a += (delta_1 * inner(kappa * (inv_kappa * q + grad(p)),
                              delta_0 * inv_kappa * w + grad(v)) * dx)
        a += delta_2 * inv_kappa * div(q) * div(w) * dx
        a += delta_3 * inner(kappa * curl(inv_kappa * q), curl(
            inv_kappa * w)) * dx
        L += delta_2 * inv_kappa * f * div(w) * dx

        return a, L
Ejemplo n.º 11
0
def form_function(u, h, v, q):
    K = 0.5 * fd.inner(u, u)
    n = fd.FacetNormal(mesh)
    uup = 0.5 * (fd.dot(u, n) + abs(fd.dot(u, n)))
    Upwind = 0.5 * (fd.sign(fd.dot(u, n)) + 1)

    eqn = (fd.inner(v, f * perp(u)) * fd.dx -
           fd.inner(perp(fd.grad(fd.inner(v, perp(u)))), u) * fd.dx +
           fd.inner(both(perp(n) * fd.inner(v, perp(u))), both(Upwind * u)) *
           fd.dS - fd.div(v) * (g * (h + b) + K) * fd.dx -
           fd.inner(fd.grad(q), u) * h * fd.dx + fd.jump(q) *
           (uup('+') * h('+') - uup('-') * h('-')) * fd.dS)
    return eqn
Ejemplo n.º 12
0
    def initialize_solvers(self):
        # Kinematics                # Right Cauchy-Green tensor
        if self.nonlin:
            d = self.X.geometric_dimension()
            I = fd.Identity(d)  # Identity tensor
            F = I + fd.grad(self.X)  # Deformation gradient
            C = F.T * F
            E = (C - I) / 2.  # Green-Lagrangian strain
#            E = 1./2.*( fd.grad(self.X).T + fd.grad(self.X) + fd.grad(self.X).T * fd.grad(self.X) ) # alternative equivalent definition
        else:
            E = 1. / 2. * (fd.grad(self.X).T + fd.grad(self.X)
                           )  # linear strain

        self.W = (self.lam / 2.) * (fd.tr(E))**2 + self.mu * fd.tr(E * E)
        #        f = fd.Constant((0, 0, -self.g)) # body force / rho
        #        T = self.surface_force()

        # Total potential energy
        Pi = self.W * fd.dx
        # Compute first variation of Pi (directional derivative about X in the direction of v)
        F_expr = fd.derivative(Pi, self.X, self.v)

        self.DBC = fd.DirichletBC(self.V, fd.as_vector([0., 0., 0.]),
                                  self.bottom_id)

        #        delX = fd.nabla_grad(self.X)
        #        delv_B = fd.nabla_grad(self.v)
        #        T_x_dv = self.lam * fd.div(self.X) * fd.div(self.v) \
        #                + self.mu * ( fd.inner( delX, delv_B + fd.transpose(delv_B) ) )

        self.a_U = fd.dot(self.trial, self.v) * fd.dx
        #        self.L_U = ( fd.dot( self.U, self.v ) - self.dt/2./self.rho * T_x_dv ) * fd.dx
        self.L_U = fd.dot(
            self.U, self.v) * fd.dx - self.dt / 2. / self.rho * F_expr  #\
        #                  + self.dt/2./self.rho*fd.dot(T,self.v)*fd.ds(1) # surface force at x==0 plane
        # + self.dt/2.*fd.dot(f,self.v)*fd.dx # body force
        self.a_X = fd.dot(self.trial, self.v) * fd.dx
        #        self.L_interface = fd.dot(self.phi_vect, self.v) * fd.ds(self.interface_id)
        self.L_X = fd.dot((self.X + self.dt * self.U), self.v) * fd.dx  #\
        #                    - self.dt/self.rho * self.L_interface

        self.LVP_U = fd.LinearVariationalProblem(self.a_U,
                                                 self.L_U,
                                                 self.U,
                                                 bcs=[self.DBC])
        self.LVS_U = fd.LinearVariationalSolver(self.LVP_U)
        self.LVP_X = fd.LinearVariationalProblem(self.a_X,
                                                 self.L_X,
                                                 self.X,
                                                 bcs=[self.DBC])
        self.LVS_X = fd.LinearVariationalSolver(self.LVP_X)
Ejemplo n.º 13
0
    def __init__(self, state, V, *, ibp="once", solver_params=None):
        self.state = state
        self.V = V
        self.ibp = ibp

        # set up functions required for forms
        self.ubar = Function(state.spaces("HDiv"))
        self.test = TestFunction(V)
        self.trial = TrialFunction(V)

        # find out if we are CG
        nvertex = V.ufl_domain().ufl_cell().num_vertices()
        entity_dofs = V.finat_element.entity_dofs()
        # If there are as many dofs on vertices as there are vertices,
        # assume a continuous space.
        try:
            self.is_cg = sum(map(len, entity_dofs[0].values())) == nvertex
        except KeyError:
            self.is_cg = sum(map(len, entity_dofs[(0, 0)].values())) == nvertex

        # DG, embedded DG and hybrid SUPG methods need surface measures,
        # n and un
        if self.is_cg:
            self.dS = None
            self.ds = None
        else:
            if V.extruded:
                self.dS = (dS_h + dS_v)
                self.ds = (ds_b + ds_t + ds_v)
            else:
                self.dS = dS
                self.ds = ds
            self.n = FacetNormal(state.mesh)
            self.un = 0.5 * (dot(self.ubar, self.n) +
                             abs(dot(self.ubar, self.n)))

        if solver_params:
            self.solver_parameters = solver_params

        # default solver options
        else:
            self.solver_parameters = {
                'ksp_type': 'cg',
                'pc_type': 'bjacobi',
                'sub_pc_type': 'ilu'
            }
        if state.output.log_level == DEBUG:
            self.solver_parameters["ksp_monitor_true_residual"] = True
Ejemplo n.º 14
0
    def __init__(self, state, V, *, ibp="once", solver_params=None):
        super().__init__(state=state,
                         V=V,
                         ibp=ibp,
                         solver_params=solver_params)

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

        if self.state.mesh.topological_dimension() == 2:
            self.perp = state.perp
            if state.on_sphere:
                outward_normals = CellNormal(state.mesh)
                self.perp_u_upwind = lambda q: self.Upwind('+') * cross(
                    outward_normals('+'), q('+')) + self.Upwind('-') * cross(
                        outward_normals('-'), q('-'))
            else:
                self.perp_u_upwind = lambda q: self.Upwind('+') * state.perp(
                    q('+')) + self.Upwind('-') * state.perp(q('-'))
            self.gradperp = lambda u: state.perp(grad(u))
        elif self.state.mesh.topological_dimension() == 3:
            if self.ibp == "twice":
                raise NotImplementedError(
                    "ibp=twice is not implemented for 3d problems")
        else:
            raise RuntimeError("topological mesh dimension must be 2 or 3")
Ejemplo n.º 15
0
    def interpolate(self, mesh, k0L):
        V = fd.VectorFunctionSpace(mesh, "CG", 1)
        x = fd.SpatialCoordinate(mesh)

        pw = fd.interpolate(self.p * fd.exp(1j * k0L * fd.dot(self.s, x)), V)

        return pw
Ejemplo n.º 16
0
    def add_dirichlet(self, g, surface):
        """
        Adds dirichlet boundary conditions to the problem.

        Args:
            g (Function, int, or float):
                The function to apply on the boundary.
            surface (int or list of int):
                The index of the boundary to apply the condition to.
        """
        # Explicitly check against False as None should not be caught here.
        if self._has_boundary is False:
            raise AttributeError('Cannot add boundary after declaring that '
                                 'there are no boundaries')
        norm = FacetNormal(self.mesh)

        if isinstance(g, (float, int)):
            g = Constant(g)

        integrand = -1 * self.v * dot(self.q, norm)

        if surface == 'all':
            dbc = DirichletBC(V=self.V, g=g, sub_domain="on_boundary")
            self.a += integrand * ds
        else:
            dbc = DirichletBC(V=self.V, g=g, sub_domain=surface)
            try:
                self.a += sum(integrand * ds(s) for s in surface)
            except TypeError:
                self.a += integrand * ds(surface)

        self.bcs.append(dbc)
        self._has_boundary = True
Ejemplo n.º 17
0
def test_ilu():
    """Tests that ILU functionality gives correct solution."""

    k = 10.0

    num_cells = utils.h_to_num_cells(k**-1.5,2)

    mesh = fd.UnitSquareMesh(num_cells,num_cells)

    V = fd.FunctionSpace(mesh,"CG",1)
    
    prob = hh.HelmholtzProblem(k,V)

    angle = 2.0 * np.pi/7.0

    d = [np.cos(angle),np.sin(angle)]
    
    prob.f_g_plane_wave(d)

    for fill_in in range(40):
    
        prob.use_ilu_gmres(fill_in)

        prob.solve()

        x = fd.SpatialCoordinate(mesh)

        # This error was found out by eye
        assert np.abs(fd.norms.errornorm(fd.exp(1j * k * fd.dot(fd.as_vector(d),x)),uh=prob.u_h,norm_type='H1')) < 0.5
Ejemplo n.º 18
0
    def test_update_a_multiple_surfaces(self):
        """
        Test a is updated correctly for a with a multiple surfaces.
        """
        T = self.problem.T
        v = self.problem.v
        q = self.problem.q
        self.problem.a = T * dx

        g = Function(self.V)
        expected_a = T * dx + -1 * v * dot(q, self.norm) * ds(0)
        expected_a += -1 * v * dot(q, self.norm) * ds(1)

        self.problem.add_dirichlet(g, [0, 1])

        self.assertEqual(expected_a, self.problem.a)
Ejemplo n.º 19
0
def poisson_gll(mesh, degree):
    V = FunctionSpace(
        mesh, FiniteElement('Q', mesh.ufl_cell(), degree, variant='spectral'))
    u = TrialFunction(V)
    v = TestFunction(V)
    dim = mesh.topological_dimension()
    finat_rule = gauss_lobatto_legendre_cube_rule(dim, degree)
    return dot(grad(u), grad(v)) * dx(rule=finat_rule)
Ejemplo n.º 20
0
    def f_g_plane_wave(self, d):
        """Sets f and g to correspond to a plane wave

        Parameters - d - list of the length of the spatial dimension;
        the direction in which the plane wave propagates.
        """

        d = fd.as_vector(d)

        self.set_f(0.0)

        x = fd.SpatialCoordinate(self.V.mesh())

        nu = fd.FacetNormal(self.V.mesh())

        self.set_g(1j*self._k*fd.exp(1j*self._k*fd.dot(x,d))\
                   *(fd.dot(d,nu)-1.0))
Ejemplo n.º 21
0
def A(fs):
    u = TrialFunction(fs)
    v = TestFunction(fs)
    a = (dot(grad(v), grad(u))) * dx
    bc = DirichletBC(fs, 0., "on_boundary")
    A = assemble(a, bcs = bc)

    return A
Ejemplo n.º 22
0
    def _A(self):
        """
        Create a stiffness matrix section.

        Returns:
            Function: A complete stiffness matrix section.
        """
        return dot(self.q, grad(self.v)) * dx
Ejemplo n.º 23
0
def continuity_form(state, test, q, ibp=IntegrateByParts.ONCE, outflow=False):

    if outflow and ibp == IntegrateByParts.NEVER:
        raise ValueError(
            "outflow is True and ibp is None are incompatible options")
    Vu = state.spaces("HDiv")
    dS_ = (dS_v + dS_h) if Vu.extruded else dS
    ubar = Function(Vu)

    if ibp == IntegrateByParts.ONCE:
        L = -inner(grad(test), outer(q, ubar)) * dx
    else:
        L = inner(test, div(outer(q, ubar))) * dx

    if ibp != IntegrateByParts.NEVER:
        n = FacetNormal(state.mesh)
        un = 0.5 * (dot(ubar, n) + abs(dot(ubar, n)))

        L += dot(jump(test), (un('+') * q('+') - un('-') * q('-'))) * dS_

        if ibp == IntegrateByParts.TWICE:
            L -= (inner(test('+'),
                        dot(ubar('+'), n('+')) * q('+')) +
                  inner(test('-'),
                        dot(ubar('-'), n('-')) * q('-'))) * dS_

    if outflow:
        n = FacetNormal(state.mesh)
        un = 0.5 * (dot(ubar, n) + abs(dot(ubar, n)))
        L += test * un * q * (ds_v + ds_t + ds_b)

    form = transporting_velocity(L, ubar)

    return ibp_label(transport(form, TransportEquationType.conservative), ibp)
Ejemplo n.º 24
0
    def residual(self, test, trial, trial_lagged, fields, bcs):
        phi = test
        n = self.n
        p = fields['pressure']

        # NOTE: we assume p is continuous

        F = dot(phi, grad(p))*self.dx

        # do nothing should be zero (normal) stress:
        F += -dot(phi, n)*p*self.ds

        # for those boundaries where the normal component of u is specified
        # we take it out again
        for id, bc in bcs.items():
            if 'u' in bc or 'un' in bc:
                F += dot(phi, n)*p*self.ds(id)

        return -F
Ejemplo n.º 25
0
def vector_manifold_advection_form(state,
                                   test,
                                   q,
                                   ibp=IntegrateByParts.ONCE,
                                   outflow=False):

    L = advection_form(state, test, q, ibp, outflow)

    Vu = state.spaces("HDiv")
    dS_ = (dS_v + dS_h) if Vu.extruded else dS
    ubar = Function(Vu)
    n = FacetNormal(state.mesh)
    un = 0.5 * (dot(ubar, n) + abs(dot(ubar, n)))
    L += un('+') * inner(test('-'),
                         n('+') + n('-')) * inner(q('+'), n('+')) * dS_
    L += un('-') * inner(test('+'),
                         n('+') + n('-')) * inner(q('-'), n('-')) * dS_

    return L
Ejemplo n.º 26
0
def curl_curl(mesh, degree):
    cell = mesh.ufl_cell()
    if cell.cellname() in ['interval * interval', 'quadrilateral']:
        hcurl_element = FiniteElement('RTCE', cell, degree)
    elif cell.cellname() == 'quadrilateral * interval':
        hcurl_element = FiniteElement('NCE', cell, degree)
    V = FunctionSpace(mesh, hcurl_element)
    u = TrialFunction(V)
    v = TestFunction(V)
    return dot(curl(u), curl(v)) * dx
Ejemplo n.º 27
0
    def residual(self, test, trial, trial_lagged, fields, bcs):
        if 'source' not in fields:
            return 0

        phi = test
        source = fields['source']

        # NOTE, here source term F is already on the RHS
        F = dot(phi, source)*self.dx

        return F
Ejemplo n.º 28
0
    def __init__(self, state, V, qbar, options=None):
        super(LinearAdvection_Vt, self).__init__(state)

        p = TestFunction(V)
        q = TrialFunction(V)
        self.dq = Function(V)

        a = p*q*dx
        k = state.k             # Upward pointing unit vector
        L = -p*dot(self.ubar,k)*dot(k,grad(qbar))*dx

        aProblem = LinearVariationalProblem(a,L,self.dq)
        if options is None:
            options = {'ksp_type':'cg',
                       'pc_type':'bjacobi',
                       'sub_pc_type':'ilu'}

        self.solver = LinearVariationalSolver(aProblem,
                                              solver_parameters=options,
                                              options_prefix='LinearAdvectionVt')
Ejemplo n.º 29
0
def test_HelmholtzProblem_solver_convergence():
    """Test that the solver is converging at the correct rate."""
    k_range = [10.0,12.0,20.0,30.0,40.0]#[10.0,12.0]#[20.0,40.0]
    num_levels = 2
    tolerance = 0.05
    log_err_L2 = np.empty((num_levels,len(k_range)))
    log_err_H1 = np.empty((num_levels,len(k_range)))

    for ii_k in range(len(k_range)):
        k = k_range[ii_k]
        print(k)
        num_points = np.ceil(np.sqrt(2.0) * k**(1.5)) * 2.0**np.arange(float(num_levels))

        log_h = np.log(np.sqrt(2.0) * 1.0 / num_points)
        for ii_points in range(num_levels):
            print(ii_points)
            # Coarsest grid has h ~ k^{-1.5}, and then do uniform refinement
            mesh = fd.UnitSquareMesh(num_points[ii_points],num_points[ii_points])
            V = fd.FunctionSpace(mesh, "CG", 1)

            prob = hh.HelmholtzProblem(k,V)

            angle = 2.0*np.pi/7.0

            d = [np.cos(angle),np.sin(angle)]
            
            prob.f_g_plane_wave(d)

            prob.solve()

            x = fd.SpatialCoordinate(mesh)
            
            exact_soln = fd.exp(1j * k * fd.dot(x,fd.as_vector(d)))

            log_err_L2[ii_points,ii_k] = np.log(fd.norms.errornorm(exact_soln,prob.u_h,norm_type="L2"))
            log_err_H1[ii_points,ii_k] = np.log(fd.norms.errornorm(exact_soln,prob.u_h,norm_type="H1"))

        #plt.plot(log_h,log_err_L2[:,ii_k])

        #plt.plot(log_h,log_err_H1[:,ii_k])

        #plt.show()

        fit_L2 = np.polyfit(log_h,log_err_L2[:,ii_k],deg=1)[0]

        fit_H1 = np.polyfit(log_h,log_err_H1[:,ii_k],deg=1)[0]

        print(fit_L2)

        print(fit_H1)

        assert abs(fit_L2 - 2.0) <= tolerance

        assert abs(fit_H1 - 1.0) <= tolerance
Ejemplo n.º 30
0
def vector_manifold_continuity_form(state,
                                    test,
                                    q,
                                    ibp=IntegrateByParts.ONCE,
                                    outflow=False):

    L = continuity_form(state, test, q, ibp, outflow)

    Vu = state.spaces("HDiv")
    dS_ = (dS_v + dS_h) if Vu.extruded else dS
    ubar = Function(Vu)
    n = FacetNormal(state.mesh)
    un = 0.5 * (dot(ubar, n) + abs(dot(ubar, n)))
    L += un('+') * inner(test('-'),
                         n('+') + n('-')) * inner(q('+'), n('+')) * dS_
    L += un('-') * inner(test('+'),
                         n('+') + n('-')) * inner(q('-'), n('-')) * dS_

    form = transporting_velocity(L, ubar)

    return transport(form)
Ejemplo n.º 31
0
    def setup(self, state):
        if not self._initialised:
            mesh_dim = state.mesh.geometric_dimension()
            try:
                field_dim = state.fields(self.fname).ufl_shape[0]
            except IndexError:
                field_dim = 1
            shape = (mesh_dim, ) * field_dim
            space = TensorFunctionSpace(state.mesh, "CG", 1, shape=shape)
            super().setup(state, space=space)

        f = state.fields(self.fname)
        test = TestFunction(space)
        trial = TrialFunction(space)
        n = FacetNormal(state.mesh)
        a = inner(test, trial)*dx
        L = -inner(div(test), f)*dx
        if space.extruded:
            L += dot(dot(test, n), f)*(ds_t + ds_b)
        prob = LinearVariationalProblem(a, L, self.field)
        self.solver = LinearVariationalSolver(prob)
Ejemplo n.º 32
0
def estimate_timestep(mesh, V, c, estimate_max_eigenvalue=True):
    """Estimate the maximum stable timestep based on the spectral radius
    using optionally the Gershgorin Circle Theorem to estimate the
    maximum generalized eigenvalue. Otherwise computes the maximum
    generalized eigenvalue exactly

    ONLY WORKS WITH KMV ELEMENTS
    """

    u, v = fd.TrialFunction(V), fd.TestFunction(V)
    quad_rule = finat.quadrature.make_quadrature(
        V.finat_element.cell, V.ufl_element().degree(), "KMV"
    )
    dxlump = fd.dx(rule=quad_rule)
    A = fd.assemble(u * v * dxlump)
    ai, aj, av = A.petscmat.getValuesCSR()
    av_inv = []
    for value in av:
        if value == 0:
            av_inv.append(0.0)
        else:
            av_inv.append(1 / value)
    Asp = scipy.sparse.csr_matrix((av, aj, ai))
    Asp_inv = scipy.sparse.csr_matrix((av_inv, aj, ai))

    K = fd.assemble(c*c*dot(grad(u), grad(v)) * dxlump)
    ai, aj, av = K.petscmat.getValuesCSR()
    Ksp = scipy.sparse.csr_matrix((av, aj, ai))

    # operator
    Lsp = Asp_inv.multiply(Ksp)
    if estimate_max_eigenvalue:
        # absolute maximum of diagonals
        max_eigval = np.amax(np.abs(Lsp.diagonal()))
    else:
        print(
            "Computing exact eigenvalues is extremely computationally demanding!",
            flush=True,
        )
        max_eigval = scipy.sparse.linalg.eigs(
            Ksp, M=Asp, k=1, which="LM", return_eigenvectors=False
        )[0]

    # print(max_eigval)
    if np.sqrt(max_eigval) > 0.0:
    	max_dt = np.float(2 / np.sqrt(max_eigval))
    else:
        max_dt = 100000000
    #print(
    #    f"Maximum stable timestep should be about: {np.float(2 / np.sqrt(max_eigval))} seconds",
    #    flush=True,
    #)
    return max_dt
Ejemplo n.º 33
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')
Ejemplo n.º 34
0
    def __init__(self, state, V, qbar, options=None):
        super(LinearAdvection_V3, self).__init__(state)

        p = TestFunction(V)
        q = TrialFunction(V)
        self.dq = Function(V)

        n = FacetNormal(state.mesh)

        a = p*q*dx
        L = (dot(grad(p), self.ubar)*qbar*dx -
             jump(self.ubar*p, n)*avg(qbar)*(dS_v + dS_h))

        aProblem = LinearVariationalProblem(a,L,self.dq)
        if options is None:
            options = {'ksp_type':'cg',
                       'pc_type':'bjacobi',
                       'sub_pc_type':'ilu'}

        self.solver = LinearVariationalSolver(aProblem,
                                              solver_parameters=options,
                                              options_prefix='LinearAdvectionV3')
Ejemplo n.º 35
0
    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')
Ejemplo n.º 36
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')
Ejemplo n.º 37
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

        # 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)
Ejemplo n.º 38
0
    def __init__(self, state, V, direction=[], supg_params=None):
        super(SUPGAdvection, self).__init__(state)
        dt = state.timestepping.dt
        params = supg_params.copy() if supg_params else {}
        params.setdefault('a0', dt/sqrt(15.))
        params.setdefault('a1', dt/sqrt(15.))

        gamma = TestFunction(V)
        theta = TrialFunction(V)
        self.theta0 = Function(V)

        # make SUPG test function
        taus = [params["a0"], params["a1"]]
        for i in direction:
            taus[i] = 0.0
        tau = Constant(((taus[0], 0.), (0., taus[1])))

        dgamma = dot(dot(self.ubar, tau), grad(gamma))
        gammaSU = gamma + dgamma

        n = FacetNormal(state.mesh)
        un = 0.5*(dot(self.ubar, n) + abs(dot(self.ubar, n)))

        a_mass = gammaSU*theta*dx
        arhs = a_mass - dt*gammaSU*dot(self.ubar, grad(theta))*dx

        if 1 in direction:
            arhs -= (
                dt*dot(jump(gammaSU), (un('+')*theta('+')
                                       - un('-')*theta('-')))*dS_v
                - dt*(gammaSU('+')*dot(self.ubar('+'), n('+'))*theta('+')
                      + gammaSU('-')*dot(self.ubar('-'), n('-'))*theta('-'))*dS_v
            )
        if 2 in direction:
            arhs -= (
                dt*dot(jump(gammaSU), (un('+')*theta('+')
                                       - un('-')*theta('-')))*dS_h
                - dt*(gammaSU('+')*dot(self.ubar('+'), n('+'))*theta('+')
                      + gammaSU('-')*dot(self.ubar('-'), n('-'))*theta('-'))*dS_h
            )

        self.theta1 = Function(V)
        self.dtheta = Function(V)
        problem = LinearVariationalProblem(a_mass, action(arhs,self.theta1), self.dtheta)
        self.solver = LinearVariationalSolver(problem,
                                              options_prefix='SUPGAdvection')
Ejemplo n.º 39
0
Ky.dat.data[...] = coords2ijk(coords[:, 0], coords[:, 1],
                                    coords[:, 2], Delta=Delta, data_array=ky_array)
Kz.dat.data[...] = coords2ijk(coords[:, 0], coords[:, 1],
                                    coords[:, 2], Delta=Delta, data_array=kz_array)

print("END: Read in reservoir fields")

# Permeability field harmonic interpolation to facets
Kx_facet = fd.conditional(fd.gt(fd.avg(Kx), 0.0), Kx('+')*Kx('-') / fd.avg(Kx), 0.0)
Ky_facet = fd.conditional(fd.gt(fd.avg(Ky), 0.0), Ky('+')*Ky('-') / fd.avg(Ky), 0.0)
Kz_facet = fd.conditional(fd.gt(fd.avg(Kz), 0.0), Kz('+')*Kz('-') / fd.avg(Kz), 0.0)

# We can now define the bilinear and linear forms for the left and right
dx = fd.dx
KdivU = fd.as_vector((Kx_facet*u.dx(0), Ky_facet*u.dx(1), Kz_facet*u.dx(2)))
a = (fd.dot(KdivU, fd.grad(v))) * dx
m = u * v * phi * dx

# Defining the eigenvalue problem

petsc_a = fd.assemble(a).M.handle
petsc_m = fd.assemble(m).M.handle

num_eigenvalues = 3

# Set solver options
opts = PETSc.Options()
opts.setValue("eps_gen_hermitian", None)
#opts.setValue("st_pc_factor_shift_type", "NONZERO")
opts.setValue("eps_type", "krylovschur")
#opts.setValue("eps_smallest_magnitude", None)
Ejemplo n.º 40
0
Khet = fd.as_tensor(((1.0 + x, 0, 0), 
                      (0, 1.0+y, 0),
                       (0, 0, 1.0+z)))

#Khet = fd.as_tensor(((1,0,0),(0,1,0),(0,0,1)))
#Khet = fd.as_tensor(((1,0),(0,1)))
Khet = fd.Function(W).interpolate(Khet)
Khet.rename('K', 'Permeability')

# Porosity
por = fd.Constant(1.0)

# We can now define the bilinear and linear forms for the left and right
# hand sides of our equation respectively::
dx = fd.dx
a = (fd.dot(Khet * fd.grad(u), fd.grad(v))) * dx
m = u * v * por * dx

# Defining the eigenvalue problem

petsc_a = fd.assemble(a).M.handle
petsc_m = fd.assemble(m).M.handle

num_eigenvalues = 20

# Set solver options
opts = PETSc.Options()
opts.setValue("eps_gen_hermitian", None)
#opts.setValue("st_pc_factor_shift_type", "NONZERO")
opts.setValue("eps_type", "krylovschur")
#opts.setValue("eps_smallest_magnitude", None)
Ejemplo n.º 41
0
 def l2(f):
     return sqrt(assemble(dot(f, f)*dx))
Ejemplo n.º 42
0
 def compute(self, state):
     u = state.field_dict['u']
     dt = Constant(state.timestepping.dt)
     return self.field(state.mesh).project(sqrt(dot(u, u))/sqrt(self.area(state.mesh))*dt)