def pml_local_op(self, w): sub_e, sub_h, sub_p, sub_q = self.split_ehpq(w) e_subset = self.get_eh_subset()[0:3] h_subset = self.get_eh_subset()[3:6] dim_subset = (True,) * self.dimensions + (False,) * (3-self.dimensions) def pad_vec(v, subset): result = numpy.zeros((3,), dtype=object) result[numpy.array(subset, dtype=bool)] = v return result from hedge.optemplate import make_sym_vector sig = pad_vec( make_sym_vector("sigma", self.dimensions), dim_subset) sig_prime = pad_vec( make_sym_vector("sigma_prime", self.dimensions), dim_subset) if self.add_decay: tau = pad_vec( make_sym_vector("tau", self.dimensions), dim_subset) else: tau = numpy.zeros((3,)) e = pad_vec(sub_e, e_subset) h = pad_vec(sub_h, h_subset) p = pad_vec(sub_p, dim_subset) q = pad_vec(sub_q, dim_subset) rhs = numpy.zeros(12, dtype=object) for mx in range(3): my = (mx+1) % 3 mz = (mx+2) % 3 from hedge.tools.mathematics import levi_civita assert levi_civita((mx,my,mz)) == 1 rhs[mx] += -sig[my]/self.epsilon*(2*e[mx]+p[mx]) - 2*tau[my]/self.epsilon*e[mx] rhs[my] += -sig[mx]/self.epsilon*(2*e[my]+p[my]) - 2*tau[mx]/self.epsilon*e[my] rhs[3+mz] += 1/(self.epsilon*self.mu) * ( sig_prime[mx] * q[mx] - sig_prime[my] * q[my]) rhs[6+mx] += sig[my]/self.epsilon*e[mx] rhs[6+my] += sig[mx]/self.epsilon*e[my] rhs[9+mx] += -sig[mx]/self.epsilon*q[mx] - (e[my] + e[mz]) from hedge.tools import full_to_subset_indices sub_idx = full_to_subset_indices(e_subset+h_subset+dim_subset+dim_subset) return rhs[sub_idx]
def pml_local_op(self, w): sub_e, sub_h, sub_p, sub_q = self.split_ehpq(w) e_subset = self.get_eh_subset()[0:3] h_subset = self.get_eh_subset()[3:6] dim_subset = (True, ) * self.dimensions + (False, ) * (3 - self.dimensions) def pad_vec(v, subset): result = numpy.zeros((3, ), dtype=object) result[numpy.array(subset, dtype=bool)] = v return result from hedge.optemplate import make_sym_vector sig = pad_vec(make_sym_vector("sigma", self.dimensions), dim_subset) sig_prime = pad_vec(make_sym_vector("sigma_prime", self.dimensions), dim_subset) if self.add_decay: tau = pad_vec(make_sym_vector("tau", self.dimensions), dim_subset) else: tau = numpy.zeros((3, )) e = pad_vec(sub_e, e_subset) h = pad_vec(sub_h, h_subset) p = pad_vec(sub_p, dim_subset) q = pad_vec(sub_q, dim_subset) rhs = numpy.zeros(12, dtype=object) for mx in range(3): my = (mx + 1) % 3 mz = (mx + 2) % 3 from hedge.tools.mathematics import levi_civita assert levi_civita((mx, my, mz)) == 1 rhs[mx] += -sig[my] / self.epsilon * ( 2 * e[mx] + p[mx]) - 2 * tau[my] / self.epsilon * e[mx] rhs[my] += -sig[mx] / self.epsilon * ( 2 * e[my] + p[my]) - 2 * tau[mx] / self.epsilon * e[my] rhs[3 + mz] += 1 / (self.epsilon * self.mu) * (sig_prime[mx] * q[mx] - sig_prime[my] * q[my]) rhs[6 + mx] += sig[my] / self.epsilon * e[mx] rhs[6 + my] += sig[mx] / self.epsilon * e[my] rhs[9 + mx] += -sig[mx] / self.epsilon * q[mx] - (e[my] + e[mz]) from hedge.tools import full_to_subset_indices sub_idx = full_to_subset_indices(e_subset + h_subset + dim_subset + dim_subset) return rhs[sub_idx]
def field_placeholder(self, w=None): "A placeholder for E and H." from hedge.tools import count_subset fld_cnt = count_subset(self.get_eh_subset()) if w is None: from hedge.optemplate import make_sym_vector w = make_sym_vector("w", fld_cnt) return w
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)
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)
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)
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)
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 bind_characteristic_velocity(self, discr): from hedge.optemplate.operators import (ElementwiseMaxOperator) from hedge.optemplate import make_sym_vector velocity_vec = make_sym_vector("v", self.dimensions) velocity = ElementwiseMaxOperator()(numpy.dot(velocity_vec, velocity_vec)**0.5) compiled = discr.compile(velocity) def do(t, u): return compiled(v=self.advec_v.volume_interpolant(t, discr)) return do
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 bind_characteristic_velocity(self, discr): from hedge.optemplate.operators import ( ElementwiseMaxOperator) from hedge.optemplate import make_sym_vector velocity_vec = make_sym_vector("v", self.dimensions) velocity = ElementwiseMaxOperator()( numpy.dot(velocity_vec, velocity_vec)**0.5) compiled = discr.compile(velocity) def do(t, u): return compiled(v=self.advec_v.volume_interpolant(t, discr)) return do
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 f_bar(self): from hedge.optemplate import make_sym_vector return make_sym_vector("f_bar", len(self.method))
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