diff --git a/.gitignore b/.gitignore index 8dbce496c638bb37ec237cae06713b9b85693771..3d736e113e2b7aeb636abe9677916725fbc1af89 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,7 @@ _local_tmp RELEASE-VERSION test-report pystencils/boundaries/createindexlistcython.c +pystencils/boundaries/createindexlistcython.*.so +pystencils_tests/tmp +pystencils_tests/kerncraft_inputs/.2d-5pt.c_kerncraft/ +pystencils_tests/kerncraft_inputs/.3d-7pt.c_kerncraft/ \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 46976b8100a67aa43024f8d1a7eb933e6ad51b70..9e7235709ad61f595cb3c191873075b31edd893b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -115,7 +115,7 @@ pycodegen-integration: image: i10git.cs.fau.de:5005/pycodegen/pycodegen/full stage: test when: manual - allow_failure: false + allow_failure: true script: - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@i10git.cs.fau.de/pycodegen/pycodegen.git - cd pycodegen @@ -142,7 +142,7 @@ pycodegen-integration: - cd ../pygrandchem - py.test -v -n $NUM_CORES . - cd ../walberla/build/ - - make CodegenJacobiCPU CodegenJacobiGPU CodegenPoissonCPU CodegenPoissonGPU MicroBenchmarkGpuLbm LbCodeGenerationExample UniformGridBenchmarkGPU_trt UniformGridBenchmarkGPU_entropic_kbc_n4 + - make CodegenJacobiCPU CodegenJacobiGPU CodegenPoissonCPU CodegenPoissonGPU MicroBenchmarkGpuLbm LbCodeGenerationExample UniformGridBenchmarkGPU_trt UniformGridBenchmarkGPU_entropic_kbc_n4 FluctuatingMRT - cd apps/benchmarks/UniformGridGPU - make -j $NUM_CORES - cd ../UniformGridGenerated @@ -173,6 +173,7 @@ build-documentation: script: - export PYTHONPATH=`pwd` - mkdir html_doc + - sphinx-build -b html doc html_doc - sphinx-build -W -b html doc html_doc tags: - docker diff --git a/MANIFEST.in b/MANIFEST.in index f32d4f3d17079502cccd556699d845504908e52a..5c16bb2001e59376e6a2a264cadec0f69c3c0b56 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,5 @@ include README.md include COPYING.txt include RELEASE-VERSION +global-include *.pyx +global-exclude boundaries/createindexlistcython.c diff --git a/conftest.py b/conftest.py index 58b088bac360c36ae32587b1b689d6a185f5fc5f..b7c535a591737e7821c5e016c62df85924ef6079 100644 --- a/conftest.py +++ b/conftest.py @@ -98,6 +98,10 @@ try: except ImportError: collect_ignore += [os.path.join(SCRIPT_FOLDER, "pystencils/datahandling/vtk.py")] +# TODO: Remove if Ubuntu 18.04 is no longer supported +if pytest_version < 50403: + collect_ignore += [os.path.join(SCRIPT_FOLDER, "pystencils_tests/test_jupyter_extensions.ipynb")] + collect_ignore += [os.path.join(SCRIPT_FOLDER, 'setup.py')] for root, sub_dirs, files in os.walk('.'): diff --git a/doc/conf.py b/doc/conf.py index de898facf492671b8290c1d0ff3e9ffb2ca605e0..00e4310320ab9534ce64fdadc55c1968398fe425 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -54,6 +54,7 @@ intersphinx_mapping = {'python': ('https://docs.python.org/3.6', None), } autodoc_member_order = 'bysource' +bibtex_bibfiles = ['sphinx/pystencils.bib'] project = 'pystencils' html_logo = "img/logo.png" diff --git a/doc/notebooks/03_tutorial_datahandling.ipynb b/doc/notebooks/03_tutorial_datahandling.ipynb index dfa0d2739dad5c45df2dc73b5ce135c2590fb557..522bf3e34253e82c75e1e2f46aa099b3b2cc42fc 100644 --- a/doc/notebooks/03_tutorial_datahandling.ipynb +++ b/doc/notebooks/03_tutorial_datahandling.ipynb @@ -200,14 +200,14 @@ { "data": { "text/html": [ - "<div class=\"highlight\"><pre><span></span><span class=\"n\">FUNC_PREFIX</span> <span class=\"kt\">void</span> <span class=\"nf\">kernel</span><span class=\"p\">(</span><span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">_data_dst</span><span class=\"p\">,</span> <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"k\">const</span> <span class=\"n\">_data_src</span><span class=\"p\">,</span> <span class=\"kt\">int64_t</span> <span class=\"k\">const</span> <span class=\"n\">_size_dst_0</span><span class=\"p\">,</span> <span class=\"kt\">int64_t</span> <span class=\"k\">const</span> <span class=\"n\">_size_dst_1</span><span class=\"p\">,</span> <span class=\"kt\">int64_t</span> <span class=\"k\">const</span> <span class=\"n\">_stride_dst_0</span><span class=\"p\">,</span> <span class=\"kt\">int64_t</span> <span class=\"k\">const</span> <span class=\"n\">_stride_dst_1</span><span class=\"p\">,</span> <span class=\"kt\">int64_t</span> <span class=\"k\">const</span> <span class=\"n\">_stride_src_0</span><span class=\"p\">,</span> <span class=\"kt\">int64_t</span> <span class=\"k\">const</span> <span class=\"n\">_stride_src_1</span><span class=\"p\">)</span>\n", + "<div class=\"highlight\"><pre><span></span><span class=\"n\">FUNC_PREFIX</span> <span class=\"kt\">void</span> <span class=\"nf\">kernel</span><span class=\"p\">(</span><span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">RESTRICT</span> <span class=\"n\">_data_dst</span><span class=\"p\">,</span> <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">RESTRICT</span> <span class=\"k\">const</span> <span class=\"n\">_data_src</span><span class=\"p\">,</span> <span class=\"kt\">int64_t</span> <span class=\"k\">const</span> <span class=\"n\">_size_dst_0</span><span class=\"p\">,</span> <span class=\"kt\">int64_t</span> <span class=\"k\">const</span> <span class=\"n\">_size_dst_1</span><span class=\"p\">,</span> <span class=\"kt\">int64_t</span> <span class=\"k\">const</span> <span class=\"n\">_stride_dst_0</span><span class=\"p\">,</span> <span class=\"kt\">int64_t</span> <span class=\"k\">const</span> <span class=\"n\">_stride_dst_1</span><span class=\"p\">,</span> <span class=\"kt\">int64_t</span> <span class=\"k\">const</span> <span class=\"n\">_stride_src_0</span><span class=\"p\">,</span> <span class=\"kt\">int64_t</span> <span class=\"k\">const</span> <span class=\"n\">_stride_src_1</span><span class=\"p\">)</span>\n", "<span class=\"p\">{</span>\n", " <span class=\"k\">for</span> <span class=\"p\">(</span><span class=\"kt\">int</span> <span class=\"n\">ctr_0</span> <span class=\"o\">=</span> <span class=\"mi\">1</span><span class=\"p\">;</span> <span class=\"n\">ctr_0</span> <span class=\"o\"><</span> <span class=\"n\">_size_dst_0</span> <span class=\"o\">-</span> <span class=\"mi\">1</span><span class=\"p\">;</span> <span class=\"n\">ctr_0</span> <span class=\"o\">+=</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n", " <span class=\"p\">{</span>\n", - " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">_data_dst_00</span> <span class=\"o\">=</span> <span class=\"n\">_data_dst</span> <span class=\"o\">+</span> <span class=\"n\">_stride_dst_0</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span><span class=\"p\">;</span>\n", - " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"k\">const</span> <span class=\"n\">_data_src_01</span> <span class=\"o\">=</span> <span class=\"n\">_data_src</span> <span class=\"o\">+</span> <span class=\"n\">_stride_src_0</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span> <span class=\"o\">+</span> <span class=\"n\">_stride_src_0</span><span class=\"p\">;</span>\n", - " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"k\">const</span> <span class=\"n\">_data_src_00</span> <span class=\"o\">=</span> <span class=\"n\">_data_src</span> <span class=\"o\">+</span> <span class=\"n\">_stride_src_0</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span><span class=\"p\">;</span>\n", - " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"k\">const</span> <span class=\"n\">_data_src_0m1</span> <span class=\"o\">=</span> <span class=\"n\">_data_src</span> <span class=\"o\">+</span> <span class=\"n\">_stride_src_0</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span> <span class=\"o\">-</span> <span class=\"n\">_stride_src_0</span><span class=\"p\">;</span>\n", + " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">RESTRICT</span> <span class=\"n\">_data_dst_00</span> <span class=\"o\">=</span> <span class=\"n\">_data_dst</span> <span class=\"o\">+</span> <span class=\"n\">_stride_dst_0</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span><span class=\"p\">;</span>\n", + " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">RESTRICT</span> <span class=\"n\">_data_src_01</span> <span class=\"o\">=</span> <span class=\"n\">_data_src</span> <span class=\"o\">+</span> <span class=\"n\">_stride_src_0</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span> <span class=\"o\">+</span> <span class=\"n\">_stride_src_0</span><span class=\"p\">;</span>\n", + " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">RESTRICT</span> <span class=\"n\">_data_src_00</span> <span class=\"o\">=</span> <span class=\"n\">_data_src</span> <span class=\"o\">+</span> <span class=\"n\">_stride_src_0</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span><span class=\"p\">;</span>\n", + " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">RESTRICT</span> <span class=\"n\">_data_src_0m1</span> <span class=\"o\">=</span> <span class=\"n\">_data_src</span> <span class=\"o\">+</span> <span class=\"n\">_stride_src_0</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span> <span class=\"o\">-</span> <span class=\"n\">_stride_src_0</span><span class=\"p\">;</span>\n", " <span class=\"k\">for</span> <span class=\"p\">(</span><span class=\"kt\">int</span> <span class=\"n\">ctr_1</span> <span class=\"o\">=</span> <span class=\"mi\">1</span><span class=\"p\">;</span> <span class=\"n\">ctr_1</span> <span class=\"o\"><</span> <span class=\"n\">_size_dst_1</span> <span class=\"o\">-</span> <span class=\"mi\">1</span><span class=\"p\">;</span> <span class=\"n\">ctr_1</span> <span class=\"o\">+=</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n", " <span class=\"p\">{</span>\n", " <span class=\"n\">_data_dst_00</span><span class=\"p\">[</span><span class=\"n\">_stride_dst_1</span><span class=\"o\">*</span><span class=\"n\">ctr_1</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"mf\">0.25</span><span class=\"o\">*</span><span class=\"n\">_data_src_00</span><span class=\"p\">[</span><span class=\"n\">_stride_src_1</span><span class=\"o\">*</span><span class=\"n\">ctr_1</span> <span class=\"o\">+</span> <span class=\"n\">_stride_src_1</span><span class=\"p\">]</span> <span class=\"o\">+</span> <span class=\"mf\">0.25</span><span class=\"o\">*</span><span class=\"n\">_data_src_00</span><span class=\"p\">[</span><span class=\"n\">_stride_src_1</span><span class=\"o\">*</span><span class=\"n\">ctr_1</span> <span class=\"o\">-</span> <span class=\"n\">_stride_src_1</span><span class=\"p\">]</span> <span class=\"o\">+</span> <span class=\"mf\">0.25</span><span class=\"o\">*</span><span class=\"n\">_data_src_01</span><span class=\"p\">[</span><span class=\"n\">_stride_src_1</span><span class=\"o\">*</span><span class=\"n\">ctr_1</span><span class=\"p\">]</span> <span class=\"o\">+</span> <span class=\"mf\">0.25</span><span class=\"o\">*</span><span class=\"n\">_data_src_0m1</span><span class=\"p\">[</span><span class=\"n\">_stride_src_1</span><span class=\"o\">*</span><span class=\"n\">ctr_1</span><span class=\"p\">];</span>\n", @@ -217,14 +217,14 @@ "</pre></div>\n" ], "text/plain": [ - "FUNC_PREFIX void kernel(double * _data_dst, double * const _data_src, int64_t const _size_dst_0, int64_t const _size_dst_1, int64_t const _stride_dst_0, int64_t const _stride_dst_1, int64_t const _stride_src_0, int64_t const _stride_src_1)\n", + "FUNC_PREFIX void kernel(double * RESTRICT _data_dst, double * RESTRICT const _data_src, int64_t const _size_dst_0, int64_t const _size_dst_1, int64_t const _stride_dst_0, int64_t const _stride_dst_1, int64_t const _stride_src_0, int64_t const _stride_src_1)\n", "{\n", " for (int ctr_0 = 1; ctr_0 < _size_dst_0 - 1; ctr_0 += 1)\n", " {\n", - " double * _data_dst_00 = _data_dst + _stride_dst_0*ctr_0;\n", - " double * const _data_src_01 = _data_src + _stride_src_0*ctr_0 + _stride_src_0;\n", - " double * const _data_src_00 = _data_src + _stride_src_0*ctr_0;\n", - " double * const _data_src_0m1 = _data_src + _stride_src_0*ctr_0 - _stride_src_0;\n", + " double * RESTRICT _data_dst_00 = _data_dst + _stride_dst_0*ctr_0;\n", + " double * RESTRICT _data_src_01 = _data_src + _stride_src_0*ctr_0 + _stride_src_0;\n", + " double * RESTRICT _data_src_00 = _data_src + _stride_src_0*ctr_0;\n", + " double * RESTRICT _data_src_0m1 = _data_src + _stride_src_0*ctr_0 - _stride_src_0;\n", " for (int ctr_1 = 1; ctr_1 < _size_dst_1 - 1; ctr_1 += 1)\n", " {\n", " _data_dst_00[_stride_dst_1*ctr_1] = 0.25*_data_src_00[_stride_src_1*ctr_1 + _stride_src_1] + 0.25*_data_src_00[_stride_src_1*ctr_1 - _stride_src_1] + 0.25*_data_src_01[_stride_src_1*ctr_1] + 0.25*_data_src_0m1[_stride_src_1*ctr_1];\n", @@ -233,9 +233,8 @@ "}" ] }, - "execution_count": 4, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" } ], "source": [ @@ -379,14 +378,14 @@ { "data": { "text/html": [ - "<div class=\"highlight\"><pre><span></span><span class=\"n\">FUNC_PREFIX</span> <span class=\"kt\">void</span> <span class=\"nf\">kernel</span><span class=\"p\">(</span><span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">_data_dst</span><span class=\"p\">,</span> <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"k\">const</span> <span class=\"n\">_data_src</span><span class=\"p\">)</span>\n", + "<div class=\"highlight\"><pre><span></span><span class=\"n\">FUNC_PREFIX</span> <span class=\"kt\">void</span> <span class=\"nf\">kernel</span><span class=\"p\">(</span><span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">RESTRICT</span> <span class=\"n\">_data_dst</span><span class=\"p\">,</span> <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">RESTRICT</span> <span class=\"k\">const</span> <span class=\"n\">_data_src</span><span class=\"p\">)</span>\n", "<span class=\"p\">{</span>\n", " <span class=\"k\">for</span> <span class=\"p\">(</span><span class=\"kt\">int</span> <span class=\"n\">ctr_0</span> <span class=\"o\">=</span> <span class=\"mi\">1</span><span class=\"p\">;</span> <span class=\"n\">ctr_0</span> <span class=\"o\"><</span> <span class=\"mi\">29</span><span class=\"p\">;</span> <span class=\"n\">ctr_0</span> <span class=\"o\">+=</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n", " <span class=\"p\">{</span>\n", - " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">_data_dst_00</span> <span class=\"o\">=</span> <span class=\"n\">_data_dst</span> <span class=\"o\">+</span> <span class=\"mi\">30</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span><span class=\"p\">;</span>\n", - " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"k\">const</span> <span class=\"n\">_data_src_01</span> <span class=\"o\">=</span> <span class=\"n\">_data_src</span> <span class=\"o\">+</span> <span class=\"mi\">30</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span> <span class=\"o\">+</span> <span class=\"mi\">30</span><span class=\"p\">;</span>\n", - " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"k\">const</span> <span class=\"n\">_data_src_00</span> <span class=\"o\">=</span> <span class=\"n\">_data_src</span> <span class=\"o\">+</span> <span class=\"mi\">30</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span><span class=\"p\">;</span>\n", - " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"k\">const</span> <span class=\"n\">_data_src_0m1</span> <span class=\"o\">=</span> <span class=\"n\">_data_src</span> <span class=\"o\">+</span> <span class=\"mi\">30</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span> <span class=\"o\">-</span> <span class=\"mi\">30</span><span class=\"p\">;</span>\n", + " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">RESTRICT</span> <span class=\"n\">_data_dst_00</span> <span class=\"o\">=</span> <span class=\"n\">_data_dst</span> <span class=\"o\">+</span> <span class=\"mi\">30</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span><span class=\"p\">;</span>\n", + " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">RESTRICT</span> <span class=\"n\">_data_src_01</span> <span class=\"o\">=</span> <span class=\"n\">_data_src</span> <span class=\"o\">+</span> <span class=\"mi\">30</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span> <span class=\"o\">+</span> <span class=\"mi\">30</span><span class=\"p\">;</span>\n", + " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">RESTRICT</span> <span class=\"n\">_data_src_00</span> <span class=\"o\">=</span> <span class=\"n\">_data_src</span> <span class=\"o\">+</span> <span class=\"mi\">30</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span><span class=\"p\">;</span>\n", + " <span class=\"kt\">double</span> <span class=\"o\">*</span> <span class=\"n\">RESTRICT</span> <span class=\"n\">_data_src_0m1</span> <span class=\"o\">=</span> <span class=\"n\">_data_src</span> <span class=\"o\">+</span> <span class=\"mi\">30</span><span class=\"o\">*</span><span class=\"n\">ctr_0</span> <span class=\"o\">-</span> <span class=\"mi\">30</span><span class=\"p\">;</span>\n", " <span class=\"k\">for</span> <span class=\"p\">(</span><span class=\"kt\">int</span> <span class=\"n\">ctr_1</span> <span class=\"o\">=</span> <span class=\"mi\">1</span><span class=\"p\">;</span> <span class=\"n\">ctr_1</span> <span class=\"o\"><</span> <span class=\"mi\">29</span><span class=\"p\">;</span> <span class=\"n\">ctr_1</span> <span class=\"o\">+=</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n", " <span class=\"p\">{</span>\n", " <span class=\"n\">_data_dst_00</span><span class=\"p\">[</span><span class=\"n\">ctr_1</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"mf\">0.25</span><span class=\"o\">*</span><span class=\"n\">_data_src_00</span><span class=\"p\">[</span><span class=\"n\">ctr_1</span> <span class=\"o\">+</span> <span class=\"mi\">1</span><span class=\"p\">]</span> <span class=\"o\">+</span> <span class=\"mf\">0.25</span><span class=\"o\">*</span><span class=\"n\">_data_src_00</span><span class=\"p\">[</span><span class=\"n\">ctr_1</span> <span class=\"o\">-</span> <span class=\"mi\">1</span><span class=\"p\">]</span> <span class=\"o\">+</span> <span class=\"mf\">0.25</span><span class=\"o\">*</span><span class=\"n\">_data_src_01</span><span class=\"p\">[</span><span class=\"n\">ctr_1</span><span class=\"p\">]</span> <span class=\"o\">+</span> <span class=\"mf\">0.25</span><span class=\"o\">*</span><span class=\"n\">_data_src_0m1</span><span class=\"p\">[</span><span class=\"n\">ctr_1</span><span class=\"p\">];</span>\n", @@ -396,14 +395,14 @@ "</pre></div>\n" ], "text/plain": [ - "FUNC_PREFIX void kernel(double * _data_dst, double * const _data_src)\n", + "FUNC_PREFIX void kernel(double * RESTRICT _data_dst, double * RESTRICT const _data_src)\n", "{\n", " for (int ctr_0 = 1; ctr_0 < 29; ctr_0 += 1)\n", " {\n", - " double * _data_dst_00 = _data_dst + 30*ctr_0;\n", - " double * const _data_src_01 = _data_src + 30*ctr_0 + 30;\n", - " double * const _data_src_00 = _data_src + 30*ctr_0;\n", - " double * const _data_src_0m1 = _data_src + 30*ctr_0 - 30;\n", + " double * RESTRICT _data_dst_00 = _data_dst + 30*ctr_0;\n", + " double * RESTRICT _data_src_01 = _data_src + 30*ctr_0 + 30;\n", + " double * RESTRICT _data_src_00 = _data_src + 30*ctr_0;\n", + " double * RESTRICT _data_src_0m1 = _data_src + 30*ctr_0 - 30;\n", " for (int ctr_1 = 1; ctr_1 < 29; ctr_1 += 1)\n", " {\n", " _data_dst_00[ctr_1] = 0.25*_data_src_00[ctr_1 + 1] + 0.25*_data_src_00[ctr_1 - 1] + 0.25*_data_src_01[ctr_1] + 0.25*_data_src_0m1[ctr_1];\n", @@ -412,9 +411,8 @@ "}" ] }, - "execution_count": 6, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" } ], "source": [ @@ -740,7 +738,7 @@ "outputs": [ { "data": { - "image/png": "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8sjzMAsAsAa7GYCl8M+iAAAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMEJwAgAAMOLItgdgM9554zXbHgF23hMfcOm2R4CdZIcB7C7PcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBCcAIAADBi7eCsqguq6g+r6q2TAwEA67GbATjszuYZzhckuW5qEADgrNnNABxqawVnVV2c5MlJXjE7DgCwDrsZgCVY9xnO30jy4iS3nOoGVXVFVR2rqmMnTpzYyHAAwCnZzQAcemcMzqp6SpKbuvv46W7X3Vd299HuPrq3t7exAQGA72Y3A7AU6zzDeVmSp1bVZ5O8Psnjqup3RqcCAE7HbgZgEc4YnN39ku6+uLsvSfLMJO/p7mePTwYAHMhuBmAp/DucAAAAjDhyNjfu7vcled/IJADAWbObATjMPMMJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADACMEJAADAiDMGZ1Xdtao+XFUfq6prq+ql52MwAOBgdjMAS3Fkjdt8K8njuvvrVXVhkg9U1X/u7g8OzwYAHMxuBmARzhic3d1Jvr768MLVW08OBQCcmt0MwFKs9RrOqrqgqq5JclOSq7v7Q7NjAQCn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\n", + "image/png": "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q+o/d/cHVzwbALA3uxmAjbRvYHZ3J/nK4sPzF2+9yqEAgJOzmwHYVEu9BrOqzquqa5PcmuTq7v7QascCAE7FbgZgEy0VmN19R3dfkuTCJE+oqu+66zFVdUVVHa2qo8ePH5+eEwA4gd0MwCY6rbvIdvdtSa5JcvkeP3dldx/p7iM7OztD4wEAp2I3A7BJlrmL7E5V3X/x/r2TPDnJJ1c9GACwN7sZgE21zF1kH5zkVVV1XnaD9PXd/dbVjgUAnILdDMBGWuYush9P8rhzMAsAsAS7GYBNdVqvwQQAAICTEZgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACMEJgAAACM2Dcwq+qhVfXeqrq+qq6rqheei8EAgL3ZzQBsqkNLHHN7khd190er6n5JjlXV1d39xyueDQDYm90MwEba9xnM7v7z7v7o4v0vJ7k+yQWrHgwA2JvdDMCmOq3XYFbV4SSPS/KhVQwDAJweuxmATbJ0YFbVfZO8McnPdveX9vj5K6rqaFUdPX78+OSMAMAe7GYANs1SgVlV52d3gb26u9+01zHdfWV3H+nuIzs7O5MzAgB3YTcDsImWuYtsJfmtJNd390tXPxIAcCp2MwCbaplnMC9N8vwkl1XVtYu3H1jxXADAydnNAGykfb9NSXe/P0mdg1kAgCXYzQBsqtO6iywAAACcjMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABghMAEAABg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\n", "text/plain": [ "<Figure size 1152x432 with 2 Axes>" ] @@ -864,9 +862,9 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAIUAAAAUBAMAAABRzuPpAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAImYQu82Z3XZU70SJMqtHo0JKAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB2ElEQVQ4EaWUPUgcURDHf7fvNud6e/GwsfQsbETIFQFFBD+w9qMJ2BxbHVaJVmITDosQUiSXNhC1EBvxo0uZLVRshK3SulhYKQqixCDqvDVnds+3hJAp9mb2N/PfeXOzC5kS/2OfdfFLffkB7uKB9p6aGRQ82O8NeF6Uiild9Ram6dNh0r6UUwC5ELuu5lCTYHlS1bKJtYIrYcLUyVnZCCTrQ0gP7EozkNMPb6+QDXEuEgo6eFFOAZnukHFYLjMAHTrVr9AWkr/WfsJEwwxcO+QWvtext3knNVaxwpBH/meiXgeiYQZddqiuRKOG6zEqmf1U6PQpGDWMQNXsMHMDhzWsSRZEw9caHgW52WTShxG4iIb0cejjzLIOTiAaQ/90lq+i8fsshXOtMYhoyOic66YuonmYgPJFQ890uY5oyFmWqtVfM9lhLPN/awDOcfXNWm0sekZ+NpopmHcsyjEtn/Tb2tgxmele1P8q0tBAoC6bTvNJdt0IaB0mV1cb8Mznm67auTti8P0pzEtNzF5vvSoZAe7EbUntfwzADh52/bHMSWo83icV0Cc76v1JlA9APIj7qUC/c4zEU/vjQdxPBfrdf/gGNdJLDaf5NxVki5KaScUC/25dcA8aXn5zNx258AAAAABJRU5ErkJggg==\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAGoAAAAVCAYAAACuVXuDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADhUlEQVRoBe2Z7W3bMBCGHaMDGO0G6gZJs0GygeNO0HiDFv1l/yvSDdpOUCQbJBsE9Qb2BnW8gfs+jE5lJUo2bIoS0BxwOvL4dXqPR1LUYLvdDnyezWaZn39J/4tPCjxCPhgOPJrP5x+VPfVUL8luEMhyXxSjnzBDIBWMJc4lPzlFzUPlOHIqOS1Xke4m1/2WfCu+kW5Vrhcrn9tyq/7OlN6E+k1tk9mQ23YwTmpP0Gwkv9OniyhlRkp/lmx0Eg1EAPPapbyH2v5S9pE+xF+Vpq97pTOv2tFJ9TcS34q/qbMf4tr+VSeJTTUvdRROsh0McTS+eXaUJJHAizeSGuHlCkl/LSUA3lmh0sxw8jv7tTb7SPoVX4mJ6J91bVSezKayDRo7Fk5g51Yp26Mm6tyFWHlQy6ucJQ/w4TJdSbEoK5V/FF+orZsVgfI2VZ3YFBOn3Cf4ZjTUg71pn33kfd4wBO6FlOtAgfVLeWrqyqbYOIHhhIi6FD80oSgHEcrBJQxvN7XNyyp72h5tDq7SlU0t4YRvLnHUO/GyDhUNnqmMfcGio1zVnBBaEq3uPs60ujFkcptaxAnfZDgKEEPLlgHGyaNx/7KKDfJNQ1lXRbFtagsnfOMcxewLRoMcxMkpuOR56DY52WY231UpKalNLePESjYiooKUhzJH7rolz7VTuTk5tLyZrrGPoAFHKFPalAAnF0ivhAezzwD14WFv4qaCDzefTpXhigP9SpIPWzY86pfJIqrxsFJuFCmfyqa2ccI3axzFbK+ALAfwohWApX9CL8l3ihFOs+sj0yHPxAvV3ZhSaaK0yJu+BZnEJr1LKzh5eDDZV0M9FuJzr2BXEg/DBclYDhtrSb7JHClNnYn4w7PG3Seie1IZVzsxyA4EFrlFnx3aZDYcjJN1kEs32U90pc5Sxt0Zl6i1pHIOFUSefbxyPcTdHndSA0kMI6o2Yg4POP+L9EyEgpS3T4Hai9Sick1CfdhyjC2MyxisDNwtFidUpZPZpLEdacwoOHn9gdfU/YuSs5Y4LMW/FsbQWGPxKNV4+4zTU5sy2bXEfpY+iEio/LZwJe08OKQQeX2iPtrEQe3vpWy+XHCSqxwqYiOpMViOUn9XNb5GT23CF/jELeUWUbwIp7hdH7fUO5auNbjb147tKGL7PtqEL4pVrvjDy0sLQLw47iGQmPffkPDnEvxOsrgo+AP8ixo954XzTQAAAABJRU5ErkJggg==\n", "text/latex": [ - "$$\\left ( 40, \\quad 10, \\quad 40\\right )$$" + "$\\displaystyle \\left( 40, \\ 10, \\ 40\\right)$" ], "text/plain": [ "(40, 10, 40)" @@ -924,7 +922,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "<Figure size 1152x432 with 1 Axes>" ] @@ -971,7 +969,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "<Figure size 1152x432 with 1 Axes>" ] @@ -1003,7 +1001,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.2" + "version": "3.8.2" } }, "nbformat": 4, diff --git a/doc/sphinx/pystencils.bib b/doc/sphinx/pystencils.bib new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/pystencils/alignedarray.py b/pystencils/alignedarray.py index 02a4f359956b109253e41a2c98a4c9020f4cd861..70271b0c0f3b50f04ceed671cabb16411554cdac 100644 --- a/pystencils/alignedarray.py +++ b/pystencils/alignedarray.py @@ -1,19 +1,32 @@ import numpy as np +from pystencils.data_types import BasicType -def aligned_empty(shape, byte_alignment=32, dtype=np.float64, byte_offset=0, order='C', align_inner_coordinate=True): +def aligned_empty(shape, byte_alignment=True, dtype=np.float64, byte_offset=0, order='C', align_inner_coordinate=True): """ Creates an aligned empty numpy array Args: shape: size of the array byte_alignment: alignment in bytes, for the start address of the array holds (a % byte_alignment) == 0 + By default, use the maximum required by the CPU (or 512 bits if this cannot be detected). dtype: numpy data type byte_offset: offset in bytes for position that should be aligned i.e. (a+byte_offset) % byte_alignment == 0 typically used to align first inner cell instead of ghost layer order: storage linearization order align_inner_coordinate: if True, the start of the innermost coordinate lines are aligned as well """ + if byte_alignment is True: + from pystencils.backends.simd_instruction_sets import (get_supported_instruction_sets, + get_vector_instruction_set) + + type_name = BasicType.numpy_name_to_c(np.dtype(dtype).name) + instruction_sets = get_supported_instruction_sets() + if instruction_sets is None: + byte_alignment = 64 + else: + byte_alignment = max([get_vector_instruction_set(type_name, is_name)['width'] * np.dtype(dtype).itemsize + for is_name in instruction_sets]) if (not align_inner_coordinate) or (not hasattr(shape, '__len__')): size = np.prod(shape) d = np.dtype(dtype) @@ -51,7 +64,7 @@ def aligned_empty(shape, byte_alignment=32, dtype=np.float64, byte_offset=0, ord return tmp -def aligned_zeros(shape, byte_alignment=16, dtype=float, byte_offset=0, order='C', align_inner_coordinate=True): +def aligned_zeros(shape, byte_alignment=True, dtype=float, byte_offset=0, order='C', align_inner_coordinate=True): arr = aligned_empty(shape, dtype=dtype, byte_offset=byte_offset, order=order, byte_alignment=byte_alignment, align_inner_coordinate=align_inner_coordinate) x = np.zeros((), arr.dtype) @@ -59,7 +72,7 @@ def aligned_zeros(shape, byte_alignment=16, dtype=float, byte_offset=0, order='C return arr -def aligned_ones(shape, byte_alignment=16, dtype=float, byte_offset=0, order='C', align_inner_coordinate=True): +def aligned_ones(shape, byte_alignment=True, dtype=float, byte_offset=0, order='C', align_inner_coordinate=True): arr = aligned_empty(shape, dtype=dtype, byte_offset=byte_offset, order=order, byte_alignment=byte_alignment, align_inner_coordinate=align_inner_coordinate) x = np.ones((), arr.dtype) diff --git a/pystencils/assignment.py b/pystencils/assignment.py index d56d0f4d6d1421463cef4d9cc921d3d309e571cb..4e51cd4a7bfeefab253872f034b97cd4c2b48eb8 100644 --- a/pystencils/assignment.py +++ b/pystencils/assignment.py @@ -1,12 +1,8 @@ import numpy as np import sympy as sp +from sympy.codegen.ast import Assignment from sympy.printing.latex import LatexPrinter -try: - from sympy.codegen.ast import Assignment -except ImportError: - Assignment = None - __all__ = ['Assignment', 'assignment_from_stencil'] @@ -21,43 +17,22 @@ def assignment_str(assignment): return r"{lhs} ← {rhs}".format(lhs=assignment.lhs, rhs=assignment.rhs) -if Assignment: - - _old_new = sp.codegen.ast.Assignment.__new__ - - def _Assignment__new__(cls, lhs, rhs, *args, **kwargs): - if isinstance(lhs, (list, tuple, sp.Matrix)) and isinstance(rhs, (list, tuple, sp.Matrix)): - assert len(lhs) == len(rhs), f'{lhs} and {rhs} must have same length when performing vector assignment!' - return tuple(_old_new(cls, a, b, *args, **kwargs) for a, b in zip(lhs, rhs)) - return _old_new(cls, lhs, rhs, *args, **kwargs) - - Assignment.__str__ = assignment_str - Assignment.__new__ = _Assignment__new__ - LatexPrinter._print_Assignment = print_assignment_latex +_old_new = sp.codegen.ast.Assignment.__new__ - sp.MutableDenseMatrix.__hash__ = lambda self: hash(tuple(self)) -else: - # back port for older sympy versions that don't have Assignment yet +def _Assignment__new__(cls, lhs, rhs, *args, **kwargs): + if isinstance(lhs, (list, tuple, sp.Matrix)) and isinstance(rhs, (list, tuple, sp.Matrix)): + assert len(lhs) == len(rhs), f'{lhs} and {rhs} must have same length when performing vector assignment!' + return tuple(_old_new(cls, a, b, *args, **kwargs) for a, b in zip(lhs, rhs)) + return _old_new(cls, lhs, rhs, *args, **kwargs) - class Assignment(sp.Rel): # pragma: no cover - rel_op = ':=' - __slots__ = [] +Assignment.__str__ = assignment_str +Assignment.__new__ = _Assignment__new__ +LatexPrinter._print_Assignment = print_assignment_latex - def __new__(cls, lhs, rhs=0, **assumptions): - from sympy.matrices.expressions.matexpr import ( - MatrixElement, MatrixSymbol) - lhs = sp.sympify(lhs) - rhs = sp.sympify(rhs) - # Tuple of things that can be on the lhs of an assignment - assignable = (sp.Symbol, MatrixSymbol, MatrixElement, sp.Indexed) - if not isinstance(lhs, assignable): - raise TypeError(f"Cannot assign to lhs of type {type(lhs)}.") - return sp.Rel.__new__(cls, lhs, rhs, **assumptions) +sp.MutableDenseMatrix.__hash__ = lambda self: hash(tuple(self)) - __str__ = assignment_str - _print_Assignment = print_assignment_latex # Apparently, in SymPy 1.4 Assignment.__hash__ is not implemented. This has been fixed in current master try: diff --git a/pystencils/astnodes.py b/pystencils/astnodes.py index 58a438717931539a07ffe066ff7f5f8421b1f14a..b874db9b0c2f869131fa4986714aa172b8bfafdc 100644 --- a/pystencils/astnodes.py +++ b/pystencils/astnodes.py @@ -37,8 +37,12 @@ class Node: def subs(self, subs_dict) -> None: """Inplace! Substitute, similar to sympy's but modifies the AST inplace.""" - for a in self.args: - a.subs(subs_dict) + for i, a in enumerate(self.args): + result = a.subs(subs_dict) + if isinstance(a, sp.Expr): # sympy expressions' subs is out-of-place + self.args[i] = result + else: # all other should be in-place + assert result is None @property def func(self): diff --git a/pystencils/backends/cbackend.py b/pystencils/backends/cbackend.py index adbef3b06eaea4ef1c0fff8431a09c2ae4e34d1a..27d6480124ee8b64d6caac19bac65aed20e57d84 100644 --- a/pystencils/backends/cbackend.py +++ b/pystencils/backends/cbackend.py @@ -18,12 +18,9 @@ from pystencils.integer_functions import ( int_div, int_power_of_2, modulo_ceil) try: - from sympy.printing.ccode import C99CodePrinter as CCodePrinter + from sympy.printing.c import C99CodePrinter as CCodePrinter # for sympy versions > 1.6 except ImportError: - try: - from sympy.printing.ccode import CCodePrinter # for sympy versions < 1.1 - except ImportError: - from sympy.printing.c import C11CodePrinter as CCodePrinter # for sympy versions > 1.6 + from sympy.printing.ccode import C99CodePrinter as CCodePrinter __all__ = ['generate_c', 'CustomCodeNode', 'PrintNode', 'get_headers', 'CustomSympyPrinter'] diff --git a/pystencils/boundaries/boundaryhandling.py b/pystencils/boundaries/boundaryhandling.py index 81d9766a746984f5d43d4de55586ce8108d4b22d..a1d23a372d1a623d8b78a5972cc7a8457fb84063 100644 --- a/pystencils/boundaries/boundaryhandling.py +++ b/pystencils/boundaries/boundaryhandling.py @@ -312,7 +312,7 @@ class BoundaryHandling: def _create_boundary_kernel(self, symbolic_field, symbolic_index_field, boundary_obj): return create_boundary_kernel(symbolic_field, symbolic_index_field, self.stencil, boundary_obj, - target=self._target, openmp=self._openmp) + target=self._target, cpu_openmp=self._openmp) def _create_index_fields(self): dh = self._data_handling @@ -442,11 +442,10 @@ class BoundaryOffsetInfo(CustomCodeNode): INV_DIR_SYMBOL = TypedSymbol("invdir", "int") -def create_boundary_kernel(field, index_field, stencil, boundary_functor, target='cpu', openmp=True, - **kernel_creation_args): +def create_boundary_kernel(field, index_field, stencil, boundary_functor, target='cpu', **kernel_creation_args): elements = [BoundaryOffsetInfo(stencil)] index_arr_dtype = index_field.dtype.numpy_dtype dir_symbol = TypedSymbol("dir", index_arr_dtype.fields['dir'][0]) elements += [Assignment(dir_symbol, index_field[0]('dir'))] elements += boundary_functor(field, direction_symbol=dir_symbol, index_field=index_field) - return create_indexed_kernel(elements, [index_field], target=target, cpu_openmp=openmp, **kernel_creation_args) + return create_indexed_kernel(elements, [index_field], target=target, **kernel_creation_args) diff --git a/pystencils/datahandling/blockiteration.py b/pystencils/datahandling/blockiteration.py index fdf2b97e8f677db586e28c61ca66c08f9426c708..bd981dc318cd855c496b70eef5e6bb847c24f2b5 100644 --- a/pystencils/datahandling/blockiteration.py +++ b/pystencils/datahandling/blockiteration.py @@ -111,15 +111,15 @@ class ParallelBlock(Block): def __getitem__(self, data_name): result = self._block[self._name_prefix + data_name] type_name = type(result).__name__ - if type_name == 'GhostLayerField': - result = wlb.field.toArray(result, withGhostLayers=self._gls) + if 'GhostLayerField' in type_name: + result = wlb.field.toArray(result, with_ghost_layers=self._gls) result = self._normalize_array_shape(result) - elif type_name == 'GpuField': - result = wlb.cuda.toGpuArray(result, withGhostLayers=self._gls) + elif 'GpuField' in type_name: + result = wlb.cuda.toGpuArray(result, with_ghost_layers=self._gls) result = self._normalize_array_shape(result) return result def _normalize_array_shape(self, arr): - if arr.shape[-1] == 1: + if arr.shape[-1] == 1 and len(arr.shape) == 4: arr = arr[..., 0] return arr[self._localSlice] diff --git a/pystencils/datahandling/parallel_datahandling.py b/pystencils/datahandling/parallel_datahandling.py index 4d3fcdf7a68aeaaebbdf5fd2618432b9c0d455cc..82d5b4cb61bca1f2c4d89469f82aea0db9835888 100644 --- a/pystencils/datahandling/parallel_datahandling.py +++ b/pystencils/datahandling/parallel_datahandling.py @@ -101,7 +101,7 @@ class ParallelDataHandling(DataHandling): raise ValueError("Data handling expects that each process has at least one block") if hasattr(dtype, 'type'): dtype = dtype.type - if name in self.blocks[0] or self.GPU_DATA_PREFIX + name in self.blocks[0]: + if name in self.blocks[0].fieldNames or self.GPU_DATA_PREFIX + name in self.blocks[0].fieldNames: raise ValueError("Data with this name has already been added") if alignment is False or alignment is None: @@ -215,15 +215,13 @@ class ParallelDataHandling(DataHandling): array = array[:, :, 0] if last_element and self.fields[name].index_dimensions > 0: array = array[..., last_element[0]] - if self.fields[name].index_dimensions == 0: - array = array[..., 0] return array def _normalize_arr_shape(self, arr, index_dimensions): - if index_dimensions == 0: + if index_dimensions == 0 and len(arr.shape) > 3: arr = arr[..., 0] - if self.dim == 2: + if self.dim == 2 and len(arr.shape) > 2: arr = arr[:, :, 0] return arr @@ -246,7 +244,7 @@ class ParallelDataHandling(DataHandling): for block in self.blocks: field_args = {} for data_name, f in data_used_in_kernel: - arr = to_array(block[data_name], withGhostLayers=[True, True, self.dim == 3]) + arr = to_array(block[data_name], with_ghost_layers=[True, True, self.dim == 3]) arr = self._normalize_arr_shape(arr, f.index_dimensions) field_args[f.name] = arr field_args.update(kwargs) diff --git a/pystencils/datahandling/serial_datahandling.py b/pystencils/datahandling/serial_datahandling.py index ce4629f6ab7f35c96cec437ab76b778dfec83e04..9e18acf4a240932bcdb0aad80a899cbe6d411a3f 100644 --- a/pystencils/datahandling/serial_datahandling.py +++ b/pystencils/datahandling/serial_datahandling.py @@ -271,7 +271,7 @@ class SerialDataHandling(DataHandling): def synchronization_function_gpu(self, names, stencil_name=None, **_): return self.synchronization_function(names, stencil_name, target='gpu') - def synchronization_function(self, names, stencil=None, target=None, **_): + def synchronization_function(self, names, stencil=None, target=None, functor=None, **_): if target is None: target = self.default_target if target == 'opencl': @@ -311,19 +311,22 @@ class SerialDataHandling(DataHandling): if len(filtered_stencil) > 0: if target == 'cpu': - from pystencils.slicing import get_periodic_boundary_functor - result.append(get_periodic_boundary_functor(filtered_stencil, ghost_layers=gls)) + if functor is None: + from pystencils.slicing import get_periodic_boundary_functor + functor = get_periodic_boundary_functor + result.append(functor(filtered_stencil, ghost_layers=gls)) else: - from pystencils.gpucuda.periodicity import get_periodic_boundary_functor as boundary_func - target = 'gpu' if not isinstance(self.array_handler, PyOpenClArrayHandler) else 'opencl' - result.append(boundary_func(filtered_stencil, self._domainSize, - index_dimensions=self.fields[name].index_dimensions, - index_dim_shape=values_per_cell, - dtype=self.fields[name].dtype.numpy_dtype, - ghost_layers=gls, - target=target, - opencl_queue=self._opencl_queue, - opencl_ctx=self._opencl_ctx)) + if functor is None: + from pystencils.gpucuda.periodicity import get_periodic_boundary_functor as functor + target = 'gpu' if not isinstance(self.array_handler, PyOpenClArrayHandler) else 'opencl' + result.append(functor(filtered_stencil, self._domainSize, + index_dimensions=self.fields[name].index_dimensions, + index_dim_shape=values_per_cell, + dtype=self.fields[name].dtype.numpy_dtype, + ghost_layers=gls, + target=target, + opencl_queue=self._opencl_queue, + opencl_ctx=self._opencl_ctx)) if target == 'cpu': def result_functor(): diff --git a/pystencils/interpolation_astnodes.py b/pystencils/interpolation_astnodes.py index c230d0115bf858213e3071986abb70ed86d23f96..a694cb8eac864fdcea59fced498f72619bbdfec1 100644 --- a/pystencils/interpolation_astnodes.py +++ b/pystencils/interpolation_astnodes.py @@ -352,7 +352,7 @@ class InterpolatorAccess(TypedSymbol): __xnew_cached_ = staticmethod(cacheit(__new_stage2__)) def __getnewargs__(self): - return tuple(self.symbol, *self.offsets) + return (self.symbol, *self.offsets) class DiffInterpolatorAccess(InterpolatorAccess): @@ -397,7 +397,7 @@ class DiffInterpolatorAccess(InterpolatorAccess): __xnew_cached_ = staticmethod(cacheit(__new_stage2__)) def __getnewargs__(self): - return tuple(self.symbol, self.diff_coordinate_idx, *self.offsets) + return (self.symbol, self.diff_coordinate_idx, *self.offsets) ########################################################################################## diff --git a/pystencils/kerncraft_coupling/kerncraft_interface.py b/pystencils/kerncraft_coupling/kerncraft_interface.py index 2d0859f7e78b113077189960cab0404b373a1cda..c0dc5888f579955bbff5092b7c0fd73b71c05176 100644 --- a/pystencils/kerncraft_coupling/kerncraft_interface.py +++ b/pystencils/kerncraft_coupling/kerncraft_interface.py @@ -342,7 +342,7 @@ class PyStencilsKerncraftKernel(KernelCode): class KerncraftParameters(DotDict): def __init__(self, **kwargs): - super(KerncraftParameters, self).__init__(**kwargs) + super(KerncraftParameters, self).__init__() self['asm_block'] = 'auto' self['asm_increment'] = 0 self['cores'] = 1 @@ -353,6 +353,7 @@ class KerncraftParameters(DotDict): self['unit'] = 'cy/CL' self['ignore_warnings'] = True self['incore_model'] = 'OSACA' + self.update(**kwargs) # ------------------------------------------- Helper functions --------------------------------------------------------- diff --git a/pystencils/rng.py b/pystencils/rng.py index bbc28bbd2c7d98cf931149d7e5572cda7fa33442..f567e0c1b77b6e07d9107825364b9227cf17b26a 100644 --- a/pystencils/rng.py +++ b/pystencils/rng.py @@ -19,12 +19,9 @@ def _get_rng_template(name, data_type, num_vars): return template -def _get_rng_code(template, dialect, vector_instruction_set, time_step, offsets, keys, dim, result_symbols): - parameters = [time_step] + [LoopOverCoordinate.get_loop_counter_symbol(i) + offsets[i] - for i in range(dim)] + [0] * (3 - dim) + list(keys) - +def _get_rng_code(template, dialect, vector_instruction_set, args, result_symbols): if dialect == 'cuda' or (dialect == 'c' and vector_instruction_set is None): - return template.format(parameters=', '.join(str(p) for p in parameters), + return template.format(parameters=', '.join(str(a) for a in args), result_symbols=result_symbols) else: raise NotImplementedError("Not yet implemented for this backend") @@ -32,42 +29,38 @@ def _get_rng_code(template, dialect, vector_instruction_set, time_step, offsets, class RNGBase(CustomCodeNode): - def __init__(self, dim, time_step=TypedSymbol("time_step", np.uint32), offsets=(0, 0, 0), keys=None): + id = 0 + + def __init__(self, dim, time_step=TypedSymbol("time_step", np.uint32), offsets=None, keys=None): if keys is None: keys = (0,) * self._num_keys + if offsets is None: + offsets = (0,) * dim if len(keys) != self._num_keys: raise ValueError(f"Provided {len(keys)} keys but need {self._num_keys}") - if len(offsets) != 3: - raise ValueError(f"Provided {len(offsets)} offsets but need {3}") - self.result_symbols = tuple(TypedSymbol(sp.Dummy().name, self._data_type) for _ in range(self._num_vars)) - symbols_read = [s for s in keys if isinstance(s, sp.Symbol)] + if len(offsets) != dim: + raise ValueError(f"Provided {len(offsets)} offsets but need {dim}") + coordinates = [LoopOverCoordinate.get_loop_counter_symbol(i) + offsets[i] for i in range(dim)] + if dim < 3: + coordinates.append(0) + + self._args = sp.sympify([time_step, *coordinates, *keys]) + self.result_symbols = tuple(TypedSymbol(f'random_{self.id}_{i}', self._data_type) + for i in range(self._num_vars)) + symbols_read = set.union(*[s.atoms(sp.Symbol) for s in self.args]) super().__init__("", symbols_read=symbols_read, symbols_defined=self.result_symbols) - self._time_step = time_step - self._offsets = offsets + self.headers = [f'"{self._name}_rand.h"'] - self.keys = tuple(keys) - self._args = sp.sympify((dim, time_step, keys)) - self._dim = dim + + RNGBase.id += 1 @property def args(self): return self._args - @property - def undefined_symbols(self): - result = {a for a in (self._time_step, *self._offsets, *self.keys) if isinstance(a, sp.Symbol)} - loop_counters = [LoopOverCoordinate.get_loop_counter_symbol(i) - for i in range(self._dim)] - result.update(loop_counters) - return result - - def fast_subs(self, *_): - return self # nothing to replace inside this node - would destroy intermediate "dummy" by re-creating them - def get_code(self, dialect, vector_instruction_set): template = _get_rng_template(self._name, self._data_type, self._num_vars) - return _get_rng_code(template, dialect, vector_instruction_set, - self._time_step, self._offsets, self.keys, self._dim, self.result_symbols) + return _get_rng_code(template, dialect, vector_instruction_set, self.args, self.result_symbols) def __repr__(self): return (", ".join(['{}'] * self._num_vars) + " \\leftarrow {}RNG").format(*self.result_symbols, diff --git a/pystencils/sympyextensions.py b/pystencils/sympyextensions.py index 072bb19ae6fe0ba7f719c0ab636e1a9ffd3d7eed..ce23f4541b46444f55b4d87ee89590bc519586a6 100644 --- a/pystencils/sympyextensions.py +++ b/pystencils/sympyextensions.py @@ -10,7 +10,7 @@ from sympy.functions import Abs from sympy.core.numbers import Zero from pystencils.assignment import Assignment -from pystencils.data_types import cast_func, get_type_of_expression, PointerType +from pystencils.data_types import cast_func, get_type_of_expression, PointerType, VectorType from pystencils.kernelparameters import FieldPointerSymbol T = TypeVar('T') @@ -465,6 +465,8 @@ def count_operations(term: Union[sp.Expr, List[sp.Expr]], base_type = get_type_of_expression(e) except ValueError: return False + if isinstance(base_type, VectorType): + return False if isinstance(base_type, PointerType): return only_type == 'int' if only_type == 'int' and (base_type.is_int() or base_type.is_uint()): diff --git a/pystencils_tests/test_astnodes.py b/pystencils_tests/test_astnodes.py index 98c755efd4d5b57e0b33f47ffe5d7fb2e11df573..1d66eae29f1ec4edd7af48813979abb6a9fd1087 100644 --- a/pystencils_tests/test_astnodes.py +++ b/pystencils_tests/test_astnodes.py @@ -1,9 +1,15 @@ +import pytest import sympy as sp -import pystencils as ps +import pystencils as ps from pystencils import Assignment -from pystencils.astnodes import Block, SkipIteration, LoopOverCoordinate, SympyAssignment -from sympy.codegen.rewriting import optims_c99 +from pystencils.astnodes import Block, LoopOverCoordinate, SkipIteration, SympyAssignment + +sympy_numeric_version = [int(x, 10) for x in sp.__version__.split('.')] +if len(sympy_numeric_version) < 3: + sympy_numeric_version.append(0) +sympy_numeric_version.reverse() +sympy_version = sum(x * (100 ** i) for i, x in enumerate(sympy_numeric_version)) dst = ps.fields('dst(8): double[2D]') s = sp.symbols('s_:8') @@ -11,6 +17,8 @@ x = sp.symbols('x') y = sp.symbols('y') +@pytest.mark.skipif(sympy_version < 10501, + reason="Old Sympy Versions behave differently which wont be supported in the near future") def test_kernel_function(): assignments = [ Assignment(dst[0, 0](0), s[0]), @@ -36,6 +44,8 @@ def test_skip_iteration(): assert skipped.undefined_symbols == set() +@pytest.mark.skipif(sympy_version < 10501, + reason="Old Sympy Versions behave differently which wont be supported in the near future") def test_block(): assignments = [ Assignment(dst[0, 0](0), s[0]), @@ -83,7 +93,8 @@ def test_loop_over_coordinate(): def test_sympy_assignment(): - + pytest.importorskip('sympy.codegen.rewriting') + from sympy.codegen.rewriting import optims_c99 assignment = SympyAssignment(dst[0, 0](0), sp.log(x + 3) / sp.log(2) + sp.log(x ** 2 + 1)) assignment.optimize(optims_c99) diff --git a/pystencils_tests/test_basic_usage_llvm.ipynb b/pystencils_tests/test_basic_usage_llvm.ipynb index 30ba23683d4253135603382679dec5c4a511f25c..4976b4b08e56887f02a9f6bb2ad4cdd61e4d7b9a 100644 --- a/pystencils_tests/test_basic_usage_llvm.ipynb +++ b/pystencils_tests/test_basic_usage_llvm.ipynb @@ -390,7 +390,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.8.5" } }, "nbformat": 4, diff --git a/pystencils_tests/test_jupyter_extensions.ipynb b/pystencils_tests/test_jupyter_extensions.ipynb index da8d178905bd56e20424741c0b434b7941626285..a34a1bd4f040865a9051b505a5eb454b5b5a0d83 100644 --- a/pystencils_tests/test_jupyter_extensions.ipynb +++ b/pystencils_tests/test_jupyter_extensions.ipynb @@ -39,7 +39,7 @@ { "data": { "text/plain": [ - "<matplotlib.image.AxesImage at 0x7ff5b00707c0>" + "<matplotlib.image.AxesImage at 0x7f5fa4f1cdc0>" ] }, "execution_count": 4, @@ -48,9 +48,9 @@ }, { "data": { - "image/png": "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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA6gAAAFpCAYAAACRagUQAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvAOZPmwAAFJxJREFUeJzt3W+MZfV93/HPN+CStE5ULBZKdnGXRhspEDVYWSFLPKF1VIgbBbsS1VLVRaol0gpLtmSpBeeB0wdIlto4VdvYEqmRqeqabmVbRqnThFBXVqTEeHGpzR8Tr4xj1lDY1K1MVYkU+PbBHMKUzO4sOzue7977ekmje+/vnHPnN/rNXXjrnnumujsAAACw135orycAAAAAiUAFAABgCIEKAADACAIVAACAEQQqAAAAIwhUAAAARhCoAAAAjCBQAQAAGEGgAgAAMIJABQAAYIQL93oCSXLJJZf0wYMH93oawDr4v4/u9QwgSfKHX/vzez0F+FM/+bN/Za+nAKy4hx9++I+7e992+40I1IMHD+bYsWN7PQ1gDbzy3w/t9RQgSXLDj1+z11OAP/XAsf+w11MAVlxV/dGZ7OcUXwAAAEYQqAAAAIwgUAEAABhh20Ctqiuq6otV9URVPVZV71/Gf6WqvltVjyxf79x0zJ1VdbyqnqyqG3bzBwAAAGA1nMlFkl5K8sHu/mpV/WiSh6vqgWXbr3X3P9u8c1VdleRIkquT/HiS362qn+zul8/lxAEAAFgt276D2t3PdvdXl/svJHkiyf7THHJTkvu6+8XufirJ8STXnovJAgAAsLre0GdQq+pgkrcl+fIy9L6q+lpV3VNVFy9j+5M8vemwEzl90AIAAMCZB2pVvTnJZ5J8oLu/n+TjSX4iyTVJnk3yq6/uusXhvcXz3VZVx6rq2MmTJ9/wxAEAAFgtZxSoVfWmbMTpp7r7s0nS3c9198vd/UqS38hrp/GeSHLFpsMPJHnm9c/Z3Xd39+HuPrxv376d/AwAAACsgDO5im8l+USSJ7r7o5vGL9+027uTPLrcvz/Jkaq6qKquTHIoyUPnbsoAAACsojO5iu91Sd6T5OtV9cgy9qEkt1TVNdk4fffbSX4pSbr7sao6muTxbFwB+HZX8AUAAGA72wZqd/9etv5c6RdOc8xdSe7awbwAAABYM2/oKr4AAACwWwQqAAAAIwhUAAAARhCoAAAAjCBQAQAAGEGgAgAAMIJABQAAYASBCgAAwAgCFQAAgBEEKgAAACMIVAAAAEYQqAAAAIwgUAEAABhBoAIAADCCQAUAAGAEgQoAAMAIAhUAAIARBCoAAAAjCFQAAABGEKgAAACMIFABAAAYQaACAAAwgkAFAABgBIEKAADACAIVAACAEQQqAAAAIwhUAAAARhCoAAAAjCBQAQAAGEGgAgAAMIJABQAAYASBCgAAwAgCFQAAgBEEKgAAACMIVAAAAEYQqAAAAIwgUAEAABhBoAIAADCCQAUAAGAEgQoAAMAIAhUAAIARBCoAAAAjCFQAAABGEKgAAACMIFABAAAYQaACAAAwgkAFAABgBIEKAADACAIVAACAEQQqAAAAIwhUAAAARhCoAAAAjCBQAQAAGEGgAgAAMMK2gVpVV1TVF6vqiap6rKrev4y/paoeqKpvLrcXbzrmzqo6XlVPVtUNu/kDAAAAsBrO5B3Ul5J8sLt/Ksnbk9xeVVcluSPJg919KMmDy+Ms244kuTrJjUk+VlUX7MbkAQAAWB3bBmp3P9vdX13uv5DkiST7k9yU5N5lt3uTvGu5f1OS+7r7xe5+KsnxJNee64kDAACwWt7QZ1Cr6mCStyX5cpLLuvvZZCNik1y67LY/ydObDjuxjAEAAMApnXGgVtWbk3wmyQe6+/un23WLsd7i+W6rqmNVdezkyZNnOg0AAABW1BkFalW9KRtx+qnu/uwy/FxVXb5svzzJ88v4iSRXbDr8QJJnXv+c3X13dx/u7sP79u072/kDAACwIs7kKr6V5BNJnujuj27adH+SW5f7tyb5/KbxI1V1UVVdmeRQkofO3ZQBAABYRReewT7XJXlPkq9X1SPL2IeSfCTJ0ap6b5LvJLk5Sbr7sao6muTxbFwB+PbufvmczxwAAICVsm2gdvfvZevPlSbJO05xzF1J7trBvAAAAFgzb+gqvgAAALBbBCoAAAAjCFQAAABGEKgAAACMIFABAAAYQaACAAAwgkAFAABgBIEKAADACAIVAACAEQQqAAAAIwhUAAAARhCoAAAAjCBQAQAAGEGgAgAAMIJABQAAYASBCgAAwAgCFQAAgBEEKgAAACMIVAAAAEYQqAAAAIwgUAEAABhBoAIAADCCQAUAAGAEgQoAAMAIAhUAAIARBCoAAAAjCFQAAABGEKgAAACMIFABAAAYQaACAAAwgkAFAABgBIEKAADACAIVAACAEQQqAAAAIwhUAAAARhCoAAAAjCBQAQAAGEGgAgAAMIJABQAAYASBCgAAwAgCFQAAgBEEKgAAACMIVAAAAEYQqAAAAIwgUAEAABhBoAIAADCCQAUAAGAEgQoAAMAIAhUAAIARBCoAAAAjCFQAAABGEKgAAACMIFABAAAYQaACAAAwgkAFAABghG0Dtaruqarnq+rRTWO/UlXfrapHlq93btp2Z1Udr6onq+qG3Zo4AAAAq+VM3kH9ZJIbtxj/te6+Zvn6QpJU1VVJjiS5ejnmY1V1wbmaLAAAAKtr20Dt7i8l+d4ZPt9NSe7r7he7+6kkx5Ncu4P5AQAAsCZ28hnU91XV15ZTgC9exvYneXrTPieWMQAAADitsw3Ujyf5iSTXJHk2ya8u47XFvr3VE1TVbVV1rKqOnTx58iynAQAAwKo4q0Dt7ue6++XufiXJb+S103hPJLli064Hkjxziue4u7sPd/fhffv2nc00AAAAWCFnFahVdfmmh+9O8uoVfu9PcqSqLqqqK5McSvLQzqYIAADAOrhwux2q6tNJrk9ySVWdSPLhJNdX1TXZOH3320l+KUm6+7GqOprk8SQvJbm9u1/enakDAACwSrYN1O6+ZYvhT5xm/7uS3LWTSQEAALB+dnIVXwAAADhnBCoAAAAjCFQAAABGEKgAAACMIFABAAAYQaACAAAwgkAFAABgBIEKAADACAIVAACAEQQqAAAAIwhUAAAARhCoAAAAjCBQAQAAGEGgAgAAMIJABQAAYASBCgAAwAgCFQAAgBEEKgAAACMIVAAAAEYQqAAAAIwgUAEAABhBoAIAADCCQAUAAGAEgQoAAMAIAhUAAIARBCoAAAAjCFQAAABGEKgAAACMIFABAAAYQaACAAAwgkAFAABgBIEKAADACAIVAACAEQQqAAAAIwhUAAAARhCoAAAAjCBQAQAAGEGgAgAAMIJABQAAYASBCgAAwAgCFQAAgBEEKgAAACMIVAAAAEYQqAAAAIwgUAEAABhBoAIAADCCQAUAAGAEgQoAAMAIAhUAAIARBCoAAAAjCFQAAABGEKgAAACMIFABAAAYQaACAAAwwraBWlX3VNXzVfXoprG3VNUDVfXN5fbiTdvurKrjVfVkVd2wWxMHAABgtZzJO6ifTHLj68buSPJgdx9K8uDyOFV1VZIjSa5ejvlYVV1wzmYLAADAyto2ULv7S0m+97rhm5Lcu9y/N8m7No3f190vdvdTSY4nufYczRUAAIAVdrafQb2su59NkuX20mV8f5KnN+13YhkDAACA0zrXF0mqLcZ6yx2rbquqY1V17OTJk+d4GgAAAJxvzjZQn6uqy5NkuX1+GT+R5IpN+x1I8sxWT9Ddd3f34e4+vG/fvrOcBgAAAKvibAP1/iS3LvdvTfL5TeNHquqiqroyyaEkD+1sigAAAKyDC7fboao+neT6JJdU1YkkH07ykSRHq+q9Sb6T5OYk6e7HqupokseTvJTk9u5+eZfmDgAAwArZNlC7+5ZTbHrHKfa/K8ldO5kUAAAA6+dcXyQJAAAAzopABQAAYASBCgAAwAgCFQAAgBEEKgAAACMIVAAAAEYQqAAAAIwgUAEAABhBoAIAADCCQAUAAGAEgQoAAMAIAhUAAIARBCoAAAAjCFQAAABGEKgAAACMIFABAAAYQaACAAAwgkAFAABgBIEKAADACAIVAACAEQQqAAAAIwhUAAAARhCoAAAAjCBQAQAAGEGgAgAAMIJABQAAYASBCgAAwAgCFQAAgBEEKgAAACMIVAAAAEYQqAAAAIwgUAEAABhBoAIAADCCQAUAAGAEgQoAAMAIAhUAAIARBCoAAAAjCFQAAABGEKgAAACMIFABAAAYQaACAAAwgkAFAABgBIEKAADACAIVAACAEQQqAAAAIwhUAAAARhCoAAAAjCBQAQAAGEGgAgAAMIJABQAAYASBCgAAwAgCFQAAgBEEKgAAACMIVAAAAEa4cCcHV9W3k7yQ5OUkL3X34ap6S5J/n+Rgkm8n+dvd/T93Nk0AAABW3bl4B/Wvdfc13X14eXxHkge7+1CSB5fHAAAAcFq7cYrvTUnuXe7fm+Rdu/A9AAAAWDE7DdRO8jtV9XBV3baMXdbdzybJcnvpDr8HAAAAa2BHn0FNcl13P1NVlyZ5oKq+caYHLkF7W5K89a1v3eE0AAAAON/t6B3U7n5muX0+yeeSXJvkuaq6PEmW2+dPcezd3X24uw/v27dvJ9MAAABgBZx1oFbVX6iqH331fpK/keTRJPcnuXXZ7dYkn9/pJAEAAFh9OznF97Ikn6uqV5/n33X3f6qqryQ5WlXvTfKdJDfvfJoAAACsurMO1O7+VpKf2WL8fyR5x04mBQAAwPrZjT8zAwAAAG+YQAUAAGAEgQoAAMAIAhUAAIARBCoAAAAjCFQAAABGEKgAAACMIFABAAAYQaACAAAwgkAFAABgBIEKAADACAIVAACAEQQqAAAAIwhUAAAARhCoAAAAjCBQAQAAGEGgAgAAMIJABQAAYASBCgAAwAgCFQAAgBEEKgAAACMIVAAAAEYQqAAAAIwgUAEAABhBoAIAADCCQAUAAGAEgQoAAMAIAhUAAIARBCoAAAAjCFQAAABGEKgAAACMIFABAAAYQaACAAAwgkAFAABgBIEKAADACAIVAACAEQQqAAAAIwhUAAAARhCoAAAAjCBQAQAAGEGgAgAAMIJABQAAYASBCgAAwAgCFQAAgBEEKgAAACMIVAAAAEYQqAAAAIwgUAEAABhBoAIAADCCQAUAAGAEgQoAAMAIAhUAAIARBCoAAAAjCFQAAABG2LVAraobq+rJqjpeVXfs1vcBAABgNexKoFbVBUl+PcnPJ7kqyS1VddVufC8AAABWw269g3ptkuPd/a3u/pMk9yW5aZe+FwAAACtgtwJ1f5KnNz0+sYwBAADAlnYrUGuLsf7/dqi6raqOVdWxkydP7tI0AAAAOF9cuEvPeyLJFZseH0jyzOYduvvuJHcnSVWdrKo/2qW5bOeSJH+8R9+bvWXt15N1X1/D1v74Xk9gXQxb95mqtnpv4bxn7deTdZ/rL5/JTtXd2+/1BlXVhUn+MMk7knw3yVeS/J3ufuycf7Mdqqpj3X14r+fBD561X0/WfX1Z+/Vk3deXtV9P1v38tyvvoHb3S1X1viS/neSCJPdMjFMAAADm2K1TfNPdX0jyhd16fgAAAFbLbl0k6Xxy915PgD1j7deTdV9f1n49Wff1Ze3Xk3U/z+3KZ1ABAADgjfIOKgAAACOsVaBW1T+tqm9U1deq6nNV9Rc3bbuzqo5X1ZNVdcOm8Z+tqq8v2/5Freh12FdZVd1cVY9V1StVdfh126z7GqmqG5e1Pl5Vd+z1fDh3quqeqnq+qh7dNPaWqnqgqr653F68aduWr33OL1V1RVV9saqeWP6df/8ybu1XXFX9cFU9VFX/bVn7f7KMW/s1UFUXVNV/rarfXB5b9xWyVoGa5IEkP93dfzUbfwbnziSpqquSHElydZIbk3ysqi5Yjvl4ktuSHFq+bvxBT5odezTJ30rypc2D1n29LGv760l+PslVSW5ZfgdYDZ/Mn32d3pHkwe4+lOTB5fF2r33OLy8l+WB3/1SStye5fVlfa7/6Xkzy17v7Z5Jck+TGqnp7rP26eH+SJzY9tu4rZK0Ctbt/p7tfWh7+QZIDy/2bktzX3S9291PZ+Ovp11bV5Ul+rLt/vzc+rPtvkrzrBz5xdqS7n+juJ7fYZN3Xy7VJjnf3t7r7T5Lcl43fAVZAd38pyfdeN3xTknuX+/fmtdfxlq/9H8hEOae6+9nu/upy/4Vs/A/r/lj7ldcb/vfy8E3LV8far7yqOpDkbyb515uGrfsKWatAfZ2/n+S3lvv7kzy9aduJZWz/cv/146wG675eTrXerK7LuvvZZCNkkly6jPtdWEFVdTDJ25J8OdZ+LSyneT6S5PkkD3S3tV8P/zzJP0ryyqYx675Cdu3voO6VqvrdJH9pi02/3N2fX/b55WycFvSpVw/bYv8+zTjDnMm6b3XYFmPWfXVZV17ld2HFVNWbk3wmyQe6+/unuWyAtV8h3f1ykmuWa4p8rqp++jS7W/sVUFW/kOT57n64qq4/k0O2GLPuw61coHb3z51ue1XdmuQXkryjX/sbOyeSXLFptwNJnlnGD2wxzjDbrfspWPf1cqr1ZnU9V1WXd/ezy6n7zy/jfhdWSFW9KRtx+qnu/uwybO3XSHf/r6r6L9n4jKG1X23XJfnFqnpnkh9O8mNV9W9j3VfKWp3iW1U3JvnHSX6xu//Ppk33JzlSVRdV1ZXZuCjOQ8spAi9U1duXq7j+vSSnejeO8491Xy9fSXKoqq6sqj+XjYsm3L/Hc2J33Z/k1uX+rXntdbzla38P5scOLf9GfyLJE9390U2brP2Kq6p9yzunqaofSfJzSb4Ra7/SuvvO7j7Q3Qez8d/x/9zdfzfWfaWs3Duo2/hXSS5K8sBy+s8fdPc/6O7Hqupoksezcerv7ctpI0nyD7NxdcgfycZnVn/rzzwro1XVu5P8yyT7kvzHqnqku2+w7uulu1+qqvcl+e0kFyS5p7sf2+NpcY5U1aeTXJ/kkqo6keTDST6S5GhVvTfJd5LcnCTbvPY5v1yX5D1Jvr58FjFJPhRrvw4uT3LvckXWH0pytLt/s6p+P9Z+HXnNr5B67SxXAAAA2DtrdYovAAAAcwlUAAAARhCoAAAAjCBQAQAAGEGgAgAAMIJABQAAYASBCgAAwAgCFQAAgBH+H8tny+i9QoiXAAAAAElFTkSuQmCC\n", "text/plain": [ - "<Figure size 1152x432 with 1 Axes>" + "<matplotlib.figure.Figure at 0x7f5fa4f425b0>" ] }, "metadata": { @@ -114,7 +114,7 @@ "data": { "text/html": [ "<video controls width=\"80%\">\n", - " <source src=\"data:video/x-m4v;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAAG7ptZGF0AAACcgYF//9u3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2MCByMzAxMSBjZGU5YTkzIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAyMCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTAgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTEzIGxvb2thaGVhZF90aHJlYWRzPTIgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50ZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MCB3ZWlnaHRwPTAga2V5aW50PTI1MCBrZXlpbnRfbWluPTI1IHNjZW5lY3V0PTQwIGludHJhX3JlZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAuNjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAOrGWIhAvyYoAAqcScnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/jpjbGB7AAzGAv7sCipqrccEuOuIt9wAQv19XnkMpGlotPm4GczKBOwyaRQEfbjkIzAXIjSREc//2ziZbN/UzdeETcuEXwGTTXk02oxGpWgc6S67htGL9CBekqo/X9B3HgDmoP/f+ceQBarBL+ZXP9oApPT4HbR3wS/wYCzUhqYDZhE+OOUh99X0hW1mMGaeH/8J8ABkkSBohw/FnngsMbX9xCvvvvvvvvvvvvvvv8f+HgsE4Cjp/jaBACYDCwrG0AVtB8IgdLCBIQUcc8YNbW1tbW18f4fQbH5CVedRSS22/+4+HhwMYQEAAQD8y9cICFNYNwdAWiHcQ6Ku50Ixi1tbW1tbW18f4fQbDOONHfzltvSS/8fDoOBLBZkwHEM8lucISAQ5cCEAeRtKWCCMcj4QDAB/oNgnwcTD0t3xAPQgQMiAcPLDg4eX4MuWUuX7Xx+AfsFYawIHG1W5BCoGcBoAX8mYqjmeQAjl3MJWNspK5uIV99999999999999/j7/DhQTwAI4v2wAECXNli4J6h+uuuuuuuuuuuuu+8NQTKoJxQDfffffffffffffffTBIp4IRQNHbW1tbW1rp5iRQACc89ra2tra2trXT0y10wRC7gjvvvvvvvvvvvvvvvrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp6euuuuuunp666666666enrp666666666666666666666666666666666666666666666666666enrrrrrrp6euuuuuuuunp66euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuv/HTEWSMD2ABmMBf3YFFTVVR01FmVSu1wAQv19XnkMpGlotPm4Gc2mBzagwiE0SX77TQmZgPkwsRXv+/0GQ0YX86mXeP/dRwobpwi+BRLtbXf7/BeISU9BJ0k11HsbmAJ/Q5/r3Vh2FgDmyh7vrTEEydhW/crm+0AKTnpeLRySFvBgLNSGpgNmET445SH31fSFbWYwZoO1/+/9Q/XXXXXXXXXXXXXXXT09ddddddPT1111111109PXT111111111111111111111111111111133+uuuuuuuuuuuuuuuuunp6666666enrrrrrrrrp6eunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp6euuuuuunp666666666enrp666666666666666666666666666666666666666666666666666enrrrrrrp6euuuuuuuunp66euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuv/HHAw2HuAAz3E2SM4hL8aBofMpMNdk05TYgdM1HOOsbocABMnENF+XJ0UYZ0HZwlzlpclJL2iwm0IhC8pS+3Do4KeXMLTXH6A5fF/Tm8gsc9ERLgBWNkHaxOojivmneEHiFcJ7criCogc8z8a0eGsdL/95wwywRiM3px9qsAFzBB0zWuQh98H47//f9Q/XXXXXXXXXXXXXXXT09ddddddPT1111111109PXT111111111111111111111111111111133+uuuuuuuuuuuuuuuuunp6666666enrrrrrrrrp6eunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp6euuuuuunp666666666enrp666666666666666666666666666666666666666666666666666enrrrrrrp6euuuuuuuunp66euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuv/HHCB2HuAAz3E2SM4hL8aBofMpMNdk00FFKQVMZHCJOv/Q4ACZOIaL8uToowy5oAAy0FYg6tFhNoRCF5Sl9tbxC+RKcqjZ/93X+5fF8IKNBIW90H/3gArGyDtYnURxX2x4ABmB/HGxXEFRA55f41Fhbocf/e+GGWCMRm9OPtVgAuYIOma1yEPvg/Hf/7/qH6666666666666666enrrrrrrp6euuuuuuuunp66euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu+/1111111111111111109PXXXXXXT09ddddddddPT109ddddddddddddddddddddddddddddddddddddddddddddddddddPT11111109PXXXXXXXXT09dPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT09ddddddPT1111111109PXT1111111111111111111111111111111//9OFA5wAH2BII3/bz8KKNeaHBWfj3dyZvdKwGEXFxzEqfbq+ELjwi/xENxXu7t8i4ncCqOcORXxdQ9TgiL8yGCuq2IDf/842AAIAQsnEIOrSQjYjEhJnL/7tA65zBFT8cNnN/7wAXMCBUzWuQh99/rqHa666666666666666enrrrrrrp6euuuuuuuunp66euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu+/1111111111111111109PXXXXXXT09ddddddddPT109ddddddddddddddddddddddddddddddddddddddddddddddddddPT11111109PXXXXXXXXT09dPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT09ddddddPT1111111109PXT11111111111111111111111111111111/fSEFyxYewCR+vYEAO+moM2jrG+9xhFKdbvreLYU6+zwYMGicVtpb01Wc153BGwYZMVjkoffB/D/AIBwQQEUOYDwvlNES50MP/wDALQQ4ACbINJO7InbrkESoGMqeu84fEf8a1r7TW+++++//xh7QqJS8ABNkGk3dkRW65BEqBjKnpvOfffffff+HGMAtBdAQ+udwAzI0Ri6kVHf7mIxnXcVLgU2i4OECQgBolQnOgPRIwhMfh0ISYtf/GH0Co9/6CQR1+i0eRfYTCz6fWsej/8mk3JpN/hx6AgQXBYACb8yp4Tv4xBDslr46NWRuBotWB0ZZZ3cmk06vla2totrC6OHct/pJaSW3KZKZyGSGTrePRgAIZum09J//gAZBfIpmyIOTZkG0UxnnQ234ceAcFwSBD7sHEEIy9KoOIAmCaBKctrtSPJrN/4AEA0C0EoOORy3xqhAKLLoyD0ZwcOMg4cZa4fwDANgtCwCG01Wrn4QmRAC4AGdftiMv4weHB9vv/8foMEMABJmEl2d0VSZzzloCNUDmVPn1v77777774/AAhhujMjyI//wAHmYSWZ3RVbB0QP0gd2UlBz33333/wx/CCHAA1YI5zGOcS7n376h+uuuuuuuuuuuuuu+v+rF4vxQewAEx+KUG+qzCF8T67ZNWnpwAPHQRFbYitH8sMaJR1SXVur33GQKrY5Uw1bv/91De2oXv+DMjAAECj7y1mdoa7/e+/3CfA9/cBTxlEYz1se6p3cSQHRVJShzGa3//KVj1Xu19TewNj/2k6UaQ3/9d8QiWk1D//dvxAg5BZXfddvE4kzHN+b/3/Xx38t/62/7h8UAAzfffff9wMMIAfYegA1uc5J+7wDgAHgI8TLWOMQboiTOve/AfOmYRbHTHEk3hsmxWFfqqRzBJeQQhBXWrA7FeYDRtO1taHUDslHLl9dY0xKlMUrDe1/1fTuuXieAkp8hCmRlFf/7sCAGsXmUEXx1WF/86F2Kxbt64+kpsUtl13251fHO9//vvt+bbN8VQcSJRWykMNw+KAAZvvvvv/Zg+ZaCgcAAcZIJn4160IQQJ/+4EjqQ0OxJinnnEVuixfjbLIHPI3ojqwDuZMtG7fvLNjUtiv7b9/kQdAAG1pa6WlpfgC8MH0wQAANnE0O5YlZekcNzFG6FsNkGNMeQ3juYolSwrJH5JtoFZZNKh/+8xoHLN9H6N/+mg7ds87v77AAhFrI5i6p+2W2WjbbBh+qiTIohK6LnFC8pI1++D/DDh/QTKAp4TXOclrCSMm8CxZWOav5+fzEdPJB1z/8/7QdtbW1vteLM6hQdX0wQAANuRoOz5qR+OC4lo1aHpZF38fkrek+DU99rGVs52/95DeKpiiRaiJ1eSbaBWWTSof/vNaByzfP0lv9bQdu2rzm/v9XMjF6zui99/VZNaMRO3h7glDRIiDp//74oXlI1/95/4fh/hMoCnhNc5yWsJIybwcWVjmr+fn6xHTyDr//9v/Mg6KANIktLS119YF0fVewQAAuWBiJvFahZu0D6AZCUJtNHF3IBGk1ifciqy4GtWnHWv5/X5//MbV2MQS7aVlN8Yk0dji6ikYqcTBST+xujf/VCFloG8ZdoZLDHH5LdV78zNmPv+3aB75xdWe5/uyUS5lX5hP+/6h+X+Ez6BJx85TXIV5cf3vlQ7PLWf+//1/mZjvX//8/6huuuuuvqwKOgbr2CAABZiJYV7VQgYvBMCNEFa2kJ7+/sWRABwwpUzH62EQbu6Jk3d785Q24ioTavQ+P/9gmYziLRznULb75mQ7EoG8pm49H9g/531NuCGpy9+bU37jZ0Nyq7fWqNEkGfPff8/5S/DxwRxeBOP0Jk3z70EXaB/h1Dddddddddddddddddddddddd9ddddddd9dddddd9dddddddddddddddd9dddddd99dddddd9ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddeAAAAT5BmjgX4D5gLigomOBmnCi/MJQPu5MEAwAP6BWCPAdSctjgSIABGQHscsPY5fgwJ5ZQJ5fiICS8DRFA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\" type=\"video/mp4\">\n", + " <source src=\"data:video/x-m4v;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAAGY9tZGF0AAACcgYF//9u3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2MCByMzAxMSBjZGU5YTkzIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAyMCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTAgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTEzIGxvb2thaGVhZF90aHJlYWRzPTIgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50ZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MCB3ZWlnaHRwPTAga2V5aW50PTI1MCBrZXlpbnRfbWluPTI1IHNjZW5lY3V0PTQwIGludHJhX3JlZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAuNjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAOjWWIhAvyYoAAqcScnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/jpjbGB7AAzGAv7sCipqrccEuOuIt9wAQv19XnkMpGlotPm4GczKBOwyaRQEfbjkIzAXIjSREc//2ziZbN/UzdeETcuEXwGTTXk02oxGpWgc6S67htGL9CBekqo/X9B3HgDmoP/f+ceQBarBL+ZXP9oApPT4HbR3wS/wYCzUhqYDZhE+OOUh99X0hW1mMGaeH/8J8ABkkSBohw/FnngsMbX9xCvvvvvvvvvvvvvvv8f+HgsE4Cjp/jaBACYDCwrG0AVtB8IgdLCBIQUcc8YNbW1tbW1wgGAB/QKwjjDRnUSaTcpkpn4BiH/BYGsLgACAj7CCFNYDJAOgLRDuIdEO7Qhpra2tra2tr4//0CsN7B0TptvPp9/8fhoOBLgOCcXpbOECwQlgC8w+QmlLBBmP4/D+gVglwejFLY4JOiAaSWHBpJfkNENbXx+AfsFYawIHG1W5BCoGcBoAX8mYqjmeQAjl3MJWNspK5uIV99999999999999/j7/DhQTwAI4v2wAECXNli4J6h+uuuuuuuuuuuuu+8NQTKoJxQDfffffffffffffffTBIp4IRQNHbW1tbW1rp5ujgAEaWlpaWlpaWunplrpgiF3BHfffffffffffffffXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT09ddddddPT1111111109PXT1111111111111111111111111111111111111111111111111109PXXXXXXT09ddddddddPT109ddddddddddddddddddddddddddddddf+OmIskYHsADMYC/uwKKmqqjpqLMqldrgAhfr6vPIZSNLRafNwM5tMDm1BhEJokv32mhMzAfJhYivf9/oMhowv51Mu8f+6jhQ3ThF8CiXa2u/3+C8Qkp6CTpJrqPY3MAT+hz/XurDsLAHNlD3fWmIJk7Ct+5XN9oAUnPS8WjkkLeDAWakNTAbMInxxykPvq+kK2sxgzQdr/9/6h+uuuuuuuuuuuuuuunp6666666enrrrrrrrrp6eunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrvv9dddddddddddddddddPT11111109PXXXXXXXXT09dPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT09ddddddPT1111111109PXT1111111111111111111111111111111111111111111111111109PXXXXXXT09ddddddddPT109ddddddddddddddddddddddddddddddf+OOBhsPcABnuJskZxCX40DQ+ZSYa7JpymxA6ZqOcdY3Q4ACZOIaL8uToowzoOzhLnLS5KSXtFhNoRCF5Sl9uHRwU8uYWmuP0By+L+nN5BY56IiXACsbIO1idRHFfNO8IPEK4T25XEFRA55n41o8NY6X/7zhhlgjEZvTj7VYALmCDpmtchD74Px3/+/6h+uuuuuuuuuuuuuuunp6666666enrrrrrrrrp6eunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrvv9dddddddddddddddddPT11111109PXXXXXXXXT09dPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT09ddddddPT1111111109PXT1111111111111111111111111111111111111111111111111109PXXXXXXT09ddddddddPT109ddddddddddddddddddddddddddddddf+OOEDsPcABnuJskZxCX40DQ+ZSYa7JpoKKUgqYyOESdf+hwAEycQ0X5cnRRhlzQABloKxB1aLCbQiELylL7a3iF8iU5VGz/7uv9y+L4QUaCQt7oP/vABWNkHaxOojivtjwADMD+ONiuIKiBzy/xqLC3Q4/+98MMsEYjN6cfarABcwQdM1rkIffB+O//3/UP11111111111111109PXXXXXXT09ddddddddPT109ddddddddddddddddddddddddddddddd9/rrrrrrrrrrrrrrrrrp6euuuuuunp666666666enrp666666666666666666666666666666666666666666666666666enrrrrrrp6euuuuuuuunp66euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunp6666666enrrrrrrrrp6eunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr//6cKBzgAPsCQRv+3n4UUa80OCs/Hu7kze6VgMIuLjmJU+3V8IXHhF/iIbivd3b5FxO4FUc4civi6h6nBEX5kMFdVsQG//5xsAAQAhZOIQdWkhGxGJCTOX/3aB1zmCKn44bOb/3gAuYECpmtchD77/XUO11111111111111109PXXXXXXT09ddddddddPT109ddddddddddddddddddddddddddddddd9/rrrrrrrrrrrrrrrrrp6euuuuuunp666666666enrp666666666666666666666666666666666666666666666666666enrrrrrrp6euuuuuuuunp66euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunp6666666enrrrrrrrrp6eunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr++kILliw9gEj9ewIAd9NQZtHWN97jCKU63fW8Wwp19ngwYNE4rbS3pqs5rzuCNgwyYrHJQ++D+H+AQDgggIocwHhfKaIlzoYf/gGAWghwAE2QaSd2RO3XIIlQMZU9d5w+I/41rX2mt99999//jD2hUSl4ACbINJu7Iit1yCJUDGVPTec++++++/8OMYBaC6Ah9c7gBmRojF1IqO/3MRjOu4qXAptFwcIEhADRKhOdAeiRhCY/DoQkxa2s6Lr/xh9AqP/+UyUy1hdC/+TSbk0m8XYTC2mvhx6AgQXBgADb2VDpHe2HiCCulgiOjrJuB6AjgdGWWzcmk06rntbW0U1tbWLRUDc5DJDPj0YBH6ce//ABhdKZskfeD9mQ0ikM9oi/hj/guwHAEkWW+gIwcQBME0CU5bXayaTf+AQANAtBKDomWW5iTQill0ZB6M4HOpYc6ltcP4BgGwWhYBDaarVz8ITIgBcADOv2xGX8YPDg+33/+P0GCGAAkzCS7O6KpM41kBGqBzKnz639999999//j9AghgAJMwkuzui9s41kBGqBzKnz6399999/8MfxghwANWCOcxjnEu59++ofrrrrrrrrrrrrrrvr/qxeL8UHsABMfilBvqswhfE+u2TVp6cADx0ERW2IrR/LDGiUdUl1bq99xkCq2OVMNW7//dQ3tqF7/gzIwABAo+8tZnaGu/3vv9wnwPf3AU8ZRGM9bHuqd3EkB0VSUocxmt//ylY9V7tfU3sDY/9pOlGkN//XfEIlpNQ//3b8QIOQWV33XbxOJMxzfm/9/18d/Lf+tv+4fFAAM33333/cDDCAH2HoANbnOSfu8A4AB4CPEy1jjEG6Ikzr3vwHzpmEWx0xxJN4bJsVhX6qkcwSXkEIQV1qwOxXmA0bTtbWh1A7JRy5fXWNMSpTFKw3tf9X07rl4ngJKfIQpkZRX/+7AgBrF5lBF8dVhf/OhdisW7euPpKbFLZdd9udXxzvf/777fm2zfFUHEiUVspDDcPigAGb7777/2YPmWgoHAAHGSCZ+NetCEECf/uBI6kNDsSYp55xFbosX42yyBzyN6I6sA7mTLRu37yzY1LYr+2/f5EHQABtbW1paWl+BLwwfTBAAA2cTQ7liVl6Rw3MUboWw2QY0x5DeO5jm3EKywnJNtArJJxUP/3mtA5ZvH6S3+xoO3aV543f4AEItZHMXVP2y2y0bbYMP1USZFEJXRc4oXlJGv3wf4YcP6CZQFPCa5zktYSRk3geLKxzV/Pz+Yjp5IOuf/n/aDtrS0tLa8WZ1Cg6vpggAAbcjQdnzUj8cFxLRq0PSyJv4/JTeifBqe+1jK2c6f+8hvFUxRItRE6vZNtIHZJNSr/960Dlm+fpPf7Gg7dpXnjd/6uZGK1ndF77+qya0YidvD3BIaJEQdM/f6uKFZSN/7/f/D8P6CZQFPCa5zktYSRk3g4srHNX8/P5iOnkg9r/+/+0HRQDXXS119YF0fVewQAAuWBiJvFahZu0D6AZCUJtNHF3IBGk1ifciqy4GtWnHWv5/X5//MbV2MQS7aVlN8Yk0dji6ikYqcTBST+xujf/RCFlBvJdoZLDHH5LdV78zNmPv+i0HvnF1e5/uyUS5licwn/f9f5f4TPoEnHzlNchXlx/e+VDs8tZ/7//X+ZmO9ff/z/uG77777+rAoaBuvYIAAFmIlhXtVCBi8EwI0QVraQnP7+xZEAHDClTNfrYRBu7omTd3vz1DbiKhNq9D5jBMxnEWjnOoa33zMh2JQN5Rdw9H9kp/2bCrghqcvdTam/cbOhuVVb61Rokgz577/n/L/CRwJ+L8CcdEJv7+9RF2kH+N75YbBxPH33311111111111111111131111111311111131111111111111113311111133111111331111111111111111111111111111111111111111111111111111111111111111111111111111111111114AAAA80GaOBfgLQ/n4ESAiqCHcDRzY/AP0GxeBwZWjnnQgF0FRlkoy/Bi5ZRcvxMDR4CQwb4a8RIfo7xPg48x3zvE+DjzHfO8T4OPMd87xPg48x3zvE+DjzHfO8T4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\" type=\"video/mp4\">\n", " Your browser does not support the video tag.\n", "</video>" ], @@ -148,9 +148,9 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ - "<Figure size 1152x432 with 1 Axes>" + "<matplotlib.figure.Figure at 0x7f5fa4e07160>" ] }, "metadata": { @@ -184,9 +184,9 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ - "<Figure size 1152x432 with 1 Axes>" + "<matplotlib.figure.Figure at 0x7f5fc03ea6a0>" ] }, "metadata": { @@ -216,7 +216,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.2" + "version": "3.8.5" } }, "nbformat": 4, diff --git a/pystencils_tests/test_phasefield_dentritic_3D.ipynb b/pystencils_tests/test_phasefield_dentritic_3D.ipynb index 1a01f103891fb229385d8192f263fb53dd837a78..b9e73677ecb083015a42b21997577495fd95f73a 100644 --- a/pystencils_tests/test_phasefield_dentritic_3D.ipynb +++ b/pystencils_tests/test_phasefield_dentritic_3D.ipynb @@ -369,7 +369,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.9" + "version": "3.8.5" } }, "nbformat": 4, diff --git a/pystencils_tests/test_random.py b/pystencils_tests/test_random.py index 1b3f89f2f81aa6e079f7bc030f27da74e778dd13..322718d1b786d28554863fdd94df9cbbd2ff02fa 100644 --- a/pystencils_tests/test_random.py +++ b/pystencils_tests/test_random.py @@ -3,7 +3,7 @@ import numpy as np import pytest import pystencils as ps -from pystencils.rng import PhiloxFourFloats, PhiloxTwoDoubles, AESNIFourFloats, AESNITwoDoubles +from pystencils.rng import PhiloxFourFloats, PhiloxTwoDoubles, AESNIFourFloats, AESNITwoDoubles, random_symbol # curand_Philox4x32_10(make_uint4(124, i, j, 0), make_uint2(0, 0)) @@ -12,58 +12,58 @@ philox_reference = np.array([[[3576608082, 1252663339, 1987745383, 348040302], [[2958765206, 3725192638, 2623672781, 1373196132], [ 850605163, 1694561295, 3285694973, 2799652583]]]) -def test_philox_double(): - for target in ('cpu', 'gpu'): - if target == 'gpu': - pytest.importorskip('pycuda') +@pytest.mark.parametrize('target', ('cpu', 'gpu')) +def test_philox_double(target): + if target == 'gpu': + pytest.importorskip('pycuda') - dh = ps.create_data_handling((2, 2), default_ghost_layers=0, default_target=target) - f = dh.add_array("f", values_per_cell=2) + dh = ps.create_data_handling((2, 2), default_ghost_layers=0, default_target=target) + f = dh.add_array("f", values_per_cell=2) - dh.fill('f', 42.0) + dh.fill('f', 42.0) - philox_node = PhiloxTwoDoubles(dh.dim) - assignments = [philox_node, - ps.Assignment(f(0), philox_node.result_symbols[0]), - ps.Assignment(f(1), philox_node.result_symbols[1])] - kernel = ps.create_kernel(assignments, target=dh.default_target).compile() + philox_node = PhiloxTwoDoubles(dh.dim) + assignments = [philox_node, + ps.Assignment(f(0), philox_node.result_symbols[0]), + ps.Assignment(f(1), philox_node.result_symbols[1])] + kernel = ps.create_kernel(assignments, target=dh.default_target).compile() - dh.all_to_gpu() - dh.run_kernel(kernel, time_step=124) - dh.all_to_cpu() + dh.all_to_gpu() + dh.run_kernel(kernel, time_step=124) + dh.all_to_cpu() - arr = dh.gather_array('f') - assert np.logical_and(arr <= 1.0, arr >= 0).all() + arr = dh.gather_array('f') + assert np.logical_and(arr <= 1.0, arr >= 0).all() - x = philox_reference[:,:,0::2] - y = philox_reference[:,:,1::2] - z = x ^ y << (53 - 32) - double_reference = z * 2.**-53 + 2.**-54 - assert(np.allclose(arr, double_reference, rtol=0, atol=np.finfo(np.float64).eps)) + x = philox_reference[:,:,0::2] + y = philox_reference[:,:,1::2] + z = x ^ y << (53 - 32) + double_reference = z * 2.**-53 + 2.**-54 + assert(np.allclose(arr, double_reference, rtol=0, atol=np.finfo(np.float64).eps)) -def test_philox_float(): - for target in ('cpu', 'gpu'): - if target == 'gpu': - pytest.importorskip('pycuda') +@pytest.mark.parametrize('target', ('cpu', 'gpu')) +def test_philox_float(target): + if target == 'gpu': + pytest.importorskip('pycuda') - dh = ps.create_data_handling((2, 2), default_ghost_layers=0, default_target=target) - f = dh.add_array("f", values_per_cell=4) + dh = ps.create_data_handling((2, 2), default_ghost_layers=0, default_target=target) + f = dh.add_array("f", values_per_cell=4) - dh.fill('f', 42.0) + dh.fill('f', 42.0) - philox_node = PhiloxFourFloats(dh.dim) - assignments = [philox_node] + [ps.Assignment(f(i), philox_node.result_symbols[i]) for i in range(4)] - kernel = ps.create_kernel(assignments, target=dh.default_target).compile() + philox_node = PhiloxFourFloats(dh.dim) + assignments = [philox_node] + [ps.Assignment(f(i), philox_node.result_symbols[i]) for i in range(4)] + kernel = ps.create_kernel(assignments, target=dh.default_target).compile() - dh.all_to_gpu() - dh.run_kernel(kernel, time_step=124) - dh.all_to_cpu() - arr = dh.gather_array('f') - assert np.logical_and(arr <= 1.0, arr >= 0).all() + dh.all_to_gpu() + dh.run_kernel(kernel, time_step=124) + dh.all_to_cpu() + arr = dh.gather_array('f') + assert np.logical_and(arr <= 1.0, arr >= 0).all() - float_reference = philox_reference * 2.**-32 + 2.**-33 - assert(np.allclose(arr, float_reference, rtol=0, atol=np.finfo(np.float32).eps)) + float_reference = philox_reference * 2.**-32 + 2.**-33 + assert(np.allclose(arr, float_reference, rtol=0, atol=np.finfo(np.float32).eps)) def test_aesni_double(): dh = ps.create_data_handling((2, 2), default_ghost_layers=0, default_target="cpu") @@ -99,4 +99,13 @@ def test_aesni_float(): dh.run_kernel(kernel, time_step=124) dh.all_to_cpu() arr = dh.gather_array('f') - assert np.logical_and(arr <= 1.0, arr >= 0).all() \ No newline at end of file + assert np.logical_and(arr <= 1.0, arr >= 0).all() + +def test_staggered(): + """Make sure that the RNG counter can be substituted during loop cutting""" + dh = ps.create_data_handling((8, 8), default_ghost_layers=0, default_target="cpu") + j = dh.add_array("j", values_per_cell=dh.dim, field_type=ps.FieldType.STAGGERED_FLUX) + a = ps.AssignmentCollection([ps.Assignment(j.staggered_access(n), 0) for n in j.staggered_stencil]) + rng_symbol_gen = random_symbol(a.subexpressions, dim=dh.dim) + a.main_assignments[0] = ps.Assignment(a.main_assignments[0].lhs, next(rng_symbol_gen)) + kernel = ps.create_staggered_kernel(a, target=dh.default_target).compile() diff --git a/pystencils_tests/test_small_block_benchmark.ipynb b/pystencils_tests/test_small_block_benchmark.ipynb index b18c4bbaf893c6cc04eec8e9880eb8884c863751..45ab56bbe194952bfbadf937be43952a9ed4a43a 100644 --- a/pystencils_tests/test_small_block_benchmark.ipynb +++ b/pystencils_tests/test_small_block_benchmark.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 11, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -21,20 +21,20 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 2, "metadata": {}, "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAATcAAAAUBAMAAAAaQ2ctAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAdt3NMolEIpm7EKvvVGZvmWXoAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADSElEQVRIDc2VTUhUURiG39G583Pv3NEEyZ2DFfSzUEKCXORsgqCFIzShG73UNnAoImkRA5GM2MJFUEbQ1WhlMBYVkaZDCyNRmF2BENOiVdCPU4Zi3r57zjgz95yjzLKzuHPO+33vc9859w9Nnfg/R/S4hfPA8OgdRb4zkjbZPCJpXNB6z4mVYLI/j2BmIi4WgGSzK8p81sks+r4+C5obTp/BoMUKnsMRz8pdpGHkJdFcAvQTuCkWhmFuYxrauljAIyvUQaLMh8tilhDwhoczbERyEsL3XpTMAoIu1TOmxzaBcBoTHpUWrXms4TWwLBZwD+FxQOaDsZjlE3CFh4vEYPySEDdOipI2Dj0mivBRuKGUJOOSpRfxFliIC7XAHybIfApMLGbpB6Z4uPpNVbiEFC6wYWsF4Uwc+EBSXYEua7cthwvnWLfM5yxmGbqPAR6OeusosndEU1I4LGwPeJvclftvi6dbLLkylXC1dluoNHT20nOl4jMWsxjOl0I53BDjVFMmIYfTnK7qFj6ncHqxgBWpcvWwTVrgt1jInkIkDxW/FM61DBbtcrhjIgEJRbjVC1uW1OiGc2zctqWKtkhS3YyoZzcRWlLyS+HIYr5sX9wJF0qLBDMuh4vOoJWedWG4l3UN+G4JOi2XbSAjyQ0xRNdVfH6LMMtX+LZs9p4DWiTCY8jhIin4/0qdbrgDFK4gVK4BD/PwpQWZ9rID0W0VvxTOtbwDevI8nJkGoTxjdXZ266lHAbK0nhc0DpxT7Bxdagr3EUHxNWPkaOdU/FI4slz/ARgFHo4+JPulk0J6CdPO4a7U5+5cD91zYoHs7Sl/Gj4xnJ/uuRx1S3wejllo58IpFi54KDkWozemMDboKfRIgS5EGwWNA42EvoJsh6f7G8yfuJzseyYW8AJP8tQq8TmLWS7a+MwfiHrHcWJosz1s9Dvzonb21ghELTRXpEvdNxZH3VEPIJAZtdDtOGtiAVrmOXUq+IzFLP5XOx9+zjTF7Se5Vo0TPvAf+bhrQcWv2Pk9x9ZaRS3PatW4IVH2CZNdCyp+xVsVbrKilme1asygN5Z93smuBfpM7DWqwhUUfbVqzBpVAPYuQMWvUChc08HK8r+a+dqsf+S+/F/QsHg/AAAAAElFTkSuQmCC\n", + "image/png": "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\n", "text/latex": [ - "$$\\left [ 2, \\quad 4, \\quad 8, \\quad 16, \\quad 32, \\quad 64, \\quad 128\\right ]$$" + "$\\displaystyle \\left[ 2, \\ 4, \\ 8, \\ 16, \\ 32, \\ 64, \\ 128\\right]$" ], "text/plain": [ "[2, 4, 8, 16, 32, 64, 128]" ] }, - "execution_count": 12, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } @@ -48,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -95,7 +95,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -129,17 +129,19 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { - "image/png": "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w9q1a/nss89ITU3F19eX6OhoCgoKAPD29nY9t1tQUMBdd91Feno67du3Z+bMma5+pbHWMmDAAN56660Kn6OISH2mglekGtSXwl5EpCrV9CMf/fr1Iz4+nilTpuB0Olm+fDnjxo2rdJxPP/2UnJwcfHx8WLp0KQsWLCArK4uLLroIX19fvvnmG7766qtSx54ubv39/cnLy2Px4sUMGzaszGP17t2bCRMmsG/fPjp06EB+fj6ZmZl06tSp0nmLiNQHKnhFRESkXgoLC2P48OGEhoZy2WWXcfXVV/+uOH379mXUqFHs27ePESNGEB4eTnBwMC+88AIhISF07tyZ3r17lzq2RYsW3HnnnQQHBxMQEEBERES5x2rVqhUpKSnceuutHDt2DICkpCQVvCIiZVDBKyIiIvXWtGnTmDZtWrG2yZP/O9Ps7+9/zmd4W7duzT/+8Y9ibU2aNOGjjz4qtf/ZqyonJSWRlJRUol9KSopre+3ata7ta6+9lrS0tBL9z+wjIiKneNRriURERERERERO0wyviIiIyDl88sknPPjgg8XaAgMDWbJkCfHx8e5JSkREzkkFr4iIiLiNtbbMlZJrk9jYWGJjY92dRq1mrXV3CiIiJeiWZhEREXELb29vDh48qELJA1hrOXjwIN7e3u5ORUSkGM3wioiIiFu0a9eOzMxMfv31V3enIlXA29ubdu3auTsNEZFiVPCKiIiIWzRq1IjAwEB3pyEiIh5MtzSLiIiIiIiIR9IMr4iIiIiIiLiNn49Psc+qpIJXRERERERE3GZiRK9qi61bmkVERERERMQjqeAVERERERERj6SCV0RERERERDySCl4RERERERHxSCp4RURERERExCOp4BURERERERGPpIJXREREREREPJIKXhEREREREfFIKnhFRERERETEI6ngFREREREREY+kgldEREREREQ8kgpeERERERER8UgqeEVERERERMQjqeAVERERERERj6SCV0RERERERDySCl4RERERERHxSCp4RURERERExCOp4BURERERERGPpIJXRESkDjHG3GCM2W2M2WeMmVLK/ibGmLeL9m80xgScsW9qUftuY0zsuWIaYwKLYuwtitm4qP2vxphtxpgtxpgvjDFXVu9Zi4iI/D4qeEVEROoIY4wX8BxwI3AlcGspxeYdwCFrbQfgaeCJorFXArcAQcANwPPGGK9zxHwCeNpa2xE4VBQb4E1rbbC1NhRIBp6qlhMWERE5Typ4RUSkzktMTGT06NEkJia6O5Xq1gvYZ63db609DiwEBp3VZxDwStH2YuA6Y4wpal9orT1mrf0O2FcUr9SYRWOuLYpBUcw/A1hr/3PG8S4AbBWfp4iISJVo6O4EREREzld2djZZWVnuTqMmXAL8eMb3TCCyrD7WWqcxJhfwK2r/6qyxlxRtlxbTD/jNWusspT/GmAnA/UBjThXGJRhjEoAEgEsvvbRCJygiIlKVNMMrIiJSd5hS2s6eXS2rT1W1n9qw9jlr7RXAg8D00pK11s6z1oZba8NbtWpVWhcREZFqpRleERGpU5JXJ5doO3T0kOvzzP1/9ry/62YC7c/43g74qYw+mcaYhkBzIOccY0trPwC0MMY0LJrlLe1YcOoW6Lm/62xERESqmcf9S0BERMSDpQEdi1ZPbsypRaiWndVnGTCmaHsYsNpaa4vabylaxTkQ6AhsKitm0Zg1RTEoivk+gDGm4xnH+xOwt4rPU0REpEpohldERKSOKHom927gE8ALWGCt3WGMeQRIt9YuA+YDrxlj9nFqZveWorE7jDGLgJ2AE5hgrT0BUFrMokM+CCw0xiQBm4tiA9xtjLkeKOTU6s2nC2wRkRqRmJhIdnY2bdq0ITm55J0/Iqep4BUREalDrLUfAh+e1TbjjO0C4OYyxs4CZlUkZlH7fk6t4nx2+72VTrwO0j+oRWqverRYoZwnFbwiIlLn+TT3KfYpUhX0D2oRkbpPBa+IiNR54SPC3Z2CiIiI1EIqeEVEpNrp1lARERFxBxW8IiJS7XRrqIiIiLhDvSl4CwsLyczMpKCgwN2pUHj11ZXqv2vXrmrKpHpV53l6e3vTrl07GjVqVNm0RERERESknqg3BW9mZibNmjUjICAAY4xbcynIzq5Uf+82baopk+pVXedpreXgwYNkZmYSGBj4e1ITkVpOt0CLiIhIVWjg7gTOxRgTbYxZb4x5wRgT/XvjFBQU4Ofn5/ZiV86fMQY/P79aMVsvItXj9C3Q2ZX8w5mIiIjImaq14DXGLDDG/NsYs/2s9huMMbuNMfuMMVPOEcYCeYA3kHme+ZzPcKlF9P9SRERERETOpbpvaU4B/gG8errBGOMFPAcM4FQBm2aMWQZ4AX8/a/ztwHpr7efGmIuBp4CR1ZyziIjUoJwVD5doO3kkx/VZYr+v3rUrIiIiFVOtBa+1dp0xJuCs5l7APmvtfgBjzEJgkLX278BN5YQ7BDQpa6cxJgFIALj00kvPI2sRERERERHxBO54hvcS4MczvmcWtZXKGDPEGPMi8BqnZotLZa2dZ60Nt9aGt2rVqsqSFRERERERkbrJHas0l/bwpS2rs7X2PeC96kun9vr+xx8ZNGIEV0dH8+WXX3LJJZfw/vvv8/rrrzNv3jyOHz9Ohw4deO211/D19SU+Ph4fHx+++eYbvv/+e15++WVeeeUVUlNTiYyMJCUlBYCVK1fy0EMPceznz7XMAAAgAElEQVTYMa644gpefvllmjZt6t6TFRGPMmtxarHvOXkFrs+z9433rrG0REREpJ5xxwxvJtD+jO/tgJ/ckEedsO+775gwYQI7duygRYsWvPvuuwwZMoS0tDS+/vprunbtyvz58139Dx06xOrVq3n66aeJi4tj0qRJ7Nixg23btrFlyxYOHDhAUlISn332Gf/6178IDw/nqaeecuMZioiU1OrCJrRt4UOrC8t8kkVERETknNwxw5sGdDTGBAJZwC3ACDfkUScEXHopoaGhAPTs2ROHw8H27duZPn06v/32G3l5ecTGxrr6x8XFYYwhODiYiy++mODgYACCgoJwOBxkZmayc+dOoqKiADh+/Dh9+vSp+RMTESnH/w0NcXcKIiIi4gGqteA1xrwFRAP+xphM4CFr7XxjzN3AJ5xamXmBtXZHdeZRlzVp3Ni17eXlxdGjR4mPj2fp0qV0796dlJQU1q5d+9/+TU7NhjRo0MC1ffq70+nEy8uLAQMG8NZbb9XYOYiIiIiIiLhDtd7SbK291Vrb1lrbyFrbzlo7v6j9Q2ttJ2vtFdbaWdWZgyc6fPgwbdu2pbCwkDfeeKNSY3v37s2GDRvYt28fAPn5+ezZs6c60hQREREREXErdzzDK+fp0UcfJTIykgEDBtClS5dKjW3VqhUpKSnceuuthISE0Lt3b7755ptqylRERERERMR93PEMb7UxxsQBcR06dHB3KlXisvbtyTjjduXJkye7tsePH1+i/+lVmAECAgLYvn17qfuuvfZa0tLSqjRXERERERGR2sajZnittcuttQnNmzd3dyoiInIG72Yt8Gnuh3ezFu5ORUREROoRj5rhFRGR2qlH3F/cnYKIiIjUQx41wysiIiIiIiJymgpeERERERER8UgqeEVERERERMQjqeAVERERERERj1RvF62atTi1SuNNG9anSuPVNIfDwZdffsmIESOqJN7SpUu57KKL6Nq5c5XEExERERERqSzN8NYRTqezWuM7HA7efPPNKjv20qVL2bV37/mmJSIiIiIi8rt5VMFrjIkzxszLzc11dyqlcjgcdOnShbETJxJx7bXcOnYs+fn5dI6I4MDBgwBkbNlCzJAhACTNns2EyZOJiYlh9OjRnDhxggceeICIiAhCQkJ48cUXyz3ek08+6er70EMPAZCWlkZISAgFBQUcOXKEoKAgtm/fzpQpU1i/fj2hoaE8/fTTpKSkcPPNNxMXF0dMTAx5eXlcd911hIWFERwczPvvv+86zquvvkpISAjdu3dn1KhRfPnllyxbtoy/PfIIkddfz36Ho3p+oCIiIiIiIuXwqFuarbXLgeXh4eF3ujuXsuzevZvnk5O5qlcvxk2axIuvvFJu/81bt7Jh40Z8fHyYN28ezZs3Jy0tjWPHjhEVFUVMTAyBgYElxq1cuZK9e/eyadMmrLUMHDiQdevW0a9fPwYOHMj06dM5evQot912G926dePxxx9n9uzZrFixAoCUlBRSU1PZunUrLVu2xOl0smTJEi688EIOHDhA7969GThwIDt37mTWrFls2LABf39/cnJyaNmyJQMHDiSmb1+G3HRTtfwcRUREREREzsWjCt66oH379lzVqxcAtw4dynMvvVRu/z/FxuLj4wOcKmK3bt3K4sWLAcjNzWXv3r1lFrwrV66kR48eAOTl5bF371769evHjBkziIiIwNvbmzlz5pR57AEDBtCyZUsArLX87W9/Y926dTRo0ICsrCx++eUXVq9ezbBhw/D39wdw9RcREREREXE3Fbw1zBhT4nvDhg05aS0ABceOFdvv6+vr2rbW8uyzzxIbG3vO41hrmTp1KuPGjSuxLycnh7y8PAoLCykoKOCCCy4oNcaZ7W+88Qa//vorGRkZNGrUiICAAAoKCrDWljgnERERERGR2sCjnuGtC3744Qe+Sk8HYNGSJVwVGcll7duz+euvAVj6wQdljo2NjWXu3LkUFhYCsGfPHo4cOVJm3wULFpCXlwdAVlYW//73vwFISEjg0UcfZeTIkTz44IMANGvWjMOHD5d57NzcXFq3bk2jRo1Ys2YN33//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\n", + "image/png": "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\n", "text/plain": [ "<Figure size 1152x432 with 2 Axes>" ] }, - "metadata": {}, + "metadata": { + "needs_background": "light" + }, "output_type": "display_data" } ], @@ -176,7 +178,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.8.2" } }, "nbformat": 4, diff --git a/pystencils_tests/test_vectorization.py b/pystencils_tests/test_vectorization.py index 3cc1be4f36b126baf19d074657b4394cdd2cefbb..f40a1875ae9320e47c90e6d6bc64a169f21781e4 100644 --- a/pystencils_tests/test_vectorization.py +++ b/pystencils_tests/test_vectorization.py @@ -7,6 +7,11 @@ from pystencils.cpu.vectorization import vectorize from pystencils.fast_approximation import insert_fast_sqrts, insert_fast_divisions from pystencils.transformations import replace_inner_stride_with_one +supported_instruction_sets = get_supported_instruction_sets() +if supported_instruction_sets: + instruction_set = supported_instruction_sets[-1] +else: + instruction_set = None def test_vector_type_propagation(): a, b, c, d, e = sp.symbols("a b c d e") @@ -19,7 +24,7 @@ def test_vector_type_propagation(): ps.Assignment(g[0, 0], b + 3 + f[0, 1])] ast = ps.create_kernel(update_rule) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) func = ast.compile() dst = np.zeros_like(arr) @@ -42,7 +47,7 @@ def test_inplace_update(): f1 @= 2 * s.tmp0 f2 @= 2 * s.tmp0 - ast = ps.create_kernel(update_rule, cpu_vectorize_info={'instruction_set': 'avx'}) + ast = ps.create_kernel(update_rule, cpu_vectorize_info={'instruction_set': instruction_set}) kernel = ast.compile() kernel(f=arr) np.testing.assert_equal(arr, 2) @@ -67,7 +72,7 @@ def test_vectorization_fixed_size(): update_rule = [ps.Assignment(g[0, 0], f[0, 0] + f[-1, 0] + f[1, 0] + f[0, 1] + f[0, -1] + 42.0)] ast = ps.create_kernel(update_rule) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) func = ast.compile() dst = np.zeros_like(arr) @@ -81,7 +86,7 @@ def test_vectorization_variable_size(): ast = ps.create_kernel(update_rule) replace_inner_stride_with_one(ast) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) func = ast.compile() arr = np.ones((23 + 2, 17 + 2)) * 5.0 @@ -102,7 +107,7 @@ def test_piecewise1(): ps.Assignment(g[0, 0], sp.Piecewise((b + 3 + f[0, 1], c), (0.0, True)))] ast = ps.create_kernel(update_rule) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) func = ast.compile() dst = np.zeros_like(arr) func(g=dst, f=arr) @@ -121,7 +126,7 @@ def test_piecewise2(): g[0, 0] @= s.result ast = ps.create_kernel(test_kernel) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) func = ast.compile() func(f=arr, g=arr) np.testing.assert_equal(arr, np.ones_like(arr)) @@ -137,7 +142,7 @@ def test_piecewise3(): g[0, 0] @= 1.0 / (s.b + s.k) if f[0, 0] > 0.0 else 1.0 ast = ps.create_kernel(test_kernel) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) ast.compile() @@ -151,7 +156,7 @@ def test_logical_operators(): g[0, 0] @= sp.Piecewise([1.0 / f[1, 0], s.c], [1.0, True]) ast = ps.create_kernel(kernel_and) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) ast.compile() @ps.kernel @@ -161,7 +166,7 @@ def test_logical_operators(): g[0, 0] @= sp.Piecewise([1.0 / f[1, 0], s.c], [1.0, True]) ast = ps.create_kernel(kernel_or) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) ast.compile() @ps.kernel @@ -171,7 +176,7 @@ def test_logical_operators(): g[0, 0] @= sp.Piecewise([1.0 / f[1, 0], s.c], [1.0, True]) ast = ps.create_kernel(kernel_equal) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) ast.compile() @@ -192,27 +197,27 @@ def test_vectorised_pow(): as6 = ps.Assignment(g[0, 0], sp.Pow(f[0, 0], -1)) ast = ps.create_kernel(as1) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) ast.compile() ast = ps.create_kernel(as2) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) ast.compile() ast = ps.create_kernel(as3) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) ast.compile() ast = ps.create_kernel(as4) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) ast.compile() ast = ps.create_kernel(as5) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) ast.compile() ast = ps.create_kernel(as6) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) ast.compile() @@ -223,16 +228,16 @@ def test_vectorised_fast_approximations(): expr = sp.sqrt(f[0, 0] + f[1, 0]) assignment = ps.Assignment(g[0, 0], insert_fast_sqrts(expr)) ast = ps.create_kernel(assignment) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) ast.compile() expr = f[0, 0] / f[1, 0] assignment = ps.Assignment(g[0, 0], insert_fast_divisions(expr)) ast = ps.create_kernel(assignment) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) ast.compile() assignment = ps.Assignment(sp.Symbol("tmp"), 3 / sp.sqrt(f[0, 0] + f[1, 0])) ast = ps.create_kernel(insert_fast_sqrts(assignment)) - vectorize(ast) + vectorize(ast, instruction_set=instruction_set) ast.compile() diff --git a/pystencils_tests/test_vectorization_specific.py b/pystencils_tests/test_vectorization_specific.py new file mode 100644 index 0000000000000000000000000000000000000000..6764f282b3e6edbb8ce1297b750162fd578306f2 --- /dev/null +++ b/pystencils_tests/test_vectorization_specific.py @@ -0,0 +1,35 @@ +import pytest + +import numpy as np +import sympy as sp + +import pystencils as ps +from pystencils.backends.simd_instruction_sets import get_supported_instruction_sets +from pystencils.cpu.vectorization import vectorize +from pystencils.fast_approximation import insert_fast_sqrts, insert_fast_divisions +from pystencils.transformations import replace_inner_stride_with_one +from pystencils.backends.simd_instruction_sets import get_supported_instruction_sets + +supported_instruction_sets = get_supported_instruction_sets() if get_supported_instruction_sets() else [] + + +@pytest.mark.parametrize('instruction_set', supported_instruction_sets) +def test_vectorisation_varying_arch(instruction_set): + shape = (9, 9, 3) + arr = np.ones(shape, order='f') + + @ps.kernel + def update_rule(s): + f = ps.fields("f(3) : [2D]", f=arr) + s.tmp0 @= f(0) + s.tmp1 @= f(1) + s.tmp2 @= f(2) + f0, f1, f2 = f(0), f(1), f(2) + f0 @= 2 * s.tmp0 + f1 @= 2 * s.tmp0 + f2 @= 2 * s.tmp0 + + ast = ps.create_kernel(update_rule, cpu_vectorize_info={'instruction_set': instruction_set}) + kernel = ast.compile() + kernel(f=arr) + np.testing.assert_equal(arr, 2) diff --git a/setup.py b/setup.py index d917867c1da2b7f4518c60cac6d1a366c270390f..b209fcbb9990b3ceb8e097d37d03fb05260f1c6d 100644 --- a/setup.py +++ b/setup.py @@ -88,7 +88,8 @@ setuptools.setup(name='pystencils', install_requires=['sympy>=1.1', 'numpy', 'appdirs', 'joblib'], package_data={'pystencils': ['include/*.h', 'backends/cuda_known_functions.txt', - 'backends/opencl1.1_known_functions.txt']}, + 'backends/opencl1.1_known_functions.txt', + 'boundaries/createindexlistcython.pyx']}, ext_modules=cython_extensions("pystencils.boundaries.createindexlistcython") if USE_CYTHON else [], classifiers=[