Ejemplo n.º 1
0
    def pml_local_op(self, w):
        sub_e, sub_h, sub_p, sub_q = self.split_ehpq(w)

        e_subset = self.get_eh_subset()[0:3]
        h_subset = self.get_eh_subset()[3:6]
        dim_subset = (True,) * self.dimensions + (False,) * (3-self.dimensions)

        def pad_vec(v, subset):
            result = numpy.zeros((3,), dtype=object)
            result[numpy.array(subset, dtype=bool)] = v
            return result

        from hedge.optemplate import make_sym_vector
        sig = pad_vec(
                make_sym_vector("sigma", self.dimensions),
                dim_subset)
        sig_prime = pad_vec(
                make_sym_vector("sigma_prime", self.dimensions),
                dim_subset)
        if self.add_decay:
            tau = pad_vec(
                    make_sym_vector("tau", self.dimensions),
                    dim_subset)
        else:
            tau = numpy.zeros((3,))

        e = pad_vec(sub_e, e_subset)
        h = pad_vec(sub_h, h_subset)
        p = pad_vec(sub_p, dim_subset)
        q = pad_vec(sub_q, dim_subset)

        rhs = numpy.zeros(12, dtype=object)

        for mx in range(3):
            my = (mx+1) % 3
            mz = (mx+2) % 3

            from hedge.tools.mathematics import levi_civita
            assert levi_civita((mx,my,mz)) == 1

            rhs[mx] += -sig[my]/self.epsilon*(2*e[mx]+p[mx]) - 2*tau[my]/self.epsilon*e[mx]
            rhs[my] += -sig[mx]/self.epsilon*(2*e[my]+p[my]) - 2*tau[mx]/self.epsilon*e[my]
            rhs[3+mz] += 1/(self.epsilon*self.mu) * (
              sig_prime[mx] * q[mx] - sig_prime[my] * q[my])

            rhs[6+mx] += sig[my]/self.epsilon*e[mx]
            rhs[6+my] += sig[mx]/self.epsilon*e[my]
            rhs[9+mx] += -sig[mx]/self.epsilon*q[mx] - (e[my] + e[mz])

        from hedge.tools import full_to_subset_indices
        sub_idx = full_to_subset_indices(e_subset+h_subset+dim_subset+dim_subset)

        return rhs[sub_idx]
Ejemplo n.º 2
0
    def pml_local_op(self, w):
        sub_e, sub_h, sub_p, sub_q = self.split_ehpq(w)

        e_subset = self.get_eh_subset()[0:3]
        h_subset = self.get_eh_subset()[3:6]
        dim_subset = (True, ) * self.dimensions + (False, ) * (3 -
                                                               self.dimensions)

        def pad_vec(v, subset):
            result = numpy.zeros((3, ), dtype=object)
            result[numpy.array(subset, dtype=bool)] = v
            return result

        from hedge.optemplate import make_sym_vector
        sig = pad_vec(make_sym_vector("sigma", self.dimensions), dim_subset)
        sig_prime = pad_vec(make_sym_vector("sigma_prime", self.dimensions),
                            dim_subset)
        if self.add_decay:
            tau = pad_vec(make_sym_vector("tau", self.dimensions), dim_subset)
        else:
            tau = numpy.zeros((3, ))

        e = pad_vec(sub_e, e_subset)
        h = pad_vec(sub_h, h_subset)
        p = pad_vec(sub_p, dim_subset)
        q = pad_vec(sub_q, dim_subset)

        rhs = numpy.zeros(12, dtype=object)

        for mx in range(3):
            my = (mx + 1) % 3
            mz = (mx + 2) % 3

            from hedge.tools.mathematics import levi_civita
            assert levi_civita((mx, my, mz)) == 1

            rhs[mx] += -sig[my] / self.epsilon * (
                2 * e[mx] + p[mx]) - 2 * tau[my] / self.epsilon * e[mx]
            rhs[my] += -sig[mx] / self.epsilon * (
                2 * e[my] + p[my]) - 2 * tau[mx] / self.epsilon * e[my]
            rhs[3 +
                mz] += 1 / (self.epsilon * self.mu) * (sig_prime[mx] * q[mx] -
                                                       sig_prime[my] * q[my])

            rhs[6 + mx] += sig[my] / self.epsilon * e[mx]
            rhs[6 + my] += sig[mx] / self.epsilon * e[my]
            rhs[9 + mx] += -sig[mx] / self.epsilon * q[mx] - (e[my] + e[mz])

        from hedge.tools import full_to_subset_indices
        sub_idx = full_to_subset_indices(e_subset + h_subset + dim_subset +
                                         dim_subset)

        return rhs[sub_idx]
Ejemplo n.º 3
0
    def field_placeholder(self, w=None):
        "A placeholder for E and H."
        from hedge.tools import count_subset
        fld_cnt = count_subset(self.get_eh_subset())
        if w is None:
            from hedge.optemplate import make_sym_vector
            w = make_sym_vector("w", fld_cnt)

        return w
Ejemplo n.º 4
0
    def field_placeholder(self, w=None):
        "A placeholder for E and H."
        from hedge.tools import count_subset
        fld_cnt = count_subset(self.get_eh_subset())
        if w is None:
            from hedge.optemplate import make_sym_vector
            w = make_sym_vector("w", fld_cnt)

        return w
Ejemplo n.º 5
0
        def apply_diff_tensor(v):
            if isinstance(self.diffusion_tensor, np.ndarray):
                sym_diff_tensor = self.diffusion_tensor
            else:
                sym_diff_tensor = make_sym_vector("diffusion", self.dimensions ** 2).reshape(
                    self.dimensions, self.dimensions
                )

            return np.dot(sym_diff_tensor, v)
Ejemplo n.º 6
0
        def apply_diff_tensor(v):
            if isinstance(self.diffusion_tensor, np.ndarray):
                sym_diff_tensor = self.diffusion_tensor
            else:
                sym_diff_tensor = (make_sym_vector("diffusion",
                                                   self.dimensions**2).reshape(
                                                       self.dimensions,
                                                       self.dimensions))

            return np.dot(sym_diff_tensor, v)
Ejemplo n.º 7
0
    def op_template(self, w=None):
        from hedge.tools import count_subset
        fld_cnt = count_subset(self.get_eh_subset())
        if w is None:
            from hedge.optemplate import make_sym_vector
            w = make_sym_vector("w", fld_cnt + 2 * self.dimensions)

        from hedge.tools import join_fields
        return join_fields(MaxwellOperator.op_template(self, w[:fld_cnt]),
                           numpy.zeros((2 * self.dimensions, ),
                                       dtype=object)) + self.pml_local_op(w)
Ejemplo n.º 8
0
    def op_template(self, w=None):
        from hedge.tools import count_subset
        fld_cnt = count_subset(self.get_eh_subset())
        if w is None:
            from hedge.optemplate import make_sym_vector
            w = make_sym_vector("w", fld_cnt+2*self.dimensions)

        from hedge.tools import join_fields
        return join_fields(
                MaxwellOperator.op_template(self, w[:fld_cnt]),
                numpy.zeros((2*self.dimensions,), dtype=object)
                ) + self.pml_local_op(w)
Ejemplo n.º 9
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.º 10
0
    def bind_characteristic_velocity(self, discr):
        from hedge.optemplate.operators import (ElementwiseMaxOperator)
        from hedge.optemplate import make_sym_vector
        velocity_vec = make_sym_vector("v", self.dimensions)
        velocity = ElementwiseMaxOperator()(numpy.dot(velocity_vec,
                                                      velocity_vec)**0.5)

        compiled = discr.compile(velocity)

        def do(t, u):
            return compiled(v=self.advec_v.volume_interpolant(t, discr))

        return do
Ejemplo n.º 11
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.º 12
0
    def bind_characteristic_velocity(self, discr):
        from hedge.optemplate.operators import (
                ElementwiseMaxOperator)
        from hedge.optemplate import make_sym_vector
        velocity_vec = make_sym_vector("v", self.dimensions)
        velocity = ElementwiseMaxOperator()(
                numpy.dot(velocity_vec, velocity_vec)**0.5)

        compiled = discr.compile(velocity)

        def do(t, u):
            return compiled(v=self.advec_v.volume_interpolant(t, discr))

        return do
Ejemplo n.º 13
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.º 14
0
 def f_bar(self):
     from hedge.optemplate import make_sym_vector
     return make_sym_vector("f_bar", len(self.method))
Ejemplo n.º 15
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.º 16
0
 def f_bar(self):
     from hedge.optemplate import make_sym_vector
     return make_sym_vector("f_bar", len(self.method))
Ejemplo n.º 17
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.º 18
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