diff --git a/.test-conda-env-py3-macos.yml b/.test-conda-env-py3-macos.yml index 54ea6a4eedb50c7200f7b4f9aebe8b7af3f2fd08..1735795e145892dc4169fdeb502e460e1f7b0154 100644 --- a/.test-conda-env-py3-macos.yml +++ b/.test-conda-env-py3-macos.yml @@ -5,6 +5,8 @@ channels: dependencies: - git - c-compiler + - pytest + - pytest-cov - binutils - scipy - conda-forge::numpy @@ -26,11 +28,17 @@ dependencies: - libgfortran>=3.0.1 - clangdev - openmp + # for pypvfmm + - openmpi-mpicxx + - fftw + - autoconf + - automake + - libtool - pip - pip: - git+https://gitlab.tiker.net/inducer/loopy - - git+https://www.github.com/xywei/gmsh_interop + - git+https://gitlab.tiker.net/inducer/gmsh_interop - git+https://gitlab.tiker.net/xywei/boxtree - git+https://gitlab.tiker.net/inducer/modepy - git+https://gitlab.tiker.net/inducer/meshmode diff --git a/.test-conda-env-py3.yml b/.test-conda-env-py3.yml index 37f7c40d06d442436c9f9398b474ef2a04ca5c5e..d5797098d4bb1ebe1790126a6776b9d0a03a84da 100644 --- a/.test-conda-env-py3.yml +++ b/.test-conda-env-py3.yml @@ -10,6 +10,8 @@ dependencies: - scipy - conda-forge::numpy - conda-forge::sympy + - pytest + - pytest-cov - pocl - islpy - pyopencl @@ -23,11 +25,14 @@ dependencies: - dealii - gmsh - python-gmsh + # for pypvfmm + - openmpi-mpicxx + - fftw - pip - pip: - git+https://gitlab.tiker.net/inducer/loopy - - git+https://www.github.com/xywei/gmsh_interop + - git+https://gitlab.tiker.net/inducer/gmsh_interop - git+https://gitlab.tiker.net/xywei/boxtree - git+https://gitlab.tiker.net/inducer/modepy - git+https://gitlab.tiker.net/inducer/meshmode diff --git a/experiments/volume_potential_3d_derivatives.py b/experiments/volume_potential_3d_derivatives.py index 023871c27bc4e7b42975179e6110db48c897eed8..db78c3a98201fa6509e9f6e92802db78e27db31d 100644 --- a/experiments/volume_potential_3d_derivatives.py +++ b/experiments/volume_potential_3d_derivatives.py @@ -323,9 +323,11 @@ local_expn_class = expn_factory.get_local_expansion_class(knl) mpole_expn_class = expn_factory.get_multipole_expansion_class(knl) exclude_self = True -from volumential.expansion_wrangler_interface import ExpansionWranglerCodeContainer +from volumential.expansion_wrangler_fpnd import ( + FPNDExpansionWranglerCodeContainer, + FPNDExpansionWrangler) -wcc = ExpansionWranglerCodeContainer( +wcc = FPNDExpansionWranglerCodeContainer( ctx, partial(mpole_expn_class, knl), partial(local_expn_class, knl), @@ -339,8 +341,6 @@ if exclude_self: else: self_extra_kwargs = {} -from volumential.expansion_wrangler_fpnd import FPNDExpansionWrangler - wrangler = FPNDExpansionWrangler( code_container=wcc, queue=queue, diff --git a/requirements.txt b/requirements.txt index 1a2bf60fdb303cac4fe55779700d92f1b95823cd..be9ec06fd84f09dc4c5ded3c20e3b053de7ad13f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,8 @@ --index-url https://pypi.python.org/simple/ -git+https://gitlab.tiker.net/xywei/pypvfmm.git#egg=pypvfmm +filelock + +# git+https://gitlab.tiker.net/xywei/pypvfmm.git#egg=pypvfmm -e git+https://gitlab.tiker.net/xywei/boxtree.git#egg=boxtree -e git+https://gitlab.tiker.net/inducer/gmsh_interop.git#egg=gmsh_interop diff --git a/test/conftest.py b/test/conftest.py index dcd9a6ac649a63b6e2471fb22e34226aa1d01eb8..68571598243b8805fbebab8cdf5c4be53ad96515 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -22,6 +22,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ +import subprocess +import glob +from filelock import FileLock import pytest # noqa: F401 # setup the ctx_factory fixture @@ -29,6 +32,9 @@ from pyopencl.tools import ( # NOQA pytest_generate_tests_for_pyopencl as pytest_generate_tests, ) +from volumential.table_manager import \ + NearFieldInteractionTableManager as NFTManager + def pytest_addoption(parser): """Add extra command line options. @@ -54,25 +60,28 @@ def requires_pypvfmm(request): pytest.skip("needs pypvfmm to run") -def pytest_sessionstart(session): - from volumential.table_manager import NearFieldInteractionTableManager - - # clean the table file, in case there was an aborted previous test run - import subprocess - subprocess.call(['rm', '-f', '/tmp/volumential-tests.hdf5']) - - # pre-compute a basic table that is re-used in many tests. - # can be easily turned off to run individual tests that do not require - # the table cache. - if 1: - with NearFieldInteractionTableManager( - "/tmp/volumential-tests.hdf5") as tm: - table, _ = tm.get_table( - 2, "Laplace", - q_order=1, force_recompute=False, queue=None) +@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']) + return table + + # get the temp directory shared by all workers + root_tmp_dir = tmp_path_factory.getbasetemp().parent + + fn = root_tmp_dir / "nft.hdf5" + with FileLock(str(fn) + ".lock"): + with NFTManager(str(fn), progress_bar=True) as table_manager: + table, _ = table_manager.get_table(2, "Laplace", q_order=1) + return table + return table def pytest_sessionfinish(session, exitstatus): # remove table caches - import subprocess - subprocess.call(['rm', '-f', '/tmp/volumential-tests.hdf5']) + for table_file in glob.glob("*.hdf5"): + subprocess.call(['rm', '-f', table_file]) diff --git a/test/test_interpolation.py b/test/test_interpolation.py index 07fffa73b3088c41600b3295508a7d5e34c25159..bcc74a483bd74c38374567151752b5c48629ab85 100644 --- a/test/test_interpolation.py +++ b/test/test_interpolation.py @@ -50,8 +50,10 @@ def random_polynomial_func(dim, degree, seed=None): npts = pts.shape[1] res = np.zeros(npts) for deg in np.ndindex(coefs.shape): + mono = np.ones(npts) for iaxis in range(dim): - res += coefs[deg] * pts[iaxis, :]**deg[iaxis] + mono += pts[iaxis, :]**deg[iaxis] + res += coefs[deg] * mono return res return poly_func diff --git a/test/test_nearfield_interaction_completeness.py b/test/test_nearfield_interaction_completeness.py index 32fafa6a9ceb56d27c79904bd204dbf134170f8c..c1f566cafd63426eb8630622eb44ea9e542b7e10 100644 --- a/test/test_nearfield_interaction_completeness.py +++ b/test/test_nearfield_interaction_completeness.py @@ -119,17 +119,14 @@ def drive_test_completeness(ctx, queue, dim, q_order): from volumential.table_manager import NearFieldInteractionTableManager - subprocess.check_call(['rm', '-f', 'nft.hdf5']) + subprocess.check_call(['rm', '-f', 'nft-test-completeness.hdf5']) + with NearFieldInteractionTableManager("nft-test-completeness.hdf5", + progress_bar=False) as tm: - with NearFieldInteractionTableManager("nft.hdf5") as tm: - - nft, _ = tm.get_table(dim, "Constant", q_order, - queue=queue, n_levels=1, alpha=0, - compute_method="DrosteSum", - n_brick_quad_points=50, - adaptive_level=False, use_symmetry=True) - - subprocess.check_call(['rm', 'nft.hdf5']) + nft, _ = tm.get_table( + dim, "Constant", q_order, queue=queue, n_levels=1, alpha=0, + compute_method="DrosteSum", n_brick_quad_points=50, + adaptive_level=False, use_symmetry=True) # {{{ expansion wrangler @@ -166,11 +163,8 @@ def drive_test_completeness(ctx, queue, dim, q_order): # }}} End sumpy expansion for laplace kernel pot = wrangler.eval_direct( - trav.target_boxes, - trav.neighbor_source_boxes_starts, - trav.neighbor_source_boxes_lists, - mode_coefs=source_vals, - ) + trav.target_boxes, trav.neighbor_source_boxes_starts, + trav.neighbor_source_boxes_lists, mode_coefs=source_vals) pot = pot[0] for p in pot[0]: assert(abs(p - 2**dim) < 1e-8) diff --git a/test/test_nearfield_potential_table.py b/test/test_nearfield_potential_table.py index c7a6dd4fedff4d2d31336d8c4204bc66ffa69fd6..ec87c3840a907a9a25711ee56313ed14ba70c0e3 100644 --- a/test/test_nearfield_potential_table.py +++ b/test/test_nearfield_potential_table.py @@ -28,14 +28,16 @@ from numpy.polynomial.chebyshev import chebval, chebval2d, chebval3d def test_const_order_1(): - table = npt.NearFieldInteractionTable(quad_order=1, build_method='Transform') + table = npt.NearFieldInteractionTable( + quad_order=1, build_method='Transform', progress_bar=False) table.build_table() for ary in table.data: assert np.allclose(ary, 1) def test_const_order_2(longrun): - table = npt.NearFieldInteractionTable(quad_order=2, build_method='Transform') + table = npt.NearFieldInteractionTable( + quad_order=2, build_method='Transform', progress_bar=False) table.build_table() for ary in table.data: assert np.allclose(ary, 0.25) @@ -43,7 +45,7 @@ def test_const_order_2(longrun): def interp_modes(q_order): table = npt.NearFieldInteractionTable( - quad_order=q_order, build_method='Transform') + quad_order=q_order, build_method='Transform', progress_bar=False) modes = [table.get_mode(i) for i in range(table.n_q_points)] @@ -88,7 +90,7 @@ def drive_test_modes_cheb_coeffs(dim, q, cheb_order): 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) + table = npt.NearFieldInteractionTable(quad_order=q, dim=dim, progress_bar=False) ccoefs = table.get_mode_cheb_coeffs(sample_mode, cheb_order) shape = (cheb_order, ) * dim ccoefs = ccoefs.reshape(*shape) diff --git a/test/test_table_manager.py b/test/test_table_manager.py index e78660fdf8ca4b6a816a09d388f5746c2d531f0c..e783cac1f689aecfb346ca1523bfd641676cb5fe 100644 --- a/test/test_table_manager.py +++ b/test/test_table_manager.py @@ -22,39 +22,52 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ +import os +import subprocess import numpy as np import pyopencl as cl import pytest import volumential as vm +from shutil import copyfile from volumential.table_manager import ( NearFieldInteractionTableManager as NFTable) def get_table(queue, q_order=1, dim=2): - with NFTable("/tmp/volumential-tests.hdf5") as table_manager: + pid = os.getpid() + + # copy from shared cache if exists + if os.path.exists("nft.hdf5"): + copyfile("nft.hdf5", + 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: table, _ = table_manager.get_table( dim, "Laplace", q_order=q_order, force_recompute=False, queue=queue) + return table -def test_case_id(ctx_factory): - cl_ctx = ctx_factory() - queue = cl.CommandQueue(cl_ctx) - table = get_table(queue) +def test_case_id(ctx_factory, table_2d_order1): + table = table_2d_order1 case_same_box = len(table.interaction_case_vecs) // 2 assert list(table.interaction_case_vecs[case_same_box]) == [0, 0] -def test_get_table(ctx_factory): - cl_ctx = ctx_factory() - queue = cl.CommandQueue(cl_ctx) - table = get_table(queue) +def test_get_table_2d_order1(table_2d_order1): + table = table_2d_order1 assert table.dim == 2 -def laplace_const_source_same_box(queue, q_order, dim=2): - nft = get_table(queue, q_order, dim) +def laplace_const_source_same_box(table_2d_order1, queue, q_order, dim=2): + if q_order == 1: + nft = table_2d_order1 + else: + nft = get_table(queue, q_order, dim) n_pairs = nft.n_pairs n_q_points = nft.n_q_points @@ -73,8 +86,12 @@ def laplace_const_source_same_box(queue, q_order, dim=2): return pot -def laplace_cons_source_neighbor_box(queue, q_order, case_id, dim=2): - nft = get_table(queue, q_order, dim) +def laplace_cons_source_neighbor_box( + table_2d_order1, queue, q_order, case_id, dim=2): + if q_order == 1: + nft = table_2d_order1 + else: + nft = get_table(queue, q_order, dim) n_pairs = nft.n_pairs n_q_points = nft.n_q_points @@ -91,15 +108,19 @@ def laplace_cons_source_neighbor_box(queue, q_order, case_id, dim=2): return pot -def test_lcssb_1(ctx_factory): +def test_lcssb_1(ctx_factory, table_2d_order1): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) - u = laplace_const_source_same_box(queue, 1) + u = laplace_const_source_same_box(table_2d_order1, queue, 1) assert len(u) == 1 -def interp_func(queue, q_order, coef, dim=2): - nft = get_table(queue, q_order, dim) +def interp_func(table_2d_order1, queue, q_order, coef, dim=2): + if q_order == 1: + nft = table_2d_order1 + else: + nft = get_table(queue, q_order, dim) + assert dim == 2 modes = [nft.get_mode(i) for i in range(nft.n_q_points)] @@ -114,7 +135,7 @@ def interp_func(queue, q_order, coef, dim=2): return func -def test_interp_func(longrun, ctx_factory): +def test_interp_func(longrun, ctx_factory, table_2d_order1): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) q_order = 3 @@ -123,7 +144,7 @@ def test_interp_func(longrun, ctx_factory): h = 0.1 xx = yy = np.arange(-1.0, 1.0, h) xi, yi = np.meshgrid(xx, yy) - func = interp_func(queue, q_order, coef) + func = interp_func(table_2d_order1, queue, q_order, coef) zi = func(xi, yi) @@ -142,10 +163,14 @@ def direct_quad(source_func, target_point, dim=2): return integral -def drive_test_direct_quad_same_box(queue, q_order, dim=2): - u = laplace_const_source_same_box(queue, q_order) - func = interp_func(queue, q_order, u) - nft = get_table(queue, q_order, dim) +def drive_test_direct_quad_same_box(table_2d_order1, queue, q_order, dim=2): + u = laplace_const_source_same_box(table_2d_order1, queue, q_order) + func = interp_func(table_2d_order1, queue, q_order, u) + + if q_order == 1: + nft = table_2d_order1 + else: + nft = get_table(queue, q_order, dim) def const_one_source_func(x, y): return 1 @@ -170,23 +195,21 @@ def drive_test_direct_quad_same_box(queue, q_order, dim=2): @pytest.mark.parametrize("q_order", [1, ]) -def test_direct_quad(q_order, ctx_factory): +def test_direct_quad(q_order, ctx_factory, table_2d_order1): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) - drive_test_direct_quad_same_box(queue, q_order) + drive_test_direct_quad_same_box(table_2d_order1, queue, q_order) @pytest.mark.parametrize("q_order", [2, 3, 4, 5]) -def test_direct_quad_longrun(longrun, ctx_factory, q_order): +def test_direct_quad_longrun(longrun, ctx_factory, q_order, table_2d_order1): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) - drive_test_direct_quad_same_box(queue, q_order) + drive_test_direct_quad_same_box(table_2d_order1, queue, q_order) -def test_case_ids(ctx_factory): - cl_ctx = ctx_factory() - queue = cl.CommandQueue(cl_ctx) - table = get_table(queue) +def test_case_ids(ctx_factory, table_2d_order1): + table = table_2d_order1 for i in range(len(table.interaction_case_vecs)): code = table.case_encode( table.interaction_case_vecs[i]) @@ -209,10 +232,8 @@ def get_target_point(case_id, target_id, table): return target_point -def test_get_neighbor_target_point(ctx_factory): - cl_ctx = ctx_factory() - queue = cl.CommandQueue(cl_ctx) - table = get_table(queue) +def test_get_neighbor_target_point(ctx_factory, table_2d_order1): + table = table_2d_order1 case_same_box = len(table.interaction_case_vecs) // 2 for cid in range(len(table.interaction_case_vecs)): if cid == case_same_box: @@ -223,8 +244,12 @@ def test_get_neighbor_target_point(ctx_factory): assert np.allclose(pt, pt2) -def laplace_const_source_neighbor_box(queue, q_order, case_id, dim=2): - nft = get_table(queue, q_order, dim) +def laplace_const_source_neighbor_box( + table_2d_order1, queue, q_order, case_id, dim=2): + if q_order == 1: + nft = table_2d_order1 + else: + nft = get_table(queue, q_order, dim) n_pairs = nft.n_pairs n_q_points = nft.n_q_points @@ -238,9 +263,14 @@ def laplace_const_source_neighbor_box(queue, q_order, case_id, dim=2): return pot -def drive_test_direct_quad_neighbor_box(queue, q_order, case_id, dim=2): - u = laplace_const_source_neighbor_box(queue, q_order, case_id) - nft = get_table(queue, q_order, dim) +def drive_test_direct_quad_neighbor_box( + table_2d_order1, queue, q_order, case_id, dim=2): + u = laplace_const_source_neighbor_box( + table_2d_order1, queue, q_order, case_id) + if q_order == 1: + nft = table_2d_order1 + else: + nft = get_table(queue, q_order, dim) def const_one_source_func(x, y): return 1 @@ -262,21 +292,24 @@ def drive_test_direct_quad_neighbor_box(queue, q_order, case_id, dim=2): @pytest.mark.parametrize("q_order", [1, ]) -def test_direct_quad_neighbor_box(ctx_factory, q_order): +def test_direct_quad_neighbor_box(ctx_factory, q_order, table_2d_order1): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) - table = get_table(queue) + table = table_2d_order1 for case_id in range(len(table.interaction_case_vecs)): - drive_test_direct_quad_neighbor_box(queue, q_order, case_id) + drive_test_direct_quad_neighbor_box( + table_2d_order1, queue, q_order, case_id) @pytest.mark.parametrize("q_order", [2, ]) -def test_direct_quad_neighbor_box_longrun(longrun, ctx_factory, q_order): +def test_direct_quad_neighbor_box_longrun( + longrun, ctx_factory, q_order, table_2d_order1): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) - table = get_table(queue) + table = table_2d_order1 for case_id in range(len(table.interaction_case_vecs)): - drive_test_direct_quad_neighbor_box(queue, q_order, case_id) + drive_test_direct_quad_neighbor_box( + table_2d_order1, queue, q_order, case_id) # fdm=marker:ft=pyopencl diff --git a/test/test_volume_fmm.py b/test/test_volume_fmm.py index 486432bef58b6b617852d1d0756fff629fa85065..df0ca1e6e520cde84165ae95fa323fd5eb9f4931 100644 --- a/test/test_volume_fmm.py +++ b/test/test_volume_fmm.py @@ -22,26 +22,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -# import volumential.volume_fmm as vfmm +import subprocess +import logging +import pytest import numpy as np import pyopencl as cl - -# import pyopencl.array -# import boxtree as bt -# import sumpy as sp -# import volumential as vm +import volumential.meshgen as mg from functools import partial -import logging - logger = logging.getLogger(__name__) -import volumential.meshgen as mg - -import pytest - # {{{ make sure context getter works @@ -103,8 +95,8 @@ def laplace_problem(ctx_factory): rratio_bot = 0.5 # bounding box - a = -1 - b = 1 + a = -1. + b = 1. m_order = 15 # multipole order @@ -123,7 +115,7 @@ def laplace_problem(ctx_factory): # {{{ generate quad points - mesh = mg.MeshGen2D(q_order, n_levels) + mesh = mg.MeshGen2D(q_order, n_levels, a, b) iloop = 0 while mesh.n_active_cells() < refined_n_cells: iloop += 1 @@ -211,7 +203,8 @@ def laplace_problem(ctx_factory): from volumential.table_manager import NearFieldInteractionTableManager - tm = NearFieldInteractionTableManager("../nft.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) # }}} End build near field potential table @@ -274,8 +267,8 @@ def laplace_problem(ctx_factory): @pytest.mark.skipif( - mg.provider != "meshgen_dealii", reason="Adaptive mesh module is not available" -) + mg.provider != "meshgen_dealii", + reason="Adaptive mesh module is not available") def test_volume_fmm_laplace(laplace_problem): trav, wrangler, source_vals, q_weights = laplace_problem @@ -283,12 +276,12 @@ def test_volume_fmm_laplace(laplace_problem): from volumential.volume_fmm import drive_volume_fmm direct_pot, = drive_volume_fmm( - trav, wrangler, source_vals * q_weights, source_vals, direct_evaluation=True - ) + trav, wrangler, source_vals * q_weights, + source_vals, direct_evaluation=True) fmm_pot, = drive_volume_fmm( - trav, wrangler, source_vals * q_weights, source_vals, direct_evaluation=False - ) + trav, wrangler, source_vals * q_weights, + source_vals, direct_evaluation=False) assert max(abs(direct_pot - fmm_pot)) < 1e-6 diff --git a/volumential/nearfield_potential_table.py b/volumential/nearfield_potential_table.py index d4a526d7be06fe0321eb584e878ffa5f59cf9e48..cb0bcbdaa74a257020fb2a6d60cc9bf4b04746bb 100644 --- a/volumential/nearfield_potential_table.py +++ b/volumential/nearfield_potential_table.py @@ -212,6 +212,7 @@ class NearFieldInteractionTable(object): source_box_extent=1, dtype=np.float64, inverse_droste=False, + progress_bar=True, **kwargs ): """ @@ -330,9 +331,11 @@ class NearFieldInteractionTable(object): total_evals = len(self.data) + self.n_q_points - from pytools import ProgressBar - - self.pb = ProgressBar("Building table:", total_evals) + if progress_bar: + from pytools import ProgressBar + self.pb = ProgressBar("Building table:", total_evals) + else: + self.pb = None self.is_built = False @@ -738,7 +741,8 @@ class NearFieldInteractionTable(object): else: pool = None - self.pb.draw() + if self.pb is not None: + self.pb.draw() self.build_normalizer_table(pool, pb=self.pb) self.has_normalizers = True @@ -750,18 +754,19 @@ class NearFieldInteractionTable(object): ] if 0: - # multiprocess disabled for py2 compatibility - # (also drops dependency on dill/multiprocess) + # multiprocess disabled to remove dependency on dill/multiprocess for entry_id, entry_val in pool.imap_unordered( self.compute_table_entry, invariant_entry_ids ): self.data[entry_id] = entry_val - self.pb.progress(1) + if self.pb is not None: + self.pb.progress(1) else: for entry_id in invariant_entry_ids: _, entry_val = self.compute_table_entry(entry_id) self.data[entry_id] = entry_val - self.pb.progress(1) + if self.pb is not None: + self.pb.progress(1) if 0: # Then complete the table via symmetry lookup @@ -771,7 +776,8 @@ class NearFieldInteractionTable(object): if centry_id == entry_id: continue self.data[entry_id] = self.data[centry_id] - self.pb.progress(1) + if self.pb is not None: + self.pb.progress(1) else: for entry_id in range(len(self.data)): _, centry_id = self.lookup_by_symmetry(entry_id) @@ -779,9 +785,11 @@ class NearFieldInteractionTable(object): if centry_id == entry_id: continue self.data[entry_id] = self.data[centry_id] - self.pb.progress(1) + if self.pb is not None: + self.pb.progress(1) - self.pb.finished() + if self.pb is not None: + self.pb.finished() for entry in self.data: assert not np.isnan(entry) diff --git a/volumential/tools.py b/volumential/tools.py index 6b24224c3fa917746b7a8d651a4287b92c604486..146c6e1f1d8d8ccb47ab6bba3a68b248956e60af 100644 --- a/volumential/tools.py +++ b/volumential/tools.py @@ -496,14 +496,13 @@ class DiscreteLegendreTransform(BoxSpecificMap): """ if filtering is None: - filter_multiplier = 1 + cl.array.zeros(queue, - self.degree**self.dim, np.float64) + filter_multiplier = 1 + cl.array.zeros( + queue, self.degree**self.dim, np.float64) elif isinstance(filtering, cl.array.Array): assert filtering.shape == (self.degree**self.dim,) filter_multiplier = filtering else: - raise RuntimeError("Invalid filtering argument: %s" - % str(filtering)) + raise RuntimeError(f"Invalid filtering argument: {str(filtering)}") knl = self.get_cached_optimized_kernel() @@ -528,6 +527,18 @@ class DiscreteLegendreTransform(BoxSpecificMap): # }}} End discrete Legendre transform +# {{{ inverse discrete Legendre transform + + +class InverseDiscreteLegendreTransform(BoxSpecificMap): + """ + Box-specific transform that maps box-local modal coefficients + to nodal values. Inverse of :class:`DiscreteLegendreTransform`. + """ + pass + +# }}} End inverse discrete Legendre transform + # }}} End box-specific maps # {{{ box-specific reductions