Ejemplo n.º 1
0
    def op_template(self, w=None):
        """The full operator template - the high level description of
        the Maxwell operator.

        Combines the relevant operator templates for spatial
        derivatives, flux, boundary conditions etc.
        """
        from hedge.tools import join_fields
        w = self.field_placeholder(w)

        if self.fixed_material:
            flux_w = w
        else:
            epsilon = self.epsilon
            mu = self.mu

            flux_w = join_fields(epsilon, mu, w)

        from hedge.optemplate import BoundaryPair, \
                InverseMassOperator, get_flux_operator

        flux_op = get_flux_operator(self.flux(self.flux_type))
        bdry_flux_op = get_flux_operator(self.flux(self.bdry_flux_type))

        from hedge.tools.indexing import count_subset
        elec_components = count_subset(self.get_eh_subset()[0:3])
        mag_components = count_subset(self.get_eh_subset()[3:6])

        if self.fixed_material:
            # need to check this
            material_divisor = ([self.epsilon] * elec_components +
                                [self.mu] * mag_components)
        else:
            material_divisor = join_fields([epsilon] * elec_components,
                                           [mu] * mag_components)

        tags_and_bcs = [
            (self.pec_tag, self.pec_bc(w)),
            (self.pmc_tag, self.pmc_bc(w)),
            (self.absorb_tag, self.absorbing_bc(w)),
            (self.incident_tag, self.incident_bc(w)),
        ]

        def make_flux_bc_vector(tag, bc):
            if self.fixed_material:
                return bc
            else:
                from hedge.optemplate import BoundarizeOperator
                return join_fields(cse(BoundarizeOperator(tag)(epsilon)),
                                   cse(BoundarizeOperator(tag)(mu)), bc)

        return (
            -self.local_derivatives(w) +
            InverseMassOperator()(flux_op(flux_w) + sum(
                bdry_flux_op(
                    BoundaryPair(flux_w, make_flux_bc_vector(tag, bc), tag))
                for tag, bc in tags_and_bcs))) / material_divisor
Ejemplo n.º 2
0
    def op_template(self, w=None):
        """The full operator template - the high level description of
        the nonlinear mechanics operator.

        Combines the relevant operator templates for spatial
        derivatives, flux, boundary conditions etc.

        NOTE: Only boundary conditions allowed currently are homogenous
        dirichlet and neumann, and I'm not sure dirichlet is done 
        properly
        """
        from hedge.optemplate import InverseMassOperator, Field, \
                make_vector_field

        from hedge.tools import join_fields
        w = self.field_placeholder(w)
       
        u,v = self.split_vars(w)
        from hedge.optemplate import make_nabla

        nabla = make_nabla(self.dimensions)
        ij = 0
        F = [0,]*9
        for i in range(self.dimensions):
            for j in range(self.dimensions):
                F[ij] = nabla[j](u[i]) 
                if i == j:
                    F[ij] = F[ij] + 1
                ij = ij + 1
        
        w = join_fields(u,v,F)
        flux_w = w

        from hedge.optemplate import BoundaryPair, get_flux_operator

        flux_op = get_flux_operator(self.flux(self.beta, is_dirich=False))
        d_flux_op = get_flux_operator(self.flux(self.beta, is_dirich=True))
        
        from hedge.optemplate import make_normal, BoundarizeOperator

        dir_normal = make_normal(self.dirichlet_tag, self.dimensions)

        dir_bc = self.dirichlet_bc(w)

        return    self.local_derivatives(w) \
                - (flux_op(flux_w) + 
                   d_flux_op(BoundaryPair(flux_w, dir_bc, self.dirichlet_tag))
                  )
    def flux_num(self, q, fluxes, bdry_tag_state_flux):
        n = self.len_q
        d = len(fluxes)
        fvph = FluxVectorPlaceholder(n*(d+1)+1)
        speed_ph = fvph[0]
        state_ph = fvph[1:n+1]
        fluxes_ph = [fvph[i*n+1:(i+1)*n+1] for i in range(1,d+1)]
        normal = make_normal(d)

        flux_strong = 0.5*sum(n_i*(f_i.ext-f_i.int) for n_i, f_i in zip(normal, fluxes_ph))

        if self.flux_type == "central":
            pass
        elif self.flux_type == "lf":
            penalty = flux_max(speed_ph.int,speed_ph.ext)*(state_ph.ext-state_ph.int)
            flux_strong = 0.5 * penalty + flux_strong
        else:
            raise ValueError("Invalid flux type '%s'" % self.flux_type)

        flux_op = get_flux_operator(flux_strong)
        int_operand = join_fields(self.wave_speed(q), q, *fluxes)

        return (flux_op(int_operand)
                +sum(flux_op(BoundaryPair(int_operand, join_fields(0, bdry_state, *bdry_fluxes), tag))
                     for tag, bdry_state, bdry_fluxes in bdry_tag_state_flux))
Ejemplo n.º 4
0
def make_lax_friedrichs_flux(wave_speed, state, fluxes, bdry_tags_states_and_fluxes,
        strong):
    from pytools.obj_array import join_fields
    from hedge.flux import make_normal, FluxVectorPlaceholder, flux_max

    n = len(state)
    d = len(fluxes)
    normal = make_normal(d)
    fvph = FluxVectorPlaceholder(len(state)*(1+d)+1)

    wave_speed_ph = fvph[0]
    state_ph = fvph[1:1+n]
    fluxes_ph = [fvph[1+i*n:1+(i+1)*n] for i in range(1, d+1)]

    penalty = flux_max(wave_speed_ph.int,wave_speed_ph.ext)*(state_ph.ext-state_ph.int)

    if not strong:
        num_flux = 0.5*(sum(n_i*(f_i.int+f_i.ext) for n_i, f_i in zip(normal, fluxes_ph))
                - penalty)
    else:
        num_flux = 0.5*(sum(n_i*(f_i.int-f_i.ext) for n_i, f_i in zip(normal, fluxes_ph))
                + penalty)

    from hedge.optemplate import get_flux_operator
    flux_op = get_flux_operator(num_flux)
    int_operand = join_fields(wave_speed, state, *fluxes)

    from hedge.optemplate import BoundaryPair
    return (flux_op(int_operand)
            + sum(
                flux_op(BoundaryPair(int_operand,
                    join_fields(0, bdry_state, *bdry_fluxes), tag))
                for tag, bdry_state, bdry_fluxes in bdry_tags_states_and_fluxes))
Ejemplo n.º 5
0
    def op_template(self):
        from hedge.optemplate import (Field, BoundaryPair, get_flux_operator,
                                      make_stiffness_t, InverseMassOperator,
                                      BoundarizeOperator,
                                      QuadratureGridUpsampler,
                                      QuadratureInteriorFacesGridUpsampler)

        u = Field("u")

        to_quad = QuadratureGridUpsampler("quad")
        to_int_face_quad = QuadratureInteriorFacesGridUpsampler("quad")

        # boundary conditions -------------------------------------------------
        bc_in = Field("bc_in")
        bc_out = BoundarizeOperator(self.outflow_tag) * u

        stiff_t = make_stiffness_t(self.dimensions)
        m_inv = InverseMassOperator()

        flux_op = get_flux_operator(self.flux())

        return m_inv(
            numpy.dot(self.v, stiff_t * u) -
            (flux_op(u) + flux_op(BoundaryPair(u, bc_in, self.inflow_tag)) +
             flux_op(BoundaryPair(u, bc_out, self.outflow_tag))))
Ejemplo n.º 6
0
    def op_template(self):
        from hedge.optemplate import (
                Field,
                BoundaryPair,
                get_flux_operator,
                make_stiffness_t,
                InverseMassOperator,
                BoundarizeOperator,
                QuadratureGridUpsampler,
                QuadratureInteriorFacesGridUpsampler)

        u = Field("u")

        to_quad = QuadratureGridUpsampler("quad")
        to_int_face_quad = QuadratureInteriorFacesGridUpsampler("quad")

        # boundary conditions -------------------------------------------------
        bc_in = Field("bc_in")
        bc_out = BoundarizeOperator(self.outflow_tag)*u

        stiff_t = make_stiffness_t(self.dimensions)
        m_inv = InverseMassOperator()

        flux_op = get_flux_operator(self.flux())

        return m_inv(numpy.dot(self.v, stiff_t*u) - (
                    flux_op(u)
                    + flux_op(BoundaryPair(u, bc_in, self.inflow_tag))
                    + flux_op(BoundaryPair(u, bc_out, self.outflow_tag))
                    ))
Ejemplo n.º 7
0
    def get_advection_op(self, q, velocity):
        from hedge.optemplate import (BoundaryPair, get_flux_operator,
                                      make_stiffness_t, InverseMassOperator)

        stiff_t = make_stiffness_t(self.method.dimensions)

        flux_op = get_flux_operator(self.get_advection_flux(velocity))
        return InverseMassOperator()(np.dot(velocity, stiff_t * q) -
                                     flux_op(q))
Ejemplo n.º 8
0
    def get_advection_op(self, q, velocity):
        from hedge.optemplate import (
                BoundaryPair,
                get_flux_operator,
                make_stiffness_t,
                InverseMassOperator)

        stiff_t = make_stiffness_t(self.method.dimensions)

        flux_op = get_flux_operator(self.get_advection_flux(velocity))
        return InverseMassOperator()(
                np.dot(velocity, stiff_t*q) - flux_op(q))
Ejemplo n.º 9
0
    def op_template(self):
        from hedge.mesh import TAG_ALL
        from hedge.optemplate import Field, BoundaryPair, \
                make_nabla, InverseMassOperator, get_flux_operator

        u = Field("u")
        bc = Field("bc")

        nabla = make_nabla(self.dimensions)
        flux_op = get_flux_operator(self.flux())

        return nabla * u - InverseMassOperator()(
            flux_op(u) + flux_op(BoundaryPair(u, bc, TAG_ALL)))
Ejemplo n.º 10
0
    def op_template(self):
        from hedge.mesh import TAG_ALL
        from hedge.optemplate import Field, BoundaryPair, \
                make_nabla, InverseMassOperator, get_flux_operator

        u = Field("u")
        bc = Field("bc")

        nabla = make_nabla(self.dimensions)
        flux_op = get_flux_operator(self.flux())

        return nabla*u - InverseMassOperator()(
                flux_op(u) +
                flux_op(BoundaryPair(u, bc, TAG_ALL)))
Ejemplo n.º 11
0
    def op_template(self):
        from hedge.optemplate import Field, BoundaryPair, \
                get_flux_operator, make_nabla, InverseMassOperator

        u = Field("u")
        bc_in = Field("bc_in")

        nabla = make_nabla(self.dimensions)
        m_inv = InverseMassOperator()

        flux_op = get_flux_operator(self.flux())

        return (-numpy.dot(self.v, nabla * u) + m_inv(
            flux_op(u) + flux_op(BoundaryPair(u, bc_in, self.inflow_tag))))
Ejemplo n.º 12
0
    def op_template(self):
        from hedge.optemplate import Field, BoundaryPair, \
                get_flux_operator, make_nabla, InverseMassOperator

        u = Field("u")
        bc_in = Field("bc_in")

        nabla = make_nabla(self.dimensions)
        m_inv = InverseMassOperator()

        flux_op = get_flux_operator(self.flux())

        return (
                -numpy.dot(self.v, nabla*u)
                + m_inv(
                flux_op(u)
                + flux_op(BoundaryPair(u, bc_in, self.inflow_tag))))
Ejemplo n.º 13
0
    def op_template(self):
        from hedge.mesh import TAG_ALL
        from hedge.optemplate import make_sym_vector, BoundaryPair, \
                get_flux_operator, make_nabla, InverseMassOperator

        nabla = make_nabla(self.dimensions)
        m_inv = InverseMassOperator()

        v = make_sym_vector("v", self.arg_count)
        bc = make_sym_vector("bc", self.arg_count)

        local_op_result = 0
        idx = 0
        for i, i_enabled in enumerate(self.subset):
            if i_enabled and i < self.dimensions:
                local_op_result += nabla[i] * v[idx]
                idx += 1

        flux_op = get_flux_operator(self.flux())

        return local_op_result - m_inv(
            flux_op(v) + flux_op(BoundaryPair(v, bc, TAG_ALL)))
Ejemplo n.º 14
0
    def op_template(self):
        from hedge.mesh import TAG_ALL
        from hedge.optemplate import make_vector_field, BoundaryPair, \
                get_flux_operator, make_nabla, InverseMassOperator

        nabla = make_nabla(self.dimensions)
        m_inv = InverseMassOperator()

        v = make_vector_field("v", self.arg_count)
        bc = make_vector_field("bc", self.arg_count)

        local_op_result = 0
        idx = 0
        for i, i_enabled in enumerate(self.subset):
            if i_enabled and i < self.dimensions:
                local_op_result += nabla[i]*v[idx]
                idx += 1

        flux_op = get_flux_operator(self.flux())

        return local_op_result - m_inv(
                flux_op(v) +
                flux_op(BoundaryPair(v, bc, TAG_ALL)))
Ejemplo n.º 15
0
def make_lax_friedrichs_flux(wave_speed, state, fluxes,
                             bdry_tags_states_and_fluxes, strong):
    from pytools.obj_array import join_fields
    from hedge.flux import make_normal, FluxVectorPlaceholder, flux_max

    n = len(state)
    d = len(fluxes)
    normal = make_normal(d)
    fvph = FluxVectorPlaceholder(len(state) * (1 + d) + 1)

    wave_speed_ph = fvph[0]
    state_ph = fvph[1:1 + n]
    fluxes_ph = [fvph[1 + i * n:1 + (i + 1) * n] for i in range(1, d + 1)]

    penalty = flux_max(wave_speed_ph.int,
                       wave_speed_ph.ext) * (state_ph.ext - state_ph.int)

    if not strong:
        num_flux = 0.5 * (sum(n_i * (f_i.int + f_i.ext)
                              for n_i, f_i in zip(normal, fluxes_ph)) -
                          penalty)
    else:
        num_flux = 0.5 * (sum(n_i * (f_i.int - f_i.ext)
                              for n_i, f_i in zip(normal, fluxes_ph)) +
                          penalty)

    from hedge.optemplate import get_flux_operator
    flux_op = get_flux_operator(num_flux)
    int_operand = join_fields(wave_speed, state, *fluxes)

    from hedge.optemplate import BoundaryPair
    return (flux_op(int_operand) + sum(
        flux_op(
            BoundaryPair(int_operand, join_fields(0, bdry_state, *bdry_fluxes),
                         tag))
        for tag, bdry_state, bdry_fluxes in bdry_tags_states_and_fluxes))
Ejemplo n.º 16
0
    def op_template(self, with_sensor=False):
        # {{{ operator preliminaries ------------------------------------------
        from hedge.optemplate import (Field, BoundaryPair, get_flux_operator,
                                      make_stiffness_t, InverseMassOperator,
                                      make_sym_vector, ElementwiseMaxOperator,
                                      BoundarizeOperator)

        from hedge.optemplate.primitives import make_common_subexpression as cse

        from hedge.optemplate.operators import (
            QuadratureGridUpsampler, QuadratureInteriorFacesGridUpsampler)

        to_quad = QuadratureGridUpsampler("quad")
        to_if_quad = QuadratureInteriorFacesGridUpsampler("quad")

        from hedge.tools import join_fields, \
                                ptwise_dot

        u = Field("u")
        v = make_sym_vector("v", self.dimensions)
        c = ElementwiseMaxOperator()(ptwise_dot(1, 1, v, v))

        quad_u = cse(to_quad(u))
        quad_v = cse(to_quad(v))

        w = join_fields(u, v, c)
        quad_face_w = to_if_quad(w)
        # }}}

        # {{{ boundary conditions ---------------------------------------------

        from hedge.mesh import TAG_ALL
        bc_c = to_quad(BoundarizeOperator(TAG_ALL)(c))
        bc_u = to_quad(Field("bc_u"))
        bc_v = to_quad(BoundarizeOperator(TAG_ALL)(v))

        if self.bc_u_f is "None":
            bc_w = join_fields(0, bc_v, bc_c)
        else:
            bc_w = join_fields(bc_u, bc_v, bc_c)

        minv_st = make_stiffness_t(self.dimensions)
        m_inv = InverseMassOperator()

        flux_op = get_flux_operator(self.flux())
        # }}}

        # {{{ diffusion -------------------------------------------------------
        if with_sensor or (self.diffusion_coeff is not None
                           and self.diffusion_coeff != 0):
            if self.diffusion_coeff is None:
                diffusion_coeff = 0
            else:
                diffusion_coeff = self.diffusion_coeff

            if with_sensor:
                diffusion_coeff += Field("sensor")

            from hedge.second_order import SecondDerivativeTarget

            # strong_form here allows IPDG to reuse the value of grad u.
            grad_tgt = SecondDerivativeTarget(self.dimensions,
                                              strong_form=True,
                                              operand=u)

            self.diffusion_scheme.grad(grad_tgt,
                                       bc_getter=None,
                                       dirichlet_tags=[],
                                       neumann_tags=[])

            div_tgt = SecondDerivativeTarget(self.dimensions,
                                             strong_form=False,
                                             operand=diffusion_coeff *
                                             grad_tgt.minv_all)

            self.diffusion_scheme.div(div_tgt,
                                      bc_getter=None,
                                      dirichlet_tags=[],
                                      neumann_tags=[])

            diffusion_part = div_tgt.minv_all
        else:
            diffusion_part = 0

        # }}}

        to_quad = QuadratureGridUpsampler("quad")
        quad_u = cse(to_quad(u))
        quad_v = cse(to_quad(v))

        return m_inv(numpy.dot(minv_st, cse(quad_v*quad_u))
                - (flux_op(quad_face_w)
                    + flux_op(BoundaryPair(quad_face_w, bc_w, TAG_ALL)))) \
                            + diffusion_part
Ejemplo n.º 17
0
def test_interior_fluxes_tri():
    """Check triangle surface integrals computed using interior fluxes
    against their known values.
    """

    from math import pi, sin, cos

    def round_trip_connect(start, end):
        for i in range(start, end):
            yield i, i + 1
        yield end, start

    a = -pi
    b = pi
    points = [(a, 0), (b, 0), (a, -1), (b, -1), (a, 1), (b, 1)]

    import meshpy.triangle as triangle

    mesh_info = triangle.MeshInfo()
    mesh_info.set_points(points)
    mesh_info.set_facets([(0, 1), (1, 3), (3, 2), (2, 0), (0, 4), (4, 5), (1, 5)])

    mesh_info.regions.resize(2)
    mesh_info.regions[0] = [0, -0.5, 1, 0.1]  # coordinate  # lower element tag  # max area
    mesh_info.regions[1] = [0, 0.5, 2, 0.01]  # coordinate  # upper element tag  # max area

    generated_mesh = triangle.build(mesh_info, attributes=True, volume_constraints=True)
    # triangle.write_gnuplot_mesh("mesh.dat", generated_mesh)

    def element_tagger(el):
        if generated_mesh.element_attributes[el.id] == 1:
            return ["upper"]
        else:
            return ["lower"]

    from hedge.mesh import make_conformal_mesh

    mesh = make_conformal_mesh(generated_mesh.points, generated_mesh.elements)

    from hedge.discretization.local import TriangleDiscretization
    from hedge.discretization import ones_on_volume

    discr = discr_class(mesh, TriangleDiscretization(4), debug=discr_class.noninteractive_debug_flags())

    def f_u(x, el):
        if generated_mesh.element_attributes[el.id] == 1:
            return cos(x[0] - x[1])
        else:
            return 0

    def f_l(x, el):
        if generated_mesh.element_attributes[el.id] == 0:
            return sin(x[0] - x[1])
        else:
            return 0

    u_l = discr.interpolate_volume_function(f_l)
    u_u = discr.interpolate_volume_function(f_u)
    u = u_u + u_u

    # discr.visualize_vtk("dual.vtk", [("u", u)])

    from hedge.flux import make_normal, FluxScalarPlaceholder
    from hedge.optemplate import Field, get_flux_operator

    fluxu = FluxScalarPlaceholder()
    res = discr.compile(get_flux_operator((fluxu.int - fluxu.ext) * make_normal(discr.dimensions)[1]) * Field("u"))(u=u)

    from hedge.discretization import ones_on_volume

    ones = ones_on_volume(discr)
    err = abs(numpy.dot(res, ones))
    # print err
    assert err < 5e-14
Ejemplo n.º 18
0
 def add_boundary_flux(self, flux, volume_expr, bdry_expr, tag):
     from hedge.optemplate import BoundaryPair, get_flux_operator
     self.boundary_fluxes = self.boundary_fluxes + \
             get_flux_operator(self.strong_neg*flux)(BoundaryPair(
                     volume_expr, bdry_expr, tag))
Ejemplo n.º 19
0
def test_interior_fluxes_tri():
    """Check triangle surface integrals computed using interior fluxes
    against their known values.
    """

    from math import pi, sin, cos

    def round_trip_connect(start, end):
        for i in range(start, end):
            yield i, i + 1
        yield end, start

    a = -pi
    b = pi
    points = [(a, 0), (b, 0), (a, -1), (b, -1), (a, 1), (b, 1)]

    import meshpy.triangle as triangle

    mesh_info = triangle.MeshInfo()
    mesh_info.set_points(points)
    mesh_info.set_facets([(0, 1), (1, 3), (3, 2), (2, 0), (0, 4), (4, 5),
                          (1, 5)])

    mesh_info.regions.resize(2)
    mesh_info.regions[0] = [
        0,
        -0.5,  # coordinate
        1,  # lower element tag
        0.1,  # max area
    ]
    mesh_info.regions[1] = [
        0,
        0.5,  # coordinate
        2,  # upper element tag
        0.01,  # max area
    ]

    generated_mesh = triangle.build(mesh_info,
                                    attributes=True,
                                    volume_constraints=True)

    #triangle.write_gnuplot_mesh("mesh.dat", generated_mesh)

    def element_tagger(el):
        if generated_mesh.element_attributes[el.id] == 1:
            return ["upper"]
        else:
            return ["lower"]

    from hedge.mesh import make_conformal_mesh
    mesh = make_conformal_mesh(generated_mesh.points, generated_mesh.elements)

    from hedge.discretization.local import TriangleDiscretization
    from hedge.discretization import ones_on_volume
    discr = discr_class(mesh,
                        TriangleDiscretization(4),
                        debug=discr_class.noninteractive_debug_flags())

    def f_u(x, el):
        if generated_mesh.element_attributes[el.id] == 1:
            return cos(x[0] - x[1])
        else:
            return 0

    def f_l(x, el):
        if generated_mesh.element_attributes[el.id] == 0:
            return sin(x[0] - x[1])
        else:
            return 0

    # u_l = discr.interpolate_volume_function(f_l)
    u_u = discr.interpolate_volume_function(f_u)
    u = u_u + u_u

    #discr.visualize_vtk("dual.vtk", [("u", u)])

    from hedge.flux import make_normal, FluxScalarPlaceholder
    from hedge.optemplate import Field, get_flux_operator
    fluxu = FluxScalarPlaceholder()
    res = discr.compile(
        get_flux_operator(
            (fluxu.int - fluxu.ext) * make_normal(discr.dimensions)[1]) *
        Field("u"))(u=u)

    ones = ones_on_volume(discr)
    err = abs(numpy.dot(res, ones))
    #print err
    assert err < 5e-14
Ejemplo n.º 20
0
def test_2d_gauss_theorem():
    """Verify Gauss's theorem explicitly on a mesh"""

    from hedge.mesh.generator import make_disk_mesh
    from math import sin, cos, sqrt, exp, pi
    from numpy import dot

    mesh = make_disk_mesh()
    order = 2

    discr = discr_class(mesh, order=order, debug=discr_class.noninteractive_debug_flags())
    ref_discr = discr_class(mesh, order=order)

    from hedge.flux import make_normal, FluxScalarPlaceholder

    normal = make_normal(discr.dimensions)
    flux_f_ph = FluxScalarPlaceholder(0)
    one_sided_x = flux_f_ph.int * normal[0]
    one_sided_y = flux_f_ph.int * normal[1]

    def f1(x, el):
        return sin(3 * x[0]) + cos(3 * x[1])

    def f2(x, el):
        return sin(2 * x[0]) + cos(x[1])

    from hedge.discretization import ones_on_volume

    ones = ones_on_volume(discr)
    f1_v = discr.interpolate_volume_function(f1)
    f2_v = discr.interpolate_volume_function(f2)

    from hedge.optemplate import BoundaryPair, Field, make_nabla, get_flux_operator

    nabla = make_nabla(discr.dimensions)
    diff_optp = nabla[0] * Field("f1") + nabla[1] * Field("f2")

    divergence = nabla[0].apply(discr, f1_v) + nabla[1].apply(discr, f2_v)
    int_div = discr.integral(divergence)

    flux_optp = get_flux_operator(one_sided_x)(BoundaryPair(Field("f1"), Field("fz"))) + get_flux_operator(one_sided_y)(
        BoundaryPair(Field("f2"), Field("fz"))
    )

    from hedge.mesh import TAG_ALL

    bdry_val = discr.compile(flux_optp)(f1=f1_v, f2=f2_v, fz=discr.boundary_zeros(TAG_ALL))
    ref_bdry_val = ref_discr.compile(flux_optp)(f1=f1_v, f2=f2_v, fz=discr.boundary_zeros(TAG_ALL))

    boundary_int = dot(bdry_val, ones)

    if False:
        from hedge.visualization import SiloVisualizer

        vis = SiloVisualizer(discr)
        visf = vis.make_file("test")

        from hedge.tools import make_obj_array
        from hedge.mesh import TAG_ALL

        vis.add_data(
            visf,
            [
                ("bdry", bdry_val),
                ("ref_bdry", ref_bdry_val),
                ("div", divergence),
                ("f", make_obj_array([f1_v, f2_v])),
                ("n", discr.volumize_boundary_field(discr.boundary_normals(TAG_ALL), TAG_ALL)),
            ],
            expressions=[("bdiff", "bdry-ref_bdry")],
        )

        # print abs(boundary_int-int_div)

    assert abs(boundary_int - int_div) < 5e-15
Ejemplo n.º 21
0
    def op_template(self, with_sensor=False):
        from hedge.optemplate import \
                Field, \
                make_sym_vector, \
                BoundaryPair, \
                get_flux_operator, \
                make_nabla, \
                InverseMassOperator, \
                BoundarizeOperator

        d = self.dimensions

        w = make_sym_vector("w", d+1)
        u = w[0]
        v = w[1:]

        from hedge.tools import join_fields
        flux_w = join_fields(self.c, w)

        # {{{ boundary conditions
        from hedge.tools import join_fields

        # Dirichlet
        dir_c = BoundarizeOperator(self.dirichlet_tag) * self.c
        dir_u = BoundarizeOperator(self.dirichlet_tag) * u
        dir_v = BoundarizeOperator(self.dirichlet_tag) * v

        dir_bc = join_fields(dir_c, -dir_u, dir_v)

        # Neumann
        neu_c = BoundarizeOperator(self.neumann_tag) * self.c
        neu_u = BoundarizeOperator(self.neumann_tag) * u
        neu_v = BoundarizeOperator(self.neumann_tag) * v

        neu_bc = join_fields(neu_c, neu_u, -neu_v)

        # Radiation
        from hedge.optemplate import make_normal
        rad_normal = make_normal(self.radiation_tag, d)

        rad_c = BoundarizeOperator(self.radiation_tag) * self.c
        rad_u = BoundarizeOperator(self.radiation_tag) * u
        rad_v = BoundarizeOperator(self.radiation_tag) * v

        rad_bc = join_fields(
                rad_c,
                0.5*(rad_u - self.time_sign*np.dot(rad_normal, rad_v)),
                0.5*rad_normal*(np.dot(rad_normal, rad_v) - self.time_sign*rad_u)
                )

        # }}}

        # {{{ diffusion -------------------------------------------------------
        from pytools.obj_array import with_object_array_or_scalar

        def make_diffusion(arg):
            if with_sensor or (
                    self.diffusion_coeff is not None and self.diffusion_coeff != 0):
                if self.diffusion_coeff is None:
                    diffusion_coeff = 0
                else:
                    diffusion_coeff = self.diffusion_coeff

                if with_sensor:
                    diffusion_coeff += Field("sensor")

                from hedge.second_order import SecondDerivativeTarget

                # strong_form here allows the reuse the value of grad u.
                grad_tgt = SecondDerivativeTarget(
                        self.dimensions, strong_form=True,
                        operand=arg)

                self.diffusion_scheme.grad(grad_tgt, bc_getter=None,
                        dirichlet_tags=[], neumann_tags=[])

                div_tgt = SecondDerivativeTarget(
                        self.dimensions, strong_form=False,
                        operand=diffusion_coeff*grad_tgt.minv_all)

                self.diffusion_scheme.div(div_tgt,
                        bc_getter=None,
                        dirichlet_tags=[], neumann_tags=[])

                return div_tgt.minv_all
            else:
                return 0

        # }}}

        # entire operator -----------------------------------------------------
        nabla = make_nabla(d)
        flux_op = get_flux_operator(self.flux())

        return (
                - join_fields(
                    - self.time_sign*self.c*np.dot(nabla, v) - make_diffusion(u)
                    + self.source,

                    -self.time_sign*self.c*(nabla*u) - with_object_array_or_scalar(
                        make_diffusion, v)
                    )
                +
                InverseMassOperator() * (
                    flux_op(flux_w)
                    + flux_op(BoundaryPair(flux_w, dir_bc, self.dirichlet_tag))
                    + flux_op(BoundaryPair(flux_w, neu_bc, self.neumann_tag))
                    + flux_op(BoundaryPair(flux_w, rad_bc, self.radiation_tag))
                    ))
Ejemplo n.º 22
0
def test_interior_fluxes_tet():
    """Check tetrahedron surface integrals computed using interior fluxes
    against their known values.
    """

    import meshpy.tet as tet
    from math import pi, sin, cos

    mesh_info = tet.MeshInfo()

    # construct a two-box extrusion of this base
    base = [(-pi, -pi, 0), (pi, -pi, 0), (pi, pi, 0), (-pi, pi, 0)]

    # first, the nodes
    mesh_info.set_points(base + [(x, y, z + pi) for x, y, z in base] + [(x, y, z + pi + 1) for x, y, z in base])

    # next, the facets

    # vertex indices for a box missing the -z face
    box_without_minus_z = [[4, 5, 6, 7], [0, 4, 5, 1], [1, 5, 6, 2], [2, 6, 7, 3], [3, 7, 4, 0]]

    def add_to_all_vertex_indices(facets, increment):
        return [[pt + increment for pt in facet] for facet in facets]

    mesh_info.set_facets(
        [[0, 1, 2, 3]]  # base
        + box_without_minus_z  # first box
        + add_to_all_vertex_indices(box_without_minus_z, 4)  # second box
    )

    # set the volume properties -- this is where the tet size constraints are
    mesh_info.regions.resize(2)
    mesh_info.regions[0] = [
        0,
        0,
        pi / 2,  # point in volume -> first box
        0,  # region tag (user-defined number)
        0.5,  # max tet volume in region
    ]
    mesh_info.regions[1] = [
        0,
        0,
        pi + 0.5,  # point in volume -> second box
        1,  # region tag (user-defined number, arbitrary)
        0.1,  # max tet volume in region
    ]

    generated_mesh = tet.build(mesh_info, attributes=True, volume_constraints=True)

    from hedge.mesh import make_conformal_mesh

    mesh = make_conformal_mesh(generated_mesh.points, generated_mesh.elements)

    from hedge.discretization.local import TetrahedronDiscretization
    from hedge.discretization import ones_on_volume

    discr = discr_class(mesh, TetrahedronDiscretization(4), debug=discr_class.noninteractive_debug_flags())

    def f_u(x, el):
        if generated_mesh.element_attributes[el.id] == 1:
            return cos(x[0] - x[1] + x[2])
        else:
            return 0

    def f_l(x, el):
        if generated_mesh.element_attributes[el.id] == 0:
            return sin(x[0] - x[1] + x[2])
        else:
            return 0

    u_l = discr.interpolate_volume_function(f_l)
    u_u = discr.interpolate_volume_function(f_u)
    u = u_l + u_u

    # visualize the produced field
    # from hedge.visualization import SiloVisualizer
    # vis = SiloVisualizer(discr)
    # visf = vis.make_file("sandwich")
    # vis.add_data(visf,
    # [("u_l", u_l), ("u_u", u_u)],
    # expressions=[("u", "u_l+u_u")])

    # make sure the surface integral of the difference
    # between top and bottom is zero
    from hedge.flux import make_normal, FluxScalarPlaceholder
    from hedge.optemplate import Field, get_flux_operator

    fluxu = FluxScalarPlaceholder()
    res = discr.compile(get_flux_operator((fluxu.int - fluxu.ext) * make_normal(discr.dimensions)[1]) * Field("u"))(u=u)

    from hedge.discretization import ones_on_volume

    ones = ones_on_volume(discr)
    assert abs(numpy.dot(res, ones)) < 5e-14
Ejemplo n.º 23
0
    def op_template(self):
        from hedge.optemplate import \
                make_vector_field, \
                BoundaryPair, \
                get_flux_operator, \
                make_nabla, \
                InverseMassOperator, \
                BoundarizeOperator

        d = self.dimensions

        w = make_vector_field("w", d + 1)
        u = w[0]
        v = w[1:]

        # boundary conditions -------------------------------------------------
        from hedge.tools import join_fields

        # dirichlet BCs -------------------------------------------------------
        from hedge.optemplate import make_normal, Field

        dir_normal = make_normal(self.dirichlet_tag, d)

        dir_u = BoundarizeOperator(self.dirichlet_tag) * u
        dir_v = BoundarizeOperator(self.dirichlet_tag) * v
        if self.dirichlet_bc_f:
            # FIXME
            from warnings import warn
            warn("Inhomogeneous Dirichlet conditions on the wave equation "
                 "are still having issues.")

            dir_g = Field("dir_bc_u")
            dir_bc = join_fields(2 * dir_g - dir_u, dir_v)
        else:
            dir_bc = join_fields(-dir_u, dir_v)

        # neumann BCs ---------------------------------------------------------
        neu_u = BoundarizeOperator(self.neumann_tag) * u
        neu_v = BoundarizeOperator(self.neumann_tag) * v
        neu_bc = join_fields(neu_u, -neu_v)

        # radiation BCs -------------------------------------------------------
        from hedge.optemplate import make_normal
        rad_normal = make_normal(self.radiation_tag, d)

        rad_u = BoundarizeOperator(self.radiation_tag) * u
        rad_v = BoundarizeOperator(self.radiation_tag) * v

        rad_bc = join_fields(
            0.5 * (rad_u - self.sign * numpy.dot(rad_normal, rad_v)), 0.5 *
            rad_normal * (numpy.dot(rad_normal, rad_v) - self.sign * rad_u))

        # entire operator -----------------------------------------------------
        nabla = make_nabla(d)
        flux_op = get_flux_operator(self.flux())

        from hedge.tools import join_fields
        result = (
            -join_fields(-self.c * numpy.dot(nabla, v), -self.c * (nabla * u))
            + InverseMassOperator() *
            (flux_op(w) + flux_op(BoundaryPair(w, dir_bc, self.dirichlet_tag))
             + flux_op(BoundaryPair(w, neu_bc, self.neumann_tag)) + flux_op(
                 BoundaryPair(w, rad_bc, self.radiation_tag))))

        if self.source_f is not None:
            result[0] += Field("source_u")

        return result
Ejemplo n.º 24
0
    def op_template(self):
        from hedge.tools import join_fields
        from hedge.optemplate import Field, make_vector_field, BoundaryPair, \
                BoundarizeOperator, make_normal, get_flux_operator, \
                make_nabla, InverseMassOperator

        w = make_vector_field("w", self.component_count)
        e, h, phi = self.split_ehphi(w)
        rho = Field("rho")


        # local part ----------------------------------------------------------
        nabla = make_nabla(self.maxwell_op.dimensions)

        # in conservation form: u_t + A u_x = 0
        # we're describing the A u_x part, the sign gets reversed
        # below.
        max_local_op = join_fields(self.maxwell_op.local_derivatives(w), 0)

        c = self.maxwell_op.c
        chi = self.chi

        hyp_local_operator = max_local_op + join_fields(
                c*chi*(nabla*phi),
                0*h,
                c*chi*numpy.dot(nabla, e) 
                - c*chi*rho/self.maxwell_op.epsilon

                # sign gets reversed below, so this is actually 
                # the decay it advertises to be.
                + self.phi_decay*phi
                )

        # BCs -----------------------------------------------------------------
        pec_tag = self.maxwell_op.pec_tag

        pec_e = BoundarizeOperator(pec_tag)(e)
        pec_h = BoundarizeOperator(pec_tag)(h)
        pec_phi = BoundarizeOperator(pec_tag)(phi)
        pec_n = make_normal(pec_tag, self.maxwell_op.dimensions)

        bc = "prev"
        print "HYP CLEAN BC", bc
        if bc == "char":
            # see hedge/doc/maxima/eclean.mac for derivation
            pec_bc = join_fields(
                    -pec_e
                    + 3/2 * pec_n * numpy.dot(pec_n, pec_e)
                    + 1/2 * pec_phi * pec_n ,

                    pec_h,

                    1/2*(pec_phi+numpy.dot(pec_n, pec_e))
                    )
        elif bc == "invent":
            # see hedge/doc/maxima/eclean.mac for derivation
            pec_bc = join_fields(
                    -pec_e
                    + 2 * pec_n * numpy.dot(pec_n, pec_e),
                    pec_h, 
                    pec_phi)
        elif bc == "munz":
            # Munz et al
            pec_bc = join_fields(
                    -pec_e, 
                    pec_h, 
                    pec_phi-numpy.dot(pec_n, pec_e))
        elif bc == "prev":
            # previous condition
            pec_bc = join_fields(
                    -pec_e
                    +2*pec_n * numpy.dot(pec_n, pec_e),

                    pec_h,

                    -pec_phi)

        # assemble operator ---------------------------------------------------
        flux_op = get_flux_operator(self.flux())
        return -hyp_local_operator + InverseMassOperator()(
                    flux_op(w)
                    + flux_op(BoundaryPair(w, pec_bc, pec_tag)))
Ejemplo n.º 25
0
def test_interior_fluxes_tet():
    """Check tetrahedron surface integrals computed using interior fluxes
    against their known values.
    """

    import meshpy.tet as tet
    from math import pi, sin, cos

    mesh_info = tet.MeshInfo()

    # construct a two-box extrusion of this base
    base = [(-pi, -pi, 0), (pi, -pi, 0), (pi, pi, 0), (-pi, pi, 0)]

    # first, the nodes
    mesh_info.set_points(base + [(x, y, z + pi)
                                 for x, y, z in base] + [(x, y, z + pi + 1)
                                                         for x, y, z in base])

    # next, the facets

    # vertex indices for a box missing the -z face
    box_without_minus_z = [
        [4, 5, 6, 7],
        [0, 4, 5, 1],
        [1, 5, 6, 2],
        [2, 6, 7, 3],
        [3, 7, 4, 0],
    ]

    def add_to_all_vertex_indices(facets, increment):
        return [[pt + increment for pt in facet] for facet in facets]

    mesh_info.set_facets(
        [[0, 1, 2, 3]]  # base
        + box_without_minus_z  # first box
        + add_to_all_vertex_indices(box_without_minus_z, 4)  # second box
    )

    # set the volume properties -- this is where the tet size constraints are
    mesh_info.regions.resize(2)
    mesh_info.regions[0] = [
        0,
        0,
        pi / 2,  # point in volume -> first box
        0,  # region tag (user-defined number)
        0.5,  # max tet volume in region
    ]
    mesh_info.regions[1] = [
        0,
        0,
        pi + 0.5,  # point in volume -> second box
        1,  # region tag (user-defined number,  arbitrary)
        0.1,  # max tet volume in region
    ]

    generated_mesh = tet.build(mesh_info,
                               attributes=True,
                               volume_constraints=True)

    from hedge.mesh import make_conformal_mesh
    mesh = make_conformal_mesh(generated_mesh.points, generated_mesh.elements)

    from hedge.discretization.local import TetrahedronDiscretization
    from hedge.discretization import ones_on_volume
    discr = discr_class(mesh,
                        TetrahedronDiscretization(4),
                        debug=discr_class.noninteractive_debug_flags())

    def f_u(x, el):
        if generated_mesh.element_attributes[el.id] == 1:
            return cos(x[0] - x[1] + x[2])
        else:
            return 0

    def f_l(x, el):
        if generated_mesh.element_attributes[el.id] == 0:
            return sin(x[0] - x[1] + x[2])
        else:
            return 0

    u_l = discr.interpolate_volume_function(f_l)
    u_u = discr.interpolate_volume_function(f_u)
    u = u_l + u_u

    # visualize the produced field
    #from hedge.visualization import SiloVisualizer
    #vis = SiloVisualizer(discr)
    #visf = vis.make_file("sandwich")
    #vis.add_data(visf,
    #[("u_l", u_l), ("u_u", u_u)],
    #expressions=[("u", "u_l+u_u")])

    # make sure the surface integral of the difference
    # between top and bottom is zero
    from hedge.flux import make_normal, FluxScalarPlaceholder
    from hedge.optemplate import Field, get_flux_operator

    fluxu = FluxScalarPlaceholder()
    res = discr.compile(
        get_flux_operator(
            (fluxu.int - fluxu.ext) * make_normal(discr.dimensions)[1]) *
        Field("u"))(u=u)

    ones = ones_on_volume(discr)
    assert abs(numpy.dot(res, ones)) < 5e-14
Ejemplo n.º 26
0
    def op_template(self):
        from hedge.tools import join_fields
        from hedge.optemplate import Field, make_vector_field, BoundaryPair, \
                BoundarizeOperator, make_normal, get_flux_operator, \
                make_nabla, InverseMassOperator

        w = make_vector_field("w", self.component_count)
        e, h, phi = self.split_ehphi(w)
        rho = Field("rho")

        # local part ----------------------------------------------------------
        nabla = make_nabla(self.maxwell_op.dimensions)

        # in conservation form: u_t + A u_x = 0
        # we're describing the A u_x part, the sign gets reversed
        # below.
        max_local_op = join_fields(self.maxwell_op.local_derivatives(w), 0)

        c = self.maxwell_op.c
        chi = self.chi

        hyp_local_operator = max_local_op + join_fields(
            c * chi * (nabla * phi),
            0 * h,
            c * chi * numpy.dot(nabla, e) -
            c * chi * rho / self.maxwell_op.epsilon

            # sign gets reversed below, so this is actually
            # the decay it advertises to be.
            + self.phi_decay * phi)

        # BCs -----------------------------------------------------------------
        pec_tag = self.maxwell_op.pec_tag

        pec_e = BoundarizeOperator(pec_tag)(e)
        pec_h = BoundarizeOperator(pec_tag)(h)
        pec_phi = BoundarizeOperator(pec_tag)(phi)
        pec_n = make_normal(pec_tag, self.maxwell_op.dimensions)

        bc = "prev"
        print "HYP CLEAN BC", bc
        if bc == "char":
            # see hedge/doc/maxima/eclean.mac for derivation
            pec_bc = join_fields(
                -pec_e + 3 / 2 * pec_n * numpy.dot(pec_n, pec_e) +
                1 / 2 * pec_phi * pec_n, pec_h,
                1 / 2 * (pec_phi + numpy.dot(pec_n, pec_e)))
        elif bc == "invent":
            # see hedge/doc/maxima/eclean.mac for derivation
            pec_bc = join_fields(-pec_e + 2 * pec_n * numpy.dot(pec_n, pec_e),
                                 pec_h, pec_phi)
        elif bc == "munz":
            # Munz et al
            pec_bc = join_fields(-pec_e, pec_h,
                                 pec_phi - numpy.dot(pec_n, pec_e))
        elif bc == "prev":
            # previous condition
            pec_bc = join_fields(-pec_e + 2 * pec_n * numpy.dot(pec_n, pec_e),
                                 pec_h, -pec_phi)

        # assemble operator ---------------------------------------------------
        flux_op = get_flux_operator(self.flux())
        return -hyp_local_operator + InverseMassOperator()(
            flux_op(w) + flux_op(BoundaryPair(w, pec_bc, pec_tag)))
Ejemplo n.º 27
0
    def op_template(self, w=None):
        """The full operator template - the high level description of
        the Maxwell operator.

        Combines the relevant operator templates for spatial
        derivatives, flux, boundary conditions etc.
        """
        from hedge.tools import join_fields
        w = self.field_placeholder(w)

        if self.fixed_material:
            flux_w = w
        else:
            epsilon = self.epsilon
            mu = self.mu

            flux_w = join_fields(epsilon, mu, w)

        from hedge.optemplate import BoundaryPair, \
                InverseMassOperator, get_flux_operator

        flux_op = get_flux_operator(self.flux(self.flux_type))
        bdry_flux_op = get_flux_operator(self.flux(self.bdry_flux_type))

        from hedge.tools.indexing import count_subset
        elec_components = count_subset(self.get_eh_subset()[0:3])
        mag_components = count_subset(self.get_eh_subset()[3:6])

        if self.fixed_material:
            # need to check this
            material_divisor = (
                    [self.epsilon]*elec_components+[self.mu]*mag_components)
        else:
            material_divisor = join_fields(
                    [epsilon]*elec_components,
                    [mu]*mag_components)

        tags_and_bcs = [
                (self.pec_tag, self.pec_bc(w)),
                (self.pmc_tag, self.pmc_bc(w)),
                (self.absorb_tag, self.absorbing_bc(w)),
                (self.incident_tag, self.incident_bc(w)),
                ]

        def make_flux_bc_vector(tag, bc):
            if self.fixed_material:
                return bc
            else:
                from hedge.optemplate import BoundarizeOperator
                return join_fields(
                        cse(BoundarizeOperator(tag)(epsilon)),
                        cse(BoundarizeOperator(tag)(mu)),
                        bc)

        return (
                - self.local_derivatives(w)
                + InverseMassOperator()(
                    flux_op(flux_w)
                    + sum(
                        bdry_flux_op(BoundaryPair(
                            flux_w, make_flux_bc_vector(tag, bc), tag))
                        for tag, bc in tags_and_bcs))
                    ) / material_divisor
Ejemplo n.º 28
0
 def add_inner_fluxes(self, flux, expr):
     from hedge.optemplate import get_flux_operator
     self.inner_fluxes = self.inner_fluxes \
             + get_flux_operator(self.strong_neg*flux)(expr)
Ejemplo n.º 29
0
 def add_boundary_flux(self, flux, volume_expr, bdry_expr, tag):
     from hedge.optemplate import BoundaryPair, get_flux_operator
     self.boundary_fluxes = self.boundary_fluxes + \
             get_flux_operator(self.strong_neg*flux)(BoundaryPair(
                     volume_expr, bdry_expr, tag))
Ejemplo n.º 30
0
 def add_inner_fluxes(self, flux, expr):
     from hedge.optemplate import get_flux_operator
     self.inner_fluxes = self.inner_fluxes \
             + get_flux_operator(self.strong_neg*flux)(expr)
Ejemplo n.º 31
0
    def op_template(self, with_sensor=False):
        # {{{ operator preliminaries ------------------------------------------
        from hedge.optemplate import (Field, BoundaryPair, get_flux_operator,
                make_stiffness_t, InverseMassOperator, make_sym_vector,
                ElementwiseMaxOperator, BoundarizeOperator)

        from hedge.optemplate.primitives import make_common_subexpression as cse

        from hedge.optemplate.operators import (
                QuadratureGridUpsampler,
                QuadratureInteriorFacesGridUpsampler)

        to_quad = QuadratureGridUpsampler("quad")
        to_if_quad = QuadratureInteriorFacesGridUpsampler("quad")

        from hedge.tools import join_fields, \
                                ptwise_dot

        u = Field("u")
        v = make_sym_vector("v", self.dimensions)
        c = ElementwiseMaxOperator()(ptwise_dot(1, 1, v, v))

        quad_u = cse(to_quad(u))
        quad_v = cse(to_quad(v))

        w = join_fields(u, v, c)
        quad_face_w = to_if_quad(w)
        # }}}

        # {{{ boundary conditions ---------------------------------------------

        from hedge.mesh import TAG_ALL
        bc_c = to_quad(BoundarizeOperator(TAG_ALL)(c))
        bc_u = to_quad(Field("bc_u"))
        bc_v = to_quad(BoundarizeOperator(TAG_ALL)(v))

        if self.bc_u_f is "None":
            bc_w = join_fields(0, bc_v, bc_c)
        else:
            bc_w = join_fields(bc_u, bc_v, bc_c)

        minv_st = make_stiffness_t(self.dimensions)
        m_inv = InverseMassOperator()

        flux_op = get_flux_operator(self.flux())
        # }}}

        # {{{ diffusion -------------------------------------------------------
        if with_sensor or (
                self.diffusion_coeff is not None and self.diffusion_coeff != 0):
            if self.diffusion_coeff is None:
                diffusion_coeff = 0
            else:
                diffusion_coeff = self.diffusion_coeff

            if with_sensor:
                diffusion_coeff += Field("sensor")

            from hedge.second_order import SecondDerivativeTarget

            # strong_form here allows IPDG to reuse the value of grad u.
            grad_tgt = SecondDerivativeTarget(
                    self.dimensions, strong_form=True,
                    operand=u)

            self.diffusion_scheme.grad(grad_tgt, bc_getter=None,
                    dirichlet_tags=[], neumann_tags=[])

            div_tgt = SecondDerivativeTarget(
                    self.dimensions, strong_form=False,
                    operand=diffusion_coeff*grad_tgt.minv_all)

            self.diffusion_scheme.div(div_tgt,
                    bc_getter=None,
                    dirichlet_tags=[], neumann_tags=[])

            diffusion_part = div_tgt.minv_all
        else:
            diffusion_part = 0

        # }}}

        to_quad = QuadratureGridUpsampler("quad")
        quad_u = cse(to_quad(u))
        quad_v = cse(to_quad(v))

        return m_inv(numpy.dot(minv_st, cse(quad_v*quad_u))
                - (flux_op(quad_face_w)
                    + flux_op(BoundaryPair(quad_face_w, bc_w, TAG_ALL)))) \
                            + diffusion_part
Ejemplo n.º 32
0
def test_2d_gauss_theorem():
    """Verify Gauss's theorem explicitly on a mesh"""

    from hedge.mesh.generator import make_disk_mesh
    from math import sin, cos
    from numpy import dot

    mesh = make_disk_mesh()
    order = 2

    discr = discr_class(mesh,
                        order=order,
                        debug=discr_class.noninteractive_debug_flags())
    ref_discr = discr_class(mesh, order=order)

    from hedge.flux import make_normal, FluxScalarPlaceholder

    normal = make_normal(discr.dimensions)
    flux_f_ph = FluxScalarPlaceholder(0)
    one_sided_x = flux_f_ph.int * normal[0]
    one_sided_y = flux_f_ph.int * normal[1]

    def f1(x, el):
        return sin(3 * x[0]) + cos(3 * x[1])

    def f2(x, el):
        return sin(2 * x[0]) + cos(x[1])

    from hedge.discretization import ones_on_volume
    ones = ones_on_volume(discr)
    f1_v = discr.interpolate_volume_function(f1)
    f2_v = discr.interpolate_volume_function(f2)

    from hedge.optemplate import BoundaryPair, Field, make_nabla, \
            get_flux_operator
    nabla = make_nabla(discr.dimensions)

    divergence = nabla[0].apply(discr, f1_v) + nabla[1].apply(discr, f2_v)
    int_div = discr.integral(divergence)

    flux_optp = (
        get_flux_operator(one_sided_x)(BoundaryPair(Field("f1"),
                                                    Field("fz"))) +
        get_flux_operator(one_sided_y)(BoundaryPair(Field("f2"), Field("fz"))))

    from hedge.mesh import TAG_ALL
    bdry_val = discr.compile(flux_optp)(f1=f1_v,
                                        f2=f2_v,
                                        fz=discr.boundary_zeros(TAG_ALL))
    ref_bdry_val = ref_discr.compile(flux_optp)(
        f1=f1_v, f2=f2_v, fz=discr.boundary_zeros(TAG_ALL))

    boundary_int = dot(bdry_val, ones)

    if False:
        from hedge.visualization import SiloVisualizer
        vis = SiloVisualizer(discr)
        visf = vis.make_file("test")

        from hedge.tools import make_obj_array
        from hedge.mesh import TAG_ALL
        vis.add_data(visf, [
            ("bdry", bdry_val),
            ("ref_bdry", ref_bdry_val),
            ("div", divergence),
            ("f", make_obj_array([f1_v, f2_v])),
            ("n",
             discr.volumize_boundary_field(discr.boundary_normals(TAG_ALL),
                                           TAG_ALL)),
        ],
                     expressions=[("bdiff", "bdry-ref_bdry")])

        #print abs(boundary_int-int_div)

    assert abs(boundary_int - int_div) < 5e-15
Ejemplo n.º 33
0
    def op_template(self, with_sensor=False):
        from hedge.optemplate import \
                Field, \
                make_vector_field, \
                BoundaryPair, \
                get_flux_operator, \
                make_nabla, \
                InverseMassOperator, \
                BoundarizeOperator

        d = self.dimensions

        w = make_vector_field("w", d + 1)
        u = w[0]
        v = w[1:]

        from hedge.tools import join_fields
        c = Field("c")
        flux_w = join_fields(c, w)

        # {{{ boundary conditions
        from hedge.flux import make_normal
        normal = make_normal(d)

        from hedge.tools import join_fields

        # Dirichlet
        dir_c = BoundarizeOperator(self.dirichlet_tag) * c
        dir_u = BoundarizeOperator(self.dirichlet_tag) * u
        dir_v = BoundarizeOperator(self.dirichlet_tag) * v

        dir_bc = join_fields(dir_c, -dir_u, dir_v)

        # Neumann
        neu_c = BoundarizeOperator(self.neumann_tag) * c
        neu_u = BoundarizeOperator(self.neumann_tag) * u
        neu_v = BoundarizeOperator(self.neumann_tag) * v

        neu_bc = join_fields(neu_c, neu_u, -neu_v)

        # Radiation
        from hedge.optemplate import make_normal
        rad_normal = make_normal(self.radiation_tag, d)

        rad_c = BoundarizeOperator(self.radiation_tag) * c
        rad_u = BoundarizeOperator(self.radiation_tag) * u
        rad_v = BoundarizeOperator(self.radiation_tag) * v

        rad_bc = join_fields(
            rad_c,
            0.5 * (rad_u - self.time_sign * numpy.dot(rad_normal, rad_v)),
            0.5 * rad_normal *
            (numpy.dot(rad_normal, rad_v) - self.time_sign * rad_u))

        # }}}

        # {{{ diffusion -------------------------------------------------------
        from pytools.obj_array import with_object_array_or_scalar

        def make_diffusion(arg):
            if with_sensor or (self.diffusion_coeff is not None
                               and self.diffusion_coeff != 0):
                if self.diffusion_coeff is None:
                    diffusion_coeff = 0
                else:
                    diffusion_coeff = self.diffusion_coeff

                if with_sensor:
                    diffusion_coeff += Field("sensor")

                from hedge.second_order import SecondDerivativeTarget

                # strong_form here allows the reuse the value of grad u.
                grad_tgt = SecondDerivativeTarget(
                    self.dimensions, strong_form=True, operand=arg)

                self.diffusion_scheme.grad(
                    grad_tgt,
                    bc_getter=None,
                    dirichlet_tags=[],
                    neumann_tags=[])

                div_tgt = SecondDerivativeTarget(
                    self.dimensions,
                    strong_form=False,
                    operand=diffusion_coeff * grad_tgt.minv_all)

                self.diffusion_scheme.div(
                    div_tgt,
                    bc_getter=None,
                    dirichlet_tags=[],
                    neumann_tags=[])

                return div_tgt.minv_all
            else:
                return 0

        # }}}

        # entire operator -----------------------------------------------------
        nabla = make_nabla(d)
        flux_op = get_flux_operator(self.flux())

        return (
            -join_fields(
                -self.time_sign * c * numpy.dot(nabla, v) - make_diffusion(u),
                -self.time_sign * c *
                (nabla * u) - with_object_array_or_scalar(make_diffusion, v)) +
            InverseMassOperator() * (flux_op(flux_w) + flux_op(
                BoundaryPair(flux_w, dir_bc, self.dirichlet_tag)) + flux_op(
                    BoundaryPair(flux_w, neu_bc, self.neumann_tag)) + flux_op(
                        BoundaryPair(flux_w, rad_bc, self.radiation_tag))))
Ejemplo n.º 34
0
    def op_template(self):
        from hedge.optemplate import \
                make_sym_vector, \
                BoundaryPair, \
                get_flux_operator, \
                make_nabla, \
                InverseMassOperator, \
                BoundarizeOperator

        d = self.dimensions

        w = make_sym_vector("w", d+1)
        u = w[0]
        v = w[1:]

        # boundary conditions -------------------------------------------------
        from hedge.tools import join_fields

        # dirichlet BCs -------------------------------------------------------
        from hedge.optemplate import normal, Field

        dir_u = BoundarizeOperator(self.dirichlet_tag) * u
        dir_v = BoundarizeOperator(self.dirichlet_tag) * v
        if self.dirichlet_bc_f:
            # FIXME
            from warnings import warn
            warn("Inhomogeneous Dirichlet conditions on the wave equation "
                    "are still having issues.")

            dir_g = Field("dir_bc_u")
            dir_bc = join_fields(2*dir_g - dir_u, dir_v)
        else:
            dir_bc = join_fields(-dir_u, dir_v)

        # neumann BCs ---------------------------------------------------------
        neu_u = BoundarizeOperator(self.neumann_tag) * u
        neu_v = BoundarizeOperator(self.neumann_tag) * v
        neu_bc = join_fields(neu_u, -neu_v)

        # radiation BCs -------------------------------------------------------
        rad_normal = normal(self.radiation_tag, d)

        rad_u = BoundarizeOperator(self.radiation_tag) * u
        rad_v = BoundarizeOperator(self.radiation_tag) * v

        rad_bc = join_fields(
                0.5*(rad_u - self.sign*np.dot(rad_normal, rad_v)),
                0.5*rad_normal*(np.dot(rad_normal, rad_v) - self.sign*rad_u)
                )

        # entire operator -----------------------------------------------------
        nabla = make_nabla(d)
        flux_op = get_flux_operator(self.flux())

        from hedge.tools import join_fields
        result = (
                - join_fields(
                    -self.c*np.dot(nabla, v),
                    -self.c*(nabla*u)
                    )
                +
                InverseMassOperator() * (
                    flux_op(w)
                    + flux_op(BoundaryPair(w, dir_bc, self.dirichlet_tag))
                    + flux_op(BoundaryPair(w, neu_bc, self.neumann_tag))
                    + flux_op(BoundaryPair(w, rad_bc, self.radiation_tag))
                    ))

        result[0] += self.source_f

        return result