Example #1
0
    def flux(self):
        from hedge.flux import FluxVectorPlaceholder, make_normal

        dim = self.dimensions
        w = FluxVectorPlaceholder(2 + dim)
        c = w[0]
        u = w[1]
        v = w[2:]
        normal = make_normal(dim)

        from hedge.tools import join_fields
        flux = self.time_sign * 1 / 2 * join_fields(
            c.ext * numpy.dot(v.ext, normal) - c.int * numpy.dot(
                v.int, normal), normal * (c.ext * u.ext - c.int * u.int))

        if self.flux_type == "central":
            pass
        elif self.flux_type == "upwind":
            flux += join_fields(
                c.ext * u.ext - c.int * u.int,
                c.ext * normal * numpy.dot(normal, v.ext) -
                c.int * normal * numpy.dot(normal, v.int))
        else:
            raise ValueError("invalid flux type '%s'" % self.flux_type)

        return flux
Example #2
0
    def flux(self):
        from hedge.flux import FluxVectorPlaceholder, make_normal

        dim = self.dimensions
        w = FluxVectorPlaceholder(1+dim)
        u = w[0]
        v = w[1:]
        normal = make_normal(dim)

        from hedge.tools import join_fields
        flux_weak = join_fields(
                np.dot(v.avg, normal),
                u.avg * normal)

        if self.flux_type == "central":
            pass
        elif self.flux_type == "upwind":
            # see doc/notes/hedge-notes.tm
            flux_weak -= self.sign*join_fields(
                    0.5*(u.int-u.ext),
                    0.5*(normal * np.dot(normal, v.int-v.ext)))
        else:
            raise ValueError("invalid flux type '%s'" % self.flux_type)

        flux_strong = join_fields(
                np.dot(v.int, normal),
                u.int * normal) - flux_weak

        return -self.c*flux_strong
Example #3
0
    def flux(self):
        from hedge.flux import FluxVectorPlaceholder, make_normal

        dim = self.dimensions
        w = FluxVectorPlaceholder(1 + dim)
        u = w[0]
        v = w[1:]
        normal = make_normal(dim)

        from hedge.tools import join_fields
        flux_weak = join_fields(numpy.dot(v.avg, normal), u.avg * normal)

        if self.flux_type == "central":
            pass
        elif self.flux_type == "upwind":
            # see doc/notes/hedge-notes.tm
            flux_weak -= self.sign * join_fields(
                0.5 * (u.int - u.ext), 0.5 *
                (normal * numpy.dot(normal, v.int - v.ext)))
        else:
            raise ValueError("invalid flux type '%s'" % self.flux_type)

        flux_strong = join_fields(numpy.dot(v.int, normal),
                                  u.int * normal) - flux_weak

        return -self.c * flux_strong
Example #4
0
    def flux(self):
        from hedge.flux import FluxVectorPlaceholder, make_normal

        dim = self.dimensions
        w = FluxVectorPlaceholder(2+dim)
        c = w[0]
        u = w[1]
        v = w[2:]
        normal = make_normal(dim)

        from hedge.tools import join_fields
        flux = self.time_sign*1/2*join_fields(
                c.ext * np.dot(v.ext, normal)
                - c.int * np.dot(v.int, normal),
                normal*(c.ext*u.ext - c.int*u.int))

        if self.flux_type == "central":
            pass
        elif self.flux_type == "upwind":
            flux += join_fields(
                    c.ext*u.ext - c.int*u.int,
                    c.ext*normal*np.dot(normal, v.ext)
                    - c.int*normal*np.dot(normal, v.int)
                    )
        else:
            raise ValueError("invalid flux type '%s'" % self.flux_type)

        return flux
Example #5
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
Example #6
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)
Example #7
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 #8
0
    def assemble_vars(self, u=None, v=None,F=None, discr=None):
        "Combines separate U and V vectors into a single array."
        if discr is None:
            def zero():
                return 0
        else:
            def zero():
                return discr.volume_zeros()

        dim = self.dimensions

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

        if self.init_velocity is None or discr is None:
            v = default_fld(v, dim)
        else:
            v = self.init_velocity.volume_interpolant(discr)

        if self.init_displacement is None or discr is None:
            u = default_fld(u, dim)
        else:
            u = self.init_displacement.volume_interpolant(discr)

        from hedge.tools import join_fields
        return join_fields(u, v)
Example #9
0
    def local_derivatives(self, w=None):
        """Template for the volume terms of the time derivatives for
        U and V.  dU/dt = V, and dV/dt = div P.  Body forces not yet
        implemented"""
        u, v, F = self.split_grad_vars(w)
        dim = self.dimensions

        from hedge.optemplate import make_stiffness_t, make_vector_field
        from hedge.tools import join_fields
 
        P = self.material.stress(F, self.dimensions)
        
        stiffness = make_stiffness_t(dim)
        Dv = [0,]*3
        for i in range(dim):
            for j in range(dim):
                Dv[i] = Dv[i] - stiffness[j](P[3*j+i])

        # in conservation form: u_t + A u_x = 0
        return join_fields(
                # time derivative of u is v
                v[0], v[1], v[2],
                # time derivative of v is div P
                Dv[0], Dv[1], Dv[2]
                )
Example #10
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)
Example #11
0
 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)
Example #12
0
File: pml.py Project: 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)
Example #13
0
 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)
Example #14
0
    def __call__(self, t, x_vec):
        # JSH/TW Nodal DG Methods, p.326

        rho = numpy.ones_like(x_vec[0])
        rho_u = x_vec[1] * x_vec[1]
        rho_v = numpy.zeros_like(x_vec[0])
        e = (2 * self.mu * x_vec[0] + 10) / (self.gamma - 1) + x_vec[1]**4 / 2

        from hedge.tools import join_fields
        return join_fields(rho, e, rho_u, rho_v)
Example #15
0
    def __call__(self, t, x_vec):
        # JSH/TW Nodal DG Methods, p.326

        rho = numpy.ones_like(x_vec[0])
        rho_u = x_vec[1] * x_vec[1]
        rho_v = numpy.zeros_like(x_vec[0])
        e = (2 * self.mu * x_vec[0] + 10) / (self.gamma - 1) + x_vec[1]**4 / 2

        from hedge.tools import join_fields
        return join_fields(rho, e, rho_u, rho_v)
Example #16
0
    def pmc_bc(self, w=None):
        "Construct part of the flux operator template for PMC boundary conditions"
        e, h = self.split_eh(self.field_placeholder(w))

        from hedge.tools import join_fields
        from hedge.optemplate import BoundarizeOperator
        pmc_e = BoundarizeOperator(self.pmc_tag)(e)
        pmc_h = BoundarizeOperator(self.pmc_tag)(h)

        return join_fields(pmc_e, -pmc_h)
Example #17
0
    def pmc_bc(self, w=None):
        "Construct part of the flux operator template for PMC boundary conditions"
        e, h = self.split_eh(self.field_placeholder(w))

        from hedge.tools import join_fields
        from hedge.optemplate import BoundarizeOperator
        pmc_e = BoundarizeOperator(self.pmc_tag)(e)
        pmc_h = BoundarizeOperator(self.pmc_tag)(h)

        return join_fields(pmc_e, -pmc_h)
Example #18
0
    def flux(self):
        from hedge.flux import make_normal, FluxVectorPlaceholder

        normal = make_normal(self.maxwell_op.dimensions)

        from hedge.tools import join_fields

        w = FluxVectorPlaceholder(self.component_count)
        e, h, phi = self.split_ehphi(w)

        # see hedge/doc/maxima/eclean.mac for derivation
        strong_flux = 0.5 * self.c * self.chi * join_fields(
            # flux e
            normal * (phi.int - phi.ext - numpy.dot(normal, e.int - e.ext)),
            # flux h
            len(h) * [0],
            # flux phi
            numpy.dot(e.int - e.ext, normal) - (phi.int - phi.ext))
        return strong_flux + join_fields(self.maxwell_op.flux(1), 0)
Example #19
0
    def __call__(self, t, x_vec):
        rho = 2 + numpy.sin(x_vec[0] + x_vec[1] + x_vec[2] - 2 * t)
        velocity = numpy.array([1, 1, 0])
        p = 1
        e = p/(self.gamma-1) + rho/2 * numpy.dot(velocity, velocity)
        rho_u = rho * velocity[0]
        rho_v = rho * velocity[1]
        rho_w = rho * velocity[2]

        from hedge.tools import join_fields
        return join_fields(rho, e, rho_u, rho_v, rho_w)
Example #20
0
    def __call__(self, t, x_vec):
        rho = 2 + numpy.sin(x_vec[0] + x_vec[1] + x_vec[2] - 2 * t)
        velocity = numpy.array([1, 1, 0])
        p = 1
        e = p / (self.gamma - 1) + rho / 2 * numpy.dot(velocity, velocity)
        rho_u = rho * velocity[0]
        rho_v = rho * velocity[1]
        rho_w = rho * velocity[2]

        from hedge.tools import join_fields
        return join_fields(rho, e, rho_u, rho_v, rho_w)
Example #21
0
    def flux(self):
        from hedge.flux import make_normal, FluxVectorPlaceholder

        normal = make_normal(self.maxwell_op.dimensions)

        from hedge.tools import join_fields

        w = FluxVectorPlaceholder(self.component_count)
        e, h, phi = self.split_ehphi(w)

        # see hedge/doc/maxima/eclean.mac for derivation
        strong_flux = 0.5*self.c*self.chi*join_fields(
                # flux e
                normal*(phi.int-phi.ext - numpy.dot(normal, e.int-e.ext)),
                # flux h
                len(h)*[0],
                # flux phi
                numpy.dot(e.int-e.ext, normal)-(phi.int-phi.ext)
                )
        return strong_flux + join_fields(self.maxwell_op.flux(1), 0)
Example #22
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)
Example #23
0
    def some_vector(discr):
        x = discr.nodes.T.astype(discr.default_scalar_type)

        from hedge.tools import join_fields

        u1 = discr.interpolate_volume_function(lambda x, el: sin(pi * x[0]))
        u2 = discr.interpolate_volume_function(lambda x, el: sin(pi * x[1]))
        u3 = discr.interpolate_volume_function(lambda x, el: sin(pi * x[0] + pi * x[1]))
        u4 = discr.interpolate_volume_function(lambda x, el: cos(pi * x[0]))

        return join_fields(u1, u2, u3, u4)
    def some_vector(discr):
        # x = discr.nodes.T.astype(discr.default_scalar_type)

        from hedge.tools import join_fields

        u1 = discr.interpolate_volume_function(lambda x, el: sin(pi * x[0]))
        u2 = discr.interpolate_volume_function(lambda x, el: sin(pi * x[1]))
        u3 = discr.interpolate_volume_function(
            lambda x, el: sin(pi * x[0] + pi * x[1]))
        u4 = discr.interpolate_volume_function(lambda x, el: cos(pi * x[0]))

        return join_fields(u1, u2, u3, u4)
Example #25
0
    def flux(self, beta, is_dirich):
        """The template for the numerical flux for variable coefficients.
            From Noels, Radovitzky 2007
        """
        from hedge.flux import (make_normal, FluxVectorPlaceholder,
                FluxConstantPlaceholder)
        from hedge.tools import join_fields
        
        dim = self.dimensions
        normal = make_normal(self.dimensions)
        w = FluxVectorPlaceholder(dim*2+9)

        # u is displacement field, v is its time derivative (velocity)
        u, v, F = self.split_grad_vars(w)
      
        P_int = self.material.stress(F.int, self.dimensions)
        C_int = self.material.tangent_moduli(F.int, self.dimensions, self.dimensions)

        # constitutive update for exterior face
        if is_dirich:
            P_ext = [0]*9  #[-3*p for p in P_int]
            C_ext = [0]*81 #C_int
        else:
            P_ext = self.material.stress(F.ext, self.dimensions)
            C_ext = self.material.tangent_moduli(F.ext, self.dimensions, self.dimensions)
        
        P_avg = [(P_int[i] + P_ext[i])/2 for i in range(dim*dim)]
        # 'force' flux
        v_flux = [0,]*self.dimensions
        for i in range(self.dimensions):
            for j in range(self.dimensions):
                v_flux[i] = v_flux[i] + P_avg[3*i+j]*normal[j]
        
        from hedge.flux import make_penalty_term
        stab_factor = beta * make_penalty_term()
        C_avg = [stab_factor * (C_int[i] + C_ext[i]) / 2 for i in range(dim*dim*dim*dim)]
        # stabilization term
        u_jump = u.ext - u.int
        for i in range(self.dimensions):
            for j in range(self.dimensions):
               for k in range(self.dimensions):
                    for l in range(self.dimensions):
                        v_flux[i] = v_flux[i] - normal[j]* \
                                                C_avg[27*i+9*j+3*k+l]* \
                                                u_jump[k]* \
                                                normal[l]

        return join_fields(
                # u needs no flux term
                0,0,0,
                # flux for v
                v_flux[0], v_flux[1], v_flux[2]
                )
Example #26
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 #27
0
def make_vector_field(name, components):
    """Return an object array of *components* subscripted
    :class:`Field` instances.

    :param components: The number of components in the vector.
    """
    if isinstance(components, int):
        components = range(components)

    from hedge.tools import join_fields
    vfld = pymbolic.primitives.Variable(name)
    return join_fields(*[vfld[i] for i in components])
Example #28
0
    def assemble_fields(self, e=None, h=None, phi=None, discr=None):
        if discr is None:
            def zero(): return 0
        else:
            def zero(): return discr.volume_zeros()

        if phi is None:
            phi = zero()

        from hedge.tools import join_fields
        return join_fields(
                self.maxwell_op.assemble_fields(e, h),
                phi)
Example #29
0
    def __call__(self,t,x_vec,q):

        vortex_loc = self.center + t*self.velocity

        # coordinates relative to vortex center
        x_rel = x_vec[0] - vortex_loc[0]
        y_rel = x_vec[1] - vortex_loc[1]

        # sources written in terms of A=1.0 solution 
        # (standard isentropic vortex)

        from math import pi
        r = numpy.sqrt(x_rel**2+y_rel**2)
        expterm = self.beta*numpy.exp(1-r**2)
        u = self.velocity[0] - expterm*y_rel/(2*pi)
        v = self.velocity[1] + expterm*x_rel/(2*pi)
        rho = (1-(self.gamma-1)/(16*self.gamma*pi**2)*expterm**2)**(1/(self.gamma-1))
        p = rho**self.gamma

        #computed necessary derivatives
        expterm_t = 2*expterm*x_rel
        expterm_x = -2*expterm*x_rel
        expterm_y = -2*expterm*y_rel
        u_x = -expterm*y_rel/(2*pi)*(-2*x_rel)
        v_y = expterm*x_rel/(2*pi)*(-2*y_rel)

        #derivatives for rho (A=1)
        facG=self.gamma-1
        rho_t = (1/facG)*(1-(facG)/(16*self.gamma*pi**2)*expterm**2)**(1/facG-1)* \
                (-facG/(16*self.gamma*pi**2)*2*expterm*expterm_t)
        rho_x = (1/facG)*(1-(facG)/(16*self.gamma*pi**2)*expterm**2)**(1/facG-1)* \
                (-facG/(16*self.gamma*pi**2)*2*expterm*expterm_x)
        rho_y = (1/facG)*(1-(facG)/(16*self.gamma*pi**2)*expterm**2)**(1/facG-1)* \
                (-facG/(16*self.gamma*pi**2)*2*expterm*expterm_y)

        #derivatives for rho (A=1) to the power of gamma
        rho_gamma_t = self.gamma*rho**(self.gamma-1)*rho_t
        rho_gamma_x = self.gamma*rho**(self.gamma-1)*rho_x
        rho_gamma_y = self.gamma*rho**(self.gamma-1)*rho_y


        factorA=self.densityA**self.gamma-self.densityA
        #construct source terms
        source_rho = x_vec[0]-x_vec[0]
        source_e = (factorA/(self.gamma-1))*(rho_gamma_t + self.gamma*(u_x*rho**self.gamma+u*rho_gamma_x)+ \
                self.gamma*(v_y*rho**self.gamma+v*rho_gamma_y))
        source_rhou = factorA*rho_gamma_x
        source_rhov = factorA*rho_gamma_y

        from hedge.tools import join_fields
        return join_fields(source_rho, source_e, source_rhou, source_rhov, x_vec[0]-x_vec[0])
Example #30
0
    def assemble_fields(self, e=None, h=None, phi=None, discr=None):
        if discr is None:

            def zero():
                return 0
        else:

            def zero():
                return discr.volume_zeros()

        if phi is None:
            phi = zero()

        from hedge.tools import join_fields
        return join_fields(self.maxwell_op.assemble_fields(e, h), phi)
Example #31
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 #32
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 __call__(self, t, x_vec):
        ones = numpy.ones_like(x_vec[0])
        rho_field = ones*self.rho

        if self.gaussian_pulse_at is not None:
            rel_to_pulse = [x_vec[i] - self.gaussian_pulse_at[i]
                    for i in range(len(x_vec))]
            rho_field +=  self.pulse_magnitude * self.rho * numpy.exp(
                - sum(rtp_i**2 for rtp_i in rel_to_pulse)/2)

        direction = self.direction_vector(x_vec.shape[0])

        from hedge.tools import make_obj_array
        u_field = make_obj_array([ones*self.velocity*dir_i
            for dir_i in direction])

        from hedge.tools import join_fields
        return join_fields(rho_field, self.e*ones, self.rho*u_field)
Example #34
0
    def __call__(self, t, x_vec):
        ones = numpy.ones_like(x_vec[0])
        rho_field = ones * self.rho

        if self.gaussian_pulse_at is not None:
            rel_to_pulse = [
                x_vec[i] - self.gaussian_pulse_at[i] for i in range(len(x_vec))
            ]
            rho_field += self.pulse_magnitude * self.rho * numpy.exp(
                -sum(rtp_i**2 for rtp_i in rel_to_pulse) / 2)

        direction = self.direction_vector(x_vec.shape[0])

        from hedge.tools import make_obj_array
        u_field = make_obj_array(
            [ones * self.velocity * dir_i for dir_i in direction])

        from hedge.tools import join_fields
        return join_fields(rho_field, self.e * ones, self.rho * u_field)
Example #35
0
    def local_derivatives(self, w=None):
        """Template for the spatial derivatives of the relevant components of
        :math:`E` and :math:`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

        nabla = make_nabla(self.dimensions)

        # in conservation form: u_t + A u_x = 0
        return join_fields((self.current - h_curl(h)), e_curl(e))
Example #36
0
    def __call__(self, t, x_vec):

        from hedge.tools import heaviside
        from hedge.tools import heaviside_a

        x_rel = x_vec[0]
        y_rel = x_vec[1]

        from math import pi
        r = numpy.sqrt(x_rel**2 + y_rel**2)
        r_shift = r - 3.0
        u = 0.0
        v = 0.0
        from numpy import sign
        rho = heaviside(-r_shift) + .125 * heaviside_a(r_shift, 1.0)
        e = (1.0 / (self.gamma - 1.0)) * (heaviside(-r_shift) +
                                          .1 * heaviside_a(r_shift, 1.0))
        p = (self.gamma - 1.0) * e

        from hedge.tools import join_fields
        return join_fields(rho, e, rho * u, rho * v)
Example #37
0
    def __call__(self, t, x_vec):
        vortex_loc = self.center + t*self.velocity

        # coordinates relative to vortex center
        x_rel = x_vec[0] - vortex_loc[0]
        y_rel = x_vec[1] - vortex_loc[1]

        # Y.C. Zhou, G.W. Wei / Journal of Computational Physics 189 (2003) 159
        # also JSH/TW Nodal DG Methods, p. 209

        from math import pi
        r = numpy.sqrt(x_rel**2+y_rel**2)
        expterm = self.beta*numpy.exp(1-r**2)
        u = self.velocity[0] - expterm*y_rel/(2*pi)
        v = self.velocity[1] + expterm*x_rel/(2*pi)
        rho = self.densityA*(1-(self.gamma-1)/(16*self.gamma*pi**2)*expterm**2)**(1/(self.gamma-1))
        p = rho**self.gamma

        e = p/(self.gamma-1) + rho/2*(u**2+v**2)

        from hedge.tools import join_fields
        return join_fields(rho, e, rho*u, rho*v)
Example #38
0
    def absorbing_bc(self, w=None):
        """Construct part of the flux operator template for 1st order
        absorbing boundary conditions.
        """

        from hedge.optemplate import normal
        absorb_normal = normal(self.absorb_tag, self.dimensions)

        from hedge.optemplate import BoundarizeOperator, Field
        from hedge.tools import join_fields

        e, h = self.split_eh(self.field_placeholder(w))

        if self.fixed_material:
            epsilon = self.epsilon
            mu = self.mu
        else:
            epsilon = cse(
                BoundarizeOperator(self.absorb_tag)(Field("epsilon")))
            mu = cse(BoundarizeOperator(self.absorb_tag)(Field("mu")))

        absorb_Z = (mu / epsilon)**0.5
        absorb_Y = 1 / absorb_Z

        absorb_e = BoundarizeOperator(self.absorb_tag)(e)
        absorb_h = BoundarizeOperator(self.absorb_tag)(h)

        bc = join_fields(
            absorb_e + 1 / 2 *
            (self.space_cross_h(absorb_normal,
                                self.space_cross_e(absorb_normal, absorb_e)) -
             absorb_Z * self.space_cross_h(absorb_normal, absorb_h)),
            absorb_h + 1 / 2 *
            (self.space_cross_e(absorb_normal,
                                self.space_cross_h(absorb_normal, absorb_h)) +
             absorb_Y * self.space_cross_e(absorb_normal, absorb_e)))

        return bc
Example #39
0
    def absorbing_bc(self, w=None):
        """Construct part of the flux operator template for 1st order
        absorbing boundary conditions.
        """

        from hedge.optemplate import normal
        absorb_normal = normal(self.absorb_tag, self.dimensions)

        from hedge.optemplate import BoundarizeOperator, Field
        from hedge.tools import join_fields

        e, h = self.split_eh(self.field_placeholder(w))

        if self.fixed_material:
            epsilon = self.epsilon
            mu = self.mu
        else:
            epsilon = cse(
                    BoundarizeOperator(self.absorb_tag)(Field("epsilon")))
            mu = cse(
                    BoundarizeOperator(self.absorb_tag)(Field("mu")))

        absorb_Z = (mu/epsilon)**0.5
        absorb_Y = 1/absorb_Z

        absorb_e = BoundarizeOperator(self.absorb_tag)(e)
        absorb_h = BoundarizeOperator(self.absorb_tag)(h)

        bc = join_fields(
                absorb_e + 1/2*(self.space_cross_h(absorb_normal, self.space_cross_e(
                    absorb_normal, absorb_e))
                    - absorb_Z*self.space_cross_h(absorb_normal, absorb_h)),
                absorb_h + 1/2*(
                    self.space_cross_e(absorb_normal, self.space_cross_h(
                        absorb_normal, absorb_h))
                    + absorb_Y*self.space_cross_e(absorb_normal, absorb_e)))

        return bc
Example #40
0
    def __call__(self, t, x_vec):

        from hedge.tools import heaviside
        from hedge.tools import heaviside_a

        x_rel = x_vec[0]
        y_rel = x_vec[1]

        from math import pi

        r = numpy.sqrt(x_rel ** 2 + y_rel ** 2)
        r_shift = r - 3.0
        u = 0.0
        v = 0.0
        from numpy import sign

        rho = heaviside(-r_shift) + 0.125 * heaviside_a(r_shift, 1.0)
        e = (1.0 / (self.gamma - 1.0)) * (heaviside(-r_shift) + 0.1 * heaviside_a(r_shift, 1.0))
        p = (self.gamma - 1.0) * e

        from hedge.tools import join_fields

        return join_fields(rho, e, rho * u, rho * v)
Example #41
0
    def local_derivatives(self, w=None):
        """Template for the spatial derivatives of the relevant components of
        :math:`E` and :math:`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

        nabla = make_nabla(self.dimensions)

        # in conservation form: u_t + A u_x = 0
        return join_fields(
                (self.current - h_curl(h)),
                e_curl(e)
                )
Example #42
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)
Example #43
0
def test_efield_vs_gauss_law():
    from hedge.mesh.generator import \
            make_box_mesh, \
            make_cylinder_mesh
    from math import sqrt, pi
    from pytools.arithmetic_container import \
            ArithmeticList, join_fields
    from random import seed
    from pytools.stopwatch import Job

    from pyrticle.units import SIUnitsWithNaturalConstants
    units = SIUnitsWithNaturalConstants()

    seed(0)

    nparticles = 10000
    beam_radius = 2.5 * units.MM
    emittance = 5 * units.MM * units.MRAD
    final_time = 0.1 * units.M / units.VACUUM_LIGHT_SPEED()
    field_dump_interval = 1
    tube_length = 20 * units.MM

    # discretization setup ----------------------------------------------------
    from pyrticle.geometry import make_cylinder_with_fine_core
    mesh = make_cylinder_with_fine_core(
        r=10 * beam_radius,
        inner_r=1 * beam_radius,
        min_z=0,
        max_z=tube_length,
        max_volume_inner=10 * units.MM**3,
        max_volume_outer=100 * units.MM**3,
        radial_subdiv=10,
    )

    from hedge.backends import guess_run_context
    rcon = guess_run_context([])
    discr = rcon.make_discretization(mesh, order=3)

    from hedge.models.em import MaxwellOperator
    max_op = MaxwellOperator(epsilon=units.EPSILON0, mu=units.MU0, flux_type=1)

    from hedge.models.nd_calculus import DivergenceOperator
    div_op = DivergenceOperator(discr.dimensions)

    # particles setup ---------------------------------------------------------
    from pyrticle.cloud import PicMethod
    from pyrticle.deposition.shape import ShapeFunctionDepositor
    from pyrticle.pusher import MonomialParticlePusher

    method = PicMethod(discr, units, ShapeFunctionDepositor(),
                       MonomialParticlePusher(), 3, 3)

    # particle ic ---------------------------------------------------------
    cloud_charge = -1e-9 * units.C
    electrons_per_particle = abs(cloud_charge / nparticles / units.EL_CHARGE)

    el_energy = 10 * units.EL_REST_ENERGY()
    el_lorentz_gamma = el_energy / units.EL_REST_ENERGY()
    beta = (1 - 1 / el_lorentz_gamma**2)**0.5
    gamma = 1 / sqrt(1 - beta**2)

    from pyrticle.distribution import KVZIntervalBeam
    beam = KVZIntervalBeam(units,
                           total_charge=cloud_charge,
                           p_charge=cloud_charge / nparticles,
                           p_mass=electrons_per_particle * units.EL_MASS,
                           radii=2 * [beam_radius],
                           emittances=2 * [5 * units.MM * units.MRAD],
                           z_length=tube_length,
                           z_pos=tube_length / 2,
                           beta=beta)

    state = method.make_state()

    method.add_particles(state, beam.generate_particles(), nparticles)

    # field ic ----------------------------------------------------------------
    from pyrticle.cloud import guess_shape_bandwidth
    guess_shape_bandwidth(method, state, 2)

    from pyrticle.cloud import compute_initial_condition

    from hedge.data import ConstantGivenFunction
    fields = compute_initial_condition(rcon,
                                       discr,
                                       method,
                                       state,
                                       maxwell_op=max_op,
                                       potential_bc=ConstantGivenFunction())

    # check against theory ----------------------------------------------------
    q_per_unit_z = cloud_charge / beam.z_length

    class TheoreticalEField:
        shape = (3, )

        def __call__(self, x, el):
            r = la.norm(x[:2])
            if r >= max(beam.radii):
                xy_unit = x / r
                xy_unit[2] = 0
                return xy_unit * ((q_per_unit_z) /
                                  (2 * pi * r * max_op.epsilon))
            else:
                return numpy.zeros((3, ))

    def theory_indicator(x, el):
        r = la.norm(x[:2])
        if r >= max(beam.radii):
            return 1
        else:
            return 0

    from hedge.tools import join_fields, to_obj_array
    e_theory = to_obj_array(
        discr.interpolate_volume_function(TheoreticalEField()))
    theory_ind = discr.interpolate_volume_function(theory_indicator)

    e_field, h_field = max_op.split_eh(fields)
    restricted_e = join_fields(*[e_i * theory_ind for e_i in e_field])

    def l2_error(field, true):
        return discr.norm(field - true) / discr.norm(true)

    outer_l2 = l2_error(restricted_e, e_theory)
    assert outer_l2 < 0.08

    if False:
        visf = vis.make_file("e_comparison")
        mesh_scalars, mesh_vectors = \
                method.add_to_vis(vis, visf)
        vis.add_data(visf, [
            ("e", restricted_e),
            ("e_theory", e_theory),
        ] + mesh_vectors + mesh_scalars)
        visf.close()
Example #44
0
 def rhs(t, y):
     return join_fields([
         vel,
         0 * vel,
         0,  # drecon
     ])
Example #45
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 #46
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 #47
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)
Example #48
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 #49
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
Example #50
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
Example #51
0
def main(write_output=True,
         flux_type_arg="upwind",
         dtype=np.float64,
         debug=[]):
    from math import sin, cos, pi, exp, sqrt  # noqa

    from hedge.backends import guess_run_context
    rcon = guess_run_context()

    if rcon.is_head_rank:
        from hedge.mesh.reader.gmsh import generate_gmsh
        mesh = generate_gmsh(GEOMETRY,
                             2,
                             allow_internal_boundaries=True,
                             force_dimension=2)

        print "%d elements" % len(mesh.elements)
        mesh_data = rcon.distribute_mesh(mesh)
    else:
        mesh_data = rcon.receive_mesh()

    discr = rcon.make_discretization(mesh_data,
                                     order=4,
                                     debug=debug,
                                     default_scalar_type=dtype)
    from hedge.timestep.runge_kutta import LSRK4TimeStepper
    stepper = LSRK4TimeStepper(dtype=dtype)

    from hedge.visualization import VtkVisualizer
    if write_output:
        vis = VtkVisualizer(discr, rcon, "fld")

    source_center = 0
    source_width = 0.05
    source_omega = 3

    import hedge.optemplate as sym
    sym_x = sym.nodes(2)
    sym_source_center_dist = sym_x - source_center

    from hedge.models.wave import StrongWaveOperator
    op = StrongWaveOperator(
        -1,
        discr.dimensions,
        source_f=sym.CFunction("sin")(
            source_omega * sym.ScalarParameter("t")) * sym.CFunction("exp")(
                -np.dot(sym_source_center_dist, sym_source_center_dist) /
                source_width**2),
        dirichlet_tag="boundary",
        neumann_tag=TAG_NONE,
        radiation_tag=TAG_NONE,
        flux_type=flux_type_arg)

    from hedge.tools import join_fields
    fields = join_fields(
        discr.volume_zeros(dtype=dtype),
        [discr.volume_zeros(dtype=dtype) for i in range(discr.dimensions)])

    # diagnostics setup -------------------------------------------------------
    from pytools.log import LogManager, \
            add_general_quantities, \
            add_simulation_quantities, \
            add_run_info

    if write_output:
        log_file_name = "wiggly.dat"
    else:
        log_file_name = None

    logmgr = LogManager(log_file_name, "w", rcon.communicator)
    add_run_info(logmgr)
    add_general_quantities(logmgr)
    add_simulation_quantities(logmgr)
    discr.add_instrumentation(logmgr)

    stepper.add_instrumentation(logmgr)

    logmgr.add_watches(["step.max", "t_sim.max", "t_step.max"])

    # timestep loop -----------------------------------------------------------
    rhs = op.bind(discr)
    try:
        from hedge.timestep import times_and_steps
        step_it = times_and_steps(
            final_time=4,
            logmgr=logmgr,
            max_dt_getter=lambda t: op.estimate_timestep(
                discr, stepper=stepper, t=t, fields=fields))

        for step, t, dt in step_it:
            if step % 10 == 0 and write_output:
                visf = vis.make_file("fld-%04d" % step)

                vis.add_data(visf, [
                    ("u", fields[0]),
                    ("v", fields[1:]),
                ],
                             time=t,
                             step=step)
                visf.close()

            fields = stepper(fields, t, dt, rhs)

        assert discr.norm(fields) < 1
        assert fields[0].dtype == dtype

    finally:
        if write_output:
            vis.close()

        logmgr.close()
        discr.close()
Example #52
0
def main(write_output=True):
    from math import sin, exp, sqrt  # noqa

    from hedge.mesh.generator import make_rect_mesh
    mesh = make_rect_mesh(a=(-0.5, -0.5), b=(0.5, 0.5), max_area=0.008)

    from hedge.backends.jit import Discretization

    discr = Discretization(mesh, order=4)

    from hedge.visualization import VtkVisualizer
    vis = VtkVisualizer(discr, None, "fld")

    source_center = np.array([0.1, 0.22])
    source_width = 0.05
    source_omega = 3

    import hedge.optemplate as sym
    sym_x = sym.nodes(2)
    sym_source_center_dist = sym_x - source_center

    from hedge.models.wave import StrongWaveOperator
    from hedge.mesh import TAG_ALL, TAG_NONE
    op = StrongWaveOperator(
        -0.1,
        discr.dimensions,
        source_f=sym.CFunction("sin")(
            source_omega * sym.ScalarParameter("t")) * sym.CFunction("exp")(
                -np.dot(sym_source_center_dist, sym_source_center_dist) /
                source_width**2),
        dirichlet_tag=TAG_NONE,
        neumann_tag=TAG_NONE,
        radiation_tag=TAG_ALL,
        flux_type="upwind")

    from hedge.tools import join_fields
    fields = join_fields(
        discr.volume_zeros(),
        [discr.volume_zeros() for i in range(discr.dimensions)])

    from hedge.timestep.runge_kutta import LSRK4TimeStepper
    stepper = LSRK4TimeStepper()
    dt = op.estimate_timestep(discr, stepper=stepper, fields=fields)

    nsteps = int(10 / dt)
    print "dt=%g nsteps=%d" % (dt, nsteps)

    rhs = op.bind(discr)
    for step in range(nsteps):
        t = step * dt

        if step % 10 == 0 and write_output:
            print step, t, discr.norm(fields[0])
            visf = vis.make_file("fld-%04d" % step)

            vis.add_data(visf, [
                ("u", fields[0]),
                ("v", fields[1:]),
            ],
                         time=t,
                         step=step)
            visf.close()

        fields = stepper(fields, t, dt, rhs)

    vis.close()
Example #53
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))
                    ))
Example #54
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
Example #55
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
Example #56
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)
Example #57
0
def main(write_output=True,
         dir_tag=TAG_NONE,
         neu_tag=TAG_NONE,
         rad_tag=TAG_ALL,
         flux_type_arg="upwind"):
    from math import sin, cos, pi, exp, sqrt  # noqa

    from hedge.backends import guess_run_context
    rcon = guess_run_context()

    dim = 2

    if dim == 1:
        if rcon.is_head_rank:
            from hedge.mesh.generator import make_uniform_1d_mesh
            mesh = make_uniform_1d_mesh(-10, 10, 500)
    elif dim == 2:
        from hedge.mesh.generator import make_rect_mesh
        if rcon.is_head_rank:
            mesh = make_rect_mesh(a=(-1, -1), b=(1, 1), max_area=0.003)
    elif dim == 3:
        if rcon.is_head_rank:
            from hedge.mesh.generator import make_ball_mesh
            mesh = make_ball_mesh(max_volume=0.0005)
    else:
        raise RuntimeError("bad number of dimensions")

    if rcon.is_head_rank:
        print "%d elements" % len(mesh.elements)
        mesh_data = rcon.distribute_mesh(mesh)
    else:
        mesh_data = rcon.receive_mesh()

    discr = rcon.make_discretization(mesh_data, order=4)

    from hedge.timestep.runge_kutta import LSRK4TimeStepper
    stepper = LSRK4TimeStepper()

    from hedge.visualization import VtkVisualizer
    if write_output:
        vis = VtkVisualizer(discr, rcon, "fld")

    source_center = np.array([0.7, 0.4])
    source_width = 1 / 16
    source_omega = 3

    import hedge.optemplate as sym
    sym_x = sym.nodes(2)
    sym_source_center_dist = sym_x - source_center

    from hedge.models.wave import VariableVelocityStrongWaveOperator
    op = VariableVelocityStrongWaveOperator(
        c=sym.If(sym.Comparison(np.dot(sym_x, sym_x), "<", 0.4**2), 1, 0.5),
        dimensions=discr.dimensions,
        source=sym.CFunction("sin")(source_omega * sym.ScalarParameter("t")) *
        sym.CFunction("exp")(
            -np.dot(sym_source_center_dist, sym_source_center_dist) /
            source_width**2),
        dirichlet_tag=dir_tag,
        neumann_tag=neu_tag,
        radiation_tag=rad_tag,
        flux_type=flux_type_arg)

    from hedge.tools import join_fields
    fields = join_fields(
        discr.volume_zeros(),
        [discr.volume_zeros() for i in range(discr.dimensions)])

    # {{{ diagnostics setup

    from pytools.log import LogManager, \
            add_general_quantities, \
            add_simulation_quantities, \
            add_run_info

    if write_output:
        log_file_name = "wave.dat"
    else:
        log_file_name = None

    logmgr = LogManager(log_file_name, "w", rcon.communicator)
    add_run_info(logmgr)
    add_general_quantities(logmgr)
    add_simulation_quantities(logmgr)
    discr.add_instrumentation(logmgr)

    from pytools.log import IntervalTimer
    vis_timer = IntervalTimer("t_vis", "Time spent visualizing")
    logmgr.add_quantity(vis_timer)
    stepper.add_instrumentation(logmgr)

    from hedge.log import LpNorm
    u_getter = lambda: fields[0]
    logmgr.add_quantity(LpNorm(u_getter, discr, 1, name="l1_u"))
    logmgr.add_quantity(LpNorm(u_getter, discr, name="l2_u"))

    logmgr.add_watches(["step.max", "t_sim.max", "l2_u", "t_step.max"])

    # }}}

    # {{{ timestep loop

    rhs = op.bind(discr)
    try:
        from hedge.timestep.stability import \
                approximate_rk4_relative_imag_stability_region
        max_dt = (1 / discr.compile(op.max_eigenvalue_expr())() *
                  discr.dt_non_geometric_factor() *
                  discr.dt_geometric_factor() *
                  approximate_rk4_relative_imag_stability_region(stepper))
        if flux_type_arg == "central":
            max_dt *= 0.25

        from hedge.timestep import times_and_steps
        step_it = times_and_steps(final_time=3,
                                  logmgr=logmgr,
                                  max_dt_getter=lambda t: max_dt)

        for step, t, dt in step_it:
            if step % 10 == 0 and write_output:
                visf = vis.make_file("fld-%04d" % step)

                vis.add_data(visf, [
                    ("u", fields[0]),
                    ("v", fields[1:]),
                ],
                             time=t,
                             step=step)
                visf.close()

            fields = stepper(fields, t, dt, rhs)

        assert discr.norm(fields) < 1
    finally:
        if write_output:
            vis.close()

        logmgr.close()
        discr.close()
Example #58
0
def main(write_output=True,
         dir_tag=TAG_NONE,
         neu_tag=TAG_NONE,
         rad_tag=TAG_ALL,
         flux_type_arg="upwind",
         dtype=np.float64,
         debug=[]):
    from math import sin, cos, pi, exp, sqrt  # noqa

    from hedge.backends import guess_run_context
    rcon = guess_run_context()

    dim = 2

    if dim == 1:
        if rcon.is_head_rank:
            from hedge.mesh.generator import make_uniform_1d_mesh
            mesh = make_uniform_1d_mesh(-10, 10, 500)
    elif dim == 2:
        from hedge.mesh.generator import make_rect_mesh
        if rcon.is_head_rank:
            mesh = make_rect_mesh(a=(-0.5, -0.5), b=(0.5, 0.5), max_area=0.008)
    elif dim == 3:
        if rcon.is_head_rank:
            from hedge.mesh.generator import make_ball_mesh
            mesh = make_ball_mesh(max_volume=0.0005)
    else:
        raise RuntimeError("bad number of dimensions")

    if rcon.is_head_rank:
        print "%d elements" % len(mesh.elements)
        mesh_data = rcon.distribute_mesh(mesh)
    else:
        mesh_data = rcon.receive_mesh()

    from hedge.timestep.runge_kutta import LSRK4TimeStepper
    stepper = LSRK4TimeStepper(dtype=dtype)

    from hedge.models.wave import StrongWaveOperator
    from hedge.mesh import TAG_ALL, TAG_NONE  # noqa

    source_center = np.array([0.1, 0.22])
    source_width = 0.05
    source_omega = 3

    import hedge.optemplate as sym
    sym_x = sym.nodes(2)
    sym_source_center_dist = sym_x - source_center

    op = StrongWaveOperator(
        -1,
        dim,
        source_f=sym.CFunction("sin")(
            source_omega * sym.ScalarParameter("t")) * sym.CFunction("exp")(
                -np.dot(sym_source_center_dist, sym_source_center_dist) /
                source_width**2),
        dirichlet_tag=dir_tag,
        neumann_tag=neu_tag,
        radiation_tag=rad_tag,
        flux_type=flux_type_arg)

    discr = rcon.make_discretization(mesh_data,
                                     order=4,
                                     debug=debug,
                                     default_scalar_type=dtype,
                                     tune_for=op.op_template())

    from hedge.visualization import VtkVisualizer
    if write_output:
        vis = VtkVisualizer(discr, rcon, "fld")

    from hedge.tools import join_fields
    fields = join_fields(
        discr.volume_zeros(dtype=dtype),
        [discr.volume_zeros(dtype=dtype) for i in range(discr.dimensions)])

    # {{{ diagnostics setup

    from pytools.log import LogManager, \
            add_general_quantities, \
            add_simulation_quantities, \
            add_run_info

    if write_output:
        log_file_name = "wave.dat"
    else:
        log_file_name = None

    logmgr = LogManager(log_file_name, "w", rcon.communicator)
    add_run_info(logmgr)
    add_general_quantities(logmgr)
    add_simulation_quantities(logmgr)
    discr.add_instrumentation(logmgr)

    from pytools.log import IntervalTimer
    vis_timer = IntervalTimer("t_vis", "Time spent visualizing")
    logmgr.add_quantity(vis_timer)
    stepper.add_instrumentation(logmgr)

    from hedge.log import LpNorm
    u_getter = lambda: fields[0]
    logmgr.add_quantity(LpNorm(u_getter, discr, 1, name="l1_u"))
    logmgr.add_quantity(LpNorm(u_getter, discr, name="l2_u"))

    logmgr.add_watches(["step.max", "t_sim.max", "l2_u", "t_step.max"])

    # }}}

    # {{{ timestep loop

    rhs = op.bind(discr)
    try:
        from hedge.timestep import times_and_steps
        step_it = times_and_steps(
            final_time=4,
            logmgr=logmgr,
            max_dt_getter=lambda t: op.estimate_timestep(
                discr, stepper=stepper, t=t, fields=fields))

        for step, t, dt in step_it:
            if step % 10 == 0 and write_output:
                visf = vis.make_file("fld-%04d" % step)

                vis.add_data(visf, [
                    ("u", discr.convert_volume(fields[0], kind="numpy")),
                    ("v", discr.convert_volume(fields[1:], kind="numpy")),
                ],
                             time=t,
                             step=step)
                visf.close()

            fields = stepper(fields, t, dt, rhs)

        assert discr.norm(fields) < 1
        assert fields[0].dtype == dtype

    finally:
        if write_output:
            vis.close()

        logmgr.close()
        discr.close()