diff --git a/lbmpy/updatekernels.py b/lbmpy/updatekernels.py index 7431e91f13f91c3805a5b277d129fdaea3e5d4e2..8edb11b7e52069dec6c72e7138039b75c97b4d7a 100644 --- a/lbmpy/updatekernels.py +++ b/lbmpy/updatekernels.py @@ -1,5 +1,6 @@ import numpy as np import sympy as sp +import warnings from lbmpy.fieldaccess import StreamPullTwoFieldsAccessor from lbmpy.methods.abstractlbmethod import LbmCollisionRule @@ -54,13 +55,24 @@ def create_lbm_kernel(collision_rule, input_field, output_field, accessor): return result -def create_stream_pull_only_kernel(stencil, numpy_arr=None, src_field_name="src", dst_field_name="dst", - generic_layout='numpy', generic_field_type=np.float64): - """Creates a stream-pull kernel, without collision. +def create_stream_only_kernel(stencil, numpy_arr=None, src_field_name="src", dst_field_name="dst", + generic_layout='numpy', generic_field_type=np.float64, + accessor=StreamPullTwoFieldsAccessor()): + """Creates a stream kernel, without collision. - For parameters see function ``create_stream_pull_collide_kernel`` - """ + Args: + stencil: lattice Boltzmann stencil which is used + numpy_arr: numpy array which containes the pdf field data. If no numpy array is provided the symbolic field + accesses are created with 'Field.create_generic'. Otherwise 'Field.create_from_numpy_array' is used. + src_field_name: name of the source field. + dst_field_name: name of the destination field. + generic_layout: data layout. for example 'fzyx' of 'zyxf'. + generic_field_type: field data type. + accessor: Field accessor which is used to create the update rule. See 'fieldaccess.PdfFieldAccessor' + Returns: + AssignmentCollection of the stream only update rule + """ dim = len(stencil[0]) if numpy_arr is None: src = Field.create_generic(src_field_name, dim, index_shape=(len(stencil),), @@ -71,15 +83,27 @@ def create_stream_pull_only_kernel(stencil, numpy_arr=None, src_field_name="src" src = Field.create_from_numpy_array(src_field_name, numpy_arr, index_dimensions=1) dst = Field.create_from_numpy_array(dst_field_name, numpy_arr, index_dimensions=1) - accessor = StreamPullTwoFieldsAccessor() eqs = [Assignment(a, b) for a, b in zip(accessor.write(dst, stencil), accessor.read(src, stencil))] return AssignmentCollection(eqs, []) +def create_stream_pull_only_kernel(stencil, numpy_arr=None, src_field_name="src", dst_field_name="dst", + generic_layout='numpy', generic_field_type=np.float64): + """Creates a stream kernel with the pull scheme, without collision. + + For parameters see function ``create_stream_pull_collide_kernel`` + """ + warnings.warn("This function is depricated. Please use create_stream_only_kernel. If no PdfFieldAccessor is " + "provided to this function a standard StreamPullTwoFieldsAccessor is used ", DeprecationWarning) + return create_stream_only_kernel(stencil, numpy_arr=numpy_arr, src_field_name=src_field_name, + dst_field_name=dst_field_name, generic_layout=generic_layout, + generic_field_type=generic_field_type, accessor=StreamPullTwoFieldsAccessor()) + + def create_stream_pull_with_output_kernel(lb_method, src_field, dst_field, output): stencil = lb_method.stencil cqc = lb_method.conserved_quantity_computation - streamed = sp.symbols("streamed_:%d" % (len(stencil),)) + streamed = sp.symbols(f"streamed_:{len(stencil)}") accessor = StreamPullTwoFieldsAccessor() stream_assignments = [Assignment(a, b) for a, b in zip(streamed, accessor.read(src_field, stencil))] output_eq_collection = cqc.output_equations_from_pdfs(streamed, output) diff --git a/lbmpy_tests/phasefield/test_phasefield.py b/lbmpy_tests/phasefield/test_phasefield.py index d8970c8d7f9af64182f5ff339c97e9d38cdd050c..4844c7dc018e022418cb048422e1426f295d99b9 100644 --- a/lbmpy_tests/phasefield/test_phasefield.py +++ b/lbmpy_tests/phasefield/test_phasefield.py @@ -88,7 +88,7 @@ def test_neumann_angle(): sc.run(10000) angles = liquid_lens_neumann_angles(sc.concentration[:, :, :]) - assert sum(angles) == 360 + np.testing.assert_almost_equal(sum(angles), 360) analytic_angles = analytic_neumann_angles([0.01, 0.02, kappa3]) for ref, simulated in zip(analytic_angles, angles): diff --git a/lbmpy_tests/test_update_kernel.py b/lbmpy_tests/test_update_kernel.py new file mode 100644 index 0000000000000000000000000000000000000000..43b780ad34b1f16e082afbfd2b1ac58348b37368 --- /dev/null +++ b/lbmpy_tests/test_update_kernel.py @@ -0,0 +1,29 @@ +import pytest + +import pystencils as ps + +from lbmpy.stencils import get_stencil +from lbmpy.fieldaccess import StreamPullTwoFieldsAccessor, StreamPushTwoFieldsAccessor,\ + AAOddTimeStepAccessor, AAEvenTimeStepAccessor, EsoTwistOddTimeStepAccessor, EsoTwistEvenTimeStepAccessor +from lbmpy.updatekernels import create_stream_only_kernel + + +@pytest.mark.parametrize('accessor', [StreamPullTwoFieldsAccessor(), StreamPushTwoFieldsAccessor(), + AAOddTimeStepAccessor(), AAEvenTimeStepAccessor(), + EsoTwistOddTimeStepAccessor(), EsoTwistEvenTimeStepAccessor()]) +def test_stream_only_kernel(accessor): + domain_size = (4, 4) + stencil = get_stencil("D2Q9") + dh = ps.create_data_handling(domain_size, default_target='cpu') + + src = dh.add_array('src', values_per_cell=len(stencil)) + dh.fill('src', 0.0, ghost_layers=True) + + dst = dh.add_array_like('dst', 'src') + dh.fill('dst', 0.0, ghost_layers=True) + + pull = create_stream_only_kernel(stencil, None, src.name, dst.name, accessor=accessor) + + for i, eq in enumerate(pull.main_assignments): + assert eq.rhs.offsets == accessor.read(src, stencil)[i].offsets + assert eq.lhs.offsets == accessor.write(dst, stencil)[i].offsets \ No newline at end of file