def operator(self, t, w): dcoll = self.dcoll u = w[0] v = w[1:] actx = u.array_context # boundary conditions ------------------------------------------------- # dirichlet BCs ------------------------------------------------------- dir_u = op.project(dcoll, "vol", self.dirichlet_tag, u) dir_v = op.project(dcoll, "vol", 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 = self.dirichlet_bc_f dir_bc = flat_obj_array(2 * dir_g - dir_u, dir_v) else: dir_bc = flat_obj_array(-dir_u, dir_v) # neumann BCs --------------------------------------------------------- neu_u = op.project(dcoll, "vol", self.neumann_tag, u) neu_v = op.project(dcoll, "vol", self.neumann_tag, v) neu_bc = flat_obj_array(neu_u, -neu_v) # radiation BCs ------------------------------------------------------- rad_normal = thaw(dcoll.normal(dd=self.radiation_tag), actx) rad_u = op.project(dcoll, "vol", self.radiation_tag, u) rad_v = op.project(dcoll, "vol", self.radiation_tag, v) rad_bc = flat_obj_array( 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 ----------------------------------------------------- def flux(tpair): return op.project(dcoll, tpair.dd, "all_faces", self.flux(tpair)) result = (op.inverse_mass( dcoll, flat_obj_array(-self.c * op.weak_local_div(dcoll, v), -self.c * op.weak_local_grad(dcoll, u)) - op.face_mass( dcoll, sum( flux(tpair) for tpair in op.interior_trace_pairs(dcoll, w)) + flux(op.bv_trace_pair(dcoll, self.dirichlet_tag, w, dir_bc)) + flux(op.bv_trace_pair(dcoll, self.neumann_tag, w, neu_bc)) + flux(op.bv_trace_pair(dcoll, self.radiation_tag, w, rad_bc))))) result[0] = result[0] + self.source_f(actx, dcoll, t) return result
def operator(self, t, u): from grudge.dof_desc import DOFDesc, DD_VOLUME, DTAG_VOLUME_ALL from meshmode.mesh import BTAG_ALL from meshmode.discretization.connection import FACE_RESTR_ALL face_dd = DOFDesc(FACE_RESTR_ALL, self.quad_tag) boundary_dd = DOFDesc(BTAG_ALL, self.quad_tag) quad_dd = DOFDesc(DTAG_VOLUME_ALL, self.quad_tag) dcoll = self.dcoll def flux(tpair): return op.project(dcoll, tpair.dd, face_dd, self.flux(tpair)) def to_quad(arg): return op.project(dcoll, DD_VOLUME, quad_dd, arg) if self.inflow_u is not None: inflow_flux = flux( op.bv_trace_pair(dcoll, boundary_dd, interior=u, exterior=self.inflow_u(t))) else: inflow_flux = 0 quad_v = to_quad(self.v) quad_u = to_quad(u) return (op.inverse_mass( dcoll, sum( op.weak_local_d_dx(dcoll, quad_dd, d, quad_u * quad_v[d]) for d in range(dcoll.ambient_dim)) - op.face_mass( dcoll, face_dd, sum( flux(quad_tpair) for quad_tpair in to_quad_int_tpairs( dcoll, u, self.quad_tag)) + inflow_flux # FIXME: Add support for inflow/outflow tags # + flux(op.bv_trace_pair(dcoll, # self.inflow_tag, # interior=u, # exterior=bc_in)) # + flux(op.bv_trace_pair(dcoll, # self.outflow_tag, # interior=u, # exterior=bc_out)) )))
def operator(self, t, w): """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 grudge.tools 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) 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)), ] dcoll = self.dcoll def flux(pair): return op.project(dcoll, pair.dd, "all_faces", self.flux(pair)) return (-self.local_derivatives(w) - op.inverse_mass( dcoll, op.face_mass( dcoll, sum( flux(tpair) for tpair in op.interior_trace_pairs(dcoll, w)) + sum( flux(op.bv_trace_pair(dcoll, tag, w, bc)) for tag, bc in tags_and_bcs)))) / material_divisor
def operator(self, t, u): from meshmode.mesh import BTAG_ALL dcoll = self.dcoll def flux(tpair): return op.project(dcoll, tpair.dd, "all_faces", self.flux(tpair)) if self.inflow_u is not None: inflow_flux = flux( op.bv_trace_pair(dcoll, BTAG_ALL, interior=u, exterior=self.inflow_u(t))) else: inflow_flux = 0 return (op.inverse_mass( dcoll, np.dot(self.v, op.weak_local_grad(dcoll, u)) - op.face_mass( dcoll, sum( flux(tpair) for tpair in op.interior_trace_pairs(dcoll, u)) + inflow_flux # FIXME: Add support for inflow/outflow tags # + flux(op.bv_trace_pair(dcoll, # self.inflow_tag, # interior=u, # exterior=bc_in)) # + flux(op.bv_trace_pair(dcoll, # self.outflow_tag, # interior=u, # exterior=bc_out)) )))
right_bndry = DTAG_BOUNDARY("right") x_vol = thaw(dcoll.nodes(), actx) x_bndry = thaw(dcoll.discr_from_dd(left_bndry).nodes(), actx) uh = initial_condition(x_vol) dt = 0.001 t = 0 t_final = 0.5 # timestepper loop while t < t_final: # extract the left boundary trace pair lbnd_tpair = op.bv_trace_pair(dcoll, dd=left_bndry, interior=uh, exterior=left_boundary_condition(x_bndry, t)) # extract the right boundary trace pair rbnd_tpair = op.bv_trace_pair(dcoll, dd=right_bndry, interior=uh, exterior=op.project(dcoll, "vol", right_bndry, uh)) # extract the trace pairs on the interior faces interior_tpair = op.interior_trace_pair(dcoll, uh) Su = op.weak_local_grad(dcoll, uh) lift = op.face_mass(dcoll, # left boundary weak-flux terms op.project(dcoll,