diff --git a/hysop/backend/device/codegen/base/variables.py b/hysop/backend/device/codegen/base/variables.py index 19abfce870cc12b5836b07bc9002d491b2ac46e4..4e00234c678b9b101435a9bafaa4f9899f7408ab 100644 --- a/hysop/backend/device/codegen/base/variables.py +++ b/hysop/backend/device/codegen/base/variables.py @@ -1,4 +1,5 @@ -import re, copy +import re +import copy import numpy as np from hysop.tools.types import to_list, check_instance, first_not_None @@ -11,65 +12,65 @@ from hysop.backend.device.opencl.opencl_types import TypeGen, OpenClTypeGen from hysop.backend.device.opencl.opencl_types import cl_type_to_dtype _ctype_to_dtype = { - 'bool': np.bool_, - - 'char': np.int8, - 'short': np.int16, - 'int': np.int32, - 'long': np.int64, - 'long int': np.int64, - 'long long int': np.int64, - - 'signed char': np.int8, - 'signed short': np.int16, - 'signed int': np.int32, - 'signed long': np.int64, - 'signed long int': np.int64, - 'signed long long int': np.int64, - - 'uchar': np.uint8, - 'ushort': np.uint16, - 'uint': np.uint32, - 'ulong': np.uint64, - - 'unsigned char': np.uint8, - 'unsigned short': np.uint16, - 'unsigned int': np.uint32, - 'unsigned long int': np.uint64, - 'unsigned long long int': np.uint64, - - 'size_t': np.uint64, # warning: host and/or device can be 32bits, do not use in kernel arguments - 'ptrdiff_t': np.int64, # warning: host and/or device can be 32bits, do not use in kernel arguments - - 'half': np.float16, - 'float' : np.float32, - 'double': np.float64, - 'long double': np.longdouble, - - 'float2': np.complex64, - 'double2': np.complex128, + 'bool': np.bool_, + + 'char': np.int8, + 'short': np.int16, + 'int': np.int32, + 'long': np.int64, + 'long int': np.int64, + 'long long int': np.int64, + + 'signed char': np.int8, + 'signed short': np.int16, + 'signed int': np.int32, + 'signed long': np.int64, + 'signed long int': np.int64, + 'signed long long int': np.int64, + + 'uchar': np.uint8, + 'ushort': np.uint16, + 'uint': np.uint32, + 'ulong': np.uint64, + + 'unsigned char': np.uint8, + 'unsigned short': np.uint16, + 'unsigned int': np.uint32, + 'unsigned long int': np.uint64, + 'unsigned long long int': np.uint64, + + 'size_t': np.uint64, # warning: host and/or device can be 32bits, do not use in kernel arguments + 'ptrdiff_t': np.int64, # warning: host and/or device can be 32bits, do not use in kernel arguments + + 'half': np.float16, + 'float': np.float32, + 'double': np.float64, + 'long double': np.longdouble, + + 'float2': np.complex64, + 'double2': np.complex128, } _dtype_to_ctype = { - np.bool_: 'bool', + np.bool_: 'bool', - np.int8: 'char', - np.int16: 'short', - np.int32: 'int', - np.int64: 'long', + np.int8: 'char', + np.int16: 'short', + np.int32: 'int', + np.int64: 'long', - np.uint8: 'uchar', - np.uint16: 'ushort', - np.uint32: 'uint', - np.uint64: 'ulong', + np.uint8: 'uchar', + np.uint16: 'ushort', + np.uint32: 'uint', + np.uint64: 'ulong', - np.float16: 'half', - np.float32: 'float', - np.float64: 'double', - np.longdouble: 'long double', + np.float16: 'half', + np.float32: 'float', + np.float64: 'double', + np.longdouble: 'long double', - np.complex64: 'float2', - np.complex128: 'double2', + np.complex64: 'float2', + np.complex128: 'double2', } @@ -77,51 +78,58 @@ def dtype_to_ctype(dtype): from hysop.tools.numerics import get_dtype dtype = get_dtype(dtype) if dtype not in _dtype_to_ctype.keys(): - msg='Unknown dtype {}.'.format(dtype) + msg = 'Unknown dtype {}.'.format(dtype) raise ValueError(msg) else: return _dtype_to_ctype[dtype] + + def ctype_to_dtype(ctype): if ctype not in _ctype_to_dtype.keys(): from hysop.backend.device.opencl.opencl_types import np_dtype return np_dtype(ctype) else: return _ctype_to_dtype[ctype] -def register_ctype_dtype(ctype,dtype): + + +def register_ctype_dtype(ctype, dtype): if dtype not in _dtype_to_ctype.keys(): _dtype_to_ctype[dtype] = ctype if ctype not in _ctype_to_dtype.keys(): _ctype_to_dtype[ctype] = dtype + class CodegenVariable(object): def __init__(self, name, ctype, typegen, - storage=None, const=False, volatile=False, - add_impl_const=False, nl=None, align=None, - ptr=False, ptr_restrict=None, ptr_volatile=None, ptr_const=None, - value=None, svalue=None, init=None, - symbolic_mode=False, struct_var=None): + storage=None, const=False, volatile=False, + add_impl_const=False, nl=None, align=None, + ptr=False, ptr_restrict=None, ptr_volatile=None, ptr_const=None, + value=None, svalue=None, init=None, + symbolic_mode=False, struct_var=None, static=False): check_instance(typegen, TypeGen) check_instance(name, str) check_instance(ctype, str) check_instance(storage, str, allow_none=True) - assert len(name)>0 - assert len(ctype)>0 - assert (storage is None) or len(ctype)>0 + assert len(name) > 0 + assert len(ctype) > 0 + assert (storage is None) or len(ctype) > 0 check_instance(const, bool) check_instance(volatile, bool) + check_instance(static, bool) check_instance(add_impl_const, bool) check_instance(nl, bool, allow_none=True) check_instance(align, bool, allow_none=True) - self.name = name - self.ctype = ctype - self.typegen = typegen - self.const = const + self.name = name + self.ctype = ctype + self.typegen = typegen + self.const = const self.volatile = volatile + self.static = static self.add_impl_const = add_impl_const self.storage = storage self.align = align @@ -132,7 +140,7 @@ class CodegenVariable(object): self.symbolic_mode = symbolic_mode # pointer - if isinstance(ptr,bool): + if isinstance(ptr, bool): is_ptr = ptr ptr_level = int(ptr) else: @@ -143,7 +151,7 @@ class CodegenVariable(object): if is_ptr: ptr_restrict = [] if (ptr_restrict is None) else to_list(ptr_restrict) - ptr_const = [] if (ptr_const is None) else to_list(ptr_const) + ptr_const = [] if (ptr_const is None) else to_list(ptr_const) ptr_volatile = [] if (ptr_volatile is None) else to_list(ptr_volatile) _len = max(len(ptr_restrict), len(ptr_const), len(ptr_volatile)) @@ -151,11 +159,11 @@ class CodegenVariable(object): ptr_restrict = np.asarray(ptr_restrict + [False]*(ptr_level-len(ptr_restrict))) ptr_volatile = np.asarray(ptr_volatile + [False]*(ptr_level-len(ptr_volatile))) - ptr_const = np.asarray(ptr_const + [False]*(ptr_level-len(ptr_const))) + ptr_const = np.asarray(ptr_const + [False]*(ptr_level-len(ptr_const))) else: assert ptr_restrict is None assert ptr_volatile is None - assert ptr_const is None + assert ptr_const is None self.is_ptr = is_ptr self.ptr_level = ptr_level @@ -171,14 +179,14 @@ class CodegenVariable(object): dtype = self.typegen.floatn(1) else: dtype = ctype_to_dtype(ctype) - value = np.asarray([value],dtype=dtype)[0] - elif value.__class__ in [list,tuple]: + value = np.asarray([value], dtype=dtype)[0] + elif value.__class__ in [list, tuple]: dtype = ctype_to_dtype(ctype) try: value = np.asarray(value, dtype=dtype) except: value = np.asarray(value, dtype=object) - elif isinstance(value,np.ndarray): + elif isinstance(value, np.ndarray): try: dtype = ctype_to_dtype(ctype) value = np.asarray(value, dtype=dtype).copy() @@ -187,21 +195,21 @@ class CodegenVariable(object): else: pass - self.value = value - self.svalue = svalue - self.init = init + self.value = value + self.svalue = svalue + self.init = init # check if add_impl_const: if (not is_ptr): if const: - msg='Variable {} is const and add_impl_const has been specified!' - msg=msg.format(name) + msg = 'Variable {} is const and add_impl_const has been specified!' + msg = msg.format(name) raise ValueError(msg) - elif len(ptr_const)>0: + elif len(ptr_const) > 0: if ptr_const[-1]: - msg='Variable {} has ptr_const[-1]=True and add_impl_const has been specified!' - msg=msg.format(name) + msg = 'Variable {} has ptr_const[-1]=True and add_impl_const has been specified!' + msg = msg.format(name) raise ValueError(msg) def nv_replace(self, old, new): @@ -220,10 +228,10 @@ class CodegenVariable(object): return self.typegen.basetype(self.ctype) def newvar(self, name, nl=False, typegen=None, - storage=None, value=None, svalue=None, init=None, - ctype=None, const=None, volatile=None, add_impl_const=None, - ptr=None, ptr_restrict=None, ptr_volatile=None, ptr_const=None, - cls=None, **kwds): + storage=None, value=None, svalue=None, init=None, + ctype=None, const=None, volatile=None, add_impl_const=None, + ptr=None, ptr_restrict=None, ptr_volatile=None, ptr_const=None, + cls=None, **kwds): ctype = self.ctype if (ctype is None) else ctype const = self.const if (const is None) else const @@ -234,19 +242,19 @@ class CodegenVariable(object): cls = self.__class__ if (cls is None) else cls if ptr is None: - ptr = self.ptr_level if (ptr is None) else ptr - ptr_const = self.ptr_const if (ptr_const is None) else ptr_const + ptr = self.ptr_level if (ptr is None) else ptr + ptr_const = self.ptr_const if (ptr_const is None) else ptr_const ptr_volatile = self.ptr_volatile if (ptr_volatile is None) else ptr_volatile ptr_restrict = self.ptr_restrict if (ptr_restrict is None) else ptr_restrict return cls(name=name, nl=nl, - value=value, svalue=svalue, init=init, - ctype=ctype, storage=storage, - const=const, volatile=volatile, - add_impl_const=add_impl_const, - ptr=ptr, ptr_restrict=ptr_restrict, - ptr_volatile=ptr_volatile, ptr_const=ptr_const, - typegen=typegen, **kwds) + value=value, svalue=svalue, init=init, + ctype=ctype, storage=storage, + const=const, volatile=volatile, + add_impl_const=add_impl_const, + ptr=ptr, ptr_restrict=ptr_restrict, + ptr_volatile=ptr_volatile, ptr_const=ptr_const, + typegen=typegen, **kwds) def alias(self, varname, **kwds): if self.symbolic_mode: @@ -258,24 +266,24 @@ class CodegenVariable(object): def pointer_alias(self, name, ctype, **kargs): handle = self.newvar(name=name, ctype=ctype, - init='({})({})'.format( - self.full_ctype(cast=True,ctype=ctype), self), - **kargs) + init='({})({})'.format( + self.full_ctype(cast=True, ctype=ctype), self), + **kargs) return handle def pointer(self, name, ptr_level, - ptr_const=None, ptr_volatile=None, ptr_restrict=None, - add_impl_const=False, with_init=True, **kargs): - ptr_const = [False]*ptr_level if (ptr_const is None) else to_list(ptr_const) + ptr_const=None, ptr_volatile=None, ptr_restrict=None, + add_impl_const=False, with_init=True, **kargs): + ptr_const = [False]*ptr_level if (ptr_const is None) else to_list(ptr_const) ptr_volatile = [False]*ptr_level if (ptr_volatile is None) else to_list(ptr_volatile) ptr_restrict = [False]*ptr_level if (ptr_restrict is None) else to_list(ptr_restrict) - assert ptr_level>0 - assert len(ptr_const) == ptr_level + assert ptr_level > 0 + assert len(ptr_const) == ptr_level assert len(ptr_volatile) == ptr_level assert len(ptr_restrict) == ptr_level if self.is_ptr: - ptr_level = self.ptr_level + ptr_level - ptr_const = self.ptr_const + ptr_const + ptr_level = self.ptr_level + ptr_level + ptr_const = self.ptr_const + ptr_const ptr_volatile = self.ptr_volatile + ptr_volatile ptr_restrict = self.ptr_restrict + ptr_restrict if with_init: @@ -283,63 +291,63 @@ class CodegenVariable(object): else: init = None return self.newvar(name=name, ptr=ptr_level, - ptr_const=ptr_const, ptr_volatile=ptr_volatile, - ptr_restrict=ptr_restrict, init=init, - add_impl_const=add_impl_const, **kargs) - + ptr_const=ptr_const, ptr_volatile=ptr_volatile, + ptr_restrict=ptr_restrict, init=init, + add_impl_const=add_impl_const, **kargs) def base_ctype(self, storage=None, ctype=None, - const=None, volatile=None, - impl=True, align=None, - add_impl_const=None): + const=None, volatile=None, + impl=True, align=None, + add_impl_const=None, static=None): align = first_not_None(align, self.align, False) - storage = self.storage if (storage is None) else storage - ctype = self.ctype if (ctype is None) else ctype + storage = self.storage if (storage is None) else storage + ctype = self.ctype if (ctype is None) else ctype volatile = self.volatile if (volatile is None) else volatile + static = self.static if (static is None) else static if (const is None): const = self.const if impl and (not self.is_ptr) and (not const): const = self.add_impl_const if (add_impl_const is None) else add_impl_const - base_ctype = '{storage}${const}${volatile}${ctype}'.format( - storage='{} '.format(storage) if (storage is not None) else '', - const='const ' if const else '', - volatile='volatile ' if volatile else '', - ctype=ctype+' ') + base_ctype = '{storage}${static}${const}${volatile}${ctype}'.format( + storage='{} '.format(storage) if (storage is not None) else '', + const='const ' if const else '', + volatile='volatile ' if volatile else '', + static='static ' if static else '', + ctype=ctype+' ') if not align: - base_ctype = base_ctype.replace('$','') + base_ctype = base_ctype.replace('$', '') return base_ctype.strip() - def ptr_ctype(self, impl=True, add_impl_const=None, cast=False): if self.is_ptr: - ptrs=[] + ptrs = [] add_impl_const = self.add_impl_const if (add_impl_const is None) else add_impl_const - for i, (c,v,r) in enumerate(zip(self.ptr_const, self.ptr_volatile, self.ptr_restrict)): - if i==self.ptr_level-1: + for i, (c, v, r) in enumerate(zip(self.ptr_const, self.ptr_volatile, self.ptr_restrict)): + if i == self.ptr_level-1: c = c or (impl and add_impl_const) - ptr=' $*{const}${volatile}${restrict}'.format( - const = 'const ' if (c and not cast) else '', - volatile = 'volatile ' if (v and not cast) else '', - restrict = 'restrict ' if (r and not cast) else '') + ptr = ' $*{const}${volatile}${restrict}'.format( + const='const ' if (c and not cast) else '', + volatile='volatile ' if (v and not cast) else '', + restrict='restrict ' if (r and not cast) else '') ptrs.append(ptr) ptr_ctype = ''.join(ptrs) else: - ptr_ctype='' + ptr_ctype = '' return ptr_ctype def full_ctype(self, storage=None, ctype=None, const=None, volatile=None, - impl=True, multidecl=False, align=None, cast=False, - add_impl_const=None): + impl=True, multidecl=False, align=None, cast=False, + add_impl_const=None, static=None): align = first_not_None(align, self.align, False) if multidecl: base_ctype = '' else: - base_ctype = self.base_ctype(storage,ctype,const,volatile,impl,align, - add_impl_const=add_impl_const) - if len(base_ctype)==0: - msg= 'Failed to get base ctype in {}.'.format(self.__class__) + base_ctype = self.base_ctype(storage, ctype, const, volatile, impl, align, + add_impl_const=add_impl_const, static=static) + if len(base_ctype) == 0: + msg = 'Failed to get base ctype in {}.'.format(self.__class__) raise RuntimeError(msg) ptr_ctype = self.ptr_ctype(impl=impl, add_impl_const=add_impl_const, cast=cast) @@ -352,20 +360,22 @@ class CodegenVariable(object): return full_ctype.strip() - def argument(self,impl, - nl=None, name=None, - **kargs): - name = self.name if (name is None) else name - nl = self.nl if (nl is None) else nl + def argument(self, impl, + nl=None, name=None, + **kargs): + name = self.name if (name is None) else name + nl = self.nl if (nl is None) else nl return '{} {name}{nl}'.format( - self.full_ctype(impl=impl, **kargs), - name=name, - nl='\n' if self.nl else '') + self.full_ctype(impl=impl, **kargs), + name=name, + nl='\n' if self.nl else '') def is_symbolic(self): return (self.value is None) or self.symbolic_mode + def in_struct(self): return (self.struct_var is not None) + def known(self): return (self.value is not None) @@ -373,6 +383,7 @@ class CodegenVariable(object): if force is None: return self.symbolic_mode = force + def set_value(self, val): assert not self.known(), 'Value was already set in variable {}!'.format(self.name) self.value = val @@ -389,7 +400,7 @@ class CodegenVariable(object): elif self.value is not None: return self.typegen.dump(self.value) else: - msg='value and svalue are not defined.' + msg = 'value and svalue are not defined.' raise RuntimeError(msg) def access_prefix(self, access): @@ -405,26 +416,26 @@ class CodegenVariable(object): return self.name def declare(self, codegen=None, align=None, - multidecl=False, const=None, _const=None, init=None, - compact=False): + multidecl=False, const=None, _const=None, init=None, + compact=False, static=None): # const means add_impl_const, ie. declare current variable as constant (not pointed types) # _const is the real const align = first_not_None(align, self.align, False) - ctype = self.full_ctype(align=align,multidecl=multidecl,add_impl_const=const, const=_const) - if (not multidecl) and len(ctype)==0: - msg= 'Failed to get full ctype in {}.'.format(self.__class__) + ctype = self.full_ctype(align=align, multidecl=multidecl, add_impl_const=const, const=_const, static=static) + if (not multidecl) and len(ctype) == 0: + msg = 'Failed to get full ctype in {}.'.format(self.__class__) raise RuntimeError(msg) # static array ctype needs to be split name = self.decl_name() if init is False: - msg='Const variable should be initialized at declaration.' + msg = 'Const variable should be initialized at declaration.' assert (not self.const) or (not self.add_impl_const), msg - init=None + init = None else: init = init if (init is not None) else self.init - if (len(ctype)>0) and ctype[-1]=='*': + if (len(ctype) > 0) and ctype[-1] == '*': code = '{}${}'.format(ctype, name) else: code = '{} ${}'.format(ctype, name) @@ -438,26 +449,26 @@ class CodegenVariable(object): self.force_symbolic(False) sval = self.sval() if compact: - code = '{}={}'.format(code,sval) + code = '{}={}'.format(code, sval) else: - code = '{} $= {}'.format(code,sval) + code = '{} $= {}'.format(code, sval) if not multidecl: - code+=';' + code += ';' self.force_symbolic() self.declared = True if not align: - code = code.replace('$','') + code = code.replace('$', '') if codegen is not None: codegen.append(code) return code.strip() def affect(self, codegen=None, align=None, init=None, - compact=False, i=None): + compact=False, i=None): align = first_not_None(align, self.align, False) - msg='Cannot affect a const variable.' + msg = 'Cannot affect a const variable.' assert (not self.const) or (not self.add_impl_const), msg init = self.init if (init is None) else init if compact: @@ -470,7 +481,7 @@ class CodegenVariable(object): var = self[i] code = code.format(var, init) if not align: - code = code.replace('$','') + code = code.replace('$', '') if codegen is not None: codegen.append(code) return code @@ -479,89 +490,91 @@ class CodegenVariable(object): def dtype(self): return ctype_to_dtype(self.ctype) - def __getitem__(self,ss): + def __getitem__(self, ss): if self.is_ptr: - return '{}[{}]'.format(self.name,ss) - elif ss==0: + return '{}[{}]'.format(self.name, ss) + elif ss == 0: return self.__call__() else: assert self.is_ptr, '{} is not a pointer!'.format(self.name) def __repr__(self): if self.is_symbolic(): - return '{}({})'.format(self.name,self.ctype) + return '{}({})'.format(self.name, self.ctype) else: - return '{}({},{})'.format(self.name,self.ctype,self.value) + return '{}({},{})'.format(self.name, self.ctype, self.value) def __call__(self): return self.sval() + def __str__(self): return self.sval() + class CodegenArray(CodegenVariable): @staticmethod def _initialize_rec(name, typegen, - storage, ctype, const, volatile, - shape, sshape, value, svalue, - ptr_level, ptr_restrict, ptr_const, ptr_volatile, - symbolic_mode): + storage, ctype, const, volatile, + shape, sshape, value, svalue, + ptr_level, ptr_restrict, ptr_const, ptr_volatile, + symbolic_mode): if (value is None): return value, svalue s0 = shape[0] - if ptr_level==1: - _name = name + if ptr_level == 1: + _name = name _value = value if (svalue is not None): _svalue = '{ ' + ', '.join(svalue) + ' }' else: - _shape = shape[1:] + _shape = shape[1:] _sshape = sshape[1:] - _ptr_level = ptr_level - 1 - _ptr_const = ptr_const[:-1] + _ptr_level = ptr_level - 1 + _ptr_const = ptr_const[:-1] _ptr_restrict = ptr_restrict[:-1] _ptr_volatile = ptr_volatile[:-1] - _value = [None]*s0 + _value = [None]*s0 _svalue = [None]*s0 for d in range(s0): - _name = '{}_{}'.format(name, d) - dvalue = value[d] + _name = '{}_{}'.format(name, d) + dvalue = value[d] dsvalue = svalue[d] val, sval = CodegenArray._initialize_rec(_name, typegen, - storage, ctype, const, volatile, - _shape, _sshape, dvalue, dsvalue, - _ptr_level, _ptr_restrict, _ptr_const, _ptr_volatile, - symbolic_mode) + storage, ctype, const, volatile, + _shape, _sshape, dvalue, dsvalue, + _ptr_level, _ptr_restrict, _ptr_const, _ptr_volatile, + symbolic_mode) var = CodegenArray(name=_name, typegen=typegen, - storage=storage, ctype=ctype, const=const, volatile=volatile, - shape=_shape, sshape=_sshape, value=val, svalue=sval, - dim=_ptr_level, ptr_const=_ptr_const, - ptr_volatile=_ptr_volatile, ptr_restrict=_ptr_restrict, - add_impl_const=False, - symbolic_mode=False, - struct_var=None, - _direct_init=True) - _value[d] = var + storage=storage, ctype=ctype, const=const, volatile=volatile, + shape=_shape, sshape=_sshape, value=val, svalue=sval, + dim=_ptr_level, ptr_const=_ptr_const, + ptr_volatile=_ptr_volatile, ptr_restrict=_ptr_restrict, + add_impl_const=False, + symbolic_mode=False, + struct_var=None, + _direct_init=True) + _value[d] = var _svalue[d] = '\n\t'.join(sval.split('\n')) if svalue is None: - _svalue=None + _svalue = None else: _svalue = '{\n\t'+',\n\t'.join(_svalue)+'\n}' return _value, _svalue def __init__(self, name, ctype, typegen, - storage=None, volatile=False, const=False, add_impl_const = False, - dim=1, ptr_const=None, ptr_volatile=None, ptr_restrict=None, - shape=None, sshape=None, - value=None, svalue=None, - symbolic_mode=False, struct_var=None, - _direct_init=False): + storage=None, volatile=False, const=False, add_impl_const=False, + dim=1, ptr_const=None, ptr_volatile=None, ptr_restrict=None, + shape=None, sshape=None, + value=None, svalue=None, + symbolic_mode=False, struct_var=None, + _direct_init=False): ptr_level = dim del dim @@ -569,10 +582,10 @@ class CodegenArray(CodegenVariable): if _direct_init: _value, _svalue = value, svalue else: - ptr_const = [] if (ptr_const is None) else to_list(ptr_const) + ptr_const = [] if (ptr_const is None) else to_list(ptr_const) ptr_volatile = [] if (ptr_volatile is None) else to_list(ptr_volatile) ptr_restrict = [] if (ptr_restrict is None) else to_list(ptr_restrict) - ptr_const += [False]*(ptr_level-len(ptr_const)) + ptr_const += [False]*(ptr_level-len(ptr_const)) ptr_volatile += [False]*(ptr_level-len(ptr_volatile)) ptr_restrict += [False]*(ptr_level-len(ptr_restrict)) @@ -594,14 +607,14 @@ class CodegenArray(CodegenVariable): if svalue.shape != value.shape: raise ValueError('Input array shape mismatch between value and svalue.') elif (value is not None): - svalue = np.zeros_like(value,dtype=object) + svalue = np.zeros_like(value, dtype=object) dtype = ctype_to_dtype(ctype) sview = svalue.flat - for i,v in enumerate(value.flat): + for i, v in enumerate(value.flat): sview[i] = typegen.dump(v) if (shape is not None): - if len(shape)!=ptr_level: + if len(shape) != ptr_level: raise ValueError('shape dim mismatch!') else: shape = (None,)*ptr_level @@ -609,24 +622,24 @@ class CodegenArray(CodegenVariable): if (sshape is None) and (shape[0] != None): sshape = [str(s) for s in shape] - elif (sshape is not None) and len(sshape)!=dim: + elif (sshape is not None) and len(sshape) != dim: raise ValueError('sshape dim mismatch!') else: sshape = (None,)*ptr_level sshape = np.asarray(sshape) _value, _svalue = CodegenArray._initialize_rec(name, typegen, - storage, ctype, const, volatile, - shape, sshape, value, svalue, - ptr_level, ptr_restrict, ptr_const, ptr_volatile, - symbolic_mode) + storage, ctype, const, volatile, + shape, sshape, value, svalue, + ptr_level, ptr_restrict, ptr_const, ptr_volatile, + symbolic_mode) super(CodegenArray, self).__init__(name=name, - storage=storage, ctype=ctype, typegen=typegen, - value=_value, svalue=_svalue, - const=const, add_impl_const=add_impl_const, volatile=volatile, - ptr=ptr_level, ptr_restrict=ptr_restrict, ptr_const=ptr_const, ptr_volatile=ptr_volatile, - symbolic_mode=symbolic_mode, struct_var=struct_var) + storage=storage, ctype=ctype, typegen=typegen, + value=_value, svalue=_svalue, + const=const, add_impl_const=add_impl_const, volatile=volatile, + ptr=ptr_level, ptr_restrict=ptr_restrict, ptr_const=ptr_const, ptr_volatile=ptr_volatile, + symbolic_mode=symbolic_mode, struct_var=struct_var) self.shape = shape self.sshape = sshape @@ -644,7 +657,7 @@ class CodegenArray(CodegenVariable): return self.shape.size if (self.sshape is not None): return self.sshape.size - msg='unknown array dim.' + msg = 'unknown array dim.' raise RuntimeError(msg) def ptr_ctype(self, impl=True, add_impl_const=None, cast=False): @@ -652,39 +665,38 @@ class CodegenArray(CodegenVariable): add_impl_const = self.add_impl_const if (add_impl_const is None) else add_impl_const dim = self.array_dim() - ptr_const = self.ptr_const[dim:] + ptr_const = self.ptr_const[dim:] ptr_volatile = self.ptr_volatile[dim:] ptr_restrict = self.ptr_restrict[dim:] - ptrs=[] - for i, (c,v,r) in enumerate(zip(ptr_const, ptr_volatile, ptr_restrict)): - if i==self.ptr_level-1: + ptrs = [] + for i, (c, v, r) in enumerate(zip(ptr_const, ptr_volatile, ptr_restrict)): + if i == self.ptr_level-1: c = c or (impl and add_impl_const) - ptr=' $*{const}${volatile}${restrict}'.format( - const = 'const ' if (c and not cast) else '', - volatile = 'volatile ' if (v and not cast) else '', - restrict = 'restrict ' if (r and not cast) else '') + ptr = ' $*{const}${volatile}${restrict}'.format( + const='const ' if (c and not cast) else '', + volatile='volatile ' if (v and not cast) else '', + restrict='restrict ' if (r and not cast) else '') ptrs.append(ptr) ptr_ctype = ''.join(ptrs) else: - ptr_ctype='' + ptr_ctype = '' return ptr_ctype - class CodegenVector(CodegenVariable): def __init__(self, name, ctype, dim, typegen, - value=None,svalue=None, - storage=None, const=False, volatile=False, - ptr=False, ptr_const=None, ptr_volatile=None, ptr_restrict=None, - add_impl_const=False, nl=None, - symbolic_mode=False, struct_var=None, - init=None): - super(CodegenVector,self).__init__(name=name,ctype=ctype,value=value,typegen=typegen, - const=const, volatile=volatile, add_impl_const=add_impl_const, - storage=storage, nl=nl, - ptr=ptr, ptr_const=ptr_const, ptr_volatile=ptr_volatile, ptr_restrict=ptr_restrict, - symbolic_mode=symbolic_mode,struct_var=struct_var,init=init) + value=None, svalue=None, + storage=None, const=False, volatile=False, + ptr=False, ptr_const=None, ptr_volatile=None, ptr_restrict=None, + add_impl_const=False, nl=None, + symbolic_mode=False, struct_var=None, + init=None): + super(CodegenVector, self).__init__(name=name, ctype=ctype, value=value, typegen=typegen, + const=const, volatile=volatile, add_impl_const=add_impl_const, + storage=storage, nl=nl, + ptr=ptr, ptr_const=ptr_const, ptr_volatile=ptr_volatile, ptr_restrict=ptr_restrict, + symbolic_mode=symbolic_mode, struct_var=struct_var, init=init) self.value = value self._dim = dim @@ -699,11 +711,11 @@ class CodegenVector(CodegenVariable): def dim(self): return self._dim - def sval(self,i=None): + def sval(self, i=None): if i is not None: - assert i<self.dim + assert i < self.dim if self.is_symbolic(): - return '{}{}[{}]'.format(self.access_prefix(False),self.name,i) + return '{}{}[{}]'.format(self.access_prefix(False), self.name, i) else: return self.svalue[i] else: @@ -711,64 +723,64 @@ class CodegenVector(CodegenVariable): return self.access_prefix(False) else: expansion = ','.join(self.svalue) - return '{ '+ expansion + ' }' + return '{ ' + expansion + ' }' - def __getitem__(self,i): + def __getitem__(self, i): return self.sval(i) def __repr__(self): if self.is_symbolic(): - return '{}({})'.format(self.name,self.ctype) + return '{}({})'.format(self.name, self.ctype) else: vals = '['+','.join(self.svalue)+']' - return '{}({},{})'.format(self.name,self.ctype,vals) + return '{}({},{})'.format(self.name, self.ctype, vals) class CodegenVectorClBuiltin(CodegenVector): - def __init__(self,name,btype,dim,typegen, - value=None,access_mode=None, - const=False, add_impl_const=False, - storage=None, nl=None, - init=None, - symbolic_mode=False, struct_var=None,**kwds): + def __init__(self, name, btype, dim, typegen, + value=None, access_mode=None, + const=False, add_impl_const=False, + storage=None, nl=None, + init=None, + symbolic_mode=False, struct_var=None, **kwds): factor = typegen.components(btype) - btype = typegen.basetype(btype) + btype = typegen.basetype(btype) dim *= factor if (dim > 1): ctype = btype+str(dim) - access_mode = access_mode if access_mode else ('pos' if dim<=4 else 'hex') - msg='Wrong vector size {}'.format(dim) + access_mode = access_mode if access_mode else ('pos' if dim <= 4 else 'hex') + msg = 'Wrong vector size {}'.format(dim) assert dim in typegen.vsizes - msg='Invalid basetype {} for vector.'.format(btype) + msg = 'Invalid basetype {} for vector.'.format(btype) assert btype in (typegen.float_base_types + typegen.signed_base_types + typegen.unsigned_base_types), msg - msg='Invalid builtin type {}.'.format(ctype) + msg = 'Invalid builtin type {}.'.format(ctype) assert ctype in typegen.builtin_types, ctype else: # scalar type ctype = btype - access_mode=None + access_mode = None svalue = None if (value is not None): dtype = ctype_to_dtype(btype) - value = np.asarray(value,dtype) + value = np.asarray(value, dtype) assert value.size == dim - svalue = [typegen.dump(np.asarray([f],dtype=dtype)[0]) for f in value] + svalue = [typegen.dump(np.asarray([f], dtype=dtype)[0]) for f in value] - super(CodegenVectorClBuiltin,self).__init__(name=name,ctype=ctype,dim=dim,typegen=typegen, - value=value,svalue=svalue, const=const, add_impl_const=add_impl_const, - storage=storage, nl=nl, symbolic_mode=symbolic_mode, struct_var=struct_var, - init=init) - self.btype = btype + super(CodegenVectorClBuiltin, self).__init__(name=name, ctype=ctype, dim=dim, typegen=typegen, + value=value, svalue=svalue, const=const, add_impl_const=add_impl_const, + storage=storage, nl=nl, symbolic_mode=symbolic_mode, struct_var=struct_var, + init=init) + self.btype = btype self.access_mode = access_mode def newvar(self, name, btype=None, dim=None, **kwds): btype = first_not_None(btype, self.btype) dim = first_not_None(dim, self.dim) return super(CodegenVectorClBuiltin, self).newvar(name=name, btype=btype, dim=dim, - **kwds) + **kwds) def view(self, name, components, const=False): if isinstance(components, slice): @@ -781,32 +793,32 @@ class CodegenVectorClBuiltin(CodegenVector): else: raise ValueError('Unknown components type {}.'.format(components.__class__.__name__)) - if dim>self.dim: + if dim > self.dim: raise ValueError('Dimension of view is greater than original vector!') return CodegenVectorClBuiltin(name=name, - btype=self.btype, - dim=dim, - typegen=self.typegen, - access_mode=self.access_mode, - const=self.const or const, - add_impl_const=self.add_impl_const, - storage=self.storage, - symbolic_mode=self.symbolic_mode, - value = self.value[components] if (self.value is not None) else None, - init=self[components]) + btype=self.btype, + dim=dim, + typegen=self.typegen, + access_mode=self.access_mode, + const=self.const or const, + add_impl_const=self.add_impl_const, + storage=self.storage, + symbolic_mode=self.symbolic_mode, + value=self.value[components] if (self.value is not None) else None, + init=self[components]) def set_value(self, value, svalue=None): assert (value is not None) value = to_list(value) dtype = ctype_to_dtype(self.btype) - value = np.asarray(value,dtype).copy() + value = np.asarray(value, dtype).copy() if (value.size != self.dim): raise ValueError('value dimension mismatch!') if (self.value != value).any(): if self.known(): - msg='Value was already set in variable {}!'.format(self.name) + msg = 'Value was already set in variable {}!'.format(self.name) raise RuntimeError(msg) self.value = value @@ -815,10 +827,10 @@ class CodegenVectorClBuiltin(CodegenVector): else: self.svalue = [self.typegen.dump(f) for f in value] - def sval(self,i=None): + def sval(self, i=None): if self.is_symbolic(): - if (i is not None) and (self.dim>1): - return self.access_prefix(True) + self.typegen.vtype_access(i,self.dim,self.access_mode) + if (i is not None) and (self.dim > 1): + return self.access_prefix(True) + self.typegen.vtype_access(i, self.dim, self.access_mode) else: return self.access_prefix(False) else: @@ -831,99 +843,99 @@ class CodegenVectorClBuiltin(CodegenVector): dim = self.dim if isinstance(key, range): key = tuple(key) - if isinstance(key,slice) : + if isinstance(key, slice): ids = tuple(range(*key.indices(dim))) - if self.declared and key.indices(dim)==(0,dim,1): + if self.declared and key.indices(dim) == (0, dim, 1): return self.name else: return self.__getitem__(ids) elif key is Ellipsis: return self.__getitem__(slice(None)) - elif isinstance(key, (tuple,list)): + elif isinstance(key, (tuple, list)): if self.is_symbolic(): - if self.dim>1: + if self.dim > 1: mode = self.access_mode access = self.access_prefix(True) - access += ('s' if mode.lower()=='hex' else '') - access += ''.join([self.typegen.vtype_component_adressing(i,mode) for i in key]) + access += ('s' if mode.lower() == 'hex' else '') + access += ''.join([self.typegen.vtype_component_adressing(i, mode) for i in key]) else: - assert len(key)==1 and key[0]==0 + assert len(key) == 1 and key[0] == 0 access = self.access_prefix(False) else: - ctype = self.btype + (str(len(key)) if len(key)!=1 else '') + ctype = self.btype + (str(len(key)) if len(key) != 1 else '') value = [self.svalue[i] for i in key] return '({})({})'.format(ctype, ','.join(value)) return access - elif isinstance(key, (int, np.integer)) : - if key<0: + elif isinstance(key, (int, np.integer)): + if key < 0: key += dim - if key<0 or key>=dim: + if key < 0 or key >= dim: raise IndexError("The index {} is out of range.".format(key)) return self.sval(key) else: - msg='Invalid key type {}!'.format(type(key)) + msg = 'Invalid key type {}!'.format(type(key)) raise TypeError(msg) def declare(self, codegen=None, init=None, **kargs): init = first_not_None(init, self.init) if isinstance(init, int): init = ','.join([self.typegen.dump(init) for _ in range(self.dim)]) - init = '({})({})'.format(self.ctype,init) - elif init.__class__ in [list,tuple,np.ndarray]: + init = '({})({})'.format(self.ctype, init) + elif init.__class__ in [list, tuple, np.ndarray]: init = ','.join([self.typegen.dump(init[i]) for i in range(self.dim)]) - init = '({})({})'.format(self.ctype,init) - return super(CodegenVectorClBuiltin,self).declare(init=init, codegen=codegen, **kargs) + init = '({})({})'.format(self.ctype, init) + return super(CodegenVectorClBuiltin, self).declare(init=init, codegen=codegen, **kargs) class CodegenVectorClBuiltinFunc(CodegenVectorClBuiltin): - def __init__(self,fname,name,btype,dim,typegen, - value=None,access_mode='pos', - symbolic_mode=False, - const=False): - super(CodegenVectorClBuiltinFunc,self).__init__(name=name,btype=btype,dim=dim,typegen=typegen, - value=value,access_mode=access_mode,const=const,symbolic_mode=symbolic_mode) + def __init__(self, fname, name, btype, dim, typegen, + value=None, access_mode='pos', + symbolic_mode=False, + const=False): + super(CodegenVectorClBuiltinFunc, self).__init__(name=name, btype=btype, dim=dim, typegen=typegen, + value=value, access_mode=access_mode, const=const, symbolic_mode=symbolic_mode) self.fname = fname - def fval(self,i=None): + def fval(self, i=None): if i is None: value = [self.fval(i) for i in range(self.dim)] return '({})({})'.format(self.ctype, ','.join(value)) else: - assert i<self.dim - return 'get_{}({})'.format(self.fname,i) + assert i < self.dim + return 'get_{}({})'.format(self.fname, i) def declare(self, codegen=None, init=None, **kargs): if init is False: init = None else: init = self.fval() if not self.known() else init - return super(CodegenVectorClBuiltinFunc,self).declare(init=init, codegen=codegen, **kargs) + return super(CodegenVectorClBuiltinFunc, self).declare(init=init, codegen=codegen, **kargs) + class CodegenStruct(CodegenVariable): def __init__(self, name, struct, - storage=None, const=False, volatile=False, - ptr=False, ptr_const=None, ptr_volatile=None, ptr_restrict=None, - add_impl_const=False, nl=None, - symbolic_mode=False, - struct_var=None, - value=None, - var_overrides=None): - - super(CodegenStruct,self).__init__( - name=name, - ctype=struct.ctype, - typegen=struct.typegen, - storage=storage, const=const, volatile=volatile, - ptr=ptr, ptr_const=ptr_const, - ptr_volatile=ptr_volatile, ptr_restrict=ptr_restrict, - add_impl_const=add_impl_const, nl=nl, - value=value, - symbolic_mode=symbolic_mode, - struct_var=struct_var) + storage=None, const=False, volatile=False, + ptr=False, ptr_const=None, ptr_volatile=None, ptr_restrict=None, + add_impl_const=False, nl=None, + symbolic_mode=False, + struct_var=None, + value=None, + var_overrides=None): + + super(CodegenStruct, self).__init__( + name=name, + ctype=struct.ctype, + typegen=struct.typegen, + storage=storage, const=const, volatile=volatile, + ptr=ptr, ptr_const=ptr_const, + ptr_volatile=ptr_volatile, ptr_restrict=ptr_restrict, + add_impl_const=add_impl_const, nl=nl, + value=value, + symbolic_mode=symbolic_mode, + struct_var=struct_var) self.genvars(struct, var_overrides) - def newvar(self, *args, **kwds): kwds.setdefault('cls', CodegenVariable) return super(CodegenStruct, self).newvar(*args, **kwds) @@ -931,16 +943,16 @@ class CodegenStruct(CodegenVariable): def force_symbolic(self, force=True): if force is None: return - super(CodegenStruct,self).force_symbolic(force) - for k,var in self.vars.items(): + super(CodegenStruct, self).force_symbolic(force) + for k, var in self.vars.items(): var.force_symbolic(force) - def __getitem__(self,key): + def __getitem__(self, key): if key in self.vars: return self.vars[key] else: - msg='Unknown field {} in struct {}.\nAvailable fields are: {}' - msg=msg.format(key,self.name,self.vars.keys()) + msg = 'Unknown field {} in struct {}.\nAvailable fields are: {}' + msg = msg.format(key, self.name, self.vars.keys()) raise KeyError(msg) def __getattr__(self, name): @@ -956,27 +968,27 @@ class CodegenStruct(CodegenVariable): self.vars = VarDict() struct_vars = re.compile(r'\s+((?:struct\s+)?\w+)\s+((?:\s*\**(?:\w+)(?:\[\d+\])*[,;])+)') - var_decl = re.compile(r'(\**)(\w+)((?:\[\d+\])*)') + var_decl = re.compile(r'(\**)(\w+)((?:\[\d+\])*)') lines = struct.c_decl().split('\n') svalue = [] for l in lines: match = struct_vars.match(l) if match: - ctype = match.group(1) - variables = match.group(2).replace(';','').split(',') + ctype = match.group(1) + variables = match.group(2).replace(';', '').split(',') for var in variables: match = var_decl.match(var) - ptrs = match.group(1) + ptrs = match.group(1) fieldname = match.group(2) - array = match.group(3) + array = match.group(3) - nptrs = len(ptrs) if ptrs else 0 - narray = [int(x) for x in array[:-1].replace('[','').split(']')] \ - if array else None + nptrs = len(ptrs) if ptrs else 0 + narray = [int(x) for x in array[:-1].replace('[', '').split(']')] \ + if array else None is_struct = (struct.fields()[fieldname][0].fields is not None) - if nptrs>0: + if nptrs > 0: raise RuntimeError('Pointer variables are not supported yet (opencl unsupported)!') elif narray is not None: raise RuntimeError('Static array variables are not supported yet!') @@ -996,31 +1008,31 @@ class CodegenStruct(CodegenVariable): var.struct_var = self var.const = self.const elif (ctype in hysop.backend.device.opencl.opencl_types.builtin_types): - tg=struct.typegen + tg = struct.typegen btype = tg.basetype(ctype) - dim = tg.components(ctype) + dim = tg.components(ctype) if (field_value is not None) and not isinstance(field_value, np.ndarray): field_value = np.asarray([field_value], dtype=btype) var = CodegenVectorClBuiltin(name=fieldname, - btype=btype, dim=dim, access_mode=None, - const=self.const, - value=field_value, - typegen=struct.typegen, - struct_var=self) + btype=btype, dim=dim, access_mode=None, + const=self.const, + value=field_value, + typegen=struct.typegen, + struct_var=self) else: - var= CodegenVariable( - name=fieldname, - ctype=ctype, - const=self.const, - value=field_value, - typegen=struct.typegen, - struct_var=self) + var = CodegenVariable( + name=fieldname, + ctype=ctype, + const=self.const, + value=field_value, + typegen=struct.typegen, + struct_var=self) var.force_symbolic(False) decl = var() decl = decl.replace('\n', '\n\t') - sval = '.{} $= {}'.format(fieldname,decl) + sval = '.{} $= {}'.format(fieldname, decl) svalue.append(sval) var.force_symbolic(self.symbolic_mode) @@ -1029,7 +1041,7 @@ class CodegenStruct(CodegenVariable): if self.known(): self.svalue = '{\n\t' + ',\n\t'.join(svalue) + '\n}' - def __getitem__(self,key): + def __getitem__(self, key): return self.vars[key] @@ -1038,21 +1050,21 @@ if __name__ == '__main__': tg = test_typegen('float') print(':: ARRAYS ::') - var = CodegenArray(name='A0',ctype='float',dim=3, - value=[[ - [1,2,3], - [4,5,6], - [7,8,9] - ], [ - [10,11,12], - [13,14,15], - [16,17,18] - ]],typegen=tg) + var = CodegenArray(name='A0', ctype='float', dim=3, + value=[[ + [1, 2, 3], + [4, 5, 6], + [7, 8, 9] + ], [ + [10, 11, 12], + [13, 14, 15], + [16, 17, 18] + ]], typegen=tg) print(var.declare()) # runtime known variable print(':: SYMBOLIC VECTOR ::') - var = CodegenVectorClBuiltin('gid','int',3, tg) + var = CodegenVectorClBuiltin('gid', 'int', 3, tg) print(var()) for i in range(var.dim): print(var[i]) @@ -1062,17 +1074,17 @@ if __name__ == '__main__': # change access mode print(':: ACCESS MODES ::') - var = CodegenVectorClBuiltin('ids','int',4, tg, access_mode='pos') + var = CodegenVectorClBuiltin('ids', 'int', 4, tg, access_mode='pos') print(var[::2]) - var = CodegenVectorClBuiltin('ids','int',16, tg, access_mode='hex') + var = CodegenVectorClBuiltin('ids', 'int', 16, tg, access_mode='hex') print(var[::2]) - var = CodegenVectorClBuiltin('ids','int',16, tg, access_mode='HEX') + var = CodegenVectorClBuiltin('ids', 'int', 16, tg, access_mode='HEX') print(var[::2]) print() # compilation time known variable print(':: KNOWN VECTOR ::') - var = CodegenVectorClBuiltin('lid','int',3, tg, value=(256,512,1024)) + var = CodegenVectorClBuiltin('lid', 'int', 3, tg, value=(256, 512, 1024)) print(var()) for i in range(var.dim): print(var[i]) @@ -1080,9 +1092,9 @@ if __name__ == '__main__': print(var.declare(const=True)) print() - #force the use of symbolic value + # force the use of symbolic value print(':: FORCE SYMBOLIC ACCESS ::') - var = CodegenVectorClBuiltin('id','int',4, tg, value=(1,2,3,4)) + var = CodegenVectorClBuiltin('id', 'int', 4, tg, value=(1, 2, 3, 4)) print(var.declare()) var.force_symbolic() print(var[:]) @@ -1092,7 +1104,7 @@ if __name__ == '__main__': # default decimal float dumper print(':: DEFAULT FLOAT DUMPER ::') - var = CodegenVectorClBuiltin('size','float',4, tg, value=(1.0,2.0,4.0,8.0)) + var = CodegenVectorClBuiltin('size', 'float', 4, tg, value=(1.0, 2.0, 4.0, 8.0)) print(var()) for i in range(var.dim): print(var[i]) @@ -1102,8 +1114,8 @@ if __name__ == '__main__': # hexadecimal deciml float dumper print(':: HEXADECIMAL FLOAT DUMPER ::') - var = CodegenVectorClBuiltin('size_hex','float',4, value=(1.0,2.0,4.0,8.0), - typegen=test_typegen('float',float_dump_mode='hex')) + var = CodegenVectorClBuiltin('size_hex', 'float', 4, value=(1.0, 2.0, 4.0, 8.0), + typegen=test_typegen('float', float_dump_mode='hex')) print(var()) for i in range(var.dim): print(var[i]) @@ -1112,8 +1124,6 @@ if __name__ == '__main__': print() # bultin opencl functions - for fname,name in [('global_size','gsize'), ('local_size','lsize'), ('global_id','gid'), ('local_id','lid')]: - var = CodegenVectorClBuiltinFunc(fname,name,'int',3, tg) + for fname, name in [('global_size', 'gsize'), ('local_size', 'lsize'), ('global_id', 'gid'), ('local_id', 'lid')]: + var = CodegenVectorClBuiltinFunc(fname, name, 'int', 3, tg) print(var.declare()) - - diff --git a/hysop/backend/device/opencl/operator/custom.py b/hysop/backend/device/opencl/operator/custom.py index eb4c7b1bd32dfb77e7670400149279017df8dfb0..976056f1b18a2e149420cc0a0f165c82a739f02c 100644 --- a/hysop/backend/device/opencl/operator/custom.py +++ b/hysop/backend/device/opencl/operator/custom.py @@ -40,7 +40,7 @@ class OpenClCustomOperator(CustomOperatorBase, OpenClOperator): fn = f.continuous_fields()[0].name mesh_info = MeshInfoStruct.create_from_mesh(fn+"_mesh", self.typegen, f.mesh, storage=OpenClCodeGenerator.default_keywords['constant']) - mesh_info[1].declare(cg, _const=True) + mesh_info[1].declare(cg, _const=True, static=True) cg.append(f"""int3 get_{fn}i_xyz(int i) {{ int iz = i/({fn}_mesh.local_mesh.resolution.x*{fn}_mesh.local_mesh.resolution.y); int iy = (i-({fn}_mesh.local_mesh.resolution.x*{fn}_mesh.local_mesh.resolution.y)*iz)/({fn}_mesh.local_mesh.resolution.x);