Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 66-absolute-access-is-probably-not-copied-correctly-after-_eval_subs
  • const_fix
  • fhennig/cpu-jit
  • fhennig/v2.0-deprecations
  • fma
  • gpu_bufferfield_fix
  • gpu_liveness_opts
  • holzer-master-patch-46757
  • hyteg
  • improved_comm
  • master
  • rangersbach/fix-gpu-atomics
  • target_dh_refactoring
  • v2.0-dev
  • vectorization_sqrt_fix
  • zikeliml/124-rework-tutorials
  • zikeliml/Task-96-dotExporterForAST
  • last/Kerncraft
  • last/LLVM
  • last/OpenCL
  • release/0.2.1
  • release/0.2.10
  • release/0.2.11
  • release/0.2.12
  • release/0.2.13
  • release/0.2.14
  • release/0.2.15
  • release/0.2.2
  • release/0.2.3
  • release/0.2.4
  • release/0.2.6
  • release/0.2.7
  • release/0.2.8
  • release/0.2.9
  • release/0.3.0
  • release/0.3.1
  • release/0.3.2
  • release/0.3.3
  • release/0.3.4
  • release/0.4.0
  • release/0.4.1
  • release/0.4.2
  • release/0.4.3
  • release/0.4.4
  • release/1.0
  • release/1.0.1
  • release/1.1
  • release/1.1.1
  • release/1.2
  • release/1.3
  • release/1.3.1
  • release/1.3.2
  • release/1.3.3
  • release/1.3.4
  • release/1.3.5
  • release/1.3.6
  • release/1.3.7
  • release/2.0.dev0
58 results

Target

Select target project
  • anirudh.jonnalagadda/pystencils
  • hyteg/pystencils
  • jbadwaik/pystencils
  • jngrad/pystencils
  • itischler/pystencils
  • ob28imeq/pystencils
  • hoenig/pystencils
  • Bindgen/pystencils
  • hammer/pystencils
  • da15siwa/pystencils
  • holzer/pystencils
  • alexander.reinauer/pystencils
  • ec93ujoh/pystencils
  • Harke/pystencils
  • seitz/pystencils
  • pycodegen/pystencils
16 results
Select Git revision
  • armneon
  • compare_fix
  • const_fix
  • gpu_liveness_opts
  • hyteg
  • improved_comm
  • jan_fix
  • jan_test
  • master
  • mr_parallel_datahandling_fix
  • philox-simd
  • target_dh_refactoring
  • test_martin
  • test_martin2
  • vectorization_sqrt_fix
  • release/0.2.1
  • release/0.2.10
  • release/0.2.11
  • release/0.2.12
  • release/0.2.13
  • release/0.2.14
  • release/0.2.15
  • release/0.2.2
  • release/0.2.3
  • release/0.2.4
  • release/0.2.6
  • release/0.2.7
  • release/0.2.8
  • release/0.2.9
29 results
Show changes
Showing
with 676 additions and 74 deletions
File added
File added
File added
...@@ -6,8 +6,8 @@ import numpy as np ...@@ -6,8 +6,8 @@ import numpy as np
import pystencils as ps import pystencils as ps
from pystencils import create_data_handling, create_kernel from pystencils import create_data_handling, create_kernel
from pystencils.datahandling.pycuda import PyCudaArrayHandler from pystencils.gpu.gpu_array_handler import GPUArrayHandler
from pystencils.datahandling.pyopencl import PyOpenClArrayHandler from pystencils.enums import Target
try: try:
import pytest import pytest
...@@ -15,6 +15,12 @@ except ImportError: ...@@ -15,6 +15,12 @@ except ImportError:
import unittest.mock import unittest.mock
pytest = unittest.mock.MagicMock() pytest = unittest.mock.MagicMock()
try:
import cupy.cuda.runtime
device_numbers = range(cupy.cuda.runtime.getDeviceCount())
except ImportError:
device_numbers = []
SCRIPT_FOLDER = Path(__file__).parent.absolute() SCRIPT_FOLDER = Path(__file__).parent.absolute()
INPUT_FOLDER = SCRIPT_FOLDER / "test_data" INPUT_FOLDER = SCRIPT_FOLDER / "test_data"
...@@ -29,7 +35,7 @@ def basic_iteration(dh): ...@@ -29,7 +35,7 @@ def basic_iteration(dh):
def access_and_gather(dh, domain_size): def access_and_gather(dh, domain_size):
dh.add_array('f1', dtype=np.dtype(np.int32)) dh.add_array('f1', dtype=np.dtype(np.int8))
dh.add_array_like('f2', 'f1') dh.add_array_like('f2', 'f1')
dh.add_array('v1', values_per_cell=3, dtype=np.int64, ghost_layers=2) dh.add_array('v1', values_per_cell=3, dtype=np.int64, ghost_layers=2)
dh.add_array_like('v2', 'v1') dh.add_array_like('v2', 'v1')
...@@ -40,7 +46,7 @@ def access_and_gather(dh, domain_size): ...@@ -40,7 +46,7 @@ def access_and_gather(dh, domain_size):
# Check symbolic field properties # Check symbolic field properties
assert dh.fields.f1.index_dimensions == 0 assert dh.fields.f1.index_dimensions == 0
assert dh.fields.f1.spatial_dimensions == len(domain_size) assert dh.fields.f1.spatial_dimensions == len(domain_size)
assert dh.fields.f1.dtype.numpy_dtype == np.int32 assert dh.fields.f1.dtype.numpy_dtype == np.int8
assert dh.fields.v1.index_dimensions == 1 assert dh.fields.v1.index_dimensions == 1
assert dh.fields.v1.spatial_dimensions == len(domain_size) assert dh.fields.v1.spatial_dimensions == len(domain_size)
...@@ -85,14 +91,10 @@ def access_and_gather(dh, domain_size): ...@@ -85,14 +91,10 @@ def access_and_gather(dh, domain_size):
def synchronization(dh, test_gpu=False): def synchronization(dh, test_gpu=False):
field_name = 'comm_field_test' field_name = 'comm_field_test'
if test_gpu: if test_gpu:
try: pytest.importorskip("cupy")
from pycuda import driver
import pycuda.autoinit
except ImportError:
return
field_name += 'Gpu' field_name += 'Gpu'
dh.add_array(field_name, ghost_layers=1, dtype=np.int32, cpu=True, gpu=test_gpu) dh.add_array(field_name, ghost_layers=1, dtype=np.int8, cpu=True, gpu=test_gpu)
# initialize everything with 1 # initialize everything with 1
for b in dh.iterate(ghost_layers=1): for b in dh.iterate(ghost_layers=1):
...@@ -102,8 +104,10 @@ def synchronization(dh, test_gpu=False): ...@@ -102,8 +104,10 @@ def synchronization(dh, test_gpu=False):
if test_gpu: if test_gpu:
dh.to_gpu(field_name) dh.to_gpu(field_name)
dh.synchronization_function_gpu(field_name)()
else:
dh.synchronization_function_cpu(field_name)()
dh.synchronization_function(field_name, target='gpu' if test_gpu else 'cpu')()
if test_gpu: if test_gpu:
dh.to_cpu(field_name) dh.to_cpu(field_name)
...@@ -114,7 +118,7 @@ def synchronization(dh, test_gpu=False): ...@@ -114,7 +118,7 @@ def synchronization(dh, test_gpu=False):
def kernel_execution_jacobi(dh, target): def kernel_execution_jacobi(dh, target):
test_gpu = target == 'gpu' or target == 'opencl' test_gpu = target == Target.GPU
dh.add_array('f', gpu=test_gpu) dh.add_array('f', gpu=test_gpu)
dh.add_array('tmp', gpu=test_gpu) dh.add_array('tmp', gpu=test_gpu)
...@@ -130,7 +134,7 @@ def kernel_execution_jacobi(dh, target): ...@@ -130,7 +134,7 @@ def kernel_execution_jacobi(dh, target):
def jacobi(): def jacobi():
dh.fields.tmp.center @= sum(dh.fields.f.neighbors(stencil)) / len(stencil) dh.fields.tmp.center @= sum(dh.fields.f.neighbors(stencil)) / len(stencil)
kernel = create_kernel(jacobi, target).compile() kernel = create_kernel(jacobi, config=ps.CreateKernelConfig(target=target)).compile()
for b in dh.iterate(ghost_layers=1): for b in dh.iterate(ghost_layers=1):
b['f'].fill(42) b['f'].fill(42)
dh.run_kernel(kernel) dh.run_kernel(kernel)
...@@ -209,26 +213,22 @@ def test_kernel(): ...@@ -209,26 +213,22 @@ def test_kernel():
for domain_shape in [(4, 5), (3, 4, 5)]: for domain_shape in [(4, 5), (3, 4, 5)]:
dh = create_data_handling(domain_size=domain_shape, periodicity=True) dh = create_data_handling(domain_size=domain_shape, periodicity=True)
assert all(dh.periodicity) assert all(dh.periodicity)
kernel_execution_jacobi(dh, 'cpu') kernel_execution_jacobi(dh, Target.CPU)
reduction(dh) reduction(dh)
try: try:
import pycuda import cupy
dh = create_data_handling(domain_size=domain_shape, periodicity=True) dh = create_data_handling(domain_size=domain_shape, periodicity=True)
kernel_execution_jacobi(dh, 'gpu') kernel_execution_jacobi(dh, Target.GPU)
except ImportError: except ImportError:
pass pass
@pytest.mark.parametrize('target', ('cpu', 'gpu', 'opencl')) @pytest.mark.parametrize('target', (Target.CPU, Target.GPU))
def test_kernel_param(target): def test_kernel_param(target):
for domain_shape in [(4, 5), (3, 4, 5)]: for domain_shape in [(4, 5), (3, 4, 5)]:
if target == 'gpu': if target == Target.GPU:
pytest.importorskip('pycuda') pytest.importorskip('cupy')
if target == 'opencl':
pytest.importorskip('pyopencl')
from pystencils.opencl.opencljit import init_globally
init_globally()
dh = create_data_handling(domain_size=domain_shape, periodicity=True, default_target=target) dh = create_data_handling(domain_size=domain_shape, periodicity=True, default_target=target)
kernel_execution_jacobi(dh, target) kernel_execution_jacobi(dh, target)
...@@ -257,6 +257,20 @@ def test_add_arrays(): ...@@ -257,6 +257,20 @@ def test_add_arrays():
assert y == dh.fields['y'] assert y == dh.fields['y']
@pytest.mark.parametrize('shape', [(17, 12), (7, 11, 18)])
@pytest.mark.parametrize('layout', ['zyxf', 'fzyx'])
def test_add_arrays_with_layout(shape, layout):
pytest.importorskip('cupy')
dh = create_data_handling(domain_size=shape, default_layout=layout, default_target=ps.Target.GPU)
f1 = dh.add_array("f1", values_per_cell=19)
dh.fill(f1.name, 1.0)
assert dh.cpu_arrays[f1.name].shape == dh.gpu_arrays[f1.name].shape
assert dh.cpu_arrays[f1.name].strides == dh.gpu_arrays[f1.name].strides
assert dh.cpu_arrays[f1.name].dtype == dh.gpu_arrays[f1.name].dtype
def test_get_kwarg(): def test_get_kwarg():
domain_shape = (10, 10) domain_shape = (10, 10)
field_description = 'src, dst' field_description = 'src, dst'
...@@ -267,7 +281,7 @@ def test_get_kwarg(): ...@@ -267,7 +281,7 @@ def test_get_kwarg():
dh.fill("dst", 0.0, ghost_layers=True) dh.fill("dst", 0.0, ghost_layers=True)
with pytest.raises(ValueError): with pytest.raises(ValueError):
dh.add_array('src') dh.add_array('src', values_per_cell=1)
ur = ps.Assignment(src.center, dst.center) ur = ps.Assignment(src.center, dst.center)
kernel = ps.create_kernel(ur).compile() kernel = ps.create_kernel(ur).compile()
...@@ -278,22 +292,20 @@ def test_get_kwarg(): ...@@ -278,22 +292,20 @@ def test_get_kwarg():
def test_add_custom_data(): def test_add_custom_data():
pytest.importorskip('pycuda') pytest.importorskip('cupy')
import cupy as cp
import pycuda.gpuarray as gpuarray
import pycuda.autoinit # noqa
def cpu_data_create_func(): def cpu_data_create_func():
return np.ones((2, 2), dtype=np.float64) return np.ones((2, 2), dtype=np.float64)
def gpu_data_create_func(): def gpu_data_create_func():
return gpuarray.zeros((2, 2), dtype=np.float64) return cp.zeros((2, 2), dtype=np.float64)
def cpu_to_gpu_transfer_func(gpuarr, cpuarray): def cpu_to_gpu_transfer_func(gpuarr, cpuarray):
gpuarr.set(cpuarray) gpuarr.set(cpuarray)
def gpu_to_cpu_transfer_func(gpuarr, cpuarray): def gpu_to_cpu_transfer_func(gpuarr, cpuarray):
gpuarr.get(cpuarray) cpuarray[:] = gpuarr.get()
dh = create_data_handling(domain_size=(10, 10)) dh = create_data_handling(domain_size=(10, 10))
dh.add_custom_data('custom_data', dh.add_custom_data('custom_data',
...@@ -359,19 +371,11 @@ def test_load_data(): ...@@ -359,19 +371,11 @@ def test_load_data():
assert np.all(dh.cpu_arrays['dst2']) == 0 assert np.all(dh.cpu_arrays['dst2']) == 0
@pytest.mark.parametrize('target', ('gpu', 'opencl')) @pytest.mark.parametrize("device_number", device_numbers)
def test_array_handler(target): def test_array_handler(device_number):
size = (2, 2) size = (2, 2)
if target == 'gpu': pytest.importorskip('cupy')
array_handler = PyCudaArrayHandler() array_handler = GPUArrayHandler(device_number)
if target == 'opencl':
pytest.importorskip('pyopencl')
import pyopencl as cl
from pystencils.opencl.opencljit import init_globally
init_globally()
ctx = cl.create_some_context(0)
queue = cl.CommandQueue(ctx)
array_handler = PyOpenClArrayHandler(queue)
zero_array = array_handler.zeros(size) zero_array = array_handler.zeros(size)
cpu_array = np.empty(size) cpu_array = np.empty(size)
...@@ -385,8 +389,23 @@ def test_array_handler(target): ...@@ -385,8 +389,23 @@ def test_array_handler(target):
empty = array_handler.empty(size) empty = array_handler.empty(size)
assert empty.strides == (16, 8) assert empty.strides == (16, 8)
empty = array_handler.empty(shape=size, layout=(1, 0)) empty = array_handler.empty(shape=size, order="F")
assert empty.strides == (8, 16) assert empty.strides == (8, 16)
random_array = array_handler.randn(size) random_array = array_handler.randn(size)
cpu_array = np.empty((20, 40), dtype=np.float64)
gpu_array = array_handler.to_gpu(cpu_array)
assert cpu_array.base is None
assert gpu_array.base is None
assert gpu_array.strides == cpu_array.strides
cpu_array2 = np.empty((20, 40), dtype=np.float64)
cpu_array2 = cpu_array2.swapaxes(0, 1)
gpu_array2 = array_handler.to_gpu(cpu_array2)
assert cpu_array2.base is not None
assert gpu_array2.base is not None
assert gpu_array2.strides == cpu_array2.strides
import numpy as np import numpy as np
import waLBerla as wlb import waLBerla as wlb
import pystencils
from pystencils import make_slice from pystencils import make_slice
from pathlib import Path
from pystencils.boundaries import BoundaryHandling, Neumann
from pystencils.slicing import slice_from_direction
from pystencils.datahandling.parallel_datahandling import ParallelDataHandling from pystencils.datahandling.parallel_datahandling import ParallelDataHandling
from pystencils_tests.test_datahandling import ( from pystencils.datahandling import create_data_handling
from tests.test_datahandling import (
access_and_gather, kernel_execution_jacobi, reduction, synchronization, vtk_output) access_and_gather, kernel_execution_jacobi, reduction, synchronization, vtk_output)
SCRIPT_FOLDER = Path(__file__).parent.absolute()
INPUT_FOLDER = SCRIPT_FOLDER / "test_data"
try: try:
import pytest import pytest
except ImportError: except ImportError:
...@@ -22,14 +33,12 @@ def test_access_and_gather(): ...@@ -22,14 +33,12 @@ def test_access_and_gather():
dh = ParallelDataHandling(blocks, default_ghost_layers=2) dh = ParallelDataHandling(blocks, default_ghost_layers=2)
access_and_gather(dh, cells) access_and_gather(dh, cells)
synchronization(dh, test_gpu=False) synchronization(dh, test_gpu=False)
if hasattr(wlb, 'cuda'): if hasattr(wlb, 'gpu'):
synchronization(dh, test_gpu=True) synchronization(dh, test_gpu=True)
def test_gpu(): def test_gpu():
if not hasattr(wlb, 'cuda'): pytest.importorskip('waLBerla.gpu')
print("Skip GPU tests because walberla was built without CUDA")
return
block_size = (4, 7, 1) block_size = (4, 7, 1)
num_blocks = (3, 2, 1) num_blocks = (3, 2, 1)
...@@ -47,24 +56,22 @@ def test_gpu(): ...@@ -47,24 +56,22 @@ def test_gpu():
np.testing.assert_equal(b['v'], 42) np.testing.assert_equal(b['v'], 42)
def test_kernel(): @pytest.mark.parametrize('target', (pystencils.Target.CPU, pystencils.Target.GPU))
def test_kernel(target):
if target == pystencils.Target.GPU:
pytest.importorskip('waLBerla.gpu')
for gpu in (True, False): # 3D
if gpu and not hasattr(wlb, 'cuda'): blocks = wlb.createUniformBlockGrid(blocks=(3, 2, 4), cellsPerBlock=(3, 2, 5), oneBlockPerProcess=False)
print("Skipping CUDA tests because walberla was built without GPU support") dh = ParallelDataHandling(blocks, default_target=target)
continue kernel_execution_jacobi(dh, target)
reduction(dh)
# 3D
blocks = wlb.createUniformBlockGrid(blocks=(3, 2, 4), cellsPerBlock=(3, 2, 5), oneBlockPerProcess=False)
dh = ParallelDataHandling(blocks)
kernel_execution_jacobi(dh, 'gpu')
reduction(dh)
# 2D # 2D
blocks = wlb.createUniformBlockGrid(blocks=(3, 2, 1), cellsPerBlock=(3, 2, 1), oneBlockPerProcess=False) blocks = wlb.createUniformBlockGrid(blocks=(3, 2, 1), cellsPerBlock=(3, 2, 1), oneBlockPerProcess=False)
dh = ParallelDataHandling(blocks, dim=2) dh = ParallelDataHandling(blocks, dim=2, default_target=target)
kernel_execution_jacobi(dh, 'gpu') kernel_execution_jacobi(dh, target)
reduction(dh) reduction(dh)
def test_vtk_output(): def test_vtk_output():
...@@ -78,7 +85,7 @@ def test_block_iteration(): ...@@ -78,7 +85,7 @@ def test_block_iteration():
num_blocks = (2, 2, 2) num_blocks = (2, 2, 2)
blocks = wlb.createUniformBlockGrid(blocks=num_blocks, cellsPerBlock=block_size, oneBlockPerProcess=False) blocks = wlb.createUniformBlockGrid(blocks=num_blocks, cellsPerBlock=block_size, oneBlockPerProcess=False)
dh = ParallelDataHandling(blocks, default_ghost_layers=2) dh = ParallelDataHandling(blocks, default_ghost_layers=2)
dh.add_array('v', values_per_cell=1, dtype=np.int64, ghost_layers=2, gpu=True) dh.add_array('v', values_per_cell=1, dtype=np.int64, ghost_layers=2)
for b in dh.iterate(): for b in dh.iterate():
b['v'].fill(1) b['v'].fill(1)
...@@ -101,10 +108,12 @@ def test_block_iteration(): ...@@ -101,10 +108,12 @@ def test_block_iteration():
def test_getter_setter(): def test_getter_setter():
pytest.importorskip('waLBerla.gpu')
block_size = (2, 2, 2) block_size = (2, 2, 2)
num_blocks = (2, 2, 2) num_blocks = (2, 2, 2)
blocks = wlb.createUniformBlockGrid(blocks=num_blocks, cellsPerBlock=block_size, oneBlockPerProcess=False) blocks = wlb.createUniformBlockGrid(blocks=num_blocks, cellsPerBlock=block_size, oneBlockPerProcess=False)
dh = ParallelDataHandling(blocks, default_ghost_layers=2) dh = ParallelDataHandling(blocks, default_ghost_layers=2, default_target=pystencils.Target.GPU)
dh.add_array('v', values_per_cell=1, dtype=np.int64, ghost_layers=2, gpu=True) dh.add_array('v', values_per_cell=1, dtype=np.int64, ghost_layers=2, gpu=True)
assert dh.shape == (4, 4, 4) assert dh.shape == (4, 4, 4)
...@@ -119,3 +128,72 @@ def test_getter_setter(): ...@@ -119,3 +128,72 @@ def test_getter_setter():
dh.to_gpu('v') dh.to_gpu('v')
assert dh.is_on_gpu('v') is True assert dh.is_on_gpu('v') is True
dh.all_to_cpu() dh.all_to_cpu()
def test_parallel_datahandling_boundary_conditions():
pytest.importorskip('waLBerla.gpu')
dh = create_data_handling(domain_size=(7, 7), periodicity=True, parallel=True,
default_target=pystencils.Target.GPU)
src = dh.add_array('src', values_per_cell=1)
dh.fill(src.name, 0.0, ghost_layers=True)
dh.fill(src.name, 1.0, ghost_layers=False)
src2 = dh.add_array('src2', values_per_cell=1)
src_cpu = dh.add_array('src_cpu', values_per_cell=1, gpu=False)
dh.fill(src_cpu.name, 0.0, ghost_layers=True)
dh.fill(src_cpu.name, 1.0, ghost_layers=False)
boundary_stencil = [(1, 0), (-1, 0), (0, 1), (0, -1)]
boundary_handling_cpu = BoundaryHandling(dh, src_cpu.name, boundary_stencil,
name="boundary_handling_cpu", target=pystencils.Target.CPU)
boundary_handling = BoundaryHandling(dh, src.name, boundary_stencil,
name="boundary_handling_gpu", target=pystencils.Target.GPU)
neumann = Neumann()
for d in ('N', 'S', 'W', 'E'):
boundary_handling.set_boundary(neumann, slice_from_direction(d, dim=2))
boundary_handling_cpu.set_boundary(neumann, slice_from_direction(d, dim=2))
boundary_handling.prepare()
boundary_handling_cpu.prepare()
boundary_handling_cpu()
dh.all_to_gpu()
boundary_handling()
dh.all_to_cpu()
for block in dh.iterate():
np.testing.assert_almost_equal(block[src_cpu.name], block[src.name])
assert dh.custom_data_names == ('boundary_handling_cpuIndexArrays', 'boundary_handling_gpuIndexArrays')
dh.swap(src.name, src2.name, gpu=True)
def test_save_data():
domain_shape = (2, 2)
dh = create_data_handling(domain_size=domain_shape, default_ghost_layers=1, parallel=True)
dh.add_array("src", values_per_cell=9)
dh.fill("src", 1.0, ghost_layers=True)
dh.add_array("dst", values_per_cell=9)
dh.fill("dst", 1.0, ghost_layers=True)
dh.save_all(str(INPUT_FOLDER) + '/datahandling_parallel_save_test')
def test_load_data():
domain_shape = (2, 2)
dh = create_data_handling(domain_size=domain_shape, default_ghost_layers=1, parallel=True)
dh.add_array("src", values_per_cell=9)
dh.fill("src", 0.0, ghost_layers=True)
dh.add_array("dst", values_per_cell=9)
dh.fill("dst", 0.0, ghost_layers=True)
dh.load_all(str(INPUT_FOLDER) + '/datahandling_parallel_load_test')
assert np.all(dh.gather_array('src')) == 1
assert np.all(dh.gather_array('src')) == 1
%% Cell type:code id: tags:
``` python
from pystencils.session import *
from pystencils.astnodes import Block, Conditional, SympyAssignment
```
%% Cell type:code id: tags:
``` python
src, dst = ps.fields("src, dst: double[2D]", layout='c')
true_block = Block([SympyAssignment(dst[0, 0], src[-1, 0])])
false_block = Block([SympyAssignment(dst[0, 0], src[1, 0])])
ur = [true_block, Conditional(dst.center() > 0.0, true_block, false_block)]
ast = ps.create_kernel(ur)
```
%% Cell type:code id: tags:
``` python
ps.show_code(ast)
```
%% Output
%% Cell type:code id: tags:
``` python
```
import pystencils as ps
from pystencils.astnodes import Block, Conditional, SympyAssignment
def test_dot_print():
src, dst = ps.fields("src, dst: double[2D]", layout='c')
true_block = Block([SympyAssignment(dst[0, 0], src[-1, 0])])
false_block = Block([SympyAssignment(dst[0, 0], src[1, 0])])
ur = [true_block, Conditional(dst.center() > 0.0, true_block, false_block)]
ast = ps.create_kernel(ur)
import pytest
import sympy as sp import sympy as sp
import pystencils as ps import pystencils as ps
...@@ -6,12 +7,13 @@ from pystencils.fast_approximation import ( ...@@ -6,12 +7,13 @@ from pystencils.fast_approximation import (
def test_fast_sqrt(): def test_fast_sqrt():
pytest.importorskip('cupy')
f, g = ps.fields("f, g: double[2D]") f, g = ps.fields("f, g: double[2D]")
expr = sp.sqrt(f[0, 0] + f[1, 0]) expr = sp.sqrt(f[0, 0] + f[1, 0])
assert len(insert_fast_sqrts(expr).atoms(fast_sqrt)) == 1 assert len(insert_fast_sqrts(expr).atoms(fast_sqrt)) == 1
assert len(insert_fast_sqrts([expr])[0].atoms(fast_sqrt)) == 1 assert len(insert_fast_sqrts([expr])[0].atoms(fast_sqrt)) == 1
ast_gpu = ps.create_kernel(ps.Assignment(g[0, 0], insert_fast_sqrts(expr)), target='gpu') ast_gpu = ps.create_kernel(ps.Assignment(g[0, 0], insert_fast_sqrts(expr)), target=ps.Target.GPU)
ast_gpu.compile() ast_gpu.compile()
code_str = ps.get_code_str(ast_gpu) code_str = ps.get_code_str(ast_gpu)
assert '__fsqrt_rn' in code_str assert '__fsqrt_rn' in code_str
...@@ -21,13 +23,14 @@ def test_fast_sqrt(): ...@@ -21,13 +23,14 @@ def test_fast_sqrt():
ac = ps.AssignmentCollection([expr], []) ac = ps.AssignmentCollection([expr], [])
assert len(insert_fast_sqrts(ac).main_assignments[0].atoms(fast_inv_sqrt)) == 1 assert len(insert_fast_sqrts(ac).main_assignments[0].atoms(fast_inv_sqrt)) == 1
ast_gpu = ps.create_kernel(insert_fast_sqrts(ac), target='gpu') ast_gpu = ps.create_kernel(insert_fast_sqrts(ac), target=ps.Target.GPU)
ast_gpu.compile() ast_gpu.compile()
code_str = ps.get_code_str(ast_gpu) code_str = ps.get_code_str(ast_gpu)
assert '__frsqrt_rn' in code_str assert '__frsqrt_rn' in code_str
def test_fast_divisions(): def test_fast_divisions():
pytest.importorskip('cupy')
f, g = ps.fields("f, g: double[2D]") f, g = ps.fields("f, g: double[2D]")
expr = f[0, 0] / f[1, 0] expr = f[0, 0] / f[1, 0]
assert len(insert_fast_divisions(expr).atoms(fast_division)) == 1 assert len(insert_fast_divisions(expr).atoms(fast_division)) == 1
...@@ -35,7 +38,7 @@ def test_fast_divisions(): ...@@ -35,7 +38,7 @@ def test_fast_divisions():
expr = 1 / f[0, 0] * 2 / f[0, 1] expr = 1 / f[0, 0] * 2 / f[0, 1]
assert len(insert_fast_divisions(expr).atoms(fast_division)) == 1 assert len(insert_fast_divisions(expr).atoms(fast_division)) == 1
ast = ps.create_kernel(ps.Assignment(g[0, 0], insert_fast_divisions(expr)), target='gpu') ast = ps.create_kernel(ps.Assignment(g[0, 0], insert_fast_divisions(expr)), target=ps.Target.GPU)
ast.compile() ast.compile()
code_str = ps.get_code_str(ast) code_str = ps.get_code_str(ast)
assert '__fdividef' in code_str assert '__fdividef' in code_str
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
from pystencils.session import * from pystencils.session import *
from pystencils.fd.derivation import * from pystencils.fd.derivation import *
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# 2D standard stencils # 2D standard stencils
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
stencil = [(-1, 0), (1, 0), (0, -1), (0, 1), (0, 0)] stencil = [(-1, 0), (1, 0), (0, -1), (0, 1), (0, 0)]
standard_2d_00 = FiniteDifferenceStencilDerivation((0,0), stencil) standard_2d_00 = FiniteDifferenceStencilDerivation((0,0), stencil)
f = ps.fields("f: [2D]") f = ps.fields("f: [2D]")
standard_2d_00_res = standard_2d_00.get_stencil() standard_2d_00_res = standard_2d_00.get_stencil()
res = standard_2d_00_res.apply(f.center) res = standard_2d_00_res.apply(f.center)
expected = f[-1, 0] - 2 * f[0, 0] + f[1, 0] expected = f[-1, 0] - 2 * f[0, 0] + f[1, 0]
assert res == expected assert res == expected
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
assert standard_2d_00_res.accuracy == 2 assert standard_2d_00_res.accuracy == 2
assert not standard_2d_00_res.is_isotropic assert not standard_2d_00_res.is_isotropic
standard_2d_00_res standard_2d_00_res
``` ```
%% Output %% Output
Finite difference stencil of accuracy 2, isotropic error: False Finite difference stencil of accuracy 2, isotropic error: False
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
standard_2d_00.get_stencil().as_array() standard_2d_00.get_stencil().as_array()
``` ```
%% Output %% Output
$\displaystyle \left[\begin{matrix}0 & 0 & 0\\1 & -2 & 1\\0 & 0 & 0\end{matrix}\right]$ $\displaystyle \left[\begin{matrix}0 & 0 & 0\\1 & -2 & 1\\0 & 0 & 0\end{matrix}\right]$
⎡0 0 0⎤ [[0, 0, 0], [1, -2, 1], [0, 0, 0]]
⎢ ⎥
⎢1 -2 1⎥
⎢ ⎥
⎣0 0 0⎦
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# 2D isotropic stencils # 2D isotropic stencils
## second x-derivative ## second x-derivative
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
stencil = [(i, j) for i in (-1, 0, 1) for j in (-1, 0, 1)] stencil = [(i, j) for i in (-1, 0, 1) for j in (-1, 0, 1)]
isotropic_2d_00 = FiniteDifferenceStencilDerivation((0,0), stencil) isotropic_2d_00 = FiniteDifferenceStencilDerivation((0,0), stencil)
isotropic_2d_00_res = isotropic_2d_00.get_stencil(isotropic=True) isotropic_2d_00_res = isotropic_2d_00.get_stencil(isotropic=True)
assert isotropic_2d_00_res.is_isotropic assert isotropic_2d_00_res.is_isotropic
assert isotropic_2d_00_res.accuracy == 2 assert isotropic_2d_00_res.accuracy == 2
isotropic_2d_00_res isotropic_2d_00_res
``` ```
%% Output %% Output
Finite difference stencil of accuracy 2, isotropic error: True Finite difference stencil of accuracy 2, isotropic error: True
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
isotropic_2d_00_res.as_array() isotropic_2d_00_res.as_array()
``` ```
%% Output %% Output
$\displaystyle \left[\begin{matrix}\frac{1}{12} & - \frac{1}{6} & \frac{1}{12}\\\frac{5}{6} & - \frac{5}{3} & \frac{5}{6}\\\frac{1}{12} & - \frac{1}{6} & \frac{1}{12}\end{matrix}\right]$ $\displaystyle \left[\begin{matrix}\frac{1}{12} & - \frac{1}{6} & \frac{1}{12}\\\frac{5}{6} & - \frac{5}{3} & \frac{5}{6}\\\frac{1}{12} & - \frac{1}{6} & \frac{1}{12}\end{matrix}\right]$
⎡1/12 -1/6 1/12⎤ [[1/12, -1/6, 1/12], [5/6, -5/3, 5/6], [1/12, -1/6, 1/12]]
⎢ ⎥
⎢5/6 -5/3 5/6 ⎥
⎢ ⎥
⎣1/12 -1/6 1/12⎦
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
plt.figure(figsize=(2,2)) plt.figure(figsize=(2,2))
isotropic_2d_00_res.visualize() isotropic_2d_00_res.visualize()
``` ```
%% Output %% Output
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
expected_result = sp.Array([[1, -2, 1], [10, -20, 10], [1, -2, 1]]) / 12 expected_result = sp.Array([[1, -2, 1], [10, -20, 10], [1, -2, 1]]) / 12
assert expected_result == isotropic_2d_00_res.as_array() assert expected_result == isotropic_2d_00_res.as_array()
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Isotropic laplacian ## Isotropic laplacian
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
isotropic_2d_11 = FiniteDifferenceStencilDerivation((1,1), stencil) isotropic_2d_11 = FiniteDifferenceStencilDerivation((1,1), stencil)
isotropic_2d_11_res = isotropic_2d_11.get_stencil(isotropic=True) isotropic_2d_11_res = isotropic_2d_11.get_stencil(isotropic=True)
iso_laplacian = isotropic_2d_00_res.as_array() + isotropic_2d_11_res.as_array() iso_laplacian = isotropic_2d_00_res.as_array() + isotropic_2d_11_res.as_array()
iso_laplacian iso_laplacian
``` ```
%% Output %% Output
$\displaystyle \left[\begin{matrix}\frac{1}{6} & \frac{2}{3} & \frac{1}{6}\\\frac{2}{3} & - \frac{10}{3} & \frac{2}{3}\\\frac{1}{6} & \frac{2}{3} & \frac{1}{6}\end{matrix}\right]$ $\displaystyle \left[\begin{matrix}\frac{1}{6} & \frac{2}{3} & \frac{1}{6}\\\frac{2}{3} & - \frac{10}{3} & \frac{2}{3}\\\frac{1}{6} & \frac{2}{3} & \frac{1}{6}\end{matrix}\right]$
⎡1/6 2/3 1/6⎤ [[1/6, 2/3, 1/6], [2/3, -10/3, 2/3], [1/6, 2/3, 1/6]]
⎢ ⎥
⎢2/3 -10/3 2/3⎥
⎢ ⎥
⎣1/6 2/3 1/6⎦
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
expected_result = sp.Array([[1, 4, 1], [4, -20, 4], [1, 4, 1]]) / 6 expected_result = sp.Array([[1, 4, 1], [4, -20, 4], [1, 4, 1]]) / 6
assert iso_laplacian == expected_result assert iso_laplacian == expected_result
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# stencils for staggered fields # stencils for staggered fields
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
half = sp.Rational(1, 2) half = sp.Rational(1, 2)
fd_points_ex = ( fd_points_ex = (
(half, 0), (half, 0),
(-half, 0), (-half, 0),
(half, 1), (half, 1),
(half, -1), (half, -1),
(-half, 1), (-half, 1),
(-half, -1) (-half, -1)
) )
assert set(fd_points_ex) == set(FiniteDifferenceStaggeredStencilDerivation("E", 2).stencil) assert set(fd_points_ex) == set(FiniteDifferenceStaggeredStencilDerivation("E", 2).stencil)
fd_points_ey = ( fd_points_ey = (
(0, half), (0, half),
(0, -half), (0, -half),
(-1,-half), (-1,-half),
(-1, half), (-1, half),
(1, -half), (1, -half),
(1, half) (1, half)
) )
assert set(fd_points_ey) == set(FiniteDifferenceStaggeredStencilDerivation("N",2).stencil) assert set(fd_points_ey) == set(FiniteDifferenceStaggeredStencilDerivation("N",2).stencil)
fd_points_c = ( fd_points_c = (
(half, half), (half, half),
(-half, -half), (-half, -half),
(half, -half), (half, -half),
(-half, half) (-half, half)
) )
assert set(fd_points_c) == set(FiniteDifferenceStaggeredStencilDerivation("NE",2).stencil) assert set(fd_points_c) == set(FiniteDifferenceStaggeredStencilDerivation("NE",2).stencil)
assert len(FiniteDifferenceStaggeredStencilDerivation("E",3).points) == 10 assert len(FiniteDifferenceStaggeredStencilDerivation("E",3).points) == 10
assert len(FiniteDifferenceStaggeredStencilDerivation("NE",3).points) == 12 assert len(FiniteDifferenceStaggeredStencilDerivation("NE",3).points) == 12
assert len(FiniteDifferenceStaggeredStencilDerivation("TNE",3).points) == 8 assert len(FiniteDifferenceStaggeredStencilDerivation("TNE",3).points) == 8
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
c = ps.fields("c: [2D]") c = ps.fields("c: [2D]")
c3 = ps.fields("c3: [3D]") c3 = ps.fields("c3: [3D]")
assert FiniteDifferenceStaggeredStencilDerivation("E", 2, (0,)).apply(c.center) == c[1, 0] - c[0, 0] assert FiniteDifferenceStaggeredStencilDerivation("E", 2, (0,)).apply(c.center) == c[1, 0] - c[0, 0]
assert FiniteDifferenceStaggeredStencilDerivation("W", 2, (0,)).apply(c.center) == c[0, 0] - c[-1, 0] assert FiniteDifferenceStaggeredStencilDerivation("W", 2, (0,)).apply(c.center) == c[0, 0] - c[-1, 0]
assert FiniteDifferenceStaggeredStencilDerivation("N", 2, (1,)).apply(c.center) == c[0, 1] - c[0, 0] assert FiniteDifferenceStaggeredStencilDerivation("N", 2, (1,)).apply(c.center) == c[0, 1] - c[0, 0]
assert FiniteDifferenceStaggeredStencilDerivation("S", 2, (1,)).apply(c.center) == c[0, 0] - c[0, -1] assert FiniteDifferenceStaggeredStencilDerivation("S", 2, (1,)).apply(c.center) == c[0, 0] - c[0, -1]
assert FiniteDifferenceStaggeredStencilDerivation("E", 3, (0,)).apply(c3.center) == c3[1, 0, 0] - c3[0, 0, 0] assert FiniteDifferenceStaggeredStencilDerivation("E", 3, (0,)).apply(c3.center) == c3[1, 0, 0] - c3[0, 0, 0]
assert FiniteDifferenceStaggeredStencilDerivation("W", 3, (0,)).apply(c3.center) == c3[0, 0, 0] - c3[-1, 0, 0] assert FiniteDifferenceStaggeredStencilDerivation("W", 3, (0,)).apply(c3.center) == c3[0, 0, 0] - c3[-1, 0, 0]
assert FiniteDifferenceStaggeredStencilDerivation("N", 3, (1,)).apply(c3.center) == c3[0, 1, 0] - c3[0, 0, 0] assert FiniteDifferenceStaggeredStencilDerivation("N", 3, (1,)).apply(c3.center) == c3[0, 1, 0] - c3[0, 0, 0]
assert FiniteDifferenceStaggeredStencilDerivation("S", 3, (1,)).apply(c3.center) == c3[0, 0, 0] - c3[0, -1, 0] assert FiniteDifferenceStaggeredStencilDerivation("S", 3, (1,)).apply(c3.center) == c3[0, 0, 0] - c3[0, -1, 0]
assert FiniteDifferenceStaggeredStencilDerivation("T", 3, (2,)).apply(c3.center) == c3[0, 0, 1] - c3[0, 0, 0] assert FiniteDifferenceStaggeredStencilDerivation("T", 3, (2,)).apply(c3.center) == c3[0, 0, 1] - c3[0, 0, 0]
assert FiniteDifferenceStaggeredStencilDerivation("B", 3, (2,)).apply(c3.center) == c3[0, 0, 0] - c3[0, 0, -1] assert FiniteDifferenceStaggeredStencilDerivation("B", 3, (2,)).apply(c3.center) == c3[0, 0, 0] - c3[0, 0, -1]
assert FiniteDifferenceStaggeredStencilDerivation("S", 2, (0,)).apply(c.center) == \ assert FiniteDifferenceStaggeredStencilDerivation("S", 2, (0,)).apply(c.center) == \
(c[1, 0] + c[1, -1] - c[-1, 0] - c[-1, -1])/4 (c[1, 0] + c[1, -1] - c[-1, 0] - c[-1, -1])/4
assert FiniteDifferenceStaggeredStencilDerivation("NE", 2, (0,)).apply(c.center) + \ assert FiniteDifferenceStaggeredStencilDerivation("NE", 2, (0,)).apply(c.center) + \
FiniteDifferenceStaggeredStencilDerivation("NE", 2, (1,)).apply(c.center) == c[1, 1] - c[0, 0] FiniteDifferenceStaggeredStencilDerivation("NE", 2, (1,)).apply(c.center) == c[1, 1] - c[0, 0]
assert FiniteDifferenceStaggeredStencilDerivation("NE", 3, (0,)).apply(c3.center) + \ assert FiniteDifferenceStaggeredStencilDerivation("NE", 3, (0,)).apply(c3.center) + \
FiniteDifferenceStaggeredStencilDerivation("NE", 3, (1,)).apply(c3.center) == c3[1, 1, 0] - c3[0, 0, 0] FiniteDifferenceStaggeredStencilDerivation("NE", 3, (1,)).apply(c3.center) == c3[1, 1, 0] - c3[0, 0, 0]
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
d = FiniteDifferenceStaggeredStencilDerivation("NE", 2, (0, 1)) d = FiniteDifferenceStaggeredStencilDerivation("NE", 2, (0, 1))
assert d.apply(c.center) == c[0,0] + c[1,1] - c[1,0] - c[0,1] assert d.apply(c.center) == c[0,0] + c[1,1] - c[1,0] - c[0,1]
d.visualize() d.visualize()
``` ```
%% Output %% Output
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
v3 = ps.fields("v(3): [3D]") v3 = ps.fields("v(3): [3D]")
for i in range(*v3.index_shape): for i in range(*v3.index_shape):
assert FiniteDifferenceStaggeredStencilDerivation("E", 3, (0,)).apply(v3.center_vector[i]) == \ assert FiniteDifferenceStaggeredStencilDerivation("E", 3, (0,)).apply(v3.center_vector[i]) == \
v3[1,0,0](i) - v3[0,0,0](i) v3[1,0,0](i) - v3[0,0,0](i)
``` ```
......
...@@ -3,35 +3,67 @@ import pytest ...@@ -3,35 +3,67 @@ import pytest
import sympy as sp import sympy as sp
import pystencils as ps import pystencils as ps
from pystencils.field import Field, FieldType, layout_string_to_tuple from pystencils import TypedSymbol
from pystencils.typing import create_type
from pystencils.field import Field, FieldType, layout_string_to_tuple, spatial_layout_string_to_tuple
def test_field_basic(): def test_field_basic():
f = Field.create_generic('f', spatial_dimensions=2) f = Field.create_generic("f", spatial_dimensions=2)
assert FieldType.is_generic(f) assert FieldType.is_generic(f)
assert f['E'] == f[1, 0] assert f["E"] == f[1, 0]
assert f['N'] == f[0, 1] assert f["N"] == f[0, 1]
assert '_' in f.center._latex('dummy') assert "_" in f.center._latex("dummy")
f = Field.create_fixed_size('f', (10, 10), strides=(80, 8), dtype=np.float64) assert (
f.index_to_physical(index_coordinates=sp.Matrix([0, 0]), staggered=False)[0]
== 0
)
assert (
f.index_to_physical(index_coordinates=sp.Matrix([0, 0]), staggered=False)[1]
== 0
)
assert (
f.physical_to_index(physical_coordinates=sp.Matrix([0, 0]), staggered=False)[0]
== 0
)
assert (
f.physical_to_index(physical_coordinates=sp.Matrix([0, 0]), staggered=False)[1]
== 0
)
f1 = f.new_field_with_different_name("f1")
assert f1.ndim == f.ndim
assert f1.values_per_cell() == f.values_per_cell()
fixed = ps.fields("f(5, 5) : double[20, 20]")
assert fixed.neighbor_vector((1, 1)).shape == (5, 5)
f = Field.create_fixed_size("f", (10, 10), strides=(80, 8), dtype=np.float64)
assert f.spatial_strides == (10, 1) assert f.spatial_strides == (10, 1)
assert f.index_strides == () assert f.index_strides == ()
assert f.center_vector == sp.Matrix([f.center]) assert f.center_vector == sp.Matrix([f.center])
f = Field.create_fixed_size('f', (8, 8, 2, 2), index_dimensions=2) f1 = f.new_field_with_different_name("f1")
assert f.center_vector == sp.Matrix([[f(0, 0), f(0, 1)], assert f1.ndim == f.ndim
[f(1, 0), f(1, 1)]]) assert f1.values_per_cell() == f.values_per_cell()
f = Field.create_fixed_size("f", (8, 8, 2, 2), index_dimensions=2)
assert f.center_vector == sp.Matrix([[f(0, 0), f(0, 1)], [f(1, 0), f(1, 1)]])
field_access = f[1, 1] field_access = f[1, 1]
assert field_access.nr_of_coordinates == 2 assert field_access.nr_of_coordinates == 2
assert field_access.offset_name == 'NE' assert field_access.offset_name == "NE"
neighbor = field_access.neighbor(coord_id=0, offset=-2) neighbor = field_access.neighbor(coord_id=0, offset=-2)
assert neighbor.offsets == (-1, 1) assert neighbor.offsets == (-1, 1)
assert '_' in neighbor._latex('dummy') assert "_" in neighbor._latex("dummy")
f = Field.create_fixed_size('f', (8, 8, 2, 2, 2), index_dimensions=3) f = Field.create_fixed_size("f", (8, 8, 2, 2, 2), index_dimensions=3)
assert f.center_vector == sp.Matrix([[[f(i, j, k) for k in range(2)] for j in range(2)] for i in range(2)]) assert f.center_vector == sp.Array(
[[[f(i, j, k) for k in range(2)] for j in range(2)] for i in range(2)]
)
f = Field.create_generic('f', spatial_dimensions=5, index_dimensions=2) f = Field.create_generic("f", spatial_dimensions=5, index_dimensions=2)
field_access = f[1, -1, 2, -3, 0](1, 0) field_access = f[1, -1, 2, -3, 0](1, 0)
assert field_access.offsets == (1, -1, 2, -3, 0) assert field_access.offsets == (1, -1, 2, -3, 0)
assert field_access.index == (1, 0) assert field_access.index == (1, 0)
...@@ -41,61 +73,71 @@ def test_error_handling(): ...@@ -41,61 +73,71 @@ def test_error_handling():
struct_dtype = np.dtype([('a', np.int32), ('b', np.float64), ('c', np.uint32)]) struct_dtype = np.dtype([('a', np.int32), ('b', np.float64), ('c', np.uint32)])
Field.create_generic('f', spatial_dimensions=2, index_dimensions=0, dtype=struct_dtype) Field.create_generic('f', spatial_dimensions=2, index_dimensions=0, dtype=struct_dtype)
with pytest.raises(ValueError) as e: with pytest.raises(ValueError) as e:
Field.create_generic('f', spatial_dimensions=2, index_dimensions=1, dtype=struct_dtype) Field.create_generic(
assert 'index dimension' in str(e.value) "f", spatial_dimensions=2, index_dimensions=1, dtype=struct_dtype
)
assert "index dimension" in str(e.value)
arr = np.array([[[(1,)*3, (2,)*3, (3,)*3]]*2], dtype=struct_dtype) arr = np.array([[[(1,) * 3, (2,) * 3, (3,) * 3]] * 2], dtype=struct_dtype)
Field.create_from_numpy_array('f', arr, index_dimensions=0) Field.create_from_numpy_array("f", arr, index_dimensions=0)
with pytest.raises(ValueError) as e: with pytest.raises(ValueError) as e:
Field.create_from_numpy_array('f', arr, index_dimensions=1) Field.create_from_numpy_array("f", arr, index_dimensions=1)
assert 'Structured arrays' in str(e.value) assert "Structured arrays" in str(e.value)
arr = np.zeros([3, 3, 3]) arr = np.zeros([3, 3, 3])
Field.create_from_numpy_array('f', arr, index_dimensions=2) Field.create_from_numpy_array("f", arr, index_dimensions=2)
with pytest.raises(ValueError) as e: with pytest.raises(ValueError) as e:
Field.create_from_numpy_array('f', arr, index_dimensions=3) Field.create_from_numpy_array("f", arr, index_dimensions=3)
assert 'Too many' in str(e.value) assert "Too many" in str(e.value)
Field.create_fixed_size('f', (3, 2, 4), index_dimensions=0, dtype=struct_dtype, layout='reverse_numpy') Field.create_fixed_size(
"f", (3, 2, 4), index_dimensions=0, dtype=struct_dtype, layout="reverse_numpy"
)
with pytest.raises(ValueError) as e: with pytest.raises(ValueError) as e:
Field.create_fixed_size('f', (3, 2, 4), index_dimensions=1, dtype=struct_dtype, layout='reverse_numpy') Field.create_fixed_size(
assert 'Structured arrays' in str(e.value) "f",
(3, 2, 4),
f = Field.create_fixed_size('f', (10, 10)) index_dimensions=1,
dtype=struct_dtype,
layout="reverse_numpy",
)
assert "Structured arrays" in str(e.value)
f = Field.create_fixed_size("f", (10, 10))
with pytest.raises(ValueError) as e: with pytest.raises(ValueError) as e:
f[1] f[1]
assert 'Wrong number of spatial indices' in str(e.value) assert "Wrong number of spatial indices" in str(e.value)
f = Field.create_generic('f', spatial_dimensions=2, index_shape=(3,)) f = Field.create_generic("f", spatial_dimensions=2, index_shape=(3,))
with pytest.raises(ValueError) as e: with pytest.raises(ValueError) as e:
f(3) f(3)
assert 'out of bounds' in str(e.value) assert "out of bounds" in str(e.value)
f = Field.create_fixed_size('f', (10, 10, 3, 4), index_dimensions=2) f = Field.create_fixed_size("f", (10, 10, 3, 4), index_dimensions=2)
with pytest.raises(ValueError) as e: with pytest.raises(ValueError) as e:
f(3, 0) f(3, 0)
assert 'out of bounds' in str(e.value) assert "out of bounds" in str(e.value)
with pytest.raises(ValueError) as e: with pytest.raises(ValueError) as e:
f(1, 0)(1, 0) f(1, 0)(1, 0)
assert 'Indexing an already indexed' in str(e.value) assert "Indexing an already indexed" in str(e.value)
with pytest.raises(ValueError) as e: with pytest.raises(ValueError) as e:
f(1) f(1)
assert 'Wrong number of indices' in str(e.value) assert "Wrong number of indices" in str(e.value)
with pytest.raises(ValueError) as e: with pytest.raises(ValueError) as e:
Field.create_generic('f', spatial_dimensions=2, layout='wrong') Field.create_generic("f", spatial_dimensions=2, layout="wrong")
assert 'Unknown layout descriptor' in str(e.value) assert "Unknown layout descriptor" in str(e.value)
assert layout_string_to_tuple('fzyx', dim=4) == (3, 2, 1, 0) assert layout_string_to_tuple("fzyx", dim=4) == (3, 2, 1, 0)
with pytest.raises(ValueError) as e: with pytest.raises(ValueError) as e:
layout_string_to_tuple('wrong', dim=4) layout_string_to_tuple("wrong", dim=4)
assert 'Unknown layout descriptor' in str(e.value) assert "Unknown layout descriptor" in str(e.value)
def test_decorator_scoping(): def test_decorator_scoping():
dst = ps.fields('dst : double[2D]') dst = ps.fields("dst : double[2D]")
def f1(): def f1():
a = sp.Symbol("a") a = sp.Symbol("a")
...@@ -115,7 +157,7 @@ def test_decorator_scoping(): ...@@ -115,7 +157,7 @@ def test_decorator_scoping():
def test_string_creation(): def test_string_creation():
x, y, z = ps.fields(' x(4), y(3,5) z : double[ 3, 47]') x, y, z = ps.fields(" x(4), y(3,5) z : double[ 3, 47]")
assert x.index_shape == (4,) assert x.index_shape == (4,)
assert y.index_shape == (3, 5) assert y.index_shape == (3, 5)
assert z.spatial_shape == (3, 47) assert z.spatial_shape == (3, 47)
...@@ -123,51 +165,140 @@ def test_string_creation(): ...@@ -123,51 +165,140 @@ def test_string_creation():
def test_itemsize(): def test_itemsize():
x = ps.fields('x: float32[1d]') x = ps.fields("x: float32[1d]")
y = ps.fields('y: float64[2d]') y = ps.fields("y: float64[2d]")
i = ps.fields('i: int16[1d]') i = ps.fields("i: int16[1d]")
assert x.itemsize == 4 assert x.itemsize == 4
assert y.itemsize == 8 assert y.itemsize == 8
assert i.itemsize == 2 assert i.itemsize == 2
def test_spatial_memory_layout_descriptors():
assert (
spatial_layout_string_to_tuple("AoS", 3)
== spatial_layout_string_to_tuple("aos", 3)
== spatial_layout_string_to_tuple("ZYXF", 3)
== spatial_layout_string_to_tuple("zyxf", 3)
== (2, 1, 0)
)
assert (
spatial_layout_string_to_tuple("SoA", 3)
== spatial_layout_string_to_tuple("soa", 3)
== spatial_layout_string_to_tuple("FZYX", 3)
== spatial_layout_string_to_tuple("fzyx", 3)
== spatial_layout_string_to_tuple("f", 3)
== spatial_layout_string_to_tuple("F", 3)
== (2, 1, 0)
)
assert (
spatial_layout_string_to_tuple("c", 3)
== spatial_layout_string_to_tuple("C", 3)
== (0, 1, 2)
)
assert spatial_layout_string_to_tuple("C", 5) == (0, 1, 2, 3, 4)
with pytest.raises(ValueError):
spatial_layout_string_to_tuple("aos", -1)
with pytest.raises(ValueError):
spatial_layout_string_to_tuple("aos", 4)
def test_memory_layout_descriptors():
assert (
layout_string_to_tuple("AoS", 4)
== layout_string_to_tuple("aos", 4)
== layout_string_to_tuple("ZYXF", 4)
== layout_string_to_tuple("zyxf", 4)
== (2, 1, 0, 3)
)
assert (
layout_string_to_tuple("SoA", 4)
== layout_string_to_tuple("soa", 4)
== layout_string_to_tuple("FZYX", 4)
== layout_string_to_tuple("fzyx", 4)
== layout_string_to_tuple("f", 4)
== layout_string_to_tuple("F", 4)
== (3, 2, 1, 0)
)
assert (
layout_string_to_tuple("c", 4)
== layout_string_to_tuple("C", 4)
== (0, 1, 2, 3)
)
assert layout_string_to_tuple("C", 5) == (0, 1, 2, 3, 4)
with pytest.raises(ValueError):
layout_string_to_tuple("aos", -1)
with pytest.raises(ValueError):
layout_string_to_tuple("aos", 5)
def test_staggered(): def test_staggered():
# D2Q5 # D2Q5
j1, j2, j3 = ps.fields('j1(2), j2(2,2), j3(2,2,2) : double[2D]', field_type=FieldType.STAGGERED) j1, j2, j3 = ps.fields(
"j1(2), j2(2,2), j3(2,2,2) : double[2D]", field_type=FieldType.STAGGERED
)
assert j1[0, 1](1) == j1.staggered_access((0, sp.Rational(1, 2))) assert j1[0, 1](1) == j1.staggered_access((0, sp.Rational(1, 2)))
assert j1[0, 1](1) == j1.staggered_access(np.array((0, sp.Rational(1, 2))))
assert j1[1, 1](1) == j1.staggered_access((1, sp.Rational(1, 2))) assert j1[1, 1](1) == j1.staggered_access((1, sp.Rational(1, 2)))
assert j1[0, 2](1) == j1.staggered_access((0, sp.Rational(3, 2))) assert j1[0, 2](1) == j1.staggered_access((0, sp.Rational(3, 2)))
assert j1[0, 1](1) == j1.staggered_access("N") assert j1[0, 1](1) == j1.staggered_access("N")
assert j1[0, 0](1) == j1.staggered_access("S") assert j1[0, 0](1) == j1.staggered_access("S")
assert j1.staggered_vector_access("N") == sp.Matrix([j1.staggered_access("N")]) assert j1.staggered_vector_access("N") == sp.Matrix([j1.staggered_access("N")])
assert j1.staggered_stencil_name == "D2Q5"
assert j1.physical_coordinates[0] == TypedSymbol("ctr_0", create_type("int"), nonnegative=True)
assert j1.physical_coordinates[1] == TypedSymbol("ctr_1", create_type("int"), nonnegative=True)
assert j1.physical_coordinates_staggered[0] == TypedSymbol("ctr_0", create_type("int"), nonnegative=True) + 0.5
assert j1.physical_coordinates_staggered[1] == TypedSymbol("ctr_1", create_type("int"), nonnegative=True) + 0.5
assert j1.index_to_physical(index_coordinates=sp.Matrix([0, 0]), staggered=True)[0] == 0.5
assert j1.index_to_physical(index_coordinates=sp.Matrix([0, 0]), staggered=True)[1] == 0.5
assert j1.physical_to_index(physical_coordinates=sp.Matrix([0, 0]), staggered=True)[0] == -0.5
assert j1.physical_to_index(physical_coordinates=sp.Matrix([0, 0]), staggered=True)[1] == -0.5
assert j2[0, 1](1, 1) == j2.staggered_access((0, sp.Rational(1, 2)), 1) assert j2[0, 1](1, 1) == j2.staggered_access((0, sp.Rational(1, 2)), 1)
assert j2[0, 1](1, 1) == j2.staggered_access("N", 1) assert j2[0, 1](1, 1) == j2.staggered_access("N", 1)
assert j2.staggered_vector_access("N") == sp.Matrix([j2.staggered_access("N", 0), j2.staggered_access("N", 1)]) assert j2.staggered_vector_access("N") == sp.Matrix(
[j2.staggered_access("N", 0), j2.staggered_access("N", 1)]
)
assert j3[0, 1](1, 1, 1) == j3.staggered_access((0, sp.Rational(1, 2)), (1, 1)) assert j3[0, 1](1, 1, 1) == j3.staggered_access((0, sp.Rational(1, 2)), (1, 1))
assert j3[0, 1](1, 1, 1) == j3.staggered_access("N", (1, 1)) assert j3[0, 1](1, 1, 1) == j3.staggered_access("N", (1, 1))
assert j3.staggered_vector_access("N") == sp.Matrix([[j3.staggered_access("N", (i, j)) assert j3.staggered_vector_access("N") == sp.Matrix(
for j in range(2)] for i in range(2)]) [[j3.staggered_access("N", (i, j)) for j in range(2)] for i in range(2)]
)
# D2Q9 # D2Q9
k1, k2 = ps.fields('k1(4), k2(2) : double[2D]', field_type=FieldType.STAGGERED) k1, k2 = ps.fields("k1(4), k2(2) : double[2D]", field_type=FieldType.STAGGERED)
assert k1[1, 1](2) == k1.staggered_access("NE") assert k1[1, 1](2) == k1.staggered_access("NE")
assert k1[0, 0](2) == k1.staggered_access("SW") assert k1[0, 0](2) == k1.staggered_access("SW")
assert k1[0, 0](3) == k1.staggered_access("NW") assert k1[0, 0](3) == k1.staggered_access("NW")
a = k1.staggered_access("NE") a = k1.staggered_access("NE")
assert a._staggered_offset(a.offsets, a.index[0]) == [sp.Rational(1, 2), sp.Rational(1, 2)] assert a._staggered_offset(a.offsets, a.index[0]) == [
sp.Rational(1, 2),
sp.Rational(1, 2),
]
a = k1.staggered_access("SW") a = k1.staggered_access("SW")
assert a._staggered_offset(a.offsets, a.index[0]) == [sp.Rational(-1, 2), sp.Rational(-1, 2)] assert a._staggered_offset(a.offsets, a.index[0]) == [
sp.Rational(-1, 2),
sp.Rational(-1, 2),
]
a = k1.staggered_access("NW") a = k1.staggered_access("NW")
assert a._staggered_offset(a.offsets, a.index[0]) == [sp.Rational(-1, 2), sp.Rational(1, 2)] assert a._staggered_offset(a.offsets, a.index[0]) == [
sp.Rational(-1, 2),
sp.Rational(1, 2),
]
# sign reversed when using as flux field # sign reversed when using as flux field
r = ps.fields('r(2) : double[2D]', field_type=FieldType.STAGGERED_FLUX) r = ps.fields("r(2) : double[2D]", field_type=FieldType.STAGGERED_FLUX)
assert r[0, 0](0) == r.staggered_access("W") assert r[0, 0](0) == r.staggered_access("W")
assert -r[1, 0](0) == r.staggered_access("E") assert -r[1, 0](0) == r.staggered_access("E")
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
""" """
import pytest
from pystencils.session import * from pystencils.session import *
from sympy import poly from sympy import poly
...@@ -22,8 +22,14 @@ def test_field_access_poly(): ...@@ -22,8 +22,14 @@ def test_field_access_poly():
def test_field_access_piecewise(): def test_field_access_piecewise():
dh = ps.create_data_handling((20, 20)) try:
ρ = dh.add_array('rho') a = sp.Piecewise((0, 1 < sp.Max(-0.5, sp.Symbol("test") + 0.5)), (1, True))
pw = sp.Piecewise((0, 1 < sp.Max(-0.5, ρ.center+0.5)), (1, True)) a.simplify()
a = sp.simplify(pw) except Exception as e:
print(a) pytest.skip(f"Bug in SymPy 1.10: {e}")
else:
dh = ps.create_data_handling((20, 20))
ρ = dh.add_array('rho')
pw = sp.Piecewise((0, 1 < sp.Max(-0.5, ρ.center+0.5)), (1, True))
a = sp.simplify(pw)
print(a)
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
from pystencils.session import * from pystencils.session import *
from pystencils.data_types import cast_func
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Test field equality behaviour ## Test field equality behaviour
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Fields create with same parameters are equal Fields create with same parameters are equal
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
f1 = ps.Field.create_generic('f', spatial_dimensions=2, index_dimensions=0) f1 = ps.Field.create_generic('f', spatial_dimensions=2, index_dimensions=0)
f2 = ps.Field.create_generic('f', spatial_dimensions=2, index_dimensions=0) f2 = ps.Field.create_generic('f', spatial_dimensions=2, index_dimensions=0)
assert f1 == f2 assert f1 == f2
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
print("Field ids equal in accesses: ", id(f1.center._field) == id(f2.center._field)) print("Field ids equal in accesses: ", id(f1.center._field) == id(f2.center._field))
print("Field accesses equal: ", f1.center == f2.center) print("Field accesses equal: ", f1.center == f2.center)
``` ```
%% Output %% Output
Field ids equal in accesses: True Field ids equal in accesses: True
Field accesses equal: True Field accesses equal: True
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
f1 = ps.Field.create_generic('f', spatial_dimensions=1, index_dimensions=0) f1 = ps.Field.create_generic('f', spatial_dimensions=1, index_dimensions=0)
f2 = ps.Field.create_generic('f', spatial_dimensions=2, index_dimensions=0) f2 = ps.Field.create_generic('f', spatial_dimensions=2, index_dimensions=0)
assert f1 != f2 assert f1 != f2
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
f1 = ps.Field.create_generic('f', spatial_dimensions=1, index_dimensions=0) f1 = ps.Field.create_generic('f', spatial_dimensions=1, index_dimensions=0)
f2 = ps.Field.create_generic('f', spatial_dimensions=1, index_dimensions=0, dtype=np.float32) f2 = ps.Field.create_generic('f', spatial_dimensions=1, index_dimensions=0, dtype=np.float32)
assert f1 != f2 assert f1 != f2
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Properties of fields: Properties of fields:
- `field_type`: enum distinguishing normal from index or buffer fields - `field_type`: enum distinguishing normal from index or buffer fields
- `_dtype`: data type of field elements - `_dtype`: data type of field elements
- `_layout`: tuple indicating the memory linearization order - `_layout`: tuple indicating the memory linearization order
- `shape`: size of field for each dimension - `shape`: size of field for each dimension
- `strides`: number of elements to jump over to increase coordinate of this dimension by one - `strides`: number of elements to jump over to increase coordinate of this dimension by one
- `latex_name`: optional display name when field is printed as latex - `latex_name`: optional display name when field is printed as latex
Equality compare of fields: Equality compare of fields:
- field has `__eq__` and ``__hash__`` overridden - field has `__eq__` and ``__hash__`` overridden
- all parameter but `latex_name` are considered for equality - all parameter but `latex_name` are considered for equality
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Test field access equality behaviour ## Test field access equality behaviour
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
f1 = ps.Field.create_generic('f', spatial_dimensions=1, index_dimensions=0) f1 = ps.Field.create_generic('f', spatial_dimensions=1, index_dimensions=0)
f2 = ps.Field.create_generic('f', spatial_dimensions=1, index_dimensions=0) f2 = ps.Field.create_generic('f', spatial_dimensions=1, index_dimensions=0)
assert f1.center == f2.center assert f1.center == f2.center
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
f1 = ps.Field.create_generic('f', spatial_dimensions=1, index_dimensions=0) f1 = ps.Field.create_generic('f', spatial_dimensions=1, index_dimensions=0)
f2 = ps.Field.create_generic('f', spatial_dimensions=1, index_dimensions=0, dtype=np.float32) f2 = ps.Field.create_generic('f', spatial_dimensions=1, index_dimensions=0, dtype=np.float32)
assert f1.center != f2.center assert f1.center != f2.center
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def print_field_accesses_debug(expr): def print_field_accesses_debug(expr):
from pystencils import Field from pystencils import Field
fas = list(expr.atoms(Field.Access)) fas = list(expr.atoms(Field.Access))
fields = list({e.field for e in fas}) fields = list({e.field for e in fas})
print("Field Accesses:") print("Field Accesses:")
for fa in fas: for fa in fas:
print(f" - {fa}, hash {hash(fa)}, offsets {fa._offsets}, index {fa._index}, {fa._hashable_content()}") print(f" - {fa}, hash {hash(fa)}, offsets {fa._offsets}, index {fa._index}, {fa._hashable_content()}")
print("") print("")
for i in range(len(fas)): for i in range(len(fas)):
for j in range(len(fas)): for j in range(len(fas)):
if not i < j: if not i < j:
continue continue
print( f" -> {i},{j} {fas[i]} == {fas[j]}: {fas[i] == {fas[j]}}") print( f" -> {i},{j} {fas[i]} == {fas[j]}: {fas[i] == {fas[j]}}")
print("Fields") print("Fields")
for f in fields: for f in fields:
print(f" - {f}, {id(f)}, shape {f.shape}, strides {f.strides}, {f._dtype}, {f.field_type}, layout {f.layout}") print(f" - {f}, {id(f)}, shape {f.shape}, strides {f.strides}, {f._dtype}, {f.field_type}, layout {f.layout}")
print("") print("")
for i in range(len(fields)): for i in range(len(fields)):
for j in range(len(fields)): for j in range(len(fields)):
if not i < j: if not i < j:
continue continue
print(f" - {fields[i]} == {fields[j]}: {fields[i] == fields[j]}, ids equal {id(fields[i])==id(fields[j])}, hash equal {hash(fields[i])==hash(fields[j])}") print(f" - {fields[i]} == {fields[j]}: {fields[i] == fields[j]}, ids equal {id(fields[i])==id(fields[j])}, hash equal {hash(fields[i])==hash(fields[j])}")
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
print_field_accesses_debug(f1.center * f2.center) print_field_accesses_debug(f1.center * f2.center)
``` ```
%% Output %% Output
Field Accesses: Field Accesses:
- f[0], hash -3276894289571194847, offsets (0,), index (), (('f_C', ('commutative', True)), ((0,), (_size_f_0,), (_stride_f_0,), 3146377891102027609, <FieldType.GENERIC: 0>, 'f', None), 0) - f[0], hash -8859424145258271267, offsets (0,), index (), ((('f_C', ('commutative', True), ('complex', True), ('extended_real', True), ('finite', True), ('hermitian', True), ('imaginary', False), ('infinite', False), ('real', True)), 2305067722319023373), ((0,), (_size_f_0,), (_stride_f_0,), <FieldType.GENERIC: 0>, 'f', None, double), 0)
- f[0], hash -1516451775709390846, offsets (0,), index (), (('f_C', ('commutative', True)), ((0,), (_size_f_0,), (_stride_f_0,), -1421177580377734245, <FieldType.GENERIC: 0>, 'f', None), 0) - f[0], hash -6454673863007224785, offsets (0,), index (), ((('f_C', ('commutative', True), ('complex', True), ('extended_real', True), ('finite', True), ('hermitian', True), ('imaginary', False), ('infinite', False), ('real', True)), 4093629613697528859), ((0,), (_size_f_0,), (_stride_f_0,), <FieldType.GENERIC: 0>, 'f', None, float), 0)
-> 0,1 f[0] == f[0]: False -> 0,1 f[0] == f[0]: False
Fields Fields
- f, 140548694371968, shape (_size_f_0,), strides (_stride_f_0,), double, FieldType.GENERIC, layout (0,) - f, 4881406800, shape (_size_f_0,), strides (_stride_f_0,), double, FieldType.GENERIC, layout (0,)
- f, 140548693963104, shape (_size_f_0,), strides (_stride_f_0,), float, FieldType.GENERIC, layout (0,) - f, 4881445024, shape (_size_f_0,), strides (_stride_f_0,), float, FieldType.GENERIC, layout (0,)
- f == f: False, ids equal False, hash equal False - f == f: False, ids equal False, hash equal False
......
...@@ -4,7 +4,8 @@ import pytest ...@@ -4,7 +4,8 @@ import pytest
import pystencils as ps import pystencils as ps
from pystencils.astnodes import LoopOverCoordinate from pystencils.astnodes import LoopOverCoordinate
from pystencils.fd import diff, diffusion, Discretization2ndOrder from pystencils.fd import diff, diffusion, Discretization2ndOrder
from pystencils.fd.spatial import discretize_spatial, fd_stencils_isotropic, fd_stencils_standard from pystencils.fd.spatial import discretize_spatial, fd_stencils_isotropic, fd_stencils_standard, \
fd_stencils_forth_order_isotropic
def test_spatial_2d_unit_sum(): def test_spatial_2d_unit_sum():
...@@ -18,7 +19,7 @@ def test_spatial_2d_unit_sum(): ...@@ -18,7 +19,7 @@ def test_spatial_2d_unit_sum():
diff(f, 1, 1), diff(f, 1, 1),
diff(f, 0, 0) + diff(f, 1, 1)] diff(f, 0, 0) + diff(f, 1, 1)]
schemes = [fd_stencils_standard, fd_stencils_isotropic] schemes = [fd_stencils_standard, fd_stencils_isotropic, 'standard', 'isotropic']
for term in terms: for term in terms:
for scheme in schemes: for scheme in schemes:
...@@ -34,7 +35,7 @@ def test_spatial_1d_unit_sum(): ...@@ -34,7 +35,7 @@ def test_spatial_1d_unit_sum():
terms = [diff(f, 0), terms = [diff(f, 0),
diff(f, 0, 0)] diff(f, 0, 0)]
schemes = [fd_stencils_standard, fd_stencils_isotropic] schemes = [fd_stencils_standard, fd_stencils_isotropic, 'standard', 'isotropic']
for term in terms: for term in terms:
for scheme in schemes: for scheme in schemes:
...@@ -43,6 +44,17 @@ def test_spatial_1d_unit_sum(): ...@@ -43,6 +44,17 @@ def test_spatial_1d_unit_sum():
assert sum(coefficients) == 0 assert sum(coefficients) == 0
def test_fd_stencils_forth_order_isotropic():
f = ps.fields("f: double[2D]")
a = fd_stencils_forth_order_isotropic([0], 1, f[0, 0](0))
sten, coefficients = ps.stencil.coefficients(a)
assert sum(coefficients) == 0
for i, direction in enumerate(sten):
counterpart = sten.index((direction[0] * -1, direction[1] * -1))
assert coefficients[i] + coefficients[counterpart] == 0
def test_staggered_laplacian(): def test_staggered_laplacian():
f = ps.fields("f : double[2D]") f = ps.fields("f : double[2D]")
a, dx = sp.symbols("a, dx") a, dx = sp.symbols("a, dx")
......