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 get_advection_op(self, q, velocity): from hedge.optemplate import (BoundaryPair, get_flux_operator, make_stiffness_t, InverseMassOperator) stiff_t = make_stiffness_t(self.method.dimensions) flux_op = get_flux_operator(self.get_advection_flux(velocity)) return InverseMassOperator()(np.dot(velocity, stiff_t * q) - flux_op(q))
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
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): 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 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): # {{{ 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, 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 compute_initial_condition(rcon, discr, method, state, maxwell_op, potential_bc, force_zero=False): from hedge.models.poisson import PoissonOperator from hedge.mesh import TAG_ALL, TAG_NONE from hedge.data import ConstantGivenFunction, GivenVolumeInterpolant def rel_l2_error(field, true): from hedge.tools import relative_error return relative_error(discr.norm(field - true), discr.norm(true)) mean_beta = method.mean_beta(state) gamma = method.units.gamma_from_beta(mean_beta) # see doc/notes.tm for derivation of IC def make_scaling_matrix(beta_scale, other_scale): if la.norm(mean_beta) < 1e-10: return other_scale * numpy.eye(discr.dimensions) else: beta_unit = mean_beta / la.norm(mean_beta) return ( other_scale * numpy.identity(discr.dimensions) + (beta_scale - other_scale) * numpy.outer(beta_unit, beta_unit)) poisson_op = PoissonOperator(discr.dimensions, diffusion_tensor=make_scaling_matrix( 1 / gamma**2, 1), dirichlet_tag=TAG_ALL, neumann_tag=TAG_NONE, dirichlet_bc=potential_bc) rho_prime = method.deposit_rho(state) rho_tilde = rho_prime / gamma bound_poisson = poisson_op.bind(discr) if force_zero: phi_tilde = discr.volume_zeros() else: from hedge.iterative import parallel_cg phi_tilde = -parallel_cg( rcon, -bound_poisson, bound_poisson.prepare_rhs(rho_tilde / maxwell_op.epsilon), debug=40 if "poisson" in method.debug else False, tol=1e-10) from hedge.tools import ptwise_dot from hedge.models.nd_calculus import GradientOperator e_tilde = ptwise_dot( 2, 1, make_scaling_matrix(1 / gamma, 1), GradientOperator(discr.dimensions).bind(discr)(phi_tilde)) e_prime = ptwise_dot(2, 1, make_scaling_matrix(1, gamma), e_tilde) from pyrticle.tools import make_cross_product v_e_to_h_cross = make_cross_product(method, maxwell_op, "v", "e", "h") h_prime = (1 / maxwell_op.mu) * gamma / maxwell_op.c * v_e_to_h_cross( mean_beta, e_tilde) if "ic" in method.debug: deposited_charge = discr.integral(rho_prime) real_charge = numpy.sum(state.charges) print "charge: supposed=%g deposited=%g error=%g %%" % ( real_charge, deposited_charge, 100 * abs(deposited_charge - real_charge) / abs(real_charge)) from hedge.models.nd_calculus import DivergenceOperator bound_div_op = DivergenceOperator(discr.dimensions).bind(discr) d_tilde = maxwell_op.epsilon * e_tilde d_prime = maxwell_op.epsilon * e_prime #divD_prime_ldg = bound_poisson.div(d_prime) #divD_prime_ldg2 = bound_poisson.div(d_prime, maxwell_op.epsilon*gamma*phi_tilde) from hedge.optemplate import InverseMassOperator divD_prime_ldg3 = maxwell_op.epsilon*\ (InverseMassOperator().apply(discr, bound_poisson.op(gamma*phi_tilde))) divD_prime_central = bound_div_op(d_prime) print "l2 div D_prime error central: %g" % \ rel_l2_error(divD_prime_central, rho_prime) #print "l2 div D_prime error ldg: %g" % \ #rel_l2_error(divD_prime_ldg, rho_prime) #print "l2 div D_prime error ldg with phi: %g" % \ #rel_l2_error(divD_prime_ldg2, rho_prime) print "l2 div D_prime error ldg with phi 3: %g" % \ rel_l2_error(divD_prime_ldg3, rho_prime) if "vis_files" in method.debug: from hedge.visualization import SiloVisualizer vis = SiloVisualizer(discr) visf = vis.make_file("ic") vis.add_data( visf, [ ("phi_moving", phi_tilde), ("rho_moving", rho_tilde), ("e_moving", e_tilde), ("rho_lab", rho_prime), #("divD_lab_ldg", divD_prime_ldg), #("divD_lab_ldg2", divD_prime_ldg2), #("divD_lab_ldg3", divD_prime_ldg3), ("divD_lab_central", divD_prime_central), ("e_lab", e_prime), ("h_lab", h_prime), ], ) method.add_to_vis(vis, visf, state) visf.close() return maxwell_op.assemble_fields(e=e_prime, h=h_prime, discr=discr)
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