def __init__(self, queue, geo_data, use_target_specific_qbx): from pytential.qbx.utils import ToHostTransferredGeoDataWrapper geo_data = ToHostTransferredGeoDataWrapper(queue, geo_data) self.geo_data = geo_data self.trav = geo_data.traversal() self.using_tsqbx = ( use_target_specific_qbx # None means use by default if possible or use_target_specific_qbx is None) ConstantOneExpansionWrangler.__init__(self, geo_data.tree())
def __init__(self, tree_indep, queue, geo_data, use_target_specific_qbx): from pytential.qbx.utils import ToHostTransferredGeoDataWrapper geo_data = ToHostTransferredGeoDataWrapper(geo_data) self.geo_data = geo_data self.trav = geo_data.traversal() self.using_tsqbx = ( use_target_specific_qbx # None means use by default if possible or use_target_specific_qbx is None) super().__init__(tree_indep, geo_data.traversal())
def __init__(self, tree_indep, geo_data, dtype, qbx_order, fmm_level_to_order, source_extra_kwargs, kernel_extra_kwargs, _use_target_specific_qbx=None): # FMMLib is CPU-only. This wrapper gets the geometry out of # OpenCL-land. from pytential.qbx.utils import ToHostTransferredGeoDataWrapper geo_data = ToHostTransferredGeoDataWrapper(geo_data) self.geo_data = geo_data self.qbx_order = qbx_order if tree_indep.k_name is None: helmholtz_k = 0 else: helmholtz_k = kernel_extra_kwargs[tree_indep.k_name] dipole_vec = None if tree_indep.source_deriv_name is not None: with cl.CommandQueue(tree_indep.cl_context) as queue: dipole_vec = np.array([ d_i.get(queue=queue) for d_i in source_extra_kwargs[ tree_indep.source_deriv_name]], order="F") def inner_fmm_level_to_nterms(tree, level): if helmholtz_k == 0: return fmm_level_to_order( LaplaceKernel(tree.dimensions), frozenset(), tree, level) else: return fmm_level_to_order( HelmholtzKernel(tree.dimensions), frozenset([("k", helmholtz_k)]), tree, level) super().__init__( tree_indep, geo_data.traversal(), helmholtz_k=helmholtz_k, dipole_vec=dipole_vec, dipoles_already_reordered=True, fmm_level_to_nterms=inner_fmm_level_to_nterms, rotation_data=geo_data)
def qbx_cost_per_box(self, queue, geo_data, kernel, kernel_arguments, calibration_params): """This function transfers *geo_data* to host if necessary """ from pytential.qbx.utils import ToHostTransferredGeoDataWrapper from pytential.qbx.geometry import QBXFMMGeometryData if not isinstance(geo_data, ToHostTransferredGeoDataWrapper): assert isinstance(geo_data, QBXFMMGeometryData) geo_data = ToHostTransferredGeoDataWrapper(queue, geo_data) return AbstractQBXCostModel.qbx_cost_per_box(self, queue, geo_data, kernel, kernel_arguments, calibration_params)
def test_compare_cl_and_py_cost_model(ctx_factory): nelements = 3600 target_order = 16 fmm_order = 5 qbx_order = fmm_order ctx = ctx_factory() queue = cl.CommandQueue(ctx) actx = PyOpenCLArrayContext(queue) # {{{ Construct geometry from meshmode.mesh.generation import make_curve_mesh, starfish mesh = make_curve_mesh(starfish, np.linspace(0, 1, nelements), target_order) from meshmode.discretization import Discretization from meshmode.discretization.poly_element import \ InterpolatoryQuadratureSimplexGroupFactory pre_density_discr = Discretization( actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order) ) qbx = QBXLayerPotentialSource( pre_density_discr, 4 * target_order, qbx_order, fmm_order=fmm_order ) places = GeometryCollection(qbx) from pytential.qbx.refinement import refine_geometry_collection places = refine_geometry_collection(places) target_discrs_and_qbx_sides = tuple([(qbx.density_discr, 0)]) geo_data_dev = qbx.qbx_fmm_geometry_data( places, places.auto_source.geometry, target_discrs_and_qbx_sides ) from pytential.qbx.utils import ToHostTransferredGeoDataWrapper geo_data = ToHostTransferredGeoDataWrapper(queue, geo_data_dev) # }}} # {{{ Construct cost models cl_cost_model = QBXCostModel() python_cost_model = _PythonQBXCostModel() tree = geo_data.tree() xlat_cost = make_pde_aware_translation_cost_model( tree.targets.shape[0], tree.nlevels ) constant_one_params = QBXCostModel.get_unit_calibration_params() constant_one_params["p_qbx"] = 5 for ilevel in range(tree.nlevels): constant_one_params["p_fmm_lev%d" % ilevel] = 10 cl_cost_factors = cl_cost_model.qbx_cost_factors_for_kernels_from_model( queue, tree.nlevels, xlat_cost, constant_one_params ) python_cost_factors = python_cost_model.qbx_cost_factors_for_kernels_from_model( None, tree.nlevels, xlat_cost, constant_one_params ) # }}} # {{{ Test process_form_qbxl cl_ndirect_sources_per_target_box = ( cl_cost_model.get_ndirect_sources_per_target_box( queue, geo_data_dev.traversal() ) ) queue.finish() start_time = time.time() cl_p2qbxl = cl_cost_model.process_form_qbxl( queue, geo_data_dev, cl_cost_factors["p2qbxl_cost"], cl_ndirect_sources_per_target_box ) queue.finish() logger.info("OpenCL time for process_form_qbxl: {}".format( str(time.time() - start_time) )) python_ndirect_sources_per_target_box = ( python_cost_model.get_ndirect_sources_per_target_box( queue, geo_data.traversal() ) ) start_time = time.time() python_p2qbxl = python_cost_model.process_form_qbxl( queue, geo_data, python_cost_factors["p2qbxl_cost"], python_ndirect_sources_per_target_box ) logger.info("Python time for process_form_qbxl: {}".format( str(time.time() - start_time) )) assert np.array_equal(cl_p2qbxl.get(), python_p2qbxl) # }}} # {{{ Test process_m2qbxl queue.finish() start_time = time.time() cl_m2qbxl = cl_cost_model.process_m2qbxl( queue, geo_data_dev, cl_cost_factors["m2qbxl_cost"] ) queue.finish() logger.info("OpenCL time for process_m2qbxl: {}".format( str(time.time() - start_time) )) start_time = time.time() python_m2qbxl = python_cost_model.process_m2qbxl( queue, geo_data, python_cost_factors["m2qbxl_cost"] ) logger.info("Python time for process_m2qbxl: {}".format( str(time.time() - start_time) )) assert np.array_equal(cl_m2qbxl.get(), python_m2qbxl) # }}} # {{{ Test process_l2qbxl queue.finish() start_time = time.time() cl_l2qbxl = cl_cost_model.process_l2qbxl( queue, geo_data_dev, cl_cost_factors["l2qbxl_cost"] ) queue.finish() logger.info("OpenCL time for process_l2qbxl: {}".format( str(time.time() - start_time) )) start_time = time.time() python_l2qbxl = python_cost_model.process_l2qbxl( queue, geo_data, python_cost_factors["l2qbxl_cost"] ) logger.info("Python time for process_l2qbxl: {}".format( str(time.time() - start_time) )) assert np.array_equal(cl_l2qbxl.get(), python_l2qbxl) # }}} # {{{ Test process_eval_qbxl queue.finish() start_time = time.time() cl_eval_qbxl = cl_cost_model.process_eval_qbxl( queue, geo_data_dev, cl_cost_factors["qbxl2p_cost"] ) queue.finish() logger.info("OpenCL time for process_eval_qbxl: {}".format( str(time.time() - start_time) )) start_time = time.time() python_eval_qbxl = python_cost_model.process_eval_qbxl( queue, geo_data, python_cost_factors["qbxl2p_cost"] ) logger.info("Python time for process_eval_qbxl: {}".format( str(time.time() - start_time) )) assert np.array_equal(cl_eval_qbxl.get(), python_eval_qbxl) # }}} # {{{ Test eval_target_specific_qbxl queue.finish() start_time = time.time() cl_eval_target_specific_qbxl = cl_cost_model.process_eval_target_specific_qbxl( queue, geo_data_dev, cl_cost_factors["p2p_tsqbx_cost"], cl_ndirect_sources_per_target_box ) queue.finish() logger.info("OpenCL time for eval_target_specific_qbxl: {}".format( str(time.time() - start_time) )) start_time = time.time() python_eval_target_specific_qbxl = \ python_cost_model.process_eval_target_specific_qbxl( queue, geo_data, python_cost_factors["p2p_tsqbx_cost"], python_ndirect_sources_per_target_box ) logger.info("Python time for eval_target_specific_qbxl: {}".format( str(time.time() - start_time) )) assert np.array_equal( cl_eval_target_specific_qbxl.get(), python_eval_target_specific_qbxl )
def __init__(self, code, queue, geo_data, dtype, qbx_order, fmm_level_to_order, source_extra_kwargs, kernel_extra_kwargs, _use_target_specific_qbx=None): self.code = code self.queue = queue # FMMLib is CPU-only. This wrapper gets the geometry out of # OpenCL-land. from pytential.qbx.utils import ToHostTransferredGeoDataWrapper geo_data = ToHostTransferredGeoDataWrapper(queue, geo_data) self.geo_data = geo_data self.qbx_order = qbx_order # {{{ digest target_kernels ifgrad = False outputs = [] source_deriv_names = [] k_names = [] using_tsqbx = ( _use_target_specific_qbx # None means use by default if possible or _use_target_specific_qbx is None) for out_knl in self.code.target_kernels: if not self.is_supported_helmknl_for_tsqbx(out_knl): if _use_target_specific_qbx: raise ValueError("not all kernels passed support TSQBX") using_tsqbx = False if self.is_supported_helmknl(out_knl): outputs.append(()) no_target_deriv_knl = out_knl elif (isinstance(out_knl, AxisTargetDerivative) and self.is_supported_helmknl(out_knl.inner_kernel)): outputs.append((out_knl.axis, )) ifgrad = True no_target_deriv_knl = out_knl.inner_kernel else: raise ValueError("only the 2/3D Laplace and Helmholtz kernel " "and their derivatives are supported") source_deriv_names.append( no_target_deriv_knl.dir_vec_name if isinstance( no_target_deriv_knl, DirectionalSourceDerivative ) else None) base_knl = out_knl.get_base_kernel() k_names.append(base_knl.helmholtz_k_name if isinstance( base_knl, HelmholtzKernel) else None) self.using_tsqbx = using_tsqbx self.outputs = outputs from pytools import is_single_valued if not is_single_valued(source_deriv_names): raise ValueError("not all kernels passed are the same in " "whether they represent a source derivative") source_deriv_name = source_deriv_names[0] if not is_single_valued(k_names): raise ValueError("not all kernels passed have the same " "Helmholtz parameter") k_name = k_names[0] if k_name is None: helmholtz_k = 0 else: helmholtz_k = kernel_extra_kwargs[k_name] # }}} dipole_vec = None if source_deriv_name is not None: dipole_vec = np.array([ d_i.get(queue=queue) for d_i in source_extra_kwargs[source_deriv_name] ], order="F") def inner_fmm_level_to_nterms(tree, level): if helmholtz_k == 0: return fmm_level_to_order(LaplaceKernel(tree.dimensions), frozenset(), tree, level) else: return fmm_level_to_order(HelmholtzKernel(tree.dimensions), frozenset([("k", helmholtz_k)]), tree, level) super().__init__(geo_data.tree(), helmholtz_k=helmholtz_k, dipole_vec=dipole_vec, dipoles_already_reordered=True, fmm_level_to_nterms=inner_fmm_level_to_nterms, rotation_data=geo_data, ifgrad=ifgrad)