Commit d72cd721 authored by Martin Bauer's avatar Martin Bauer
Browse files

PEP8 name refactoring

- test run again
- notebooks not yet
parent 3bcfac93
from pystencils.field import Field, FieldType, extractCommonSubexpressions
from pystencils.field import Field, FieldType
from pystencils.data_types import TypedSymbol
from pystencils.slicing import makeSlice
from pystencils.kernelcreation import createKernel, createIndexedKernel
from pystencils.kernelcreation import create_kernel, create_indexed_kernel
from pystencils.display_utils import show_code, to_dot
from pystencils.assignment_collection import AssignmentCollection
from pystencils.assignment import Assignment
from pystencils.sympyextensions import SymbolCreator
__all__ = ['Field', 'FieldType', 'extractCommonSubexpressions',
__all__ = ['Field', 'FieldType',
'TypedSymbol',
'makeSlice',
'createKernel', 'createIndexedKernel',
'create_kernel', 'create_indexed_kernel',
'show_code', 'to_dot',
'AssignmentCollection',
'Assignment',
......
import numpy as np
def aligned_empty(shape, byteAlignment=32, dtype=np.float64, byteOffset=0, order='C', alignInnerCoordinate=True):
def aligned_empty(shape, byte_alignment=32, dtype=np.float64, byte_offset=0, order='C', align_inner_coordinate=True):
"""
Creates an aligned empty numpy array
:param shape: size of the array
:param byteAlignment: alignment in bytes, for the start address of the array holds (a % byteAlignment) == 0
:param byte_alignment: alignment in bytes, for the start address of the array holds (a % byteAlignment) == 0
:param dtype: numpy data type
:param byteOffset: offset in bytes for position that should be aligned i.e. (a+byteOffset) % byteAlignment == 0
:param byte_offset: offset in bytes for position that should be aligned i.e. (a+byte_offset) % byteAlignment == 0
typically used to align first inner cell instead of ghost layer
:param order: storage linearization order
:param alignInnerCoordinate: if True, the start of the innermost coordinate lines are aligned as well
:param align_inner_coordinate: if True, the start of the innermost coordinate lines are aligned as well
:return:
"""
if (not alignInnerCoordinate) or (not hasattr(shape, '__len__')):
N = np.prod(shape)
if (not align_inner_coordinate) or (not hasattr(shape, '__len__')):
size = np.prod(shape)
d = np.dtype(dtype)
tmp = np.empty(N * d.itemsize + byteAlignment, dtype=np.uint8)
tmp = np.empty(size * d.itemsize + byte_alignment, dtype=np.uint8)
address = tmp.__array_interface__['data'][0]
offset = (byteAlignment - (address + byteOffset) % byteAlignment) % byteAlignment
t1 = tmp[offset:offset + N * d.itemsize]
return tmp[offset:offset + N * d.itemsize].view(dtype=d).reshape(shape, order=order)
offset = (byte_alignment - (address + byte_offset) % byte_alignment) % byte_alignment
return tmp[offset:offset + size * d.itemsize].view(dtype=d).reshape(shape, order=order)
else:
if order == 'C':
ndim0 = shape[-1]
dim0_size = shape[-1]
dim0 = -1
ndim1 = np.prod(shape[:-1])
dim1_size = np.prod(shape[:-1])
else:
ndim0 = shape[0]
dim0_size = shape[0]
dim0 = 0
ndim1 = np.prod(shape[1:])
dim1_size = np.prod(shape[1:])
d = np.dtype(dtype)
assert byteAlignment >= d.itemsize and byteAlignment % d.itemsize == 0
padding = (byteAlignment - ((ndim0 * d.itemsize) % byteAlignment)) % byteAlignment
assert byte_alignment >= d.itemsize and byte_alignment % d.itemsize == 0
padding = (byte_alignment - ((dim0_size * d.itemsize) % byte_alignment)) % byte_alignment
N = ndim1 * padding + np.prod(shape) * d.itemsize
tmp = aligned_empty(N, byteAlignment=byteAlignment, dtype=np.uint8, byteOffset=byteOffset).view(dtype=dtype)
bshape = [i for i in shape]
bshape[dim0] = ndim0 + padding // d.itemsize
tmp = tmp.reshape(bshape, order=order)
size = dim1_size * padding + np.prod(shape) * d.itemsize
tmp = aligned_empty(size, byte_alignment=byte_alignment, dtype=np.uint8, byte_offset=byte_offset)
tmp = tmp.view(dtype=dtype)
shape_in_bytes = [i for i in shape]
shape_in_bytes[dim0] = dim0_size + padding // d.itemsize
tmp = tmp.reshape(shape_in_bytes, order=order)
if tmp.flags['C_CONTIGUOUS']:
tmp = tmp[..., :shape[-1]]
else:
......@@ -48,17 +48,17 @@ def aligned_empty(shape, byteAlignment=32, dtype=np.float64, byteOffset=0, order
return tmp
def aligned_zeros(shape, byteAlignment=16, dtype=float, byteOffset=0, order='C', alignInnerCoordinate=True):
arr = aligned_empty(shape, dtype=dtype, byteOffset=byteOffset,
order=order, byteAlignment=byteAlignment, alignInnerCoordinate=alignInnerCoordinate)
def aligned_zeros(shape, byte_alignment=16, 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)
arr[...] = x
return arr
def aligned_ones(shape, byteAlignment=16, dtype=float, byteOffset=0, order='C', alignInnerCoordinate=True):
arr = aligned_empty(shape, dtype=dtype, byteOffset=byteOffset,
order=order, byteAlignment=byteAlignment, alignInnerCoordinate=alignInnerCoordinate)
def aligned_ones(shape, byte_alignment=16, 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)
arr[...] = x
return arr
import sympy as sp
from sympy.tensor import IndexedBase
from pystencils.field import Field
from pystencils.data_types import TypedSymbol, create_type, castFunc
from pystencils.data_types import TypedSymbol, create_type, cast_func
from pystencils.sympyextensions import fast_subs
from typing import List, Set, Optional, Union, Any
......@@ -113,34 +113,34 @@ class KernelFunction(Node):
class Argument:
def __init__(self, name, dtype, symbol, kernel_function_node):
from pystencils.transformations import symbolNameToVariableName
from pystencils.transformations import symbol_name_to_variable_name
self.name = name
self.dtype = dtype
self.isFieldPtrArgument = False
self.isFieldShapeArgument = False
self.isFieldStrideArgument = False
self.isFieldArgument = False
self.fieldName = ""
self.field_name = ""
self.coordinate = None
self.symbol = symbol
if name.startswith(Field.DATA_PREFIX):
self.isFieldPtrArgument = True
self.isFieldArgument = True
self.fieldName = name[len(Field.DATA_PREFIX):]
self.field_name = name[len(Field.DATA_PREFIX):]
elif name.startswith(Field.SHAPE_PREFIX):
self.isFieldShapeArgument = True
self.isFieldArgument = True
self.fieldName = name[len(Field.SHAPE_PREFIX):]
self.field_name = name[len(Field.SHAPE_PREFIX):]
elif name.startswith(Field.STRIDE_PREFIX):
self.isFieldStrideArgument = True
self.isFieldArgument = True
self.fieldName = name[len(Field.STRIDE_PREFIX):]
self.field_name = name[len(Field.STRIDE_PREFIX):]
self.field = None
if self.isFieldArgument:
field_map = {symbolNameToVariableName(f.name): f for f in kernel_function_node.fields_accessed}
self.field = field_map[self.fieldName]
field_map = {symbol_name_to_variable_name(f.name): f for f in kernel_function_node.fields_accessed}
self.field = field_map[self.field_name]
def __lt__(self, other):
def score(l):
......@@ -167,12 +167,12 @@ class KernelFunction(Node):
self._body = body
body.parent = self
self._parameters = None
self.functionName = function_name
self.function_name = function_name
self._body.parent = self
self.compile = None
self.ghostLayers = ghost_layers
self.ghost_layers = ghost_layers
# these variables are assumed to be global, so no automatic parameter is generated for them
self.globalVariables = set()
self.global_variables = set()
self.backend = backend
@property
......@@ -202,19 +202,19 @@ class KernelFunction(Node):
return set(o.field for o in self.atoms(ResolvedFieldAccess))
def _update_parameters(self):
undefined_symbols = self._body.undefined_symbols - self.globalVariables
undefined_symbols = self._body.undefined_symbols - self.global_variables
self._parameters = [KernelFunction.Argument(s.name, s.dtype, s, self) for s in undefined_symbols]
self._parameters.sort()
def __str__(self):
self._update_parameters()
return '{0} {1}({2})\n{3}'.format(type(self).__name__, self.functionName, self.parameters,
return '{0} {1}({2})\n{3}'.format(type(self).__name__, self.function_name, self.parameters,
("\t" + "\t".join(str(self.body).splitlines(True))))
def __repr__(self):
self._update_parameters()
return '{0} {1}({2})'.format(type(self).__name__, self.functionName, self.parameters)
return '{0} {1}({2})'.format(type(self).__name__, self.function_name, self.parameters)
class Block(Node):
......@@ -392,8 +392,8 @@ class LoopOverCoordinate(Node):
@property
def is_outermost_loop(self):
from pystencils.transformations import getNextParentOfType
return getNextParentOfType(self, LoopOverCoordinate) is None
from pystencils.transformations import get_next_parent_of_type
return get_next_parent_of_type(self, LoopOverCoordinate) is None
@property
def is_innermost_loop(self):
......@@ -417,7 +417,7 @@ class SympyAssignment(Node):
self._lhsSymbol = lhs_symbol
self.rhs = rhs_expr
self._isDeclaration = True
is_cast = self._lhsSymbol.func == castFunc
is_cast = self._lhsSymbol.func == cast_func
if isinstance(self._lhsSymbol, Field.Access) or isinstance(self._lhsSymbol, ResolvedFieldAccess) or is_cast:
self._isDeclaration = False
self._isConst = is_const
......@@ -430,7 +430,7 @@ class SympyAssignment(Node):
def lhs(self, new_value):
self._lhsSymbol = new_value
self._isDeclaration = True
is_cast = self._lhsSymbol.func == castFunc
is_cast = self._lhsSymbol.func == cast_func
if isinstance(self._lhsSymbol, Field.Access) or isinstance(self._lhsSymbol, sp.Indexed) or is_cast:
self._isDeclaration = False
......
from .cbackend import print_c
from .cbackend import generate_c
try:
from .dot import print_dot
......
import sympy as sp
from collections import namedtuple
from sympy.core import S
from typing import Optional
from typing import Optional, Set
try:
from sympy.printing.ccode import C99CodePrinter as CCodePrinter
except ImportError:
from sympy.printing.ccode import CCodePrinter # for sympy versions < 1.1
from pystencils.bitoperations import xor, rightShift, leftShift, bitwiseAnd, bitwiseOr
from pystencils.bitoperations import bitwise_xor, bit_shift_right, bit_shift_left, bitwise_and, bitwise_or
from pystencils.astnodes import Node, ResolvedFieldAccess, SympyAssignment
from pystencils.data_types import create_type, PointerType, get_type_of_expression, VectorType, castFunc
from pystencils.data_types import create_type, PointerType, get_type_of_expression, VectorType, cast_func
from pystencils.backends.simd_instruction_sets import selectedInstructionSet
__all__ = ['print_c']
__all__ = ['generate_c', 'CustomCppCode', 'get_headers']
def print_c(ast_node: Node, signature_only: bool = False, use_float_constants: Optional[bool] = None) -> str:
def generate_c(ast_node: Node, signature_only: bool = False, use_float_constants: Optional[bool] = None) -> str:
"""Prints an abstract syntax tree node as C or CUDA code.
This function does not need to distinguish between C, C++ or CUDA code, it just prints 'C-like' code as encoded
......@@ -42,7 +42,8 @@ def print_c(ast_node: Node, signature_only: bool = False, use_float_constants: O
return printer(ast_node)
def get_headers(ast_node):
def get_headers(ast_node: Node) -> Set[str]:
"""Return a set of header files, necessary to compile the printed C-like code."""
headers = set()
if hasattr(ast_node, 'headers'):
......@@ -131,7 +132,7 @@ class CBackend:
def _print_KernelFunction(self, node):
function_arguments = ["%s %s" % (str(s.dtype), s.name) for s in node.parameters]
func_declaration = "FUNC_PREFIX void %s(%s)" % (node.functionName, ", ".join(function_arguments))
func_declaration = "FUNC_PREFIX void %s(%s)" % (node.function_name, ", ".join(function_arguments))
if self._signatureOnly:
return func_declaration
......@@ -163,7 +164,7 @@ class CBackend:
return "%s %s = %s;" % (data_type, self.sympyPrinter.doprint(node.lhs), self.sympyPrinter.doprint(node.rhs))
else:
lhs_type = get_type_of_expression(node.lhs)
if type(lhs_type) is VectorType and node.lhs.func == castFunc:
if type(lhs_type) is VectorType and node.lhs.func == cast_func:
return self._vectorInstructionSet['storeU'].format("&" + self.sympyPrinter.doprint(node.lhs.args[0]),
self.sympyPrinter.doprint(node.rhs)) + ';'
else:
......@@ -231,13 +232,13 @@ class CustomSympyPrinter(CCodePrinter):
def _print_Function(self, expr):
function_map = {
xor: '^',
rightShift: '>>',
leftShift: '<<',
bitwiseOr: '|',
bitwiseAnd: '&',
bitwise_xor: '^',
bit_shift_right: '>>',
bit_shift_left: '<<',
bitwise_or: '|',
bitwise_and: '&',
}
if expr.func == castFunc:
if expr.func == cast_func:
arg, data_type = expr.args
return "*((%s)(& %s))" % (PointerType(data_type), self._print(arg))
elif expr.func in function_map:
......@@ -263,7 +264,7 @@ class VectorizedCustomSympyPrinter(CustomSympyPrinter):
return None
def _print_Function(self, expr):
if expr.func == castFunc:
if expr.func == cast_func:
arg, data_type = expr.args
if type(data_type) is VectorType:
if type(arg) is ResolvedFieldAccess:
......
......@@ -72,7 +72,7 @@ def __shortened(node):
elif isinstance(node, KernelFunction):
params = [f.name for f in node.fields_accessed]
params += [p.name for p in node.parameters if not p.isFieldArgument]
return "Func: %s (%s)" % (node.functionName, ",".join(params))
return "Func: %s (%s)" % (node.function_name, ",".join(params))
elif isinstance(node, SympyAssignment):
return repr(node.lhs)
elif isinstance(node, Block):
......
import sympy as sp
xor = sp.Function("⊻")
rightShift = sp.Function("rshift")
leftShift = sp.Function("lshift")
bitwiseAnd = sp.Function("Bit&")
bitwiseOr = sp.Function("Bit|")
bitwise_xor = sp.Function("⊻")
bit_shift_right = sp.Function("rshift")
bit_shift_left = sp.Function("lshift")
bitwise_and = sp.Function("Bit&")
bitwise_or = sp.Function("Bit|")
from pystencils import Assignment
from pystencils.boundaries.boundaryhandling import BoundaryOffsetInfo
from typing import List, Tuple, Any
class Boundary(object):
......@@ -8,29 +9,30 @@ class Boundary(object):
def __init__(self, name=None):
self._name = name
def __call__(self, field, directionSymbol, indexField):
"""
This function defines the boundary behavior and must therefore be implemented by all boundaries.
Here the boundary is defined as a list of sympy equations, from which a boundary kernel is generated.
:param field: pystencils field where boundary condition should be applied.
The current cell is cell next to the boundary, which is influenced by the boundary
cell i.e. has a link from the boundary cell to itself.
:param directionSymbol: a sympy symbol that can be used as index to the pdfField. It describes
the direction pointing from the fluid to the boundary cell
:param indexField: the boundary index field that can be used to retrieve and update boundary data
:return: list of sympy equations
def __call__(self, field, direction_symbol, index_field) -> List[Assignment]:
"""Defines the boundary behavior and must therefore be implemented by all boundaries.
Here the boundary is defined as a list of sympy assignments, from which a boundary kernel is generated.
Args:
field: pystencils field where boundary condition should be applied.
The current cell is cell next to the boundary, which is influenced by the boundary
cell i.e. has a link from the boundary cell to itself.
direction_symbol: a sympy symbol that can be used as index to the pdfField. It describes
the direction pointing from the fluid to the boundary cell
index_field: the boundary index field that can be used to retrieve and update boundary data
"""
raise NotImplementedError("Boundary class has to overwrite __call__")
@property
def additionalData(self):
def additional_data(self) -> Tuple[str, Any]:
"""Return a list of (name, type) tuples for additional data items required in this boundary
These data items can either be initialized in separate kernel see additionalDataKernelInit or by
Python callbacks - see additionalDataCallback """
return []
@property
def additionalDataInitCallback(self):
def additional_data_init_callback(self):
"""Return a callback function called with a boundary data setter object and returning a dict of
data-name to data for each element that should be initialized"""
return None
......@@ -43,22 +45,22 @@ class Boundary(object):
return type(self).__name__
@name.setter
def name(self, newValue):
self._name = newValue
def name(self, new_value):
self._name = new_value
class Neumann(Boundary):
def __call__(self, field, directionSymbol, **kwargs):
def __call__(self, field, direction_symbol, **kwargs):
neighbor = BoundaryOffsetInfo.offsetFromDir(directionSymbol, field.spatialDimensions)
if field.indexDimensions == 0:
neighbor = BoundaryOffsetInfo.offset_from_dir(direction_symbol, field.spatial_dimensions)
if field.index_dimensions == 0:
return [Assignment(field[neighbor], field.center)]
else:
from itertools import product
if not field.hasFixedIndexShape:
if not field.has_fixed_index_shape:
raise NotImplementedError("Neumann boundary works only for fields with fixed index shape")
indexIter = product(*(range(i) for i in field.indexShape))
return [Assignment(field[neighbor](*idx), field(*idx)) for idx in indexIter]
index_iter = product(*(range(i) for i in field.index_shape))
return [Assignment(field[neighbor](*idx), field(*idx)) for idx in index_iter]
def __hash__(self):
# All boundaries of these class behave equal -> should also be equal
......
This diff is collapsed.
......@@ -6,7 +6,7 @@ try:
import pyximport;
pyximport.install()
from pystencils.boundaries.createindexlistcython import createBoundaryIndexList2D, createBoundaryIndexList3D
from pystencils.boundaries.createindexlistcython import create_boundary_index_list_2d, create_boundary_index_list_3d
cythonFuncsAvailable = True
except Exception:
......@@ -22,7 +22,7 @@ def numpyDataTypeForBoundaryObject(boundaryObject, dim):
coordinateNames = boundaryIndexArrayCoordinateNames[:dim]
return np.dtype([(name, np.int32) for name in coordinateNames] +
[(directionMemberName, np.int32)] +
[(i[0], i[1].numpy_dtype) for i in boundaryObject.additionalData], align=True)
[(i[0], i[1].numpy_dtype) for i in boundaryObject.additional_data], align=True)
def _createBoundaryIndexListPython(flagFieldArr, nrOfGhostLayers, boundaryMask, fluidMask, stencil):
......@@ -51,9 +51,9 @@ def createBoundaryIndexList(flagField, stencil, boundaryMask, fluidMask, nrOfGho
if cythonFuncsAvailable:
stencil = np.array(stencil, dtype=np.int32)
if dim == 2:
idxList = createBoundaryIndexList2D(flagField, nrOfGhostLayers, boundaryMask, fluidMask, stencil)
idxList = create_boundary_index_list_2d(flagField, nrOfGhostLayers, boundaryMask, fluidMask, stencil)
elif dim == 3:
idxList = createBoundaryIndexList3D(flagField, nrOfGhostLayers, boundaryMask, fluidMask, stencil)
idxList = create_boundary_index_list_3d(flagField, nrOfGhostLayers, boundaryMask, fluidMask, stencil)
else:
raise ValueError("Flag field has to be a 2 or 3 dimensional numpy array")
return np.array(idxList, dtype=indexArrDtype)
......@@ -67,7 +67,7 @@ def createBoundaryIndexArray(flagField, stencil, boundaryMask, fluidMask, bounda
idxArray = createBoundaryIndexList(flagField, stencil, boundaryMask, fluidMask, nrOfGhostLayers)
dim = len(flagField.shape)
if boundaryObject.additionalData:
if boundaryObject.additional_data:
coordinateNames = boundaryIndexArrayCoordinateNames[:dim]
indexArrDtype = numpyDataTypeForBoundaryObject(boundaryObject, dim)
extendedIdxField = np.empty(len(idxArray), dtype=indexArrDtype)
......
......@@ -15,49 +15,49 @@ ctypedef fused IntegerType:
@cython.boundscheck(False) # turn off bounds-checking for entire function
@cython.wraparound(False) # turn off negative index wrapping for entire function
def createBoundaryIndexList2D(object[IntegerType, ndim=2] flagField,
int nrOfGhostLayers, IntegerType boundaryMask, IntegerType fluidMask,
object[int, ndim=2] stencil):
def create_boundary_index_list_2d(object[IntegerType, ndim=2] flag_field,
int nr_of_ghost_layers, IntegerType boundary_mask, IntegerType fluid_mask,
object[int, ndim=2] stencil):
cdef int xs, ys, x, y
cdef int dirIdx, numDirections, dx, dy
cdef int dirIdx, num_directions, dx, dy
xs, ys = flagField.shape
boundaryIndexList = []
numDirections = stencil.shape[0]
xs, ys = flag_field.shape
boundary_index_list = []
num_directions = stencil.shape[0]
for y in range(nrOfGhostLayers,ys-nrOfGhostLayers):
for x in range(nrOfGhostLayers,xs-nrOfGhostLayers):
if flagField[x,y] & fluidMask:
for dirIdx in range(1, numDirections):
for y in range(nr_of_ghost_layers, ys - nr_of_ghost_layers):
for x in range(nr_of_ghost_layers, xs - nr_of_ghost_layers):
if flag_field[x, y] & fluid_mask:
for dirIdx in range(1, num_directions):
dx = stencil[dirIdx,0]
dy = stencil[dirIdx,1]
if flagField[x+dx, y+dy] & boundaryMask:
boundaryIndexList.append((x,y, dirIdx))
return boundaryIndexList
if flag_field[x + dx, y + dy] & boundary_mask:
boundary_index_list.append((x,y, dirIdx))
return boundary_index_list
@cython.boundscheck(False) # turn off bounds-checking for entire function
@cython.wraparound(False) # turn off negative index wrapping for entire function
def createBoundaryIndexList3D(object[IntegerType, ndim=3] flagField,
int nrOfGhostLayers, IntegerType boundaryMask, IntegerType fluidMask,
object[int, ndim=2] stencil):
def create_boundary_index_list_3d(object[IntegerType, ndim=3] flagField,
int nrOfGhostLayers, IntegerType boundaryMask, IntegerType fluidMask,
object[int, ndim=2] stencil):
cdef int xs, ys, zs, x, y, z
cdef int dirIdx, numDirections, dx, dy, dz
cdef int dirIdx, num_directions, dx, dy, dz
xs, ys, zs = flagField.shape
boundaryIndexList = []
numDirections = stencil.shape[0]
boundary_index_list = []
num_directions = stencil.shape[0]
for z in range(nrOfGhostLayers, zs-nrOfGhostLayers):
for y in range(nrOfGhostLayers,ys-nrOfGhostLayers):
for x in range(nrOfGhostLayers,xs-nrOfGhostLayers):
if flagField[x, y, z] & fluidMask:
for dirIdx in range(1, numDirections):
for dirIdx in range(1, num_directions):
dx = stencil[dirIdx,0]
dy = stencil[dirIdx,1]
dz = stencil[dirIdx,2]
if flagField[x + dx, y + dy, z + dz] & boundaryMask:
boundaryIndexList.append((x,y,z, dirIdx))
return boundaryIndexList
boundary_index_list.append((x,y,z, dirIdx))
return boundary_index_list
import sympy as sp
from pystencils import Field, TypedSymbol
from pystencils.bitoperations import bitwiseAnd
from pystencils.bitoperations import bitwise_and
from pystencils.boundaries.boundaryhandling import FlagInterface
from pystencils.data_types import create_type
def addNeumannBoundary(eqs, fields, flagField, boundaryFlag="neumannFlag", inverseFlag=False):
def add_neumann_boundary(eqs, fields, flag_field, boundary_flag="neumannFlag", inverse_flag=False):
"""
Replaces all neighbor accesses by flag field guarded accesses.
If flag in neighboring cell is set, the center value is used instead
:param eqs: list of equations containing field accesses to direct neighbors
:param fields: fields for which the Neumann boundary should be applied
:param flagField: integer field marking boundary cells
:param boundaryFlag: if flag field has value 'boundaryFlag' (no bitoperations yet) the cell is assumed to be boundary
:param inverseFlag: if true, boundary cells are where flagfield has not the value of boundaryFlag
:param flag_field: integer field marking boundary cells
:param boundary_flag: if flag field has value 'boundaryFlag' (no bit operations yet)
the cell is assumed to be boundary
:param inverse_flag: if true, boundary cells are where flag field has not the value of boundaryFlag
:return: list of equations with guarded field accesses
"""
if not hasattr(fields, "__len__"):
fields = [fields]
fields = set(fields)
if type(boundaryFlag) is str:
boundaryFlag = TypedSymbol(boundaryFlag, dtype=create_type(FlagInterface.FLAG_DTYPE))
if type(boundary_flag) is str:
boundary_flag = TypedSymbol(boundary_flag, dtype=create_type(FlagInterface.FLAG_DTYPE))
substitutions = {}
for eq in eqs:
......@@ -33,10 +34,10 @@ def addNeumannBoundary(eqs, fields, flagField, boundaryFlag="neumannFlag", inver
if all(offset == 0 for offset in fa.offsets):
continue
if inverseFlag:
condition = sp.Eq(bitwiseAnd(flagField[tuple(fa.offsets)], boundaryFlag), 0)
if inverse_flag:
condition = sp.Eq(bitwise_and(flag_field[tuple(fa.offsets)], boundary_flag), 0)
else:
condition = sp.Ne(bitwiseAnd(flagField[tuple(fa.offsets)], boundaryFlag), 0)
condition = sp.Ne(bitwise_and(flag_field[tuple(fa.offsets)], boundary_flag), 0)
center = fa.field(*fa.index)