def op_template(self): q = make_vector_field('q', self.len_q) fluxes = self.flux(q) # Boundary conditions q_bc_stressfree = BoundarizeOperator(self.boundaryconditions_tag['stressfree'])(q) q_bc_stressfree_null = BoundarizeOperator(self.boundaryconditions_tag['stressfree'])(0) q_bc_fixed = BoundarizeOperator(self.boundaryconditions_tag['fixed'])(q) q_bc_fixed_null = BoundarizeOperator(self.boundaryconditions_tag['fixed'])(0) all_tags_and_bcs = [ (self.boundaryconditions_tag['stressfree'], q_bc_stressfree, q_bc_stressfree_null), (self.boundaryconditions_tag['fixed'], q_bc_fixed, q_bc_fixed_null) ] bdry_tag_state_flux = [(tag, bc, self.bdry_flux(bc, bc_null, tag)) for tag, bc, bc_null in all_tags_and_bcs] # Entire operator nabla = make_nabla(self.dimensions) result = (numpy.dot(nabla, fluxes) + InverseMassOperator() * (self.flux_num(q, fluxes, bdry_tag_state_flux))) result = self.add_sources(result) return result
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) )
def test_tri_diff_mat(): """Check differentiation matrix along the coordinate axes on a disk Uses sines as the function to differentiate. """ from hedge.mesh.generator import make_disk_mesh from hedge.discretization.local import TriangleDiscretization from math import sin, cos, sqrt from hedge.optemplate import make_nabla nabla = make_nabla(2) for coord in [0, 1]: mesh = make_disk_mesh() discr = discr_class(make_disk_mesh(), TriangleDiscretization(4), debug=discr_class.noninteractive_debug_flags()) f = discr.interpolate_volume_function(lambda x, el: sin(3 * x[coord])) df = discr.interpolate_volume_function(lambda x, el: 3 * cos(3 * x[coord])) df_num = nabla[coord].apply(discr, f) # discr.visualize_vtk("diff-err.vtk", # [("f", f), ("df", df), ("df_num", df_num), ("error", error)]) linf_error = la.norm(df_num - df, numpy.Inf) print linf_error assert linf_error < 4e-5
def test_tri_diff_mat(): """Check differentiation matrix along the coordinate axes on a disk Uses sines as the function to differentiate. """ from hedge.mesh.generator import make_disk_mesh from hedge.discretization.local import TriangleDiscretization from math import sin, cos from hedge.optemplate import make_nabla nabla = make_nabla(2) for coord in [0, 1]: discr = discr_class(make_disk_mesh(), TriangleDiscretization(4), debug=discr_class.noninteractive_debug_flags()) f = discr.interpolate_volume_function(lambda x, el: sin(3 * x[coord])) df = discr.interpolate_volume_function( lambda x, el: 3 * cos(3 * x[coord])) df_num = nabla[coord].apply(discr, f) #discr.visualize_vtk("diff-err.vtk", #[("f", f), ("df", df), ("df_num", df_num), ("error", error)]) linf_error = la.norm(df_num - df, numpy.Inf) print linf_error assert linf_error < 4e-5
def op_template(self): dim = self.dimensions q = make_vector_field('q', self.len_q) f2 = make_vector_field('f2', self.len_f2) w = join_fields(q, f2) dim_subset = (True,) * dim + (False,) * (3-dim) def pad_vec(v, subset): result = numpy.zeros((3,), dtype=object) result[numpy.array(subset, dtype=bool)] = v return result sigma = pad_vec(make_vector_field('sigma', dim),dim_subset) alpha = pad_vec(make_vector_field('alpha', dim),dim_subset) kappa = pad_vec(make_vector_field('kappa', dim),dim_subset) fluxes = self.flux(w, kappa) # Boundary conditions q_bc_stressfree = BoundarizeOperator(self.boundaryconditions_tag['stressfree'])(q) q_bc_stressfree_null = BoundarizeOperator(self.boundaryconditions_tag['stressfree'])(0) q_bc_fixed = BoundarizeOperator(self.boundaryconditions_tag['fixed'])(q) q_bc_fixed_null = BoundarizeOperator(self.boundaryconditions_tag['fixed'])(0) all_tags_and_bcs = [ (self.boundaryconditions_tag['stressfree'], q_bc_stressfree, q_bc_stressfree_null), (self.boundaryconditions_tag['fixed'], q_bc_fixed, q_bc_fixed_null) ] bdry_tag_state_flux = [(tag, bc, self.bdry_flux(bc, bc_null, tag)) for tag, bc, bc_null in all_tags_and_bcs] # Entire operator nabla = make_nabla(dim) res_q = (numpy.dot(nabla, fluxes) + InverseMassOperator() * (self.flux_num(q, fluxes, bdry_tag_state_flux))) res_q = self.add_sources(res_q) F2 = self.F2(w) P = self.P(q) v = self.v(q) if dim == 1: F = [P[0],v[0]] elif dim == 2: F = [P[0],P[2],v[0],v[1], P[2],P[1],v[1],v[0]] elif dim == 3: F = [P[0],P[5],P[4],v[0],v[2],v[1], P[5],P[1],P[3],v[1],v[2],v[0], P[4],P[3],P[2],v[2],v[1],v[0]] else: raise ValueError("Invalid dimension") res_f2 = numpy.zeros(self.len_f2, dtype=object) for i in range(dim): for j in range(dim*2): res_f2[i*dim*2+j] = (-1)*F2[i*dim*2+j]*alpha[i]-sigma[i]/kappa[i]*(F2[i*dim*2+j]+F[i*dim*2+j]) return join_fields(res_q, res_f2)
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.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 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 max_eigenvalue(self, t, fields=None, discr=None): """Return the wave speed in the material""" u,v = self.split_vars(fields) from hedge.optemplate import make_nabla nabla = make_nabla(self.dimensions) dim = self.dimensions F = [0,]*dim*dim ij = 0 for i in range(self.dimensions): for j in range(self.dimensions): F[ij] = nabla[i]*u[j] if i == j: F[ij] = F[ij] + 1 ij = ij + 1 speed = self.material.celerity(F, self.dimensions) max_speed = discr.nodewise_max(speed) return max_speed * self.beta
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 calculate_piola(self,u=None): from hedge.optemplate import make_nabla from hedge.optemplate import make_vector_field u = make_vector_field('u', 3) nabla = make_nabla(self.dimensions) ij = 0 F = [0,]*9 for i in range(self.dimensions): for j in range(self.dimensions): F[ij] = nabla[i](u[j]) if i == j: F[ij] = F[ij] + 1 ij = ij + 1 return make_obj_array(self.material.stress(F, self.dimensions))
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))
def op_template(self): from hedge.mesh import TAG_ALL from hedge.optemplate import make_sym_vector, BoundaryPair, \ get_flux_operator, make_nabla, InverseMassOperator nabla = make_nabla(self.dimensions) m_inv = InverseMassOperator() v = make_sym_vector("v", self.arg_count) bc = make_sym_vector("bc", self.arg_count) local_op_result = 0 idx = 0 for i, i_enabled in enumerate(self.subset): if i_enabled and i < self.dimensions: local_op_result += nabla[i] * v[idx] idx += 1 flux_op = get_flux_operator(self.flux()) return local_op_result - m_inv( flux_op(v) + flux_op(BoundaryPair(v, bc, TAG_ALL)))
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) )
def op_template(self): from hedge.mesh import TAG_ALL from hedge.optemplate import make_vector_field, BoundaryPair, \ get_flux_operator, make_nabla, InverseMassOperator nabla = make_nabla(self.dimensions) m_inv = InverseMassOperator() v = make_vector_field("v", self.arg_count) bc = make_vector_field("bc", self.arg_count) local_op_result = 0 idx = 0 for i, i_enabled in enumerate(self.subset): if i_enabled and i < self.dimensions: local_op_result += nabla[i]*v[idx] idx += 1 flux_op = get_flux_operator(self.flux()) return local_op_result - m_inv( flux_op(v) + flux_op(BoundaryPair(v, bc, TAG_ALL)))
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 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)) ))
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 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 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, sqrt, exp, pi 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) diff_optp = nabla[0] * Field("f1") + nabla[1] * Field("f2") 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): 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
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): 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 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))))
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