diff --git a/benchmarks/scalar_field.py b/benchmarks/scalar_field.py index 038d3e8..4206cda 100644 --- a/benchmarks/scalar_field.py +++ b/benchmarks/scalar_field.py @@ -23,15 +23,19 @@ import os import time import warnings -import pyopencl as cl -import pyopencl.clrandom + import numpy as np + import loopy as lp import pymbolic as pmbl import pymbolic.primitives as primitives -from pymbolic.functions import sin, cos, exp, tan, log # noqa: F401 +import pyopencl as cl +import pyopencl.clrandom +from pymbolic.functions import cos, exp, log, sin, tan # noqa: F401 + from volumential.tools import ScalarFieldExpressionEvaluation + # {{{ math functions # cf. @@ -66,7 +70,7 @@ def math_func_mangler(target, name, arg_dtypes): fname = name.name if not (isinstance(name.aggregate, pmbl.primitives.Variable) - and name.aggregate.name == 'math'): + and name.aggregate.name == "math"): raise RuntimeError("unexpected aggregate '%s'" % str(name.aggregate)) @@ -80,7 +84,7 @@ def math_func_mangler(target, name, arg_dtypes): arg_dtype) return lp.CallMangleInfo( - target_name="%s_%s" % (tpname, fname), + target_name=f"{tpname}_{fname}", result_dtypes=(arg_dtype,), arg_dtypes=(arg_dtype,)) @@ -139,7 +143,7 @@ def get_evaluator(dim, expression, variables=None): # needed for using loopy.statistics knl = lp.add_and_infer_dtypes( knl, - dict(x0=np.float64, x1=np.float64, x2=np.float64)) + {"x0": np.float64, "x1": np.float64, "x2": np.float64}) knl = lp.set_options(knl, ignore_boostable_into=True) # {{{ wall time @@ -178,13 +182,13 @@ def get_evaluator(dim, expression, variables=None): op_map = lp.get_op_map(knl, subgroup_size=ncpus, count_redundant_work=True, count_within_subscripts=True) -params = dict(n_targets=pts.shape[1]) -print('Operation counts:') +params = {"n_targets": pts.shape[1]} +print("Operation counts:") total_ops = 0 for op in op_map.keys(): sub_count = op_map[op].eval_with_dict(params) total_ops += sub_count - print('\t', op.name, op_map[op], sub_count) + print("\t", op.name, op_map[op], sub_count) print("Total:", total_ops) # TODO: weight each operation by running micro-benchmarks diff --git a/benchmarks/table_build.py b/benchmarks/table_build.py index 8a80ba8..785b30b 100644 --- a/benchmarks/table_build.py +++ b/benchmarks/table_build.py @@ -20,12 +20,15 @@ THE SOFTWARE. """ +import logging import time + import pyopencl as cl + from volumential.table_manager import NearFieldInteractionTableManager -import logging -logging.basicConfig(format='%(name)s:%(levelname)s: %(message)s') + +logging.basicConfig(format="%(name)s:%(levelname)s: %(message)s") def bench_table_build(queue): @@ -68,5 +71,5 @@ def main(): bench_table_build(queue) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/doc/source/conf.py b/doc/source/conf.py index 32f1445..1652222 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- # # Volumential documentation build configuration file, created by # sphinx-quickstart on Mon Oct 23 10:27:37 2017. @@ -20,9 +19,11 @@ import os import sys from datetime import datetime + import volumential.version as __version__ -sys.path.insert(0, os.path.abspath('..')) + +sys.path.insert(0, os.path.abspath("..")) # -- General configuration ------------------------------------------------ @@ -35,35 +36,38 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.todo', - 'sphinx.ext.autosummary', - 'sphinx.ext.coverage', - 'sphinx.ext.mathjax', - 'sphinx.ext.ifconfig', - 'sphinx.ext.viewcode', - 'sphinx.ext.intersphinx', - 'sphinx.ext.githubpages'] + "sphinx.ext.autodoc", + "sphinx.ext.todo", + "sphinx.ext.autosummary", + "sphinx.ext.coverage", + "sphinx.ext.mathjax", + "sphinx.ext.ifconfig", + "sphinx.ext.viewcode", + "sphinx.ext.intersphinx", + "sphinx.ext.githubpages"] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # Set the mathjax CDN -mathjax_path = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML" +mathjax_path = ( + "https://cdnjs.cloudflare.com/ajax/libs/" + "mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML" +) # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'Volumential' -copyright = '%s, Xiaoyu Wei' % str(datetime.today().year) -author = 'Xiaoyu Wei' +project = "Volumential" +copyright = "%s, Xiaoyu Wei" % str(datetime.today().year) +author = "Xiaoyu Wei" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -88,7 +92,7 @@ exclude_patterns = [] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True @@ -99,7 +103,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'sphinx_rtd_theme' +html_theme = "sphinx_rtd_theme" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -110,7 +114,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Custom sidebar templates, must be a dictionary that maps document names # to template names. @@ -118,9 +122,9 @@ # This is required for the alabaster theme # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars html_sidebars = { - '**': [ - 'relations.html', # needs 'show_related': True theme option to display - 'searchbox.html', + "**": [ + "relations.html", # needs 'show_related': True theme option to display + "searchbox.html", ] } @@ -128,7 +132,7 @@ # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. -htmlhelp_basename = 'Volumentialdoc' +htmlhelp_basename = "Volumentialdoc" # -- Options for LaTeX output --------------------------------------------- @@ -154,8 +158,8 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'Volumential.tex', 'Volumential Documentation', - 'Xiaoyu Wei', 'manual'), + (master_doc, "Volumential.tex", "Volumential Documentation", + "Xiaoyu Wei", "manual"), ] @@ -164,7 +168,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'volumential', 'Volumential Documentation', + (master_doc, "volumential", "Volumential Documentation", [author], 1) ] @@ -175,7 +179,7 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'Volumential', 'Volumential Documentation', - author, 'Volumential', 'One line description of project.', - 'Miscellaneous'), + (master_doc, "Volumential", "Volumential Documentation", + author, "Volumential", "One line description of project.", + "Miscellaneous"), ] diff --git a/examples/laplace2d.py b/examples/laplace2d.py index 383951f..fc0ab91 100644 --- a/examples/laplace2d.py +++ b/examples/laplace2d.py @@ -1,7 +1,6 @@ """ This example evaluates the volume potential over [-1,1]^2 with the Laplace kernel. """ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" @@ -27,6 +26,7 @@ import logging + logger = logging.getLogger(__name__) if 1: @@ -36,12 +36,14 @@ # clean logging.basicConfig(level=logging.CRITICAL) +from functools import partial + import numpy as np -import pyopencl as cl -from volumential.tools import ScalarFieldExpressionEvaluation as Eval import pymbolic as pmbl -from functools import partial +import pyopencl as cl + +from volumential.tools import ScalarFieldExpressionEvaluation as Eval def main(): @@ -205,17 +207,18 @@ def main(): # {{{ build near field potential table - from volumential.table_manager import NearFieldInteractionTableManager import os + from volumential.table_manager import NearFieldInteractionTableManager + if download_table and (not os.path.isfile(table_filename)): import json - with open("table_urls.json", 'r') as fp: + with open("table_urls.json") as fp: urls = json.load(fp) - print("Downloading table from %s" % urls['Laplace2D']) + print("Downloading table from %s" % urls["Laplace2D"]) import subprocess - subprocess.call(["wget", "-q", urls['Laplace2D'], table_filename]) + subprocess.call(["wget", "-q", urls["Laplace2D"], table_filename]) tm = NearFieldInteractionTableManager( table_filename, root_extent=root_table_source_extent, @@ -280,9 +283,7 @@ def main(): exclude_self = True from volumential.expansion_wrangler_fpnd import ( - FPNDExpansionWranglerCodeContainer, - FPNDExpansionWrangler - ) + FPNDExpansionWrangler, FPNDExpansionWranglerCodeContainer) wcc = FPNDExpansionWranglerCodeContainer( ctx, @@ -317,9 +318,9 @@ def main(): # {{{ conduct fmm computation - from volumential.volume_fmm import drive_volume_fmm - import time + + from volumential.volume_fmm import drive_volume_fmm queue.finish() t0 = time.time() @@ -386,8 +387,8 @@ def main(): from mpl_toolkits.mplot3d import Axes3D plt3d = plt.figure() - ax = Axes3D(plt3d) # noqa - surf = ax.plot_surface(oxx, oyy, opot.reshape(oxx.shape)) # noqa + ax = Axes3D(plt3d) + surf = ax.plot_surface(oxx, oyy, opot.reshape(oxx.shape)) # noqa: F841 # ax.scatter(x, y, src.get()) # ax.set_zlim(-0.25, 0.25) @@ -472,7 +473,7 @@ def main(): # }}} End postprocess and plot -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/examples/laplace3d.py b/examples/laplace3d.py index 31e9615..5fdce13 100644 --- a/examples/laplace3d.py +++ b/examples/laplace3d.py @@ -1,7 +1,6 @@ """ This example evaluates the volume potential over [-1,1]^3 with the Laplace kernel. """ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" @@ -26,15 +25,16 @@ """ import logging +from functools import partial import numpy as np -import pyopencl as cl import pymbolic as pmbl import pymbolic.functions +import pyopencl as cl + from volumential.tools import ScalarFieldExpressionEvaluation as Eval -from functools import partial verbose = True logger = logging.getLogger(__name__) @@ -215,17 +215,18 @@ def main(): # {{{ build near field potential table - from volumential.table_manager import NearFieldInteractionTableManager import os + from volumential.table_manager import NearFieldInteractionTableManager + if download_table and (not os.path.isfile(table_filename)): import json - with open("table_urls.json", 'r') as fp: + with open("table_urls.json") as fp: urls = json.load(fp) - print("Downloading table from %s" % urls['Laplace3D']) + print("Downloading table from %s" % urls["Laplace3D"]) import subprocess - subprocess.call(["wget", "-q", urls['Laplace3D'], table_filename]) + subprocess.call(["wget", "-q", urls["Laplace3D"], table_filename]) tm = NearFieldInteractionTableManager( table_filename, root_extent=root_table_source_extent, @@ -293,8 +294,7 @@ def main(): exclude_self = True from volumential.expansion_wrangler_fpnd import ( - FPNDExpansionWrangler, - FPNDExpansionWranglerCodeContainer) + FPNDExpansionWrangler, FPNDExpansionWranglerCodeContainer) wcc = FPNDExpansionWranglerCodeContainer( ctx, @@ -329,9 +329,9 @@ def main(): # {{{ conduct fmm computation - from volumential.volume_fmm import drive_volume_fmm - import time + + from volumential.volume_fmm import drive_volume_fmm queue.finish() t0 = time.time() @@ -425,11 +425,10 @@ def main(): from meshmode.mesh.io import read_gmsh modemesh = read_gmsh("box_grid.msh", force_ambient_dim=None) - from meshmode.discretization.poly_element import ( - LegendreGaussLobattoTensorProductGroupFactory, - ) from meshmode.array_context import PyOpenCLArrayContext from meshmode.discretization import Discretization + from meshmode.discretization.poly_element import ( + LegendreGaussLobattoTensorProductGroupFactory) actx = PyOpenCLArrayContext(queue) box_discr = Discretization( @@ -490,7 +489,7 @@ def clean_file(filename): # }}} End postprocess and plot -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/experiments/sep.py b/experiments/sep.py index 5cc0c11..2fd636d 100644 --- a/experiments/sep.py +++ b/experiments/sep.py @@ -391,8 +391,8 @@ def main(): from mpl_toolkits.mplot3d import Axes3D plt3d = plt.figure() - ax = Axes3D(plt3d) # noqa - surf = ax.plot_surface(oxx, oyy, opot.reshape(oxx.shape)) # noqa + ax = Axes3D(plt3d) + surf = ax.plot_surface(oxx, oyy, opot.reshape(oxx.shape)) # noqa: F841 # ax.scatter(x, y, src.get()) # ax.set_zlim(-0.25, 0.25) diff --git a/setup.cfg b/setup.cfg index 65a7a4a..2ab192f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,5 +2,20 @@ ignore = E126,E127,E128,E123,E226,E241,E242,E265,E402,W503 max-line-length=85 +inline-quotes = " +docstring-quotes = """ +multiline-quotes = """ + +# enable-flake8-bugbear +# enable-flake8-isort + [pycodestyle] max-line-length=85 + +[isort] +known_firstparty=pytools,pyopencl,loopy,modepy,pymbolic,boxtree,pytential,sumpy,meshmode +known_local_folder=volumential +line_length = 85 +lines_after_imports = 2 +combine_as_imports = True +multi_line_output = 4 diff --git a/setup.py b/setup.py index 740739b..339c8a3 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- encoding: utf-8 -*- __copyright__ = "Copyright (C) 2017 Xiaoyu Wei" @@ -47,8 +46,7 @@ def find_git_revision(tree_root): (git_rev, _) = p.communicate() import sys - if sys.version_info >= (3,): - git_rev = git_rev.decode() + git_rev = git_rev.decode() git_rev = git_rev.rstrip() @@ -68,7 +66,7 @@ def write_git_revision(package_name): git_rev = find_git_revision(dn) with open(join(dn, package_name, "_git_rev.py"), "w") as outf: - outf.write("GIT_REVISION = %s\n" % repr(git_rev)) + outf.write(f'GIT_REVISION = "{git_rev}"\n') # }}} @@ -79,7 +77,7 @@ def main(): init_filename = "volumential/version.py" os.environ["AKPYTHON_EXEC_FROM_WITHIN_WITHIN_SETUP_PY"] = "1" exec(compile( - open(init_filename, "r").read(), init_filename, "exec"), + open(init_filename).read(), init_filename, "exec"), version_dict) write_git_revision("volumential") diff --git a/test/conftest.py b/test/conftest.py index 6857159..dd294e1 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,4 +1,3 @@ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2018 Xiaoyu Wei" @@ -22,18 +21,17 @@ THE SOFTWARE. """ -import subprocess import glob +import subprocess + +import pytest from filelock import FileLock -import pytest # noqa: F401 # setup the ctx_factory fixture -from pyopencl.tools import ( # NOQA - pytest_generate_tests_for_pyopencl as pytest_generate_tests, -) +from pyopencl.tools import ( # noqa: F401 + pytest_generate_tests_for_pyopencl as pytest_generate_tests) -from volumential.table_manager import \ - NearFieldInteractionTableManager as NFTManager +from volumential.table_manager import NearFieldInteractionTableManager as NFTManager def pytest_addoption(parser): @@ -42,17 +40,17 @@ def pytest_addoption(parser): --longrun Skip expensive tests unless told otherwise. """ - parser.addoption('--longrun', action='store_true', dest="longrun", + parser.addoption("--longrun", action="store_true", dest="longrun", default=False, help="enable longrundecorated tests") -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def longrun(request): if not request.config.option.longrun: pytest.skip("needs --longrun option to run") -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def requires_pypvfmm(request): try: import pypvfmm # noqa: F401 @@ -60,14 +58,14 @@ def requires_pypvfmm(request): pytest.skip("needs pypvfmm to run") -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def table_2d_order1(tmp_path_factory, worker_id): if not worker_id: # not executing in with multiple workers, just produce the data and let # pytest's fixture caching do its job with NFTManager("nft.hdf5", progress_bar=True) as table_manager: table, _ = table_manager.get_table(2, "Laplace", q_order=1) - subprocess.check_call(['rm', '-f', 'nft.hdf5']) + subprocess.check_call(["rm", "-f", "nft.hdf5"]) return table # get the temp directory shared by all workers @@ -84,4 +82,4 @@ def table_2d_order1(tmp_path_factory, worker_id): def pytest_sessionfinish(session, exitstatus): # remove table caches for table_file in glob.glob("*.hdf5"): - subprocess.call(['rm', '-f', table_file]) + subprocess.call(["rm", "-f", table_file]) diff --git a/test/test_cahn_hilliard.py b/test/test_cahn_hilliard.py index 5a6dd9e..c4f7e42 100644 --- a/test/test_cahn_hilliard.py +++ b/test/test_cahn_hilliard.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, print_function - __copyright__ = "Copyright (C) 2017 Xiaoyu Wei" __license__ = """ @@ -23,9 +21,11 @@ """ import numpy as np -import volumential.nearfield_potential_table as npt + from sumpy.point_calculus import CalculusPatch +import volumential.nearfield_potential_table as npt + dim = 2 patch_order = 6 @@ -51,7 +51,7 @@ def test_patch_cahn_hilliard(): import random - for r in range(rep): + for _ in range(rep): center_x = random.uniform(-1, 1) center_y = random.uniform(-1, 1) center = [center_x, center_y] @@ -119,7 +119,7 @@ def test_cahn_hilliard_same_box_on_patch(longrun): # inside the box import random - for r in range(rep): + for _ in range(rep): center_x = random.uniform(size / 2, 1 - size / 2) center_y = random.uniform(size / 2, 1 - size / 2) center = [center_x, center_y] diff --git a/test/test_droste.py b/test/test_droste.py index 1363db5..ba74600 100644 --- a/test/test_droste.py +++ b/test/test_droste.py @@ -1,4 +1,3 @@ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2019 Xiaoyu Wei" @@ -22,12 +21,14 @@ THE SOFTWARE. """ +import numpy as np import pytest +from numpy.polynomial.chebyshev import chebval + import loopy as lp -import numpy as np import pyopencl as cl + from volumential.droste import DrosteReduced -from numpy.polynomial.chebyshev import chebval def drive_test_cheb_poly(queue, deg, nnodes): @@ -50,7 +51,7 @@ def drive_test_cheb_poly(queue, deg, nnodes): results[f0, i] = basis_eval0 end end - """.replace('EVAL_CHEB_POINT', code)], + """.replace("EVAL_CHEB_POINT", code)], lang_version=(2018, 2) ) @@ -154,7 +155,8 @@ def drive_test_cheb_tables_laplace3d(requires_pypvfmm, ctx_factory, q_order): def drive_test_cheb_tables_grad_laplace3d( requires_pypvfmm, ctx_factory, q_order, axis): - from sumpy.kernel import LaplaceKernel, AxisTargetDerivative + from sumpy.kernel import AxisTargetDerivative, LaplaceKernel + from volumential.list1_symmetry import Flip, Swap cl_ctx = ctx_factory() diff --git a/test/test_expansion_wrangler_interface.py b/test/test_expansion_wrangler_interface.py index 11ade59..2fc83ea 100644 --- a/test/test_expansion_wrangler_interface.py +++ b/test/test_expansion_wrangler_interface.py @@ -1,4 +1,3 @@ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" @@ -29,95 +28,80 @@ def test_interface_allocation(): # make the interface instantiable by overriding its set of abstract methods ewi.ExpansionWranglerInterface.__abstractmethods__ = frozenset() wrglr = ewi.ExpansionWranglerInterface() - try: - wrglr.multipole_expansion_zeros() - wrglr.local_expansion_zeros() - wrglr.output_zeros() - except NotImplementedError: - assert False - assert True + + wrglr.multipole_expansion_zeros() + wrglr.local_expansion_zeros() + wrglr.output_zeros() def test_interface_utilities(): # make the interface instantiable by overriding its set of abstract methods ewi.ExpansionWranglerInterface.__abstractmethods__ = frozenset() wrglr = ewi.ExpansionWranglerInterface() - try: - wrglr.reorder_sources(None) - wrglr.reorder_potentials(None) - wrglr.finalize_potentials(None) - except NotImplementedError: - assert False - assert True + + wrglr.reorder_sources(None) + wrglr.reorder_potentials(None) + wrglr.finalize_potentials(None) def test_interface_multipole_formation(): # make the interface instantiable by overriding its set of abstract methods ewi.ExpansionWranglerInterface.__abstractmethods__ = frozenset() wrglr = ewi.ExpansionWranglerInterface() - try: - wrglr.form_multipoles( - level_start_source_box_nrs=None, source_boxes=None, src_weights=None - ) - wrglr.form_locals( - level_start_target_or_target_parent_box_nrs=None, - target_or_target_parent_boxes=None, - starts=None, - lists=None, - src_weights=None, - ) - except NotImplementedError: - assert False - assert True + + wrglr.form_multipoles( + level_start_source_box_nrs=None, source_boxes=None, src_weights=None + ) + wrglr.form_locals( + level_start_target_or_target_parent_box_nrs=None, + target_or_target_parent_boxes=None, + starts=None, + lists=None, + src_weights=None, + ) def test_interface_multipole_evaluation(): # make the interface instantiable by overriding its set of abstract methods ewi.ExpansionWranglerInterface.__abstractmethods__ = frozenset() wrglr = ewi.ExpansionWranglerInterface() - try: - wrglr.eval_direct( - target_boxes=None, - neighbor_sources_starts=None, - neighbor_sources_lists=None - ) - wrglr.eval_locals( - level_start_target_box_nrs=None, target_boxes=None, local_exps=None - ) - wrglr.eval_multipoles( - level_start_target_box_nrs=None, - target_boxes=None, - starts=None, - lists=None, - mpole_exps=None, - ) - except NotImplementedError: - assert False - assert True + + wrglr.eval_direct( + target_boxes=None, + neighbor_sources_starts=None, + neighbor_sources_lists=None + ) + wrglr.eval_locals( + level_start_target_box_nrs=None, target_boxes=None, local_exps=None + ) + wrglr.eval_multipoles( + level_start_target_box_nrs=None, + target_boxes=None, + starts=None, + lists=None, + mpole_exps=None, + ) def test_interface_multipole_manipulation(): # make the interface instantiable by overriding its set of abstract methods ewi.ExpansionWranglerInterface.__abstractmethods__ = frozenset() wrglr = ewi.ExpansionWranglerInterface() - try: - wrglr.coarsen_multipoles( - level_start_source_parent_box_nrs=None, - source_parent_boxes=None, - mpoles=None, - ) - wrglr.multipole_to_local( - level_start_target_or_target_parent_box_nrs=None, - target_or_target_parent_boxes=None, - starts=None, - lists=None, - mpole_exps=None, - ) - wrglr.refine_locals( - level_start_target_or_target_parent_box_nrs=None, - target_or_target_parent_boxes=None, - local_exps=None, - ) - except NotImplementedError: - assert False - assert True + + wrglr.coarsen_multipoles( + level_start_source_parent_box_nrs=None, + source_parent_boxes=None, + mpoles=None, + ) + wrglr.multipole_to_local( + level_start_target_or_target_parent_box_nrs=None, + target_or_target_parent_boxes=None, + starts=None, + lists=None, + mpole_exps=None, + ) + wrglr.refine_locals( + level_start_target_or_target_parent_box_nrs=None, + target_or_target_parent_boxes=None, + local_exps=None, + ) diff --git a/test/test_function_extension.py b/test/test_function_extension.py index aff8d2a..242fe85 100644 --- a/test/test_function_extension.py +++ b/test/test_function_extension.py @@ -1,4 +1,3 @@ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2019 Xiaoyu Wei" @@ -22,21 +21,19 @@ THE SOFTWARE. """ -import pytest -from volumential.function_extension import compute_harmonic_extension import numpy as np - import numpy.linalg as la -import pyopencl as cl -import pyopencl.clmath # noqa +import pytest +import pyopencl as cl +import pyopencl.clmath from meshmode.discretization import Discretization -from meshmode.discretization.poly_element import \ - InterpolatoryQuadratureSimplexGroupFactory - -from pytential import bind, sym, norm # noqa +from meshmode.discretization.poly_element import ( + InterpolatoryQuadratureSimplexGroupFactory) from pytential.target import PointsTarget +from volumential.function_extension import compute_harmonic_extension + @pytest.mark.skip(reason="this test needs to be updated to use GeometryCollection") def test_harmonic_extension_exterior_3d(ctx_factory): diff --git a/test/test_import.py b/test/test_import.py index 4d0ae8f..bb5309d 100644 --- a/test/test_import.py +++ b/test/test_import.py @@ -1,4 +1,3 @@ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" @@ -24,10 +23,4 @@ def test_import(): - try: - # Silence flake8 on this import - import volumential # NOQA - - assert True - except ImportError: - assert False + import volumential # noqa: F401 diff --git a/test/test_interpolation.py b/test/test_interpolation.py index 8d2ae6c..a5cc0dc 100644 --- a/test/test_interpolation.py +++ b/test/test_interpolation.py @@ -19,20 +19,20 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -import pytest import numpy as np -import pyopencl as cl +import pytest +import pyopencl as cl from meshmode.array_context import PyOpenCLArrayContext +from meshmode.discretization import Discretization +from meshmode.discretization.poly_element import PolynomialWarpAndBlendGroupFactory from meshmode.dof_array import flatten, thaw from meshmode.mesh.generation import generate_regular_rect_mesh -from meshmode.discretization import Discretization -from meshmode.discretization.poly_element import ( - PolynomialWarpAndBlendGroupFactory) -from volumential.interpolation import ( - ElementsToSourcesLookupBuilder, LeavesToNodesLookupBuilder, - interpolate_from_meshmode, interpolate_to_meshmode) + from volumential.geometry import BoundingBoxFactory, BoxFMMGeometryFactory +from volumential.interpolation import ( + ElementsToSourcesLookupBuilder, LeavesToNodesLookupBuilder, + interpolate_from_meshmode, interpolate_to_meshmode) # {{{ test data @@ -75,7 +75,7 @@ def eval_func_on_discr_nodes(queue, discr, func): def drive_test_from_meshmode_interpolation( cl_ctx, queue, dim, degree, nel_1d, n_levels, q_order, - a=-0.5, b=0.5, seed=0, test_case='exact'): + a=-0.5, b=0.5, seed=0, test_case="exact"): """ meshmode mesh control: nel_1d, degree volumential mesh control: n_levels, q_order @@ -99,10 +99,10 @@ def drive_test_from_meshmode_interpolation( cl_ctx, tree=boxgeo.tree, discr=discr) lookup, evt = lookup_fac(queue) - if test_case == 'exact': + if test_case == "exact": # algebraically exact interpolation func = random_polynomial_func(dim, degree, seed) - elif test_case == 'non-exact': + elif test_case == "non-exact": if dim == 2: def func(pts): x, y = pts @@ -122,7 +122,7 @@ def func(pts): tree = boxgeo.tree.get(queue) ref = func(np.vstack(tree.sources)) - if test_case == 'exact': + if test_case == "exact": return np.allclose(ref, res) resid = np.linalg.norm(ref - res, ord=np.inf) @@ -132,7 +132,7 @@ def func(pts): def drive_test_to_meshmode_interpolation( cl_ctx, queue, dim, degree, nel_1d, n_levels, q_order, - a=-0.5, b=0.5, seed=0, test_case='exact'): + a=-0.5, b=0.5, seed=0, test_case="exact"): """ meshmode mesh control: nel_1d, degree volumential mesh control: n_levels, q_order @@ -156,10 +156,10 @@ def drive_test_to_meshmode_interpolation( cl_ctx, trav=boxgeo.trav, discr=discr) lookup, evt = lookup_fac(queue) - if test_case == 'exact': + if test_case == "exact": # algebraically exact interpolation func = random_polynomial_func(dim, degree, seed) - elif test_case == 'non-exact': + elif test_case == "non-exact": if dim == 2: def func(pts): x, y = pts @@ -178,7 +178,7 @@ def func(pts): res = interpolate_to_meshmode(queue, potential, lookup).get(queue) ref = eval_func_on_discr_nodes(queue, discr, func).get(queue) - if test_case == 'exact': + if test_case == "exact": return np.allclose(ref, res) resid = np.linalg.norm(ref - res, ord=np.inf) @@ -195,7 +195,7 @@ def test_from_meshmode_interpolation_2d_exact(ctx_factory, params): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) assert drive_test_from_meshmode_interpolation( - cl_ctx, queue, 2, *params, test_case='exact') + cl_ctx, queue, 2, *params, test_case="exact") @pytest.mark.parametrize("params", [ @@ -205,7 +205,7 @@ def test_from_meshmode_interpolation_2d_nonexact(ctx_factory, params): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) assert drive_test_from_meshmode_interpolation( - cl_ctx, queue, 2, *params, test_case='non-exact') < 1e-3 + cl_ctx, queue, 2, *params, test_case="non-exact") < 1e-3 @pytest.mark.parametrize("params", [ @@ -216,7 +216,7 @@ def test_to_meshmode_interpolation_2d_exact(ctx_factory, params): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) assert drive_test_to_meshmode_interpolation( - cl_ctx, queue, 2, *params, test_case='exact') + cl_ctx, queue, 2, *params, test_case="exact") @pytest.mark.parametrize("params", [ @@ -226,7 +226,7 @@ def test_to_meshmode_interpolation_2d_nonexact(ctx_factory, params): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) assert drive_test_to_meshmode_interpolation( - cl_ctx, queue, 2, *params, test_case='non-exact') < 1e-3 + cl_ctx, queue, 2, *params, test_case="non-exact") < 1e-3 # }}} End 2d tests @@ -241,7 +241,7 @@ def test_from_meshmode_interpolation_3d_exact(ctx_factory, params): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) assert drive_test_from_meshmode_interpolation( - cl_ctx, queue, 3, *params, test_case='exact') + cl_ctx, queue, 3, *params, test_case="exact") @pytest.mark.parametrize("params", [ @@ -251,7 +251,7 @@ def test_from_meshmode_interpolation_3d_nonexact(ctx_factory, params): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) assert drive_test_from_meshmode_interpolation( - cl_ctx, queue, 3, *params, test_case='non-exact') < 1e-3 + cl_ctx, queue, 3, *params, test_case="non-exact") < 1e-3 @pytest.mark.parametrize("params", [ @@ -262,7 +262,7 @@ def test_to_meshmode_interpolation_3d_exact(ctx_factory, params): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) assert drive_test_to_meshmode_interpolation( - cl_ctx, queue, 3, *params, test_case='exact') + cl_ctx, queue, 3, *params, test_case="exact") @pytest.mark.parametrize("params", [ @@ -272,12 +272,12 @@ def test_to_meshmode_interpolation_3d_nonexact(ctx_factory, params): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) assert drive_test_to_meshmode_interpolation( - cl_ctx, queue, 3, *params, test_case='non-exact') < 1e-3 + cl_ctx, queue, 3, *params, test_case="non-exact") < 1e-3 # }}} End 3d tests -if __name__ == '__main__': +if __name__ == "__main__": cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) resid = drive_test_to_meshmode_interpolation( diff --git a/test/test_laplace.py b/test/test_laplace.py index b19f676..6cc64e5 100644 --- a/test/test_laplace.py +++ b/test/test_laplace.py @@ -1,4 +1,3 @@ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" @@ -23,9 +22,11 @@ """ import numpy as np -import volumential.nearfield_potential_table as npt + from sumpy.point_calculus import CalculusPatch +import volumential.nearfield_potential_table as npt + # Directly evaluate volume integrals on a calculus patch to # test the correctness of singular quadrature and formulation @@ -53,7 +54,7 @@ def test_patch_laplace(): import random - for r in range(rep): + for _ in range(rep): center_x = random.uniform(-1, 1) center_y = random.uniform(-1, 1) center = [center_x, center_y] @@ -153,4 +154,4 @@ def test_laplace_same_box_on_patch(longrun): print("f_vals", f_values) print("lap", lap) - assert max(abs((lap))) < 0.1 + assert max(abs(lap)) < 0.1 diff --git a/test/test_laplace3d.py b/test/test_laplace3d.py index b639701..3333905 100644 --- a/test/test_laplace3d.py +++ b/test/test_laplace3d.py @@ -1,4 +1,3 @@ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2018 Xiaoyu Wei" @@ -24,9 +23,9 @@ import numpy as np -# import volumential.nearfield_potential_table as npt from sumpy.point_calculus import CalculusPatch + dim = 3 patch_order = 3 @@ -42,7 +41,7 @@ def test_patch_laplace(): import random - for r in range(rep): + for _ in range(rep): center = [random.uniform(-1, 1) for d in range(dim)] patch = make_patch(center, size) diff --git a/test/test_list1_gallery.py b/test/test_list1_gallery.py index 2fdf289..6c3eea6 100644 --- a/test/test_list1_gallery.py +++ b/test/test_list1_gallery.py @@ -1,4 +1,3 @@ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" diff --git a/test/test_nearfield_interaction_completeness.py b/test/test_nearfield_interaction_completeness.py index cd590c7..fc353b1 100644 --- a/test/test_nearfield_interaction_completeness.py +++ b/test/test_nearfield_interaction_completeness.py @@ -1,4 +1,3 @@ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" @@ -23,10 +22,12 @@ """ import subprocess +from functools import partial + import numpy as np + import pyopencl as cl -import pyopencl.array # NOQA -from functools import partial +import pyopencl.array # noqa: F401 def drive_test_completeness(ctx, queue, dim, q_order): @@ -119,7 +120,7 @@ def source_field(x): from volumential.table_manager import NearFieldInteractionTableManager - subprocess.check_call(['rm', '-f', 'nft-test-completeness.hdf5']) + subprocess.check_call(["rm", "-f", "nft-test-completeness.hdf5"]) with NearFieldInteractionTableManager("nft-test-completeness.hdf5", progress_bar=False) as tm: @@ -130,9 +131,9 @@ def source_field(x): # {{{ expansion wrangler - from sumpy.kernel import LaplaceKernel - from sumpy.expansion.multipole import VolumeTaylorMultipoleExpansion from sumpy.expansion.local import VolumeTaylorLocalExpansion + from sumpy.expansion.multipole import VolumeTaylorMultipoleExpansion + from sumpy.kernel import LaplaceKernel knl = LaplaceKernel(dim) out_kernels = [knl] @@ -140,8 +141,7 @@ def source_field(x): mpole_expn_class = partial(VolumeTaylorMultipoleExpansion, use_rscale=None) from volumential.expansion_wrangler_fpnd import ( - FPNDExpansionWranglerCodeContainer, - FPNDExpansionWrangler) + FPNDExpansionWrangler, FPNDExpansionWranglerCodeContainer) wcc = FPNDExpansionWranglerCodeContainer( ctx, @@ -167,7 +167,7 @@ def source_field(x): trav.neighbor_source_boxes_lists, mode_coefs=source_vals) pot = pot[0] for p in pot[0]: - assert(abs(p - 2**dim) < 1e-8) + assert abs(p - 2**dim) < 1.0e-8 def test_completeness_1(ctx_factory): diff --git a/test/test_nearfield_potential_table.py b/test/test_nearfield_potential_table.py index ec87c38..03796d5 100644 --- a/test/test_nearfield_potential_table.py +++ b/test/test_nearfield_potential_table.py @@ -1,4 +1,3 @@ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" @@ -22,14 +21,15 @@ THE SOFTWARE. """ -import volumential.nearfield_potential_table as npt import numpy as np from numpy.polynomial.chebyshev import chebval, chebval2d, chebval3d +import volumential.nearfield_potential_table as npt + def test_const_order_1(): table = npt.NearFieldInteractionTable( - quad_order=1, build_method='Transform', progress_bar=False) + quad_order=1, build_method="Transform", progress_bar=False) table.build_table() for ary in table.data: assert np.allclose(ary, 1) @@ -37,7 +37,7 @@ def test_const_order_1(): def test_const_order_2(longrun): table = npt.NearFieldInteractionTable( - quad_order=2, build_method='Transform', progress_bar=False) + quad_order=2, build_method="Transform", progress_bar=False) table.build_table() for ary in table.data: assert np.allclose(ary, 0.25) @@ -45,7 +45,7 @@ def test_const_order_2(longrun): def interp_modes(q_order): table = npt.NearFieldInteractionTable( - quad_order=q_order, build_method='Transform', progress_bar=False) + quad_order=q_order, build_method="Transform", progress_bar=False) modes = [table.get_mode(i) for i in range(table.n_q_points)] @@ -82,12 +82,12 @@ def cheb_eval(dim, coefs, coords): elif dim == 3: return chebval3d(coords[0], coords[1], coords[2], coefs) else: - raise NotImplementedError('dimension %d not supported' % dim) + raise NotImplementedError("dimension %d not supported" % dim) def drive_test_modes_cheb_coeffs(dim, q, cheb_order): if not cheb_order >= q: - raise RuntimeError('Insufficient cheb_order to fully resolve the modes') + raise RuntimeError("Insufficient cheb_order to fully resolve the modes") sample_mode = np.random.randint(q**dim) table = npt.NearFieldInteractionTable(quad_order=q, dim=dim, progress_bar=False) diff --git a/test/test_singular_integral_2d.py b/test/test_singular_integral_2d.py index e69f15f..5a7d5af 100644 --- a/test/test_singular_integral_2d.py +++ b/test/test_singular_integral_2d.py @@ -1,4 +1,3 @@ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" @@ -23,6 +22,7 @@ """ import numpy as np + import volumential.singular_integral_2d as sint diff --git a/test/test_table_builder_symmetry.py b/test/test_table_builder_symmetry.py index 4d0ae8f..bb5309d 100644 --- a/test/test_table_builder_symmetry.py +++ b/test/test_table_builder_symmetry.py @@ -1,4 +1,3 @@ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" @@ -24,10 +23,4 @@ def test_import(): - try: - # Silence flake8 on this import - import volumential # NOQA - - assert True - except ImportError: - assert False + import volumential # noqa: F401 diff --git a/test/test_table_manager.py b/test/test_table_manager.py index e783cac..9b048e6 100644 --- a/test/test_table_manager.py +++ b/test/test_table_manager.py @@ -1,4 +1,3 @@ -from __future__ import absolute_import, division, print_function __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" @@ -24,13 +23,15 @@ import os import subprocess +from shutil import copyfile + import numpy as np -import pyopencl as cl import pytest + +import pyopencl as cl + import volumential as vm -from shutil import copyfile -from volumential.table_manager import ( - NearFieldInteractionTableManager as NFTable) +from volumential.table_manager import NearFieldInteractionTableManager as NFTable def get_table(queue, q_order=1, dim=2): @@ -41,7 +42,7 @@ def get_table(queue, q_order=1, dim=2): copyfile("nft.hdf5", f"nft-test-table-manager-{pid}.hdf5") - subprocess.check_call(['rm', '-f', f'nft-test-table-manager-{pid}.hdf5']) + subprocess.check_call(["rm", "-f", f"nft-test-table-manager-{pid}.hdf5"]) with NFTable(f"nft-test-table-manager-{pid}.hdf5", progress_bar=True) as table_manager: diff --git a/test/test_volume_fmm.py b/test/test_volume_fmm.py index 8ee1084..7294e6e 100644 --- a/test/test_volume_fmm.py +++ b/test/test_volume_fmm.py @@ -1,4 +1,3 @@ -from __future__ import division, absolute_import, print_function __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" @@ -22,15 +21,17 @@ THE SOFTWARE. """ -import subprocess import logging -import pytest +import subprocess +from functools import partial import numpy as np +import pytest + import pyopencl as cl + import volumential.meshgen as mg -from functools import partial logger = logging.getLogger(__name__) @@ -203,7 +204,7 @@ def exact_solu(x, y): from volumential.table_manager import NearFieldInteractionTableManager - subprocess.check_call(['rm', '-f', 'nft-test-volume-fmm.hdf5']) + subprocess.check_call(["rm", "-f", "nft-test-volume-fmm.hdf5"]) tm = NearFieldInteractionTableManager("nft-test-volume-fmm.hdf5") nftable, _ = tm.get_table(dim, "Laplace", q_order) @@ -211,15 +212,12 @@ def exact_solu(x, y): # {{{ sumpy expansion for laplace kernel - from sumpy.kernel import LaplaceKernel - + from sumpy.expansion.local import LinearPDEConformingVolumeTaylorLocalExpansion # from sumpy.expansion.multipole import VolumeTaylorMultipoleExpansion # from sumpy.expansion.local import VolumeTaylorLocalExpansion - - from sumpy.expansion.multipole import \ - LinearPDEConformingVolumeTaylorMultipoleExpansion - from sumpy.expansion.local import \ - LinearPDEConformingVolumeTaylorLocalExpansion + from sumpy.expansion.multipole import ( + LinearPDEConformingVolumeTaylorMultipoleExpansion) + from sumpy.kernel import LaplaceKernel knl = LaplaceKernel(dim) out_kernels = [knl] @@ -230,8 +228,7 @@ def exact_solu(x, y): exclude_self = True from volumential.expansion_wrangler_fpnd import ( - FPNDExpansionWranglerCodeContainer, - FPNDExpansionWrangler) + FPNDExpansionWrangler, FPNDExpansionWranglerCodeContainer) wcc = FPNDExpansionWranglerCodeContainer( ctx, diff --git a/volumential/__init__.py b/volumential/__init__.py index 5d79290..1a2edb7 100644 --- a/volumential/__init__.py +++ b/volumential/__init__.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, print_function - __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" __license__ = """ @@ -22,14 +20,15 @@ THE SOFTWARE. """ import os + from pytools.persistent_dict import WriteOncePersistentDict +from volumential.nearfield_potential_table import ( # noqa: F401 + NearFieldInteractionTable) from volumential.singular_integral_2d import box_quad -from volumential.version import VERSION_TEXT from volumential.table_manager import NearFieldInteractionTableManager # noqa: F401 -from volumential.nearfield_potential_table import ( # noqa: F401 - NearFieldInteractionTable, -) +from volumential.version import VERSION_TEXT + volumential_version = VERSION_TEXT @@ -73,7 +72,7 @@ def set_caching_enabled(flag): CACHING_ENABLED = flag -class CacheMode(object): +class CacheMode: """A context manager for setting whether :mod:`volumential` is allowed to use disk caches. """ diff --git a/volumential/droste.py b/volumential/droste.py index e594bf9..c066cc6 100644 --- a/volumential/droste.py +++ b/volumential/droste.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, print_function - __copyright__ = "Copyright (C) 2018 Xiaoyu Wei" __license__ = """ @@ -22,11 +20,14 @@ THE SOFTWARE. """ +import logging + import numpy as np + import loopy as lp + from volumential.tools import KernelCacheWrapper -import logging logger = logging.getLogger(__name__) @@ -92,7 +93,7 @@ def __init__(self, integral_knl, quad_order, case_vecs, n_brick_quad_points, ) else: self.ncases = 0 - case_vecs = list() + case_vecs = [] self.interaction_case_vecs = np.array([]) self.interaction_case_scls = np.array( @@ -163,8 +164,8 @@ def make_brick_domain(self, variables, n, lbound=0, ubound=0): else: ubound_pwaff = pwaffs[0] + n - from functools import reduce import operator + from functools import reduce return reduce( operator.and_, @@ -178,8 +179,7 @@ def make_brick_quadrature_kwargs(self): """ # sps.legendre blows up easily at high order import scipy.special as sps - # legendre_nodes, _, legendre_weights = sps.legendre( - # nquad_points).weights.T + legendre_nodes, legendre_weights = sps.p_roots(self.nquad_points) legendre_nodes = legendre_nodes * 0.5 + 0.5 legendre_weights = legendre_weights * 0.5 @@ -213,14 +213,18 @@ def make_brick_quadrature_kwargs(self): ts_nodes = ts_nodes * 0.5 + 0.5 ts_weights *= 0.5 - return dict(quadrature_nodes=legendre_nodes, - quadrature_weights=legendre_weights, - radial_quadrature_nodes=ts_nodes, - radial_quadrature_weights=ts_weights) + return { + "quadrature_nodes": legendre_nodes, + "quadrature_weights": legendre_weights, + "radial_quadrature_nodes": ts_nodes, + "radial_quadrature_weights": ts_weights, + } else: - return dict(quadrature_nodes=legendre_nodes, - quadrature_weights=legendre_weights) + return { + "quadrature_nodes": legendre_nodes, + "quadrature_weights": legendre_weights, + } def get_sumpy_kernel_insns(self): # get sumpy kernel insns @@ -240,12 +244,11 @@ def get_sumpy_kernel_insns(self): ), ) sac.run_global_cse() - import six from sumpy.codegen import to_loopy_insns loopy_insns = to_loopy_insns( - six.iteritems(sac.assignments), - vector_names=set(["dist"]), + sac.assignments.items(), + vector_names={"dist"}, pymbolic_expr_maps=[self.integral_knl.get_code_transformer()], retain_names=[result_name], complex_dtype=np.complex128, @@ -471,7 +474,7 @@ def make_result_array(self, **kwargs): def get_kernel_code(self): return [ self.make_dim_independent( - """ # noqa + """ # noqa: E501 for iaxis <> root_center[iaxis] = 0.5 * ( root_brick[iaxis, 1] + root_brick[iaxis, 0]) {dup=iaxis} @@ -687,7 +690,7 @@ def postprocess_cheb_table(self, cheb_table, cheb_coefs): # transform to interpolatory basis functions # NOTE: the reversed order of indices, e.g., # mccoefs[f0, f1, f2], and cheb_table[f2, f1, f0] - concat_axes = [iaxis for iaxis in range(self.dim)] + concat_axes = list(range(self.dim)) for mid in range(self.n_q_points): mccoefs = cheb_coefs[mid] nfp_table[mid] = np.tensordot( @@ -720,7 +723,7 @@ def __init__(self, integral_knl, quad_order, case_vecs, n_brick_quad_points=50, special_radial_quadrature=False, nradial_quad_points=None): - super(DrosteFull, self).__init__( + super().__init__( integral_knl, quad_order, case_vecs, n_brick_quad_points, special_radial_quadrature, nradial_quad_points) self.name = "DrosteFull" @@ -760,7 +763,7 @@ def get_kernel(self, **kwargs): if "extra_kernel_kwarg_types" in kwargs: extra_kernel_kwarg_types = kwargs["extra_kernel_kwarg_types"] - loopy_knl = lp.make_kernel( # NOQA + loopy_knl = lp.make_kernel( [domain], self.get_kernel_code() + self.get_sumpy_kernel_eval_insns(), @@ -797,6 +800,7 @@ def get_kernel(self, **kwargs): def get_optimized_kernel(self, ncpus=None, **kwargs): if ncpus is None: import multiprocessing + # NOTE: this detects the number of logical cores, which # may result in suboptimal performance. ncpus = multiprocessing.cpu_count() @@ -932,7 +936,7 @@ def __init__( special_radial_quadrature=False, nradial_quad_points=None, ): - super(DrosteReduced, self).__init__( + super().__init__( integral_knl, quad_order, case_vecs, n_brick_quad_points, special_radial_quadrature, nradial_quad_points) @@ -1006,8 +1010,8 @@ def make_loop_domain(self, base_case_id): else: prev_swappable[iaxis] = list(group)[axid - 1] - from functools import reduce import operator + from functools import reduce tgt_domain_ubounds = reduce( operator.and_, @@ -1125,18 +1129,12 @@ def conjunct(var): assert vid >= 0 and vid < self.dim return var[0] + str(self.dim - 1 - vid) - from itertools import product, permutations + from itertools import permutations, product - ext_ids = [ - ext - for ext in product( - [fid for fid in product([0, 1], repeat=nflippables)], - *[ - [sid for sid in permutations(sgroup)] - for sgroup in swappable_groups - ] - ) - ] + ext_ids = product( + product([0, 1], repeat=nflippables), + *[permutations(sgroup) for sgroup in swappable_groups] + ) # The idea is that, any member of the hyperoctahedral group # has the decomposition m = f * s, where f is a flip and s @@ -1172,8 +1170,8 @@ def conjunct(var): ext_tgt_ordering.reverse() ext_fun_ordering.reverse() - ext_instruction_ids = ':'.join([ - 'result_ext_' + str(eid) + ext_instruction_ids = ":".join([ + "result_ext_" + str(eid) for eid in range(len(ext_ids)) if eid != ext_index ]) @@ -1212,7 +1210,7 @@ def get_kernel(self, **kwargs): extra_kernel_kwarg_types = kwargs["extra_kernel_kwarg_types"] if self.get_kernel_id == 0: - loopy_knl = lp.make_kernel( # NOQA + loopy_knl = lp.make_kernel( [domain], self.get_kernel_code() # FIXME: cannot have expansion in the same kernel, since it @@ -1240,7 +1238,7 @@ def get_kernel(self, **kwargs): ) elif self.get_kernel_id == 1: - loopy_knl = lp.make_kernel( # NOQA + loopy_knl = lp.make_kernel( [domain], self.get_kernel_expansion_by_symmetry_code(), [ @@ -1277,6 +1275,7 @@ def get_optimized_kernel(self, ncpus=None, **kwargs): # self.current_base_case, self.get_kernel_id if ncpus is None: import multiprocessing + # NOTE: this detects the number of logical cores, which # may result in suboptimal performance. ncpus = multiprocessing.cpu_count() @@ -1435,23 +1434,17 @@ def build_cheb_table(self, queue, **kwargs): assert len(flippable) == self.dim flippable_ids = [i for i in range(self.dim) if flippable[i]] - from itertools import product, permutations + from itertools import permutations, product - ext_ids = [ - ext - for ext in product( - [fid for fid in product([0, 1], repeat=nflippables)], - *[ - [sid for sid in permutations(sgroup)] - for sgroup in swappable_groups - ] - ) - ] + ext_ids = product( + product([0, 1], repeat=nflippables), + *[permutations(sgroup) for sgroup in swappable_groups] + ) base_case_vec = self.reduce_by_symmetry.full_vecs[case_id] assert (base_case_vec == self.reduce_by_symmetry.reduced_vecs[base_case_id]) - for ext_index, ext_id in zip(range(len(ext_ids)), ext_ids): + for _, ext_id in zip(range(len(ext_ids)), ext_ids): # start from the base vec ext_vec = list(base_case_vec) swapped_axes = list(range(self.dim)) @@ -1512,7 +1505,7 @@ def build_cheb_table(self, queue, **kwargs): def get_cache_key(self): if self.reduce_by_symmetry.symmetry_tags is None: # Bn: the full n-dimensional hyperoctahedral group - symmetry_info = 'B%d' % self.dim + symmetry_info = "B%d" % self.dim else: symmetry_info = "Span{%s}" % ",".join([ repr(tag) for tag in @@ -1601,7 +1594,7 @@ def __init__(self, integral_knl, quad_order, case_vecs, """ :param auto_windowing: auto-detect window radius. """ - super(InverseDrosteReduced, self).__init__( + super().__init__( integral_knl, quad_order, case_vecs, n_brick_quad_points, special_radial_quadrature, nradial_quad_points, knl_symmetry_tags) @@ -1628,10 +1621,11 @@ def codegen_basis_tgt_eval(self, iaxis): """ # only valid for self-interactions - assert all([self.reduce_by_symmetry.reduced_vecs[ - self.current_base_case][d] == 0 for d in range(self.dim)]) + assert all( + self.reduce_by_symmetry.reduced_vecs[self.current_base_case][d] == 0 + for d in range(self.dim)) - code = """ # noqa + code = """ # noqa: E501 <> T0_tgt_IAXIS = 1 <> T1_tgt_IAXIS = template_true_target[IAXIS] {dep=template_true_targets} <> Tprev_tgt_IAXIS = T0_tgt_IAXIS {id=t0_tgt_IAXIS} @@ -1673,10 +1667,11 @@ def codegen_der2_basis_tgt_eval(self, iaxis): """ # only valid for self-interactions - assert all([self.reduce_by_symmetry.reduced_vecs[ - self.current_base_case][d] == 0 for d in range(self.dim)]) + assert all( + self.reduce_by_symmetry.reduced_vecs[self.current_base_case][d] == 0 + for d in range(self.dim)) - code = """ # noqa + code = """ # noqa: E501 <> U0_tgt_IAXIS = 1 <> U1_tgt_IAXIS = 2 * template_true_target[IAXIS] {dep=template_true_targets} <> Uprev_tgt_IAXIS = U0_tgt_IAXIS {id=u0_tgt_IAXIS} @@ -1748,7 +1743,7 @@ def codegen_windowing_function(self): code.append("<> fc = if(1 - rndist > 0, exp(-1 / (1 - rndist)), 0)") code.append("<> windowing = 1 - fv / (fv + fc)") - return '\n'.join(code) + return "\n".join(code) def make_dim_independent(self, knlstring): r"""Produce the correct @@ -1757,8 +1752,9 @@ def make_dim_independent(self, knlstring): """ # detect for self-interactions - if all([self.reduce_by_symmetry.reduced_vecs[ - self.current_base_case][d] == 0 for d in range(self.dim)]): + if all( + self.reduce_by_symmetry.reduced_vecs[self.current_base_case][d] == 0 + for d in range(self.dim)): target_box_is_source = True else: target_box_is_source = False @@ -1774,7 +1770,7 @@ def make_dim_independent(self, knlstring): if self.get_kernel_id == 0: resknl = resknl.replace( "POSTPROCESS_KNL_VAL", - '\n'.join([ + "\n".join([ self.codegen_windowing_function(), "<> knl_val_post = windowing * knl_val {id=pp_kval}" ]) @@ -1782,7 +1778,7 @@ def make_dim_independent(self, knlstring): elif self.get_kernel_id == 1: resknl = resknl.replace( "POSTPROCESS_KNL_VAL", - '\n'.join([ + "\n".join([ self.codegen_windowing_function(), "<> knl_val_post = (1 - windowing) * knl_val {id=pp_kval}" ]) @@ -1810,10 +1806,10 @@ def make_dim_independent(self, knlstring): "PREPARE_BASIS_VALS", "\n".join(basis_eval_insns + [ "... nop {id=basis_evals,dep=%s}" - % ':'.join( - ['basis%d' % i for i in range(self.dim)] - + ['tgtbasis%d' % i for i in range(self.dim)] - + ['tgtd2basis%d' % i for i in range(self.dim)] + % ":".join( + ["basis%d" % i for i in range(self.dim)] + + ["tgtbasis%d" % i for i in range(self.dim)] + + ["tgtd2basis%d" % i for i in range(self.dim)] ), ]) ) @@ -1822,8 +1818,8 @@ def make_dim_independent(self, knlstring): "PREPARE_BASIS_VALS", "\n".join(basis_eval_insns + [ "... nop {id=basis_evals,dep=%s}" - % ':'.join( - ['basis%d' % i for i in range(self.dim)] + % ":".join( + ["basis%d" % i for i in range(self.dim)] ), ]) ) @@ -1832,7 +1828,7 @@ def make_dim_independent(self, knlstring): if target_box_is_source: resknl = resknl.replace( "DENSITY_VAL_ASSIGNMENT", - ' '.join([ + " ".join([ "0.5 * der2_basis_tgt_eval0 * (dist[0]**2)", ]) ) @@ -1846,7 +1842,7 @@ def make_dim_independent(self, knlstring): if target_box_is_source: resknl = resknl.replace( "DENSITY_VAL_ASSIGNMENT", - ' '.join([ + " ".join([ " 0.5 * der2_basis_tgt_eval0 * basis_tgt_eval1 * (dist[0]**2)", # noqa: E501 "+ 0.5 * basis_tgt_eval0 * der2_basis_tgt_eval1 * (dist[1]**2)", # noqa: E501 ]) @@ -1861,7 +1857,7 @@ def make_dim_independent(self, knlstring): if target_box_is_source: resknl = resknl.replace( "DENSITY_VAL_ASSIGNMENT", - ' '.join([ + " ".join([ " 0.5 * der2_basis_tgt_eval0 * basis_tgt_eval1 * basis_tgt_eval2 * (dist[0]**2)", # noqa: E501 "+ 0.5 * basis_tgt_eval0 * der2_basis_tgt_eval1 * basis_tgt_eval2 * (dist[1]**2)", # noqa: E501 "+ 0.5 * basis_tgt_eval0 * basis_tgt_eval1 * der2_basis_tgt_eval2 * (dist[2]**2)", # noqa: E501 @@ -1884,18 +1880,18 @@ def make_dim_independent(self, knlstring): "PREPARE_BASIS_VALS", "\n".join(basis_eval_insns + [ "... nop {id=basis_evals,dep=%s}" - % ':'.join( - ['basis%d' % i for i in range(self.dim)] - + ['tgtbasis%d' % i for i in range(self.dim)] + % ":".join( + ["basis%d" % i for i in range(self.dim)] + + ["tgtbasis%d" % i for i in range(self.dim)] ), ]) ) resknl = resknl.replace( "DENSITY_VAL_ASSIGNMENT", - ' - '.join([ - ' * '.join( + " - ".join([ + " * ".join( ["basis_tgt_eval%d" % i for i in range(self.dim)]), - ' * '.join( + " * ".join( ["basis_eval%d" % i for i in range(self.dim)]), ]) ) @@ -1905,14 +1901,14 @@ def make_dim_independent(self, knlstring): "PREPARE_BASIS_VALS", "\n".join(basis_eval_insns + [ "... nop {id=basis_evals,dep=%s}" - % ':'.join( - ['basis%d' % i for i in range(self.dim)] + % ":".join( + ["basis%d" % i for i in range(self.dim)] ), ]) ) resknl = resknl.replace( "DENSITY_VAL_ASSIGNMENT", - ' - ' + ' * '.join( + " - " + " * ".join( ["basis_eval%d" % i for i in range(self.dim)] ) ) @@ -1979,7 +1975,7 @@ def get_kernel(self, **kwargs): extra_loopy_kernel_kwargs = kwargs["extra_loopy_kernel_kwargs"] if self.get_kernel_id == 0 or self.get_kernel_id == 1: - loopy_knl = lp.make_kernel( # NOQA + loopy_knl = lp.make_kernel( [domain], self.get_kernel_code() + self.get_sumpy_kernel_eval_insns(), @@ -2006,7 +2002,7 @@ def get_kernel(self, **kwargs): ) elif self.get_kernel_id == 2: - loopy_knl = lp.make_kernel( # NOQA + loopy_knl = lp.make_kernel( [domain], self.get_kernel_expansion_by_symmetry_code(), [ @@ -2186,7 +2182,7 @@ def call_loopy_kernel_case(self, queue, base_case_id, **kwargs): except Exception: # noqa: B902 pass knl2 = self.get_cached_optimized_kernel() - result_array = res0['result'] + res1['result'] + result_array = res0["result"] + res1["result"] evt2, res2 = knl2( queue, diff --git a/volumential/expansion_wrangler_fpnd.py b/volumential/expansion_wrangler_fpnd.py index b691f63..2f58e9d 100644 --- a/volumential/expansion_wrangler_fpnd.py +++ b/volumential/expansion_wrangler_fpnd.py @@ -1,5 +1,3 @@ -from __future__ import division, absolute_import, print_function - __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" __license__ = """ @@ -22,23 +20,24 @@ THE SOFTWARE. """ -import numpy as np import logging + +import numpy as np + import pyopencl as cl import pyopencl.array +from boxtree.pyfmmlib_integration import FMMLibExpansionWrangler from pytools.obj_array import make_obj_array +from sumpy.fmm import ( + SumpyExpansionWrangler, SumpyExpansionWranglerCodeContainer, SumpyTimingFuture) +from sumpy.kernel import ( + AxisTargetDerivative, DirectionalSourceDerivative, HelmholtzKernel, + LaplaceKernel) -# from pytools import memoize_method -from volumential.nearfield_potential_table import NearFieldInteractionTable from volumential.expansion_wrangler_interface import ( - ExpansionWranglerInterface, ExpansionWranglerCodeContainerInterface) -from sumpy.fmm import SumpyExpansionWrangler, \ - SumpyTimingFuture, SumpyExpansionWranglerCodeContainer -from boxtree.pyfmmlib_integration import FMMLibExpansionWrangler + ExpansionWranglerCodeContainerInterface, ExpansionWranglerInterface) +from volumential.nearfield_potential_table import NearFieldInteractionTable -from sumpy.kernel import ( - LaplaceKernel, HelmholtzKernel, AxisTargetDerivative, - DirectionalSourceDerivative) logger = logging.getLogger(__name__) @@ -152,7 +151,7 @@ def __init__( # dictionary of lists of tables elif isinstance(near_field_table, dict): - self.n_tables = dict() + self.n_tables = {} for out_knl in self.code.target_kernels: if repr(out_knl) not in near_field_table: raise RuntimeError( @@ -287,7 +286,7 @@ def reorder_sources(self, source_array): return SumpyExpansionWrangler.reorder_sources(self, source_array) def reorder_targets(self, target_array): - if not hasattr(self.tree, 'user_target_ids'): + if not hasattr(self.tree, "user_target_ids"): self.tree.user_target_ids = inverse_id_map( self.queue, self.tree.sorted_target_ids) return target_array.with_queue(self.queue)[self.tree.user_target_ids] @@ -601,8 +600,11 @@ def __init__(self, cl_context, self.exclude_self = True def get_wrangler(self, queue, tree, dtype, fmm_level_to_order, - source_extra_kwargs={}, kernel_extra_kwargs=None, + source_extra_kwargs=None, kernel_extra_kwargs=None, *args, **kwargs): + if source_extra_kwargs is None: + source_extra_kwargs = {} + return FPNDFMMLibExpansionWrangler(self, queue, tree, dtype, fmm_level_to_order, source_extra_kwargs, kernel_extra_kwargs, @@ -727,7 +729,7 @@ def __init__(self, code_container, queue, tree, # dictionary of lists of tables elif isinstance(near_field_table, dict): - self.n_tables = dict() + self.n_tables = {} for out_knl in self.code.target_kernels: if repr(out_knl) not in near_field_table: raise RuntimeError( @@ -845,10 +847,10 @@ def inner_fmm_level_to_nterms(tree, level): frozenset([("k", helmholtz_k)]), tree, level) rotation_data = None - if 'traversal' in kwargs: + if "traversal" in kwargs: # add rotation data if traversal is passed as a keyword argument from boxtree.pyfmmlib_integration import FMMLibRotationData - rotation_data = FMMLibRotationData(self.queue, kwargs['traversal']) + rotation_data = FMMLibRotationData(self.queue, kwargs["traversal"]) else: logger.warning("Rotation data is not utilized since traversal is " "not known to FPNDFMMLibExpansionWrangler.") @@ -901,7 +903,7 @@ def reorder_sources(self, source_array): return FMMLibExpansionWrangler.reorder_sources(self, source_array) def reorder_targets(self, target_array): - if not hasattr(self.tree, 'user_target_ids'): + if not hasattr(self.tree, "user_target_ids"): self.tree.user_target_ids = inverse_id_map( self.queue, self.tree.sorted_target_ids) return target_array[self.tree.user_target_ids] diff --git a/volumential/expansion_wrangler_interface.py b/volumential/expansion_wrangler_interface.py index 4418f13..db901fb 100644 --- a/volumential/expansion_wrangler_interface.py +++ b/volumential/expansion_wrangler_interface.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, print_function - __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" __license__ = """ @@ -23,10 +21,11 @@ """ import logging +from abc import ABCMeta, abstractmethod + logger = logging.getLogger(__name__) -from abc import ABCMeta, abstractmethod __doc__ = """ .. autoclass::ExpansionWranglerInterface @@ -37,7 +36,7 @@ # NOTE: abstractmethod's signatures (arguement lists) are not enforced -class ExpansionWranglerInterface(object): +class ExpansionWranglerInterface: """ Abstract expansion handling interface. The interface is adapted from, and stays compatible with boxtree/fmm. @@ -216,7 +215,7 @@ def finalize_potentials(self, potentials): # {{{ code container interface -class ExpansionWranglerCodeContainerInterface(object): +class ExpansionWranglerCodeContainerInterface: """ Abstract expansion code container interface. The interface is adapted from, and stays compatible with boxtree/fmm. diff --git a/volumential/function_extension.py b/volumential/function_extension.py index b2f1390..c838132 100644 --- a/volumential/function_extension.py +++ b/volumential/function_extension.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, print_function - """Function extension with regularity contraints: 1. :math:`L^2`: extend with constant value @@ -41,12 +39,15 @@ import logging import numpy as np + import pyopencl as cl -from pytools.obj_array import make_obj_array from pymbolic import var from pytential import bind, sym from pytential.solve import gmres -from pytential.symbolic.stokes import StressletWrapper, StokesletWrapper +from pytential.symbolic.stokes import StokesletWrapper, StressletWrapper +from pytools.obj_array import make_obj_array +from sumpy.kernel import AxisTargetDerivative, ExpressionKernel + # {{{ helper functions @@ -177,11 +178,11 @@ def compute_harmonic_extension(queue, target_discr, # }}} debugging_info = {} - debugging_info['gmres_result'] = gmres_result + debugging_info["gmres_result"] = gmres_result # {{{ postprocess - repr_kwargs = dict(qbx_forced_limit=None) + repr_kwargs = {"qbx_forced_limit": None} representation_sym = ( sym.S(kernel, inv_sqrt_w_sigma, **repr_kwargs) + sym.D(kernel, inv_sqrt_w_sigma, **repr_kwargs)) @@ -189,9 +190,9 @@ def compute_harmonic_extension(queue, target_discr, qbx_stick_out = qbx.copy( target_association_tolerance=target_association_tolerance) - debugging_info['qbx'] = qbx_stick_out - debugging_info['representation'] = representation_sym - debugging_info['density'] = sigma + debugging_info["qbx"] = qbx_stick_out + debugging_info["representation"] = representation_sym + debugging_info["density"] = sigma ext_f = bind( (qbx_stick_out, target_discr), @@ -226,7 +227,7 @@ def eval_ext_f(target_discr): (qbx_stick_out, target_discr), representation_sym)(queue, sigma=sigma).real + matching_const - debugging_info['eval_ext_f'] = eval_ext_f + debugging_info["eval_ext_f"] = eval_ext_f return ext_f, debugging_info @@ -237,8 +238,6 @@ def eval_ext_f(target_discr): # {{{ Goursat kernels -from sumpy.kernel import ExpressionKernel, AxisTargetDerivative - class ComplexLogKernel(ExpressionKernel): @@ -255,7 +254,7 @@ def __init__(self, dim=None): else: raise NotImplementedError("unsupported dimensionality") - super(ComplexLogKernel, self).__init__( + super().__init__( dim, expression=expr, global_scaling_const=scaling, @@ -303,7 +302,7 @@ def __init__(self, dim=None): else: raise NotImplementedError("unsupported dimensionality") - super(ComplexLinearLogKernel, self).__init__( + super().__init__( dim, expression=expr, global_scaling_const=scaling, @@ -332,7 +331,7 @@ def __init__(self, dim=None): else: raise NotImplementedError("unsupported dimensionality") - super(ComplexLinearKernel, self).__init__( + super().__init__( dim, expression=expr, global_scaling_const=scaling, @@ -373,7 +372,7 @@ def __init__(self, dim=None): else: raise NotImplementedError("unsupported dimensionality") - super(ComplexFractionalKernel, self).__init__( + super().__init__( dim, expression=expr, global_scaling_const=scaling, @@ -413,9 +412,9 @@ def get_extension_bie_symbolic_operator(loc_sign=1): bdry_op_sym = ( loc_sign * 0.5 * sigma_sym - stresslet_obj.apply(sigma_sym, nvec_sym, mu_sym, - qbx_forced_limit='avg') + qbx_forced_limit="avg") - stokeslet_obj.apply(sigma_sym, mu_sym, - qbx_forced_limit='avg') + int_sigma) + qbx_forced_limit="avg") + int_sigma) return bdry_op_sym @@ -587,11 +586,11 @@ def compute_biharmonic_extension(queue, target_discr, queue, integrand=omega_S_bdry+omega_D_bdry+omega_W_bdry) debugging_info = {} - debugging_info['omega_S'] = omega_S - debugging_info['omega_D'] = omega_D - debugging_info['omega_W'] = omega_W - debugging_info['omega_v1'] = v1 - debugging_info['omega_D1'] = omega_D1 + debugging_info["omega_S"] = omega_S + debugging_info["omega_D"] = omega_D + debugging_info["omega_W"] = omega_W + debugging_info["omega_v1"] = v1 + debugging_info["omega_D1"] = omega_D1 int_interior_func_bdry = bind(qbx, sym.integral(2, 1, var("integrand")))( queue, integrand=f) diff --git a/volumential/geometry.py b/volumential/geometry.py index 0250c91..92ee446 100644 --- a/volumential/geometry.py +++ b/volumential/geometry.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, print_function - __copyright__ = "Copyright (C) 2019 Xiaoyu Wei" __license__ = """ @@ -23,19 +21,21 @@ """ import numpy as np + import pyopencl as cl -from pytools.obj_array import make_obj_array from boxtree.pyfmmlib_integration import FMMLibRotationData +from pytools.obj_array import make_obj_array + # {{{ bounding box factory -class BoundingBoxFactory(): +class BoundingBoxFactory: def __init__(self, dim, center=None, radius=None, - dtype=np.dtype("float64")): + dtype=float): self.dim = dim - self.dtype = dtype + self.dtype = np.dtype(dtype) self.center = center self.radius = radius @@ -97,8 +97,8 @@ def __call__(self, ctx, self.lbounds = box_center - box_radius self.ubounds = box_center + box_radius - from boxtree.tools import AXIS_NAMES from boxtree.bounding_box import make_bounding_box_dtype + from boxtree.tools import AXIS_NAMES axis_names = AXIS_NAMES[:self.dim] bbox_type, _ = make_bounding_box_dtype( @@ -116,7 +116,7 @@ def __call__(self, ctx, # {{{ box mesh data factory -class BoxFMMGeometryFactory(): +class BoxFMMGeometryFactory: """Builds the geometry information needed for performing volume FMM. The objects of this class is designed to be "interactive", i.e., be manipulated repeatedly and on demand, produce a series of desired @@ -166,6 +166,7 @@ def __init__( self.dim = dim if quadrature_formula is None: from modepy import LegendreGaussQuadrature + # order = degree + 1 self.quadrature_formula = LegendreGaussQuadrature(order - 1) else: diff --git a/volumential/interpolation.py b/volumential/interpolation.py index 7330118..ef8e59b 100644 --- a/volumential/interpolation.py +++ b/volumential/interpolation.py @@ -1,6 +1,4 @@ -__copyright__ = """ -Copyright (C) 2020 Xiaoyu Wei -""" +__copyright__ = "Copyright (C) 2020 Xiaoyu Wei" __license__ = """ Permission is hereby granted, free of charge, to any person obtaining a copy @@ -23,17 +21,21 @@ """ import itertools +import logging + import numpy as np -import pyopencl as cl + import loopy as lp -from pytools import memoize_method, ProcessLogger -from pytools.obj_array import make_obj_array +import pyopencl as cl from boxtree.tools import DeviceDataRecord from meshmode.array_context import PyOpenCLArrayContext -from meshmode.dof_array import unflatten, flatten, thaw +from meshmode.dof_array import flatten, thaw, unflatten +from pytools import ProcessLogger, memoize_method +from pytools.obj_array import make_obj_array + from volumential.volume_fmm import interpolate_volume_potential -import logging + logger = logging.getLogger(__name__) diff --git a/volumential/list1.py b/volumential/list1.py index e845589..9061953 100644 --- a/volumential/list1.py +++ b/volumential/list1.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, print_function - __copyright__ = "Copyright (C) 2018 Xiaoyu Wei" __license__ = """ @@ -29,17 +27,18 @@ :members: """ +import logging + import numpy as np + import loopy import pyopencl as cl from volumential.tools import KernelCacheWrapper -import logging logger = logging.getLogger(__name__) -logging.basicConfig(level=logging.INFO) # {{{ near field eval base class @@ -55,7 +54,7 @@ def __init__( integral_kernel, table_data_shapes, potential_kind=1, - options=[], + options=None, name=None, device=None, **kwargs @@ -70,6 +69,8 @@ def __init__( The two kinds share the same far-field code, but the second kind requires exterior_mode_nmlz when computing the list1 interactions. """ + if options is None: + options = [] self.integral_kernel = integral_kernel @@ -149,7 +150,7 @@ def codegen_vec_id(self): code = code + "+" + self.codegen_vec_component(d) return code - def codegen_compute_scaling(self, box_name='sbox'): + def codegen_compute_scaling(self, box_name="sbox"): """box_name: the name of the box whose extent is used. """ if ("infer_kernel_scaling" in self.extra_kwargs) and ( @@ -204,17 +205,17 @@ def codegen_compute_scaling(self, box_name='sbox'): elif "kernel_scaling_code" in self.extra_kwargs: # user-defined scaling rule - assert isinstance(self.extra_kwargs['kernel_scaling_code'], str) + assert isinstance(self.extra_kwargs["kernel_scaling_code"], str) logger.info("Using scaling rule %s for %s.", - self.extra_kwargs['kernel_scaling_code'], self.kname + self.extra_kwargs["kernel_scaling_code"], self.kname ) - return self.extra_kwargs['kernel_scaling_code'] + return self.extra_kwargs["kernel_scaling_code"] else: logger.info("not scaling for " + self.kname) logger.info("(using multiple tables)") return "1.0" - def codegen_compute_displacement(self, box_name='sbox'): + def codegen_compute_displacement(self, box_name="sbox"): if ("infer_kernel_scaling" in self.extra_kwargs) and ( self.extra_kwargs["infer_kernel_scaling"] ): @@ -250,12 +251,12 @@ def codegen_compute_displacement(self, box_name='sbox'): elif "kernel_displacement_code" in self.extra_kwargs: # user-defined displacement rule assert isinstance( - self.extra_kwargs['kernel_displacement_code'], str) + self.extra_kwargs["kernel_displacement_code"], str) logger.info("Using displacement %s for %s.", - self.extra_kwargs['kernel_displacement_code'], + self.extra_kwargs["kernel_displacement_code"], self.kname ) - code = self.extra_kwargs['kernel_displacement_code'] + code = self.extra_kwargs["kernel_displacement_code"] else: logger.info("no displacement for " + self.kname) logger.info("(using multiple tables)") @@ -263,7 +264,7 @@ def codegen_compute_displacement(self, box_name='sbox'): return code.replace("BOX", box_name) - def codegen_get_table_level(self, box_name='sbox'): + def codegen_get_table_level(self, box_name="sbox"): if ("infer_kernel_scaling" in self.extra_kwargs) and ( self.extra_kwargs["infer_kernel_scaling"] ): @@ -310,7 +311,7 @@ def get_kernel(self): else: potential_dtype = np.float64 - lpknl = loopy.make_kernel( # NOQA + lpknl = loopy.make_kernel( [ "{ [ tbox ] : 0 <= tbox < n_tgt_boxes }", "{ [ tid, sbox ] : 0 <= tid < n_box_targets and \ @@ -402,11 +403,11 @@ def get_kernel(self): .replace("COMPUTE_VEC_ID", self.codegen_vec_id()) .replace("COMPUTE_SCALING", self.codegen_compute_scaling()) .replace("COMPUTE_DISPLACEMENT", self.codegen_compute_displacement()) - .replace("COMPUTE_TGT_SCALING", self.codegen_compute_scaling('tbox')) + .replace("COMPUTE_TGT_SCALING", self.codegen_compute_scaling("tbox")) .replace("COMPUTE_TGT_DISPLACEMENT", - self.codegen_compute_displacement('tbox')) + self.codegen_compute_displacement("tbox")) .replace("GET_TABLE_LEVEL", self.codegen_get_table_level()) - .replace("GET_TGT_TABLE_LEVEL", self.codegen_get_table_level('tbox')) + .replace("GET_TGT_TABLE_LEVEL", self.codegen_get_table_level("tbox")) .replace("EXTERIOR_PART", self.codegen_exterior_part()), [ loopy.TemporaryVariable("vec_id", np.int32), @@ -456,6 +457,7 @@ def get_cache_key(self): def get_optimized_kernel(self, ncpus=None): if ncpus is None: import multiprocessing + # NOTE: this detects the number of logical cores, disable hyperthreading # for the optimal performance. ncpus = multiprocessing.cpu_count() @@ -486,12 +488,10 @@ def __call__(self, queue, **kwargs): table_data_combined = kwargs.pop("table_data_combined") target_boxes = kwargs.pop("target_boxes") - integral_kernel_init_kargs = { - name: val - for name, val in zip( - self.integral_kernel.init_arg_names, - self.integral_kernel.__getinitargs__()) - } + integral_kernel_init_kargs = dict( + zip(self.integral_kernel.init_arg_names, + self.integral_kernel.__getinitargs__()) + ) # help loopy's type inference for key, val in integral_kernel_init_kargs.items(): @@ -540,12 +540,12 @@ def __call__(self, queue, **kwargs): **extra_knl_args_from_init ) - res['result'].add_event(evt) + res["result"].add_event(evt) if isinstance(result, cl.array.Array): assert result is res["result"] else: assert isinstance(result, np.ndarray) - result = res['result'].get(queue) + result = res["result"].get(queue) queue.finish() logger.info("list1 evaluation finished") diff --git a/volumential/list1_gallery.py b/volumential/list1_gallery.py index 70463ec..a930663 100644 --- a/volumential/list1_gallery.py +++ b/volumential/list1_gallery.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, print_function - __doc__ = """ .. autofunction:: generate_list1_gallery """ @@ -95,8 +93,7 @@ def generate_boxes_on_level(box, ilevel): """ if ilevel: for child in box.children: - for result in generate_boxes_on_level(child, ilevel - 1): - yield result + yield from generate_boxes_on_level(child, ilevel - 1) else: yield box @@ -108,8 +105,7 @@ def generate_boxes(box): yield box for child in box.children: - for result in generate_boxes(child): - yield result + yield from generate_boxes(child) def linf_dist(box1, box2): @@ -163,7 +159,7 @@ def postprocess_interactions(near_neighbor_interactions): tb0, wb0 = near_neighbor_interactions[0] unique_interaction_vectors.add(tuple(tb0.center - tb0.center)) - list1_interactions = sorted(list(unique_interaction_vectors)) + list1_interactions = sorted(unique_interaction_vectors) return list1_interactions diff --git a/volumential/list1_symmetry.py b/volumential/list1_symmetry.py index ff15f1d..fae7a28 100644 --- a/volumential/list1_symmetry.py +++ b/volumential/list1_symmetry.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, print_function - __copyright__ = "Copyright (C) 2018 Xiaoyu Wei" __license__ = """ @@ -22,18 +20,20 @@ THE SOFTWARE. """ -import numpy as np import math +import numpy as np + + # {{{ symmetry operations -class SymmetryOperationBase(object): +class SymmetryOperationBase: def __init__(self, index): self._index = index def __lt__(self, other): - if type(self) == type(other): + if type(self) is type(other): return self._index < other._index # differnt operations in lexicographical order @@ -46,7 +46,7 @@ class Flip(SymmetryOperationBase): """ def __init__(self, iaxis): - super(Flip, self).__init__(iaxis) + super().__init__(iaxis) self.axis = iaxis def __repr__(self): @@ -60,7 +60,7 @@ class Swap(SymmetryOperationBase): def __init__(self, iaxis, jaxis): self.axes = (iaxis, jaxis) - super(Swap, self).__init__(sorted(self.axes)) + super().__init__(sorted(self.axes)) def __repr__(self): return "Swap(%d,%d)" % tuple(sorted(self.axes)) @@ -69,7 +69,7 @@ def __repr__(self): # }}} End symmetry operations -class CaseVecReduction(object): +class CaseVecReduction: """ Reduce a set of case vectors based on symmetry. """ @@ -108,7 +108,7 @@ def parse_symmetry_tags(self, tags): if tags is None: flippable += 1 - swappable_groups.append({i for i in range(self.dim)}) + swappable_groups.append(set(range(self.dim))) return flippable, swappable_groups for tag in tags: diff --git a/volumential/meshgen.py b/volumential/meshgen.py index cc936b2..9e0bf36 100644 --- a/volumential/meshgen.py +++ b/volumential/meshgen.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, print_function - __copyright__ = "Copyright (C) 2018 Xiaoyu Wei" __license__ = """ @@ -34,10 +32,13 @@ """ import logging + import numpy as np + import pyopencl as cl from pytools.obj_array import make_obj_array + logger = logging.getLogger(__name__) provider = None @@ -45,7 +46,7 @@ # {{{ meshgen Python provider -class MeshGenBase(object): +class MeshGenBase: """Base class for Meshgen via BoxTree. The interface is similar to the Meshgen via Deal.II, except that the arguments a and b can also be of higher dimensions to allow @@ -264,11 +265,7 @@ def dimension_specific_setup(self): else: # noexcept on importing meshgen_dealii logger.info("Using Meshgen via Deal.II interface.") - from volumential.meshgen_dealii import ( # noqa: F401 - greet, - MeshGen2D, - MeshGen3D, - ) + from volumential.meshgen_dealii import MeshGen2D, MeshGen3D, greet # noqa: F401 def make_uniform_cubic_grid(degree, level, dim, queue=None): from volumential.meshgen_dealii import make_uniform_cubic_grid as _mucg diff --git a/volumential/nearfield_potential_table.py b/volumential/nearfield_potential_table.py index 8cef4d2..241f3cf 100644 --- a/volumential/nearfield_potential_table.py +++ b/volumential/nearfield_potential_table.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, print_function - __copyright__ = "Copyright (C) 2017 - 2018 Xiaoyu Wei" __license__ = """ @@ -23,17 +21,19 @@ """ import logging +from functools import partial + import numpy as np -import loopy as lp -import pyopencl as cl from scipy.interpolate import BarycentricInterpolator as Interpolator -from functools import partial +import loopy as lp +import pyopencl as cl import volumential.list1_gallery as gallery import volumential.singular_integral_2d as squad -logger = logging.getLogger('NearFieldInteractionTable') + +logger = logging.getLogger("NearFieldInteractionTable") def _self_tp(vec, tpd=2): @@ -165,7 +165,7 @@ def get_cahn_hilliard_laplacian(dim, b=0, c=0): def sumpy_kernel_to_lambda(sknl): - from sympy import Symbol, symbols, lambdify + from sympy import Symbol, lambdify, symbols var_name_prefix = "x" var_names = " ".join([var_name_prefix + str(i) for i in range(sknl.dim)]) @@ -185,7 +185,7 @@ def func(x, y=None, z=None): # {{{ table data structure -class NearFieldInteractionTable(object): +class NearFieldInteractionTable: """Class for a near-field interaction table. A near-field interaction table stores precomputed singular integrals @@ -298,8 +298,8 @@ def __init__( # quad points in [-1,1] import volumential.meshgen as mg - if 'queue' in kwargs: - queue = kwargs['queue'] + if "queue" in kwargs: + queue = kwargs["queue"] else: queue = None @@ -359,7 +359,7 @@ def decode_index(self, entry_id): """This is the inverse function of get_entry_index() """ - index_info = dict() + index_info = {} case_id = entry_id // self.n_pairs pair_id = entry_id % self.n_pairs @@ -473,7 +473,7 @@ def get_mode_cheb_coeffs(self, mode_index, cheb_order): mode = self.get_template_mode(mode_index) grid = np.meshgrid( *[cheby_nodes for d in range(self.dim)], - indexing='ij') + indexing="ij") mvals = mode(*grid) from numpy.polynomial.chebyshev import Chebyshev @@ -714,7 +714,7 @@ def build_normalizer_table(self, pool=None, pb=None): pool = Pool(processes=None) for mode_id, nmlz in pool.imap_unordered( - self.compute_nmlz, [i for i in range(self.n_q_points)] + self.compute_nmlz, range(self.n_q_points) ): self.mode_normalizers[mode_id] = nmlz if pb is not None: @@ -771,7 +771,7 @@ def build_table_via_transform(self): if 0: # Then complete the table via symmetry lookup for entry_id, centry_id in pool.imap_unordered( - self.lookup_by_symmetry, [i for i in range(len(self.data))]): + self.lookup_by_symmetry, range(len(self.data))): assert not np.isnan(self.data[centry_id]) if centry_id == entry_id: continue @@ -1110,17 +1110,16 @@ def fl_scaling(k, s): ) * fl_scaling(k=self.dim, s=s) return - from meshmode.array_context import PyOpenCLArrayContext - from meshmode.dof_array import thaw, flatten - from meshmode.mesh.io import read_gmsh - from meshmode.discretization import Discretization - from meshmode.discretization.poly_element import \ - PolynomialWarpAndBlendGroupFactory - # {{{ gmsh processing - import gmsh + from meshmode.array_context import PyOpenCLArrayContext + from meshmode.discretization import Discretization + from meshmode.discretization.poly_element import ( + PolynomialWarpAndBlendGroupFactory) + from meshmode.dof_array import flatten, thaw + from meshmode.mesh.io import read_gmsh + gmsh.initialize() gmsh.option.setNumber("General.Terminal", 1) @@ -1137,7 +1136,7 @@ def fl_scaling(k, s): hs = self.source_box_extent / 2 # radius of bouding sphere r = hs * np.sqrt(self.dim) - logger.debug("r_inner = %f, r_outer = %f" % (hs, r)) + logger.debug(f"r_inner = {hs:f}, r_outer = {r:f}") if self.dim == 2: tag_box = gmsh.model.occ.addRectangle(x=0, y=0, z=0, @@ -1165,10 +1164,10 @@ def fl_scaling(k, s): gmsh.model.occ.synchronize() gmsh.model.mesh.generate(self.dim) - from tempfile import mkdtemp from os.path import join + from tempfile import mkdtemp temp_dir = mkdtemp(prefix="tmp_volumential_nft") - msh_filename = join(temp_dir, 'chinese_lucky_coin.msh') + msh_filename = join(temp_dir, "chinese_lucky_coin.msh") gmsh.write(msh_filename) gmsh.finalize() @@ -1248,7 +1247,7 @@ def fl_scaling(k, s): if "extra_kernel_kwarg_types" in kwargs: extra_kernel_kwarg_types = kwargs["extra_kernel_kwarg_types"] - lpknl = lp.make_kernel( # NOQA + lpknl = lp.make_kernel( "{ [iqpt, iaxis]: 0<=iqpt= 3 return AxisTargetDerivative(2, LaplaceKernel(dim)) @@ -473,12 +471,12 @@ def get_sumpy_kernel(self, dim, kernel_type): return YukawaKernel(dim) elif kernel_type == "Yukawa-Dx": - from sumpy.kernel import YukawaKernel, AxisTargetDerivative + from sumpy.kernel import AxisTargetDerivative, YukawaKernel return AxisTargetDerivative(0, YukawaKernel(dim)) elif kernel_type == "Yukawa-Dy": - from sumpy.kernel import YukawaKernel, AxisTargetDerivative + from sumpy.kernel import AxisTargetDerivative, YukawaKernel return AxisTargetDerivative(1, YukawaKernel(dim)) @@ -489,23 +487,19 @@ def get_sumpy_kernel(self, dim, kernel_type): elif kernel_type == "Cahn-Hilliard-Laplacian": from sumpy.kernel import ( - FactorizedBiharmonicKernel, - LaplacianTargetDerivative, - ) + FactorizedBiharmonicKernel, LaplacianTargetDerivative) return LaplacianTargetDerivative(FactorizedBiharmonicKernel(dim)) elif kernel_type == "Cahn-Hilliard-Dx": - from sumpy.kernel import FactorizedBiharmonicKernel, AxisTargetDerivative + from sumpy.kernel import AxisTargetDerivative, FactorizedBiharmonicKernel return AxisTargetDerivative(0, FactorizedBiharmonicKernel(dim)) elif kernel_type == "Cahn-Hilliard-Laplacian-Dx": from sumpy.kernel import ( - FactorizedBiharmonicKernel, - LaplacianTargetDerivative, - ) - from sumpy.kernel import AxisTargetDerivative + AxisTargetDerivative, FactorizedBiharmonicKernel, + LaplacianTargetDerivative) return AxisTargetDerivative( 0, LaplacianTargetDerivative(FactorizedBiharmonicKernel(dim)) @@ -513,17 +507,15 @@ def get_sumpy_kernel(self, dim, kernel_type): elif kernel_type == "Cahn-Hilliard-Laplacian-Dy": from sumpy.kernel import ( - FactorizedBiharmonicKernel, - LaplacianTargetDerivative, - ) - from sumpy.kernel import AxisTargetDerivative + AxisTargetDerivative, FactorizedBiharmonicKernel, + LaplacianTargetDerivative) return AxisTargetDerivative( 1, LaplacianTargetDerivative(FactorizedBiharmonicKernel(dim)) ) elif kernel_type == "Cahn-Hilliard-Dy": - from sumpy.kernel import FactorizedBiharmonicKernel, AxisTargetDerivative + from sumpy.kernel import AxisTargetDerivative, FactorizedBiharmonicKernel return AxisTargetDerivative(1, FactorizedBiharmonicKernel(dim)) @@ -601,17 +593,17 @@ def compute_and_update_table( assert "Order_" + str(q_order) in self.datafile[str(dim) + "D"][kernel_type] if compute_method == "Transform": - if 'knl_func' not in kwargs: + if "knl_func" not in kwargs: knl_func = self.get_kernel_function(dim, kernel_type, **kwargs) else: - knl_func = kwargs['knl_func'] + knl_func = kwargs["knl_func"] sumpy_knl = None elif compute_method == "DrosteSum": knl_func = None - if 'sumpy_knl' not in kwargs: + if "sumpy_knl" not in kwargs: sumpy_knl = self.get_sumpy_kernel(dim, kernel_type) else: - sumpy_knl = kwargs['sumpy_knl'] + sumpy_knl = kwargs["sumpy_knl"] else: raise NotImplementedError("Unsupported compute_method.") @@ -633,9 +625,9 @@ def compute_and_update_table( if 0: # self-similarly shrink delta - if 'delta' in kwargs: - delta = kwargs.pop('delta') * (2 ** (-source_box_level)) - kwargs['delta'] = delta + if "delta" in kwargs: + delta = kwargs.pop("delta") * (2 ** (-source_box_level)) + kwargs["delta"] = delta table.build_table(cl_ctx, queue, **kwargs) assert table.is_built diff --git a/volumential/tools.py b/volumential/tools.py index d5bc213..b22628a 100644 --- a/volumential/tools.py +++ b/volumential/tools.py @@ -1,6 +1,3 @@ -from __future__ import absolute_import, division, print_function -import six - __copyright__ = "Copyright (C) 2018 Xiaoyu Wei" __license__ = """ @@ -23,15 +20,17 @@ THE SOFTWARE. """ +import logging + import numpy as np + import loopy as lp -import pyopencl as cl import pymbolic as pmbl +import pyopencl as cl +from pymbolic.primitives import ( + Expression as ExpressionType, Variable as VariableType) from pytools import memoize_method -from pymbolic.primitives import Variable as VariableType -from pymbolic.primitives import Expression as ExpressionType -import logging logger = logging.getLogger(__name__) @@ -62,7 +61,7 @@ def clean_file(filename, new_name=None): # {{{ loopy kernel cache wrapper -class KernelCacheWrapper(object): +class KernelCacheWrapper: # FIXME: largely code duplication with sumpy. def __init__(self): @@ -81,15 +80,16 @@ def get_optimized_kernel(self): @memoize_method def get_cached_optimized_kernel(self, **kwargs): - from sumpy import code_cache, CACHING_ENABLED, OPT_ENABLED + from sumpy import CACHING_ENABLED, OPT_ENABLED, code_cache if CACHING_ENABLED: import loopy.version from sumpy.version import KERNEL_VERSION as SUMPY_KERNEL_VERSION + from volumential.version import KERNEL_VERSION cache_key = ( self.get_cache_key() - + tuple(sorted(six.iteritems(kwargs))) + + tuple(sorted(kwargs.items())) + (loopy.version.DATA_MODEL_VERSION,) + (SUMPY_KERNEL_VERSION,) + (KERNEL_VERSION,) @@ -97,16 +97,14 @@ def get_cached_optimized_kernel(self, **kwargs): try: result = code_cache[cache_key] - logger.debug("%s: kernel cache hit [key=%s]" % ( - self.name, cache_key)) + logger.debug(f"{self.name}: kernel cache hit [key={cache_key}]") return result except KeyError: pass logger.info("%s: kernel cache miss" % self.name) if CACHING_ENABLED: - logger.info("%s: kernel cache miss [key=%s]" % ( - self.name, cache_key)) + logger.info(f"{self.name}: kernel cache miss [key={cache_key}]") from pytools import MinRecursionLimit with MinRecursionLimit(3000): @@ -205,7 +203,7 @@ def get_kernel(self, **kwargs): for insn in [scalar_assignment] ] - loopy_knl = lp.make_kernel( # NOQA + loopy_knl = lp.make_kernel( "{ [itgt]: 0<=itgt