def _get_centers_and_expansion_radii(queue, source, target_discr, qbx_forced_limit): """ :arg queue: a :class:`pyopencl.CommandQueue`. :arg source: a :class:`pytential.source.LayerPotentialSourceBase`. :arg target_discr: a :class:`meshmode.discretization.Discretization`. :arg qbx_forced_limit: an integer (*+1* or *-1*). :return: a tuple of `(centers, radii)` for each node in *target_discr*. """ if source.density_discr is target_discr: # NOTE: skip expensive target association centers = bind( source, sym.expansion_centers(source.ambient_dim, qbx_forced_limit))(queue) radii = bind(source, sym.expansion_radii(source.ambient_dim))(queue) else: from pytential.qbx.utils import get_interleaved_centers centers = get_interleaved_centers(queue, source) radii = bind( source, sym.expansion_radii(source.ambient_dim, granularity=sym.GRANULARITY_CENTER))(queue) # NOTE: using a very small tolerance to make sure all the stage2 # targets are associated to a center. We can't use the user provided # source.target_association_tolerance here because it will likely be # way too small. target_association_tolerance = 1.0e-1 from pytential.qbx.target_assoc import associate_targets_to_qbx_centers code_container = source.target_association_code_container assoc = associate_targets_to_qbx_centers( source, code_container.get_wrangler(queue), [(target_discr, qbx_forced_limit)], target_association_tolerance=target_association_tolerance) centers = [ cl.array.take(c, assoc.target_to_center, queue=queue) for c in centers ] radii = cl.array.take(radii, assoc.target_to_center, queue=queue) return centers, radii
def weights_and_area_elements(self): import pytential.symbolic.primitives as p from pytential.symbolic.execution import bind with cl.CommandQueue(self.cl_context) as queue: # quad_stage2_density_discr is not guaranteed to be usable for # interpolation/differentiation. Use density_discr to find # area element instead, then upsample that. area_element = self.resampler( queue, bind( self.density_discr, p.area_element(self.ambient_dim, self.dim) )(queue)) qweight = bind(self.quad_stage2_density_discr, p.QWeight())(queue) return (area_element.with_queue(queue)*qweight).with_queue(None)
def _norm_inf_op(discr, num_components): from pytential import sym, bind if num_components is not None: from pymbolic.primitives import make_sym_vector v = make_sym_vector("arg", num_components) max_arg = sym.abs(v) else: max_arg = sym.abs(sym.var("arg")) return bind(discr, sym.NodeMax(max_arg))
def _norm_op(discr, num_components): from pytential import sym, bind if num_components is not None: from pymbolic.primitives import make_sym_vector v = make_sym_vector("integrand", num_components) integrand = sym.real(np.dot(sym.conj(v), v)) else: integrand = sym.abs(sym.var("integrand"))**2 return bind(discr, sym.integral(integrand))
def _norm_2_op(discr, num_components): from pytential import sym, bind if num_components is not None: from pymbolic.primitives import make_sym_vector v = make_sym_vector("integrand", num_components) integrand = sym.real(np.dot(sym.conj(v), v)) else: integrand = sym.abs(sym.var("integrand"))**2 return bind(discr, sym.integral(discr.ambient_dim, discr.dim, integrand))
def _get_weights_and_area_elements(queue, source, source_discr): """ :arg queue: a :class:`pyopencl.CommandQueue`. :arg source: a :class:`pytential.source.LayerPotentialSourceBase`. :arg source_discr: a :class:`meshmode.discretization.Discretization`. :return: quadrature weights for each node in *source_discr*. """ if source.quad_stage2_density_discr is source_discr: waa = source.weights_and_area_elements().with_queue(queue) else: # NOTE: copied from `weights_and_area_elements`, but using the # discretization given by `where` and no interpolation area = bind(source_discr, sym.area_element(source.ambient_dim, source.dim))(queue) qweight = bind(source_discr, sym.QWeight())(queue) waa = area * qweight return waa
def map_num_reference_derivative(self, expr): rec_operand = self.rec(expr.operand) assert isinstance(rec_operand, np.ndarray) if self.is_kind_matrix(rec_operand): raise NotImplementedError("derivatives") where_discr = self.places[expr.where] op = sym.NumReferenceDerivative(expr.ref_axes, sym.var("u")) return bind(where_discr, op)( self.queue, u=cl.array.to_device(self.queue, rec_operand)).get()
def map_num_reference_derivative(self, expr): rec_operand = self.rec(expr.operand) assert isinstance(rec_operand, np.ndarray) if self.is_kind_matrix(rec_operand): raise NotImplementedError("derivatives") rec_operand = cl.array.to_device(self.queue, rec_operand) op = sym.NumReferenceDerivative(ref_axes=expr.ref_axes, operand=sym.var("u"), dofdesc=expr.dofdesc) return bind(self.places, op)(self.queue, u=rec_operand).get()
def map_call(self, expr): arg, = expr.parameters rec_arg = self.rec(arg) if isinstance(rec_arg, np.ndarray) and self.is_kind_matrix(rec_arg): raise RuntimeError("expression is nonlinear in variable") if isinstance(rec_arg, np.ndarray): rec_arg = cl.array.to_device(self.queue, rec_arg) op = expr.function(sym.var("u")) result = bind(self.dep_source, op)(self.queue, u=rec_arg) if isinstance(result, cl.array.Array): result = result.get() return result
def _coarsest_quad_resolution(self, last_dim_length="npanels"): """This measures the quadrature resolution across the mesh. In a 1D uniform mesh of uniform 'parametrization speed', it should be the same as the panel length. """ import pytential.qbx.utils as utils from pytential import sym, bind with cl.CommandQueue(self.cl_context) as queue: maxstretch = bind( self, sym._simplex_mapping_max_stretch_factor( self.ambient_dim) )(queue) maxstretch = utils.to_last_dim_length( self.density_discr, maxstretch, last_dim_length) maxstretch = maxstretch.with_queue(None) return maxstretch
def _stage2_coarsest_quad_resolution(self, last_dim_length="npanels"): """This measures the quadrature resolution across the mesh. In a 1D uniform mesh of uniform 'parametrization speed', it should be the same as the panel length. """ if last_dim_length != "npanels": # Not technically required below, but no need to loosen for now. raise NotImplementedError() import pytential.qbx.utils as utils from pytential import sym, bind with cl.CommandQueue(self.cl_context) as queue: maxstretch = bind( self, sym._simplex_mapping_max_stretch_factor( self.ambient_dim, where=sym.QBXSourceStage2(sym.DEFAULT_SOURCE)) )(queue) maxstretch = utils.to_last_dim_length( self.stage2_density_discr, maxstretch, last_dim_length) maxstretch = maxstretch.with_queue(None) return maxstretch
def _integral_op(discr): from pytential import sym, bind return bind(discr, sym.integral( discr.ambient_dim, discr.dim, sym.var("integrand")))
def _integral_op(discr): from pytential import sym, bind return bind( discr, sym.integral(discr.ambient_dim, discr.dim, sym.var("integrand")))
def map_node_coordinate_component(self, expr): where_discr = self.places[expr.where] op = sym.NodeCoordinateComponent(expr.ambient_axis) return bind(where_discr, op)(self.queue).get()
def _integral_op(discr): from pytential import sym, bind return bind(discr, sym.integral(sym.var("integrand")))
def map_node_coordinate_component(self, expr): op = sym.NodeCoordinateComponent(expr.ambient_axis, dofdesc=expr.dofdesc) return bind(self.places, op)(self.queue).get()