Exemplo n.º 1
0
Arquivo: pml.py Projeto: felipeh/hedge
    def assemble_ehpq(self, e=None, h=None, p=None, q=None, discr=None):
        if discr is None:
            def zero():
                return 0
        else:
            def zero():
                return discr.volume_zeros()

        from hedge.tools import count_subset
        e_components = count_subset(self.get_eh_subset()[0:3])
        h_components = count_subset(self.get_eh_subset()[3:6])

        def default_fld(fld, comp):
            if fld is None:
                return [zero() for i in xrange(comp)]
            else:
                return fld

        e = default_fld(e, e_components)
        h = default_fld(h, h_components)
        p = default_fld(p, self.dimensions)
        q = default_fld(q, self.dimensions)

        from hedge.tools import join_fields
        return join_fields(e, h, p, q)
Exemplo n.º 2
0
    def assemble_ehpq(self, e=None, h=None, p=None, q=None, discr=None):
        if discr is None:

            def zero():
                return 0
        else:

            def zero():
                return discr.volume_zeros()

        from hedge.tools import count_subset
        e_components = count_subset(self.get_eh_subset()[0:3])
        h_components = count_subset(self.get_eh_subset()[3:6])

        def default_fld(fld, comp):
            if fld is None:
                return [zero() for i in xrange(comp)]
            else:
                return fld

        e = default_fld(e, e_components)
        h = default_fld(h, h_components)
        p = default_fld(p, self.dimensions)
        q = default_fld(q, self.dimensions)

        from hedge.tools import join_fields
        return join_fields(e, h, p, q)
Exemplo n.º 3
0
    def assemble_eh(self, e=None, h=None, discr=None):
        "Combines separate E and H vectors into a single array."
        if discr is None:

            def zero():
                return 0
        else:

            def zero():
                return discr.volume_zeros()

        from hedge.tools import count_subset
        e_components = count_subset(self.get_eh_subset()[0:3])
        h_components = count_subset(self.get_eh_subset()[3:6])

        def default_fld(fld, comp):
            if fld is None:
                return [zero() for i in xrange(comp)]
            else:
                return fld

        e = default_fld(e, e_components)
        h = default_fld(h, h_components)

        from hedge.tools import join_fields
        return join_fields(e, h)
Exemplo n.º 4
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
Exemplo n.º 5
0
    def split_ehphi(self, w):
        e, h = self.split_eh(w)

        from hedge.tools import count_subset
        eh_components = count_subset(self.maxwell_op.get_eh_subset())
        phi = w[eh_components]
        return e, h, phi
Exemplo n.º 6
0
    def split_ehphi(self, w):
        e, h = self.split_eh(w)

        from hedge.tools import count_subset
        eh_components = count_subset(self.maxwell_op.get_eh_subset())
        phi = w[eh_components]
        return e, h, phi
Exemplo n.º 7
0
Arquivo: em.py Projeto: 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)
                )
Exemplo n.º 8
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
Exemplo n.º 9
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
Exemplo n.º 10
0
    def __init__(self, maxwell_op, chi=1, phi_decay=0):
        self.maxwell_op = maxwell_op
        self.chi = chi
        self.phi_decay = phi_decay

        assert chi > 0
        assert phi_decay >= 0

        from hedge.tools import count_subset
        self.component_count = count_subset(maxwell_op.get_eh_subset())+1
Exemplo n.º 11
0
    def __init__(self, maxwell_op, chi=1, phi_decay=0):
        self.maxwell_op = maxwell_op
        self.chi = chi
        self.phi_decay = phi_decay

        assert chi > 0
        assert phi_decay >= 0

        from hedge.tools import count_subset
        self.component_count = count_subset(maxwell_op.get_eh_subset()) + 1
Exemplo n.º 12
0
    def __init__(self, dimensions, subset=None):
        self.dimensions = dimensions

        if subset is None:
            self.subset = dimensions * [True,]
        else:
            # chop off any extra dimensions
            self.subset = subset[:dimensions]

        from hedge.tools import count_subset
        self.arg_count = count_subset(self.subset)
Exemplo n.º 13
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)
Exemplo n.º 14
0
Arquivo: pml.py Projeto: 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)
Exemplo n.º 15
0
    def __init__(self, dimensions, subset=None):
        self.dimensions = dimensions

        if subset is None:
            self.subset = dimensions * [
                True,
            ]
        else:
            # chop off any extra dimensions
            self.subset = subset[:dimensions]

        from hedge.tools import count_subset
        self.arg_count = count_subset(self.subset)
Exemplo n.º 16
0
    def assemble_eh(self, e=None, h=None, discr=None):
        "Combines separate E and H vectors into a single array."
        if discr is None:
            def zero():
                return 0
        else:
            def zero():
                return discr.volume_zeros()

        from hedge.tools import count_subset
        e_components = count_subset(self.get_eh_subset()[0:3])
        h_components = count_subset(self.get_eh_subset()[3:6])

        def default_fld(fld, comp):
            if fld is None:
                return [zero() for i in xrange(comp)]
            else:
                return fld

        e = default_fld(e, e_components)
        h = default_fld(h, h_components)

        from hedge.tools import join_fields
        return join_fields(e, h)
Exemplo n.º 17
0
    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
        fld_cnt = count_subset(self.get_eh_subset())

        from hedge.tools import is_zero
        incident_bc_data = self.incident_bc_data(self, e, h)
        if is_zero(incident_bc_data):
            return make_obj_array([0]*fld_cnt)
        else:
            return cse(-incident_bc_data)
Exemplo n.º 18
0
    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
        fld_cnt = count_subset(self.get_eh_subset())

        from hedge.tools import is_zero
        incident_bc_data = self.incident_bc_data(self, e, h)
        if is_zero(incident_bc_data):
            return make_obj_array([0] * fld_cnt)
        else:
            return cse(-incident_bc_data)
Exemplo n.º 19
0
Arquivo: em.py Projeto: 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
Exemplo n.º 20
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
Exemplo n.º 21
0
    def flux(self, flux_type):
        """The template for the numerical flux for variable coefficients.

        :param flux_type: can be in [0,1] for anything between central and upwind,
          or "lf" for Lax-Friedrichs.

        As per Hesthaven and Warburton page 433.
        """
        from hedge.flux import (make_normal, FluxVectorPlaceholder,
                                FluxConstantPlaceholder)
        from hedge.tools import join_fields

        normal = make_normal(self.dimensions)

        if self.fixed_material:
            from hedge.tools import count_subset
            w = FluxVectorPlaceholder(count_subset(self.get_eh_subset()))

            e, h = self.split_eh(w)
            epsilon = FluxConstantPlaceholder(self.epsilon)
            mu = FluxConstantPlaceholder(self.mu)

        else:
            from hedge.tools import count_subset
            w = FluxVectorPlaceholder(count_subset(self.get_eh_subset()) + 2)

            epsilon, mu, e, h = self.split_eps_mu_eh(w)

        Z_int = (mu.int / epsilon.int)**0.5
        Y_int = 1 / Z_int
        Z_ext = (mu.ext / epsilon.ext)**0.5
        Y_ext = 1 / Z_ext

        if flux_type == "lf":
            if self.fixed_material:
                max_c = (self.epsilon * self.mu)**(-0.5)
            else:
                from hedge.flux import Max
                c_int = (epsilon.int * mu.int)**(-0.5)
                c_ext = (epsilon.ext * mu.ext)**(-0.5)
                max_c = Max(c_int, c_ext)  # noqa

            return join_fields(
                # flux e,
                1 / 2 * (
                    -self.space_cross_h(normal, h.int - h.ext)
                    # multiplication by epsilon undoes material divisor below
                    #-max_c*(epsilon.int*e.int - epsilon.ext*e.ext)
                ),
                # flux h
                1 / 2 * (
                    self.space_cross_e(normal, e.int - e.ext)
                    # multiplication by mu undoes material divisor below
                    #-max_c*(mu.int*h.int - mu.ext*h.ext)
                ))
        elif isinstance(flux_type, (int, float)):
            # see doc/maxima/maxwell.mac
            return join_fields(
                # flux e,
                (-1 / (Z_int + Z_ext) * self.space_cross_h(
                    normal,
                    Z_ext * (h.int - h.ext) -
                    flux_type * self.space_cross_e(normal, e.int - e.ext))),
                # flux h
                (1 / (Y_int + Y_ext) * self.space_cross_e(
                    normal,
                    Y_ext * (e.int - e.ext) +
                    flux_type * self.space_cross_h(normal, h.int - h.ext))),
            )
        else:
            raise ValueError("maxwell: invalid flux_type (%s)" %
                             self.flux_type)
Exemplo n.º 22
0
    def flux(self, flux_type):
        """The template for the numerical flux for variable coefficients.

        :param flux_type: can be in [0,1] for anything between central and upwind,
          or "lf" for Lax-Friedrichs.

        As per Hesthaven and Warburton page 433.
        """
        from hedge.flux import (make_normal, FluxVectorPlaceholder,
                FluxConstantPlaceholder)
        from hedge.tools import join_fields

        normal = make_normal(self.dimensions)

        if self.fixed_material:
            from hedge.tools import count_subset
            w = FluxVectorPlaceholder(count_subset(self.get_eh_subset()))

            e, h = self.split_eh(w)
            epsilon = FluxConstantPlaceholder(self.epsilon)
            mu = FluxConstantPlaceholder(self.mu)

        else:
            from hedge.tools import count_subset
            w = FluxVectorPlaceholder(count_subset(self.get_eh_subset())+2)

            epsilon, mu, e, h = self.split_eps_mu_eh(w)

        Z_int = (mu.int/epsilon.int)**0.5
        Y_int = 1/Z_int
        Z_ext = (mu.ext/epsilon.ext)**0.5
        Y_ext = 1/Z_ext

        if flux_type == "lf":
            if self.fixed_material:
                max_c = (self.epsilon*self.mu)**(-0.5)
            else:
                from hedge.flux import Max
                c_int = (epsilon.int*mu.int)**(-0.5)
                c_ext = (epsilon.ext*mu.ext)**(-0.5)
                max_c = Max(c_int, c_ext)  # noqa

            return join_fields(
                    # flux e,
                    1/2*(
                        -self.space_cross_h(normal, h.int-h.ext)
                        # multiplication by epsilon undoes material divisor below
                        #-max_c*(epsilon.int*e.int - epsilon.ext*e.ext)
                    ),
                    # flux h
                    1/2*(
                        self.space_cross_e(normal, e.int-e.ext)
                        # multiplication by mu undoes material divisor below
                        #-max_c*(mu.int*h.int - mu.ext*h.ext)
                    ))
        elif isinstance(flux_type, (int, float)):
            # see doc/maxima/maxwell.mac
            return join_fields(
                    # flux e,
                    (
                        -1/(Z_int+Z_ext)*self.space_cross_h(normal,
                            Z_ext*(h.int-h.ext)
                            - flux_type*self.space_cross_e(normal, e.int-e.ext))
                        ),
                    # flux h
                    (
                        1/(Y_int + Y_ext)*self.space_cross_e(normal,
                            Y_ext*(e.int-e.ext)
                            + flux_type*self.space_cross_h(normal, h.int-h.ext))
                        ),
                    )
        else:
            raise ValueError("maxwell: invalid flux_type (%s)"
                    % self.flux_type)