Example #1
0
File: pml.py Project: felipeh/hedge
    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_vector_field
        sig = pad_vec(
                make_vector_field("sigma", self.dimensions),
                dim_subset)
        sig_prime = pad_vec(
                make_vector_field("sigma_prime", self.dimensions),
                dim_subset)
        if self.add_decay:
            tau = pad_vec(
                    make_vector_field("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]
Example #2
0
 def field_placeholder(self, w=None):
     "A placeholder for u and v."
     fld_cnt = self.dimensions*2
     if w is None:
         from hedge.optemplate import make_vector_field
         w = make_vector_field("w", fld_cnt)
     return w
Example #3
0
File: em.py Project: felipeh/hedge
    def local_derivatives(self, w=None):
        """Template for the spatial derivatives of the relevant components of E and H"""
        e, h = self.split_eh(self.field_placeholder(w))

        def e_curl(field):
            return self.space_cross_e(nabla, field)

        def h_curl(field):
            return self.space_cross_h(nabla, field)

        from hedge.optemplate import make_nabla
        from hedge.tools import join_fields, count_subset

        nabla = make_nabla(self.dimensions)

        if self.current is not None:
            from hedge.optemplate import make_vector_field
            j = make_vector_field("j",
                    count_subset(self.get_eh_subset()[:3]))
        else:
            j = 0

        # in conservation form: u_t + A u_x = 0
        return join_fields(
                (j - h_curl(h)),
                e_curl(e)
                )
Example #4
0
        def apply_diff_tensor(v):
            if isinstance(self.diffusion_tensor, numpy.ndarray):
                sym_diff_tensor = self.diffusion_tensor
            else:
                sym_diff_tensor = (make_vector_field(
                        "diffusion", self.dimensions**2)
                        .reshape(self.dimensions, self.dimensions))

            return numpy.dot(sym_diff_tensor, v)
Example #5
0
File: em.py Project: felipeh/hedge
    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_vector_field
            w = make_vector_field("w", fld_cnt)

        return w
Example #6
0
File: pml.py Project: felipeh/hedge
    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_vector_field
            w = make_vector_field("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)
Example #7
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)))
Example #8
0
    def bind_characteristic_velocity(self, discr):
        from hedge.optemplate.operators import (
                ElementwiseMaxOperator)
        from hedge.optemplate import make_vector_field
        velocity_vec = make_vector_field("v", self.dimensions)
        velocity = ElementwiseMaxOperator()(
                numpy.dot(velocity_vec, velocity_vec)**0.5)

        from hedge.optemplate import Field
        compiled = discr.compile(velocity)

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

        return do
Example #9
0
    def dirichlet_bc(self, w=None):
        """
        Flux term for dirichlet (displacement) boundary conditions
        """
        u, v = self.split_vars(self.field_placeholder(w))

        if self.dirichlet_bc_data is not None:
            from hedge.optemplate import make_vector_field
            dir_field = cse(
                    -make_vector_field("dirichlet_bc", 3))
        else:
            dir_field = make_obj_array([0,]*3)
        
        from hedge.tools import join_fields
        return join_fields(dir_field, [0]*3, [0,]*9)
Example #10
0
    def calculate_piola(self,u=None):
        from hedge.optemplate import make_nabla
        from hedge.optemplate import make_vector_field
        
        u = make_vector_field('u', 3)

        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[i](u[j])
                if i == j:
                    F[ij] = F[ij] + 1
                ij = ij + 1
        
        return make_obj_array(self.material.stress(F, self.dimensions))
Example #11
0
File: em.py Project: felipeh/hedge
    def incident_bc(self, w=None):
        "Flux terms for incident boundary conditions"
        # NOTE: Untested for inhomogeneous materials, but would usually be
        # physically meaningless anyway (are there exceptions to this?)

        e, h = self.split_eh(self.field_placeholder(w))
        if not self.fixed_material:
            from warnings import warn
            if self.incident_tag != hedge.mesh.TAG_NONE:
                warn("Incident boundary conditions assume homogeneous"+
                     " background material, results may be unphysical")

        from hedge.tools import count_subset
        from hedge.tools import join_fields
        fld_cnt = count_subset(self.get_eh_subset())

        if self.incident_bc_data is not None:
            from hedge.optemplate import make_vector_field
            inc_field = cse(
                   -make_vector_field("incident_bc", fld_cnt))
        else:
            inc_field = make_obj_array([0]*fld_cnt)

        return inc_field
Example #12
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)))
Example #13
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)))
Example #14
0
    def op_template(self, with_sensor=False):
        # {{{ operator preliminaries ------------------------------------------
        from hedge.optemplate import (Field, BoundaryPair, get_flux_operator,
                make_stiffness_t, InverseMassOperator, make_vector_field, 
                ElementwiseMaxOperator, BoundarizeOperator)

        from hedge.tools.symbolic 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_vector_field("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
Example #15
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
Example #16
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))))
Example #17
0
File: lbm.py Project: felipeh/hedge
 def f_bar(self):
     from hedge.optemplate import make_vector_field
     return make_vector_field("f_bar", len(self.method))