def op_template(self): from hedge.optemplate import (Field, BoundaryPair, get_flux_operator, make_stiffness_t, InverseMassOperator, BoundarizeOperator, QuadratureGridUpsampler, QuadratureInteriorFacesGridUpsampler) u = Field("u") to_quad = QuadratureGridUpsampler("quad") to_int_face_quad = QuadratureInteriorFacesGridUpsampler("quad") # boundary conditions ------------------------------------------------- bc_in = Field("bc_in") bc_out = BoundarizeOperator(self.outflow_tag) * u stiff_t = make_stiffness_t(self.dimensions) m_inv = InverseMassOperator() flux_op = get_flux_operator(self.flux()) return m_inv( numpy.dot(self.v, stiff_t * u) - (flux_op(u) + flux_op(BoundaryPair(u, bc_in, self.inflow_tag)) + flux_op(BoundaryPair(u, bc_out, self.outflow_tag))))
def make_optemplate(): from hedge.optemplate.operators import QuadratureGridUpsampler from hedge.optemplate import Field, make_stiffness_t u = Field("u") qu = QuadratureGridUpsampler("quad")(u) return make_stiffness_t(2)[0](Field("intercept")(qu))
def op_template(self): from hedge.mesh import TAG_ALL from hedge.optemplate import Field, BoundaryPair, \ make_nabla, InverseMassOperator, get_flux_operator u = Field("u") bc = Field("bc") nabla = make_nabla(self.dimensions) flux_op = get_flux_operator(self.flux()) return nabla * u - InverseMassOperator()( flux_op(u) + flux_op(BoundaryPair(u, bc, TAG_ALL)))
def op_template(self): from hedge.optemplate import Field, BoundaryPair, \ get_flux_operator, make_nabla, InverseMassOperator u = Field("u") bc_in = Field("bc_in") nabla = make_nabla(self.dimensions) m_inv = InverseMassOperator() flux_op = get_flux_operator(self.flux()) return (-numpy.dot(self.v, nabla * u) + m_inv( flux_op(u) + flux_op(BoundaryPair(u, bc_in, self.inflow_tag))))
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
def bind_characteristic_velocity(self, discr): from hedge.optemplate import Field compiled = discr.compile( self.characteristic_velocity_optemplate(Field("u"))) def do(u): return compiled(u=u) return do
def bind(self, discr): from hedge.optemplate import Field bound_op = discr.compile(self(Field("f"))) def apply_op(field): from hedge.tools import with_object_array_or_scalar return with_object_array_or_scalar(lambda f: bound_op(f=f), field) return apply_op
def op_template(self, apply_minv, u=None, dir_bc=None, neu_bc=None): from hedge.optemplate import Field if u is None: u = Field("u") result = PoissonOperator.op_template(self, apply_minv, u, dir_bc, neu_bc) if apply_minv: return result + self.k**2 * u else: from hedge.optemplate import MassOperator return result + self.k**2 * MassOperator()(u)
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
def test_quadrature_tri_mass_mat_monomial(): """Check that quadrature integration on triangles is exact as designed.""" from hedge.mesh.generator import make_square_mesh mesh = make_square_mesh(a=-1, b=1, max_area=4 * 1 / 8 + 0.001) order = 4 discr = discr_class(mesh, order=order, debug=discr_class.noninteractive_debug_flags(), quad_min_degrees={"quad": 3 * order}) m, n = 2, 1 f = Monomial((m, n)) f_vec = discr.interpolate_volume_function(lambda x, el: f(x)) from hedge.discretization import ones_on_volume ones = ones_on_volume(discr) if False: from hedge.visualization import SiloVisualizer vis = SiloVisualizer(discr) visf = vis.make_file("test") vis.add_data(visf, [("f", f_vec * f_vec)]) visf.close() from hedge.optemplate import (MassOperator, Field, QuadratureGridUpsampler) f_fld = Field("f") mass_op = discr.compile(MassOperator()(f_fld * f_fld)) from hedge.optemplate.primitives import make_common_subexpression as cse f_upsamp = cse(QuadratureGridUpsampler("quad")(f_fld)) quad_mass_op = discr.compile(MassOperator()(f_upsamp * f_upsamp)) num_integral_1 = numpy.dot(ones, mass_op(f=f_vec)) num_integral_2 = numpy.dot(ones, quad_mass_op(f=f_vec)) true_integral = 4 / ((2 * m + 1) * (2 * n + 1)) err_1 = abs(num_integral_1 - true_integral) err_2 = abs(num_integral_2 - true_integral) print num_integral_1, num_integral_2, true_integral print err_1, err_2 assert err_1 > 1e-8 assert err_2 < 1e-14
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
def test_interior_fluxes_tet(): """Check tetrahedron surface integrals computed using interior fluxes against their known values. """ import meshpy.tet as tet from math import pi, sin, cos mesh_info = tet.MeshInfo() # construct a two-box extrusion of this base base = [(-pi, -pi, 0), (pi, -pi, 0), (pi, pi, 0), (-pi, pi, 0)] # first, the nodes mesh_info.set_points(base + [(x, y, z + pi) for x, y, z in base] + [(x, y, z + pi + 1) for x, y, z in base]) # next, the facets # vertex indices for a box missing the -z face box_without_minus_z = [ [4, 5, 6, 7], [0, 4, 5, 1], [1, 5, 6, 2], [2, 6, 7, 3], [3, 7, 4, 0], ] def add_to_all_vertex_indices(facets, increment): return [[pt + increment for pt in facet] for facet in facets] mesh_info.set_facets( [[0, 1, 2, 3]] # base + box_without_minus_z # first box + add_to_all_vertex_indices(box_without_minus_z, 4) # second box ) # set the volume properties -- this is where the tet size constraints are mesh_info.regions.resize(2) mesh_info.regions[0] = [ 0, 0, pi / 2, # point in volume -> first box 0, # region tag (user-defined number) 0.5, # max tet volume in region ] mesh_info.regions[1] = [ 0, 0, pi + 0.5, # point in volume -> second box 1, # region tag (user-defined number, arbitrary) 0.1, # max tet volume in region ] generated_mesh = tet.build(mesh_info, attributes=True, volume_constraints=True) from hedge.mesh import make_conformal_mesh mesh = make_conformal_mesh(generated_mesh.points, generated_mesh.elements) from hedge.discretization.local import TetrahedronDiscretization from hedge.discretization import ones_on_volume discr = discr_class(mesh, TetrahedronDiscretization(4), debug=discr_class.noninteractive_debug_flags()) def f_u(x, el): if generated_mesh.element_attributes[el.id] == 1: return cos(x[0] - x[1] + x[2]) else: return 0 def f_l(x, el): if generated_mesh.element_attributes[el.id] == 0: return sin(x[0] - x[1] + x[2]) else: return 0 u_l = discr.interpolate_volume_function(f_l) u_u = discr.interpolate_volume_function(f_u) u = u_l + u_u # visualize the produced field #from hedge.visualization import SiloVisualizer #vis = SiloVisualizer(discr) #visf = vis.make_file("sandwich") #vis.add_data(visf, #[("u_l", u_l), ("u_u", u_u)], #expressions=[("u", "u_l+u_u")]) # make sure the surface integral of the difference # between top and bottom is zero from hedge.flux import make_normal, FluxScalarPlaceholder from hedge.optemplate import Field, get_flux_operator fluxu = FluxScalarPlaceholder() res = discr.compile( get_flux_operator( (fluxu.int - fluxu.ext) * make_normal(discr.dimensions)[1]) * Field("u"))(u=u) ones = ones_on_volume(discr) assert abs(numpy.dot(res, ones)) < 5e-14
def test_2d_gauss_theorem(): """Verify Gauss's theorem explicitly on a mesh""" from hedge.mesh.generator import make_disk_mesh from math import sin, cos from numpy import dot mesh = make_disk_mesh() order = 2 discr = discr_class(mesh, order=order, debug=discr_class.noninteractive_debug_flags()) ref_discr = discr_class(mesh, order=order) from hedge.flux import make_normal, FluxScalarPlaceholder normal = make_normal(discr.dimensions) flux_f_ph = FluxScalarPlaceholder(0) one_sided_x = flux_f_ph.int * normal[0] one_sided_y = flux_f_ph.int * normal[1] def f1(x, el): return sin(3 * x[0]) + cos(3 * x[1]) def f2(x, el): return sin(2 * x[0]) + cos(x[1]) from hedge.discretization import ones_on_volume ones = ones_on_volume(discr) f1_v = discr.interpolate_volume_function(f1) f2_v = discr.interpolate_volume_function(f2) from hedge.optemplate import BoundaryPair, Field, make_nabla, \ get_flux_operator nabla = make_nabla(discr.dimensions) divergence = nabla[0].apply(discr, f1_v) + nabla[1].apply(discr, f2_v) int_div = discr.integral(divergence) flux_optp = ( get_flux_operator(one_sided_x)(BoundaryPair(Field("f1"), Field("fz"))) + get_flux_operator(one_sided_y)(BoundaryPair(Field("f2"), Field("fz")))) from hedge.mesh import TAG_ALL bdry_val = discr.compile(flux_optp)(f1=f1_v, f2=f2_v, fz=discr.boundary_zeros(TAG_ALL)) ref_bdry_val = ref_discr.compile(flux_optp)( f1=f1_v, f2=f2_v, fz=discr.boundary_zeros(TAG_ALL)) boundary_int = dot(bdry_val, ones) if False: from hedge.visualization import SiloVisualizer vis = SiloVisualizer(discr) visf = vis.make_file("test") from hedge.tools import make_obj_array from hedge.mesh import TAG_ALL vis.add_data(visf, [ ("bdry", bdry_val), ("ref_bdry", ref_bdry_val), ("div", divergence), ("f", make_obj_array([f1_v, f2_v])), ("n", discr.volumize_boundary_field(discr.boundary_normals(TAG_ALL), TAG_ALL)), ], expressions=[("bdiff", "bdry-ref_bdry")]) #print abs(boundary_int-int_div) assert abs(boundary_int - int_div) < 5e-15
def op_template(self, with_sensor): from hedge.optemplate import (Field, make_stiffness_t, make_nabla, InverseMassOperator, ElementwiseMaxOperator, get_flux_operator) from hedge.optemplate.operators import ( QuadratureGridUpsampler, QuadratureInteriorFacesGridUpsampler) to_quad = QuadratureGridUpsampler("quad") to_if_quad = QuadratureInteriorFacesGridUpsampler("quad") u = Field("u") u0 = Field("u0") # boundary conditions ------------------------------------------------- minv_st = make_stiffness_t(self.dimensions) nabla = make_nabla(self.dimensions) m_inv = InverseMassOperator() def flux(u): return u**2 / 2 #return u0*u emax_u = self.characteristic_velocity_optemplate(u) from hedge.flux.tools import make_lax_friedrichs_flux from pytools.obj_array import make_obj_array num_flux = make_lax_friedrichs_flux( #u0, to_if_quad(emax_u), make_obj_array([to_if_quad(u)]), [make_obj_array([flux(to_if_quad(u))])], [], strong=False)[0] from hedge.second_order import SecondDerivativeTarget if self.viscosity is not None or with_sensor: viscosity_coeff = 0 if with_sensor: viscosity_coeff += Field("sensor") if isinstance(self.viscosity, float): viscosity_coeff += self.viscosity elif self.viscosity is None: pass else: raise TypeError("unsupported type of viscosity coefficient") # strong_form here allows IPDG to reuse the value of grad u. grad_tgt = SecondDerivativeTarget(self.dimensions, strong_form=True, operand=u) self.viscosity_scheme.grad(grad_tgt, bc_getter=None, dirichlet_tags=[], neumann_tags=[]) div_tgt = SecondDerivativeTarget(self.dimensions, strong_form=False, operand=viscosity_coeff * grad_tgt.minv_all) self.viscosity_scheme.div(div_tgt, bc_getter=None, dirichlet_tags=[], neumann_tags=[]) viscosity_bit = div_tgt.minv_all else: viscosity_bit = 0 return m_inv((minv_st[0](flux(to_quad(u)))) - num_flux) \ + viscosity_bit
def op_template(self, apply_minv, u=None, dir_bc=None, neu_bc=None): """ :param apply_minv: :class:`bool` specifying whether to compute a complete divergence operator. If False, the final application of the inverse mass operator is skipped. This is used in :meth:`op` in order to reduce the scheme :math:`M^{-1} S u = f` to :math:`S u = M f`, so that the mass operator only needs to be applied once, when preparing the right hand side in :meth:`prepare_rhs`. :class:`hedge.models.diffusion.DiffusionOperator` needs this. """ from hedge.optemplate import Field, make_sym_vector from hedge.second_order import SecondDerivativeTarget if u is None: u = Field("u") if dir_bc is None: dir_bc = Field("dir_bc") if neu_bc is None: neu_bc = Field("neu_bc") # strong_form here allows IPDG to reuse the value of grad u. grad_tgt = SecondDerivativeTarget(self.dimensions, strong_form=True, operand=u) def grad_bc_getter(tag, expr): assert tag == self.dirichlet_tag return dir_bc self.scheme.grad(grad_tgt, bc_getter=grad_bc_getter, dirichlet_tags=[self.dirichlet_tag], neumann_tags=[self.neumann_tag]) def apply_diff_tensor(v): if isinstance(self.diffusion_tensor, np.ndarray): sym_diff_tensor = self.diffusion_tensor else: sym_diff_tensor = (make_sym_vector("diffusion", self.dimensions**2).reshape( self.dimensions, self.dimensions)) return np.dot(sym_diff_tensor, v) div_tgt = SecondDerivativeTarget(self.dimensions, strong_form=False, operand=apply_diff_tensor( grad_tgt.minv_all)) def div_bc_getter(tag, expr): if tag == self.dirichlet_tag: return dir_bc elif tag == self.neumann_tag: return neu_bc else: assert False, "divergence bc getter " \ "asked for '%s' BC for '%s'" % (tag, expr) self.scheme.div(div_tgt, div_bc_getter, dirichlet_tags=[self.dirichlet_tag], neumann_tags=[self.neumann_tag]) if apply_minv: return div_tgt.minv_all else: return div_tgt.all
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
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)))
def test_interior_fluxes_tri(): """Check triangle surface integrals computed using interior fluxes against their known values. """ from math import pi, sin, cos def round_trip_connect(start, end): for i in range(start, end): yield i, i + 1 yield end, start a = -pi b = pi points = [(a, 0), (b, 0), (a, -1), (b, -1), (a, 1), (b, 1)] import meshpy.triangle as triangle mesh_info = triangle.MeshInfo() mesh_info.set_points(points) mesh_info.set_facets([(0, 1), (1, 3), (3, 2), (2, 0), (0, 4), (4, 5), (1, 5)]) mesh_info.regions.resize(2) mesh_info.regions[0] = [ 0, -0.5, # coordinate 1, # lower element tag 0.1, # max area ] mesh_info.regions[1] = [ 0, 0.5, # coordinate 2, # upper element tag 0.01, # max area ] generated_mesh = triangle.build(mesh_info, attributes=True, volume_constraints=True) #triangle.write_gnuplot_mesh("mesh.dat", generated_mesh) def element_tagger(el): if generated_mesh.element_attributes[el.id] == 1: return ["upper"] else: return ["lower"] from hedge.mesh import make_conformal_mesh mesh = make_conformal_mesh(generated_mesh.points, generated_mesh.elements) from hedge.discretization.local import TriangleDiscretization from hedge.discretization import ones_on_volume discr = discr_class(mesh, TriangleDiscretization(4), debug=discr_class.noninteractive_debug_flags()) def f_u(x, el): if generated_mesh.element_attributes[el.id] == 1: return cos(x[0] - x[1]) else: return 0 def f_l(x, el): if generated_mesh.element_attributes[el.id] == 0: return sin(x[0] - x[1]) else: return 0 # u_l = discr.interpolate_volume_function(f_l) u_u = discr.interpolate_volume_function(f_u) u = u_u + u_u #discr.visualize_vtk("dual.vtk", [("u", u)]) from hedge.flux import make_normal, FluxScalarPlaceholder from hedge.optemplate import Field, get_flux_operator fluxu = FluxScalarPlaceholder() res = discr.compile( get_flux_operator( (fluxu.int - fluxu.ext) * make_normal(discr.dimensions)[1]) * Field("u"))(u=u) ones = ones_on_volume(discr) err = abs(numpy.dot(res, ones)) #print err assert err < 5e-14