diff --git a/.flake8 b/.flake8 index f4cc20cdb9b463d730f1b33406c3ab41de5d367a..5701df707c82aa801b4a6bb80a98a56b42cb1e8c 100644 --- a/.flake8 +++ b/.flake8 @@ -3,4 +3,4 @@ max-line-length=120 exclude=pystencils/jupyter.py, pystencils/plot.py pystencils/session.py -ignore = W293 W503 W291 C901 +ignore = W293 W503 W291 C901 E741 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 25fd966970490ad8260b82ea35f137e0407562ba..9bf21bcfbc32fe15e0dc15aef4f2a70b7b489c7e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,6 +13,7 @@ tests-and-coverage: - $ENABLE_NIGHTLY_BUILDS image: i10git.cs.fau.de:5005/pycodegen/pycodegen/full script: + - env - pip list - export NUM_CORES=$(nproc --all) - mkdir -p ~/.config/matplotlib diff --git a/conftest.py b/conftest.py index d6b74818a5d90824dc09ab6faf802ec86e77c1da..eba25a7424432f630e75f642fcc7e755304ea08e 100644 --- a/conftest.py +++ b/conftest.py @@ -152,6 +152,7 @@ class IPyNbFile(pytest.File): notebook = nbformat.read(notebook_contents, 4) code, _ = exporter.from_notebook_node(notebook) yield IPyNbTest(self.name, self, code) + # pytest v 2.4>: yield IPyNbTest.from_parent(name=self.name, parent=self, code=code) def teardown(self): pass @@ -161,3 +162,4 @@ def pytest_collect_file(path, parent): glob_exprs = ["*demo*.ipynb", "*tutorial*.ipynb", "test_*.ipynb"] if any(path.fnmatch(g) for g in glob_exprs): return IPyNbFile(path, parent) + # pytest v 2.4 >: return IPyNbFile.from_parent(fspath=path, parent=parent) diff --git a/pystencils/assignment.py b/pystencils/assignment.py index 147a829f4d6698dc67ffd9a50a7b043c34064f9c..d56d0f4d6d1421463cef4d9cc921d3d309e571cb 100644 --- a/pystencils/assignment.py +++ b/pystencils/assignment.py @@ -53,7 +53,7 @@ else: # Tuple of things that can be on the lhs of an assignment assignable = (sp.Symbol, MatrixSymbol, MatrixElement, sp.Indexed) if not isinstance(lhs, assignable): - raise TypeError("Cannot assign to lhs of type %s." % type(lhs)) + raise TypeError(f"Cannot assign to lhs of type {type(lhs)}.") return sp.Rel.__new__(cls, lhs, rhs, **assumptions) __str__ = assignment_str diff --git a/pystencils/astnodes.py b/pystencils/astnodes.py index 7bce77e0dd99926d71ccbfc6bf2c5722e84c99f1..85c6033c513bb42646c76168eb13abc51f9b37ce 100644 --- a/pystencils/astnodes.py +++ b/pystencils/astnodes.py @@ -113,14 +113,14 @@ class Conditional(Node): return self.__repr__() def __repr__(self): - repr = 'if:({!r}) '.format(self.condition_expr) + result = f'if:({self.condition_expr!r}) ' if self.true_block: - repr += '\n\t{}) '.format(self.true_block) + result += f'\n\t{self.true_block}) ' if self.false_block: - repr = 'else: '.format(self.false_block) - repr += '\n\t{} '.format(self.false_block) + result = 'else: ' + result += f'\n\t{self.false_block} ' - return repr + return result def replace_by_true_block(self): """Replaces the conditional by its True block""" @@ -264,7 +264,7 @@ class KernelFunction(Node): def __repr__(self): params = [p.symbol for p in self.get_parameters()] - return '{0} {1}({2})'.format(type(self).__name__, self.function_name, params) + return f'{type(self).__name__} {self.function_name}({params})' def compile(self, *args, **kwargs): if self._compile_function is None: @@ -475,11 +475,11 @@ class LoopOverCoordinate(Node): @staticmethod def get_loop_counter_name(coordinate_to_loop_over): - return "%s_%s" % (LoopOverCoordinate.LOOP_COUNTER_NAME_PREFIX, coordinate_to_loop_over) + return f"{LoopOverCoordinate.LOOP_COUNTER_NAME_PREFIX}_{coordinate_to_loop_over}" @staticmethod def get_block_loop_counter_name(coordinate_to_loop_over): - return "%s_%s" % (LoopOverCoordinate.BlOCK_LOOP_COUNTER_NAME_PREFIX, coordinate_to_loop_over) + return f"{LoopOverCoordinate.BlOCK_LOOP_COUNTER_NAME_PREFIX}_{coordinate_to_loop_over}" @property def loop_counter_name(self): @@ -612,7 +612,7 @@ class SympyAssignment(Node): replacement.parent = self self.rhs = replacement else: - raise ValueError('%s is not in args of %s' % (replacement, self.__class__)) + raise ValueError(f'{replacement} is not in args of {self.__class__}') def __repr__(self): return repr(self.lhs) + " ↠" + repr(self.rhs) @@ -620,7 +620,7 @@ class SympyAssignment(Node): def _repr_html_(self): printed_lhs = sp.latex(self.lhs) printed_rhs = sp.latex(self.rhs) - return "${printed_lhs} \\leftarrow {printed_rhs}$".format(printed_lhs=printed_lhs, printed_rhs=printed_rhs) + return f"${printed_lhs} \\leftarrow {printed_rhs}$" def __hash__(self): return hash((self.lhs, self.rhs)) @@ -663,7 +663,7 @@ class ResolvedFieldAccess(sp.Indexed): def __str__(self): top = super(ResolvedFieldAccess, self).__str__() - return "%s (%s)" % (top, self.typed_symbol.dtype) + return f"{top} ({self.typed_symbol.dtype})" def __getnewargs__(self): return self.base, self.indices[0], self.field, self.offsets, self.idx_coordinate_values @@ -740,7 +740,7 @@ def early_out(condition): def get_dummy_symbol(dtype='bool'): - return TypedSymbol('dummy%s' % uuid.uuid4().hex, create_type(dtype)) + return TypedSymbol(f'dummy{uuid.uuid4().hex}', create_type(dtype)) class SourceCodeComment(Node): diff --git a/pystencils/backends/cbackend.py b/pystencils/backends/cbackend.py index 46d9e3a77e6a163acec4fbfcf1ddf0f9a15f8712..bb25a6a4ca9e119886d3b553ab937b188bad1173 100644 --- a/pystencils/backends/cbackend.py +++ b/pystencils/backends/cbackend.py @@ -158,7 +158,7 @@ class CustomCodeNode(Node): class PrintNode(CustomCodeNode): # noinspection SpellCheckingInspection def __init__(self, symbol_to_print): - code = '\nstd::cout << "%s = " << %s << std::endl; \n' % (symbol_to_print.name, symbol_to_print.name) + code = f'\nstd::cout << "{symbol_to_print.name} = " << {symbol_to_print.name} << std::endl; \n' super(PrintNode, self).__init__(code, symbols_read=[symbol_to_print], symbols_defined=set()) self.headers.append("<iostream>") @@ -203,12 +203,12 @@ class CBackend: return str(node) def _print_KernelFunction(self, node): - function_arguments = ["%s %s" % (self._print(s.symbol.dtype), s.symbol.name) for s in node.get_parameters()] + function_arguments = [f"{self._print(s.symbol.dtype)} {s.symbol.name}" for s in node.get_parameters()] launch_bounds = "" if self._dialect == 'cuda': max_threads = node.indexing.max_threads_per_block() if max_threads: - launch_bounds = "__launch_bounds__({}) ".format(max_threads) + launch_bounds = f"__launch_bounds__({max_threads}) " func_declaration = "FUNC_PREFIX %svoid %s(%s)" % (launch_bounds, node.function_name, ", ".join(function_arguments)) if self._signatureOnly: @@ -222,19 +222,19 @@ class CBackend: return "{\n%s\n}" % (self._indent + self._indent.join(block_contents.splitlines(True))) def _print_PragmaBlock(self, node): - return "%s\n%s" % (node.pragma_line, self._print_Block(node)) + return f"{node.pragma_line}\n{self._print_Block(node)}" def _print_LoopOverCoordinate(self, node): counter_symbol = node.loop_counter_name - start = "int %s = %s" % (counter_symbol, self.sympy_printer.doprint(node.start)) - condition = "%s < %s" % (counter_symbol, self.sympy_printer.doprint(node.stop)) - update = "%s += %s" % (counter_symbol, self.sympy_printer.doprint(node.step),) - loop_str = "for (%s; %s; %s)" % (start, condition, update) + start = f"int {counter_symbol} = {self.sympy_printer.doprint(node.start)}" + condition = f"{counter_symbol} < {self.sympy_printer.doprint(node.stop)}" + update = f"{counter_symbol} += {self.sympy_printer.doprint(node.step)}" + loop_str = f"for ({start}; {condition}; {update})" prefix = "\n".join(node.prefix_lines) if prefix: prefix += "\n" - return "%s%s\n%s" % (prefix, loop_str, self._print(node.body)) + return f"{prefix}{loop_str}\n{self._print(node.body)}" def _print_SympyAssignment(self, node): if node.is_declaration: @@ -262,7 +262,7 @@ class CBackend: instr = 'maskStore' if aligned else 'maskStoreU' printed_mask = self.sympy_printer.doprint(mask) if self._vector_instruction_set['dataTypePrefix']['double'] == '__mm256d': - printed_mask = "_mm256_castpd_si256({})".format(printed_mask) + printed_mask = f"_mm256_castpd_si256({printed_mask})" rhs_type = get_type_of_expression(node.rhs) if type(rhs_type) is not VectorType: @@ -274,7 +274,7 @@ class CBackend: self.sympy_printer.doprint(rhs), printed_mask) + ';' else: - return "%s = %s;" % (self.sympy_printer.doprint(node.lhs), self.sympy_printer.doprint(node.rhs)) + return f"{self.sympy_printer.doprint(node.lhs)} = {self.sympy_printer.doprint(node.rhs)};" def _print_TemporaryMemoryAllocation(self, node): align = 64 @@ -314,7 +314,7 @@ class CBackend: raise ValueError("Problem with Conditional inside vectorized loop - use vec_any or vec_all") condition_expr = self.sympy_printer.doprint(node.condition_expr) true_block = self._print_Block(node.true_block) - result = "if (%s)\n%s " % (condition_expr, true_block) + result = f"if ({condition_expr})\n{true_block} " if node.false_block: false_block = self._print_Block(node.false_block) result += "else " + false_block @@ -343,7 +343,7 @@ class CustomSympyPrinter(CCodePrinter): if expr.exp.is_integer and expr.exp.is_number and 0 < expr.exp < 8: return "(" + self._print(sp.Mul(*[expr.base] * expr.exp, evaluate=False)) + ")" elif expr.exp.is_integer and expr.exp.is_number and - 8 < expr.exp < 0: - return "1 / ({})".format(self._print(sp.Mul(*[expr.base] * (-expr.exp), evaluate=False))) + return f"1 / ({self._print(sp.Mul(*([expr.base] * -expr.exp), evaluate=False))})" else: return super(CustomSympyPrinter, self)._print_Pow(expr) @@ -362,10 +362,10 @@ class CustomSympyPrinter(CCodePrinter): return result.replace("\n", "") def _print_Abs(self, expr): - if expr.is_integer: - return 'abs({0})'.format(self._print(expr.args[0])) + if expr.args[0].is_integer: + return f'abs({self._print(expr.args[0])})' else: - return 'fabs({0})'.format(self._print(expr.args[0])) + return f'fabs({self._print(expr.args[0])})' def _print_Type(self, node): return str(node) @@ -382,37 +382,37 @@ class CustomSympyPrinter(CCodePrinter): return expr.to_c(self._print) if isinstance(expr, reinterpret_cast_func): arg, data_type = expr.args - return "*((%s)(& %s))" % (self._print(PointerType(data_type, restrict=False)), self._print(arg)) + return f"*(({self._print(PointerType(data_type, restrict=False))})(& {self._print(arg)}))" elif isinstance(expr, address_of): assert len(expr.args) == 1, "address_of must only have one argument" - return "&(%s)" % self._print(expr.args[0]) + return f"&({self._print(expr.args[0])})" elif isinstance(expr, cast_func): arg, data_type = expr.args if isinstance(arg, sp.Number) and arg.is_finite: return self._typed_number(arg, data_type) else: - return "((%s)(%s))" % (data_type, self._print(arg)) + return f"(({data_type})({self._print(arg)}))" elif isinstance(expr, fast_division): - return "({})".format(self._print(expr.args[0] / expr.args[1])) + return f"({self._print(expr.args[0] / expr.args[1])})" elif isinstance(expr, fast_sqrt): - return "({})".format(self._print(sp.sqrt(expr.args[0]))) + return f"({self._print(sp.sqrt(expr.args[0]))})" elif isinstance(expr, vec_any) or isinstance(expr, vec_all): return self._print(expr.args[0]) elif isinstance(expr, fast_inv_sqrt): - return "({})".format(self._print(1 / sp.sqrt(expr.args[0]))) + return f"({self._print(1 / sp.sqrt(expr.args[0]))})" elif isinstance(expr, sp.Abs): - return "abs({})".format(self._print(expr.args[0])) + return f"abs({self._print(expr.args[0])})" elif isinstance(expr, sp.Mod): if expr.args[0].is_integer and expr.args[1].is_integer: - return "({} % {})".format(self._print(expr.args[0]), self._print(expr.args[1])) + return f"({self._print(expr.args[0])} % {self._print(expr.args[1])})" else: - return "fmod({}, {})".format(self._print(expr.args[0]), self._print(expr.args[1])) + return f"fmod({self._print(expr.args[0])}, {self._print(expr.args[1])})" elif expr.func in infix_functions: - return "(%s %s %s)" % (self._print(expr.args[0]), infix_functions[expr.func], self._print(expr.args[1])) + return f"({self._print(expr.args[0])} {infix_functions[expr.func]} {self._print(expr.args[1])})" elif expr.func == int_power_of_2: - return "(1 << (%s))" % (self._print(expr.args[0])) + return f"(1 << ({self._print(expr.args[0])}))" elif expr.func == int_div: - return "((%s) / (%s))" % (self._print(expr.args[0]), self._print(expr.args[1])) + return f"(({self._print(expr.args[0])}) / ({self._print(expr.args[1])}))" else: name = expr.name if hasattr(expr, 'name') else expr.__class__.__name__ arg_str = ', '.join(self._print(a) for a in expr.args) @@ -540,14 +540,14 @@ class VectorizedCustomSympyPrinter(CustomSympyPrinter): result = self.instruction_set['/'].format(self._print(expr.args[0]), self._print(expr.args[1])) return result elif expr.func == fast_sqrt: - return "({})".format(self._print(sp.sqrt(expr.args[0]))) + return f"({self._print(sp.sqrt(expr.args[0]))})" elif expr.func == fast_inv_sqrt: result = self._scalarFallback('_print_Function', expr) if not result: if self.instruction_set['rsqrt']: return self.instruction_set['rsqrt'].format(self._print(expr.args[0])) else: - return "({})".format(self._print(1 / sp.sqrt(expr.args[0]))) + return f"({self._print(1 / sp.sqrt(expr.args[0]))})" elif isinstance(expr, vec_any): expr_type = get_type_of_expression(expr.args[0]) if type(expr_type) is not VectorType: diff --git a/pystencils/backends/cuda_backend.py b/pystencils/backends/cuda_backend.py index d590d65b4082e72745658f0b06eb152d64872944..ef8f22ea2e24ef00bf6a9ff1c020f0dbae2a131f 100644 --- a/pystencils/backends/cuda_backend.py +++ b/pystencils/backends/cuda_backend.py @@ -98,7 +98,7 @@ class CudaSympyPrinter(CustomSympyPrinter): if isinstance(expr, fast_division): return "__fdividef(%s, %s)" % tuple(self._print(a) for a in expr.args) elif isinstance(expr, fast_sqrt): - return "__fsqrt_rn(%s)" % tuple(self._print(a) for a in expr.args) + return f"__fsqrt_rn({tuple(self._print(a) for a in expr.args)})" elif isinstance(expr, fast_inv_sqrt): - return "__frsqrt_rn(%s)" % tuple(self._print(a) for a in expr.args) + return f"__frsqrt_rn({tuple(self._print(a) for a in expr.args)})" return super()._print_Function(expr) diff --git a/pystencils/backends/dot.py b/pystencils/backends/dot.py index 64610c47af6148d6008780ba80530d678e518486..83ae1c705d8600b06b5d5d85c31f7151a3f9beb0 100644 --- a/pystencils/backends/dot.py +++ b/pystencils/backends/dot.py @@ -57,7 +57,7 @@ def __shortened(node): params = node.get_parameters() param_names = [p.field_name for p in params if p.is_field_pointer] param_names += [p.symbol.name for p in params if not p.is_field_parameter] - return "Func: %s (%s)" % (node.function_name, ",".join(param_names)) + return f"Func: {node.function_name} ({','.join(param_names)})" elif isinstance(node, SympyAssignment): return repr(node.lhs) elif isinstance(node, Block): @@ -65,7 +65,7 @@ def __shortened(node): elif isinstance(node, Conditional): return repr(node) else: - raise NotImplementedError("Cannot handle node type %s" % (type(node),)) + raise NotImplementedError(f"Cannot handle node type {type(node)}") def print_dot(node, view=False, short=False, **kwargs): diff --git a/pystencils/backends/opencl_backend.py b/pystencils/backends/opencl_backend.py index 3ab7f820ea30adebf584977625b2e559f897ca27..1813d63ef6ce5f50c3fae276f6b3d00e8e5aff6c 100644 --- a/pystencils/backends/opencl_backend.py +++ b/pystencils/backends/opencl_backend.py @@ -98,7 +98,7 @@ class OpenClSympyPrinter(CudaSympyPrinter): if isinstance(expr, fast_division): return "native_divide(%s, %s)" % tuple(self._print(a) for a in expr.args) elif isinstance(expr, fast_sqrt): - return "native_sqrt(%s)" % tuple(self._print(a) for a in expr.args) + return f"native_sqrt({tuple(self._print(a) for a in expr.args)})" elif isinstance(expr, fast_inv_sqrt): - return "native_rsqrt(%s)" % tuple(self._print(a) for a in expr.args) + return f"native_rsqrt({tuple(self._print(a) for a in expr.args)})" return CustomSympyPrinter._print_Function(self, expr) diff --git a/pystencils/backends/simd_instruction_sets.py b/pystencils/backends/simd_instruction_sets.py index be8523e90913d7f62eb908ace8cbdf0189c31fbf..7e2be4dee3d1d6a0203c91dad91369ae1a9891a6 100644 --- a/pystencils/backends/simd_instruction_sets.py +++ b/pystencils/backends/simd_instruction_sets.py @@ -51,7 +51,7 @@ def get_vector_instruction_set(data_type='double', instruction_set='avx'): }) for comparison_op, constant in comparisons.items(): - base_names[comparison_op] = 'cmp[0, 1, %s]' % (constant,) + base_names[comparison_op] = f'cmp[0, 1, {constant}]' headers = { 'avx512': ['<immintrin.h>'], @@ -89,16 +89,16 @@ def get_vector_instruction_set(data_type='double', instruction_set='avx'): name = function_shortcut[:function_shortcut.index('[')] if intrinsic_id == 'makeVecConst': - arg_string = "({})".format(",".join(["{0}"] * result['width'])) + arg_string = f"({','.join(['{0}'] * result['width'])})" elif intrinsic_id == 'makeVec': params = ["{" + str(i) + "}" for i in reversed(range(result['width']))] - arg_string = "({})".format(",".join(params)) + arg_string = f"({','.join(params)})" elif intrinsic_id == 'makeVecBool': - params = ["(({{{i}}} ? -1.0 : 0.0)".format(i=i) for i in reversed(range(result['width']))] - arg_string = "({})".format(",".join(params)) + params = [f"(({{{i}}} ? -1.0 : 0.0)" for i in reversed(range(result['width']))] + arg_string = f"({','.join(params)})" elif intrinsic_id == 'makeVecConstBool': params = ["(({0}) ? -1.0 : 0.0)" for _ in range(result['width'])] - arg_string = "({})".format(",".join(params)) + arg_string = f"({','.join(params)})" else: args = function_shortcut[function_shortcut.index('[') + 1: -1] arg_string = "(" @@ -141,9 +141,9 @@ def get_vector_instruction_set(data_type='double', instruction_set='avx'): result['bool'] = "__mmask%d" % (size,) params = " | ".join(["({{{i}}} ? {power} : 0)".format(i=i, power=2 ** i) for i in range(8)]) - result['makeVecBool'] = "__mmask8(({}) )".format(params) + result['makeVecBool'] = f"__mmask8(({params}) )" params = " | ".join(["({{0}} ? {power} : 0)".format(power=2 ** i) for i in range(8)]) - result['makeVecConstBool'] = "__mmask8(({}) )".format(params) + result['makeVecConstBool'] = f"__mmask8(({params}) )" if instruction_set == 'avx' and data_type == 'float': result['rsqrt'] = "_mm256_rsqrt_ps({0})" diff --git a/pystencils/boundaries/boundaryhandling.py b/pystencils/boundaries/boundaryhandling.py index e164006350582bb1b05aa30c3570f07b53ae52e4..b80d3c72f707fdb75cc6c777729f8334772a8446 100644 --- a/pystencils/boundaries/boundaryhandling.py +++ b/pystencils/boundaries/boundaryhandling.py @@ -66,13 +66,13 @@ class FlagInterface: self._used_flags.add(flag) assert self._is_power_of_2(flag) return flag - raise ValueError("All available {} flags are reserved".format(self.max_bits)) + raise ValueError(f"All available {self.max_bits} flags are reserved") def reserve_flag(self, flag): assert self._is_power_of_2(flag) flag = self.dtype(flag) if flag in self._used_flags: - raise ValueError("The flag {flag} is already reserved".format(flag=flag)) + raise ValueError(f"The flag {flag} is already reserved") self._used_flags.add(flag) return flag @@ -392,12 +392,12 @@ class BoundaryDataSetter: def __setitem__(self, key, value): if key not in self.boundary_data_names: - raise KeyError("Invalid boundary data name %s. Allowed are %s" % (key, self.boundary_data_names)) + raise KeyError(f"Invalid boundary data name {key}. Allowed are {self.boundary_data_names}") self.index_array[key] = value def __getitem__(self, item): if item not in self.boundary_data_names: - raise KeyError("Invalid boundary data name %s. Allowed are %s" % (item, self.boundary_data_names)) + raise KeyError(f"Invalid boundary data name {item}. Allowed are {self.boundary_data_names}") return self.index_array[item] @@ -437,7 +437,7 @@ class BoundaryOffsetInfo(CustomCodeNode): @staticmethod def _offset_symbols(dim): - return [TypedSymbol("c%s" % (d,), create_type(np.int64)) for d in ['x', 'y', 'z'][:dim]] + return [TypedSymbol(f"c{d}", create_type(np.int64)) for d in ['x', 'y', 'z'][:dim]] INV_DIR_SYMBOL = TypedSymbol("invdir", "int") diff --git a/pystencils/cpu/cpujit.py b/pystencils/cpu/cpujit.py index 07a8a84d9c6d10ed8580a7ef83d6720b522cfd98..5b011535826fbb364595f75ea25f2922980ad6c0 100644 --- a/pystencils/cpu/cpujit.py +++ b/pystencils/cpu/cpujit.py @@ -362,7 +362,7 @@ def create_function_boilerplate_code(parameter_info, name, insert_checks=True): field = param.fields[0] pre_call_code += template_extract_array.format(name=field.name) post_call_code += template_release_buffer.format(name=field.name) - parameters.append("({dtype} *)buffer_{name}.buf".format(dtype=str(field.dtype), name=field.name)) + parameters.append(f"({str(field.dtype)} *)buffer_{field.name}.buf") if insert_checks: np_dtype = field.dtype.numpy_dtype @@ -375,12 +375,12 @@ def create_function_boilerplate_code(parameter_info, name, insert_checks=True): pre_call_code += template_check_array.format(cond=dtype_cond, what="data type", name=field.name, expected=str(field.dtype.numpy_dtype)) - item_size_cond = "buffer_{name}.itemsize == {size}".format(name=field.name, size=item_size) + item_size_cond = f"buffer_{field.name}.itemsize == {item_size}" pre_call_code += template_check_array.format(cond=item_size_cond, what="itemsize", name=field.name, expected=item_size) if field.has_fixed_shape: - shape_cond = ["buffer_{name}.shape[{i}] == {s}".format(s=s, name=field.name, i=i) + shape_cond = [f"buffer_{field.name}.shape[{i}] == {s}" for i, s in enumerate(field.spatial_shape)] shape_cond = " && ".join(shape_cond) pre_call_code += template_check_array.format(cond=shape_cond, what="shape", name=field.name, @@ -403,7 +403,7 @@ def create_function_boilerplate_code(parameter_info, name, insert_checks=True): parameters.append("buffer_{name}.strides[{i}] / {bytes}".format(bytes=item_size, i=param.symbol.coordinate, name=field.name)) elif param.is_field_shape: - parameters.append("buffer_{name}.shape[{i}]".format(i=param.symbol.coordinate, name=param.field_name)) + parameters.append(f"buffer_{param.field_name}.shape[{param.symbol.coordinate}]") else: extract_function, target_type = type_mapping[param.symbol.dtype.numpy_dtype.type] if np.issubdtype(param.symbol.dtype.numpy_dtype, np.complexfloating): @@ -490,8 +490,8 @@ class ExtensionModuleCode: includes = "\n".join(["#include %s" % (include_file,) for include_file in header_list]) print(includes, file=file) print("\n", file=file) - print("#define RESTRICT %s" % (restrict_qualifier,), file=file) - print("#define FUNC_PREFIX %s" % (function_prefix,), file=file) + print(f"#define RESTRICT {restrict_qualifier}", file=file) + print(f"#define FUNC_PREFIX {function_prefix}", file=file) print("\n", file=file) for ast, name in zip(self._ast_nodes, self._function_names): @@ -541,7 +541,7 @@ def compile_module(code, code_hash, base_dir): import sysconfig config_vars = sysconfig.get_config_vars() py_lib = os.path.join(config_vars["installed_base"], "libs", - "python{}.lib".format(config_vars["py_version_nodot"])) + f"python{config_vars['py_version_nodot']}.lib") run_compile_step(['link.exe', py_lib, '/DLL', '/out:' + lib_file, object_file]) elif platform.system().lower() == 'darwin': with atomic_file_write(lib_file) as file_name: diff --git a/pystencils/cpu/kernelcreation.py b/pystencils/cpu/kernelcreation.py index 38ce169af754fae27d80cadfa993ac83a03e0999..457944db6d5a6a4d18a6e0be48f78ef42876c757 100644 --- a/pystencils/cpu/kernelcreation.py +++ b/pystencils/cpu/kernelcreation.py @@ -129,7 +129,7 @@ def create_indexed_kernel(assignments: AssignmentOrAstNodeList, index_fields, fu rhs = idx_field[0](name) lhs = TypedSymbol(name, BasicType(data_type.get_element_type(name))) return SympyAssignment(lhs, rhs) - raise ValueError("Index %s not found in any of the passed index fields" % (name,)) + raise ValueError(f"Index {name} not found in any of the passed index fields") coordinate_symbol_assignments = [get_coordinate_symbol_assignment(n) for n in coordinate_names[:spatial_coordinates]] @@ -173,7 +173,7 @@ def add_openmp(ast_node, schedule="static", num_threads=True, collapse=None, ass assert type(ast_node) is ast.KernelFunction body = ast_node.body - threads_clause = "" if num_threads and isinstance(num_threads, bool) else " num_threads(%s)" % (num_threads,) + threads_clause = "" if num_threads and isinstance(num_threads, bool) else f" num_threads({num_threads})" wrapper_block = ast.PragmaBlock('#pragma omp parallel' + threads_clause, body.take_child_nodes()) body.append(wrapper_block) @@ -204,7 +204,7 @@ def add_openmp(ast_node, schedule="static", num_threads=True, collapse=None, ass except TypeError: pass - prefix = "#pragma omp for schedule(%s)" % (schedule,) + prefix = f"#pragma omp for schedule({schedule})" if collapse: prefix += " collapse(%d)" % (collapse, ) loop_to_parallelize.prefix_lines.append(prefix) diff --git a/pystencils/cpu/msvc_detection.py b/pystencils/cpu/msvc_detection.py index 94b2bcf5bc978c70c083ab3c2d0a6a6e0b2aea62..9cc1fc5ad64a9e50d24788f6e4eea8135cbf7a2c 100644 --- a/pystencils/cpu/msvc_detection.py +++ b/pystencils/cpu/msvc_detection.py @@ -71,7 +71,7 @@ def normalize_msvc_version(version): def get_environment_from_vc_vars_file(vc_vars_file, arch): out = subprocess.check_output( - 'cmd /u /c "{}" {} && set'.format(vc_vars_file, arch), + f'cmd /u /c "{vc_vars_file}" {arch} && set', stderr=subprocess.STDOUT, ).decode('utf-16le', errors='replace') diff --git a/pystencils/cpu/vectorization.py b/pystencils/cpu/vectorization.py index 12b492cf452e27220b3013ac6339aeaf6073c051..0ee5200a069bdc00e1bb751ba5fb914b0707a62b 100644 --- a/pystencils/cpu/vectorization.py +++ b/pystencils/cpu/vectorization.py @@ -115,7 +115,7 @@ def vectorize_inner_loops_and_adapt_load_stores(ast_node, vector_width, assume_a break typed_symbol = base.label assert type(typed_symbol.dtype) is PointerType, \ - "Type of access is {}, {}".format(typed_symbol.dtype, indexed) + f"Type of access is {typed_symbol.dtype}, {indexed}" vec_type = VectorType(typed_symbol.dtype.base_type, vector_width) use_aligned_access = aligned_access and assume_aligned diff --git a/pystencils/data_types.py b/pystencils/data_types.py index 786351f528573179543900bde760f675ddfe10a6..365ef8aa787733d61b4e8b5367eda1fe6daac51d 100644 --- a/pystencils/data_types.py +++ b/pystencils/data_types.py @@ -396,7 +396,7 @@ def ctypes_from_llvm(data_type): elif isinstance(data_type, ir.VoidType): return None # Void type is not supported by ctypes else: - raise NotImplementedError('Data type %s of %s is not supported yet' % (type(data_type), data_type)) + raise NotImplementedError(f'Data type {type(data_type)} of {data_type} is not supported yet') def to_llvm_type(data_type, nvvm_target=False): @@ -603,7 +603,7 @@ class BasicType(Type): elif name == 'bool': return 'bool' else: - raise NotImplementedError("Can map numpy to C name for %s" % (name,)) + raise NotImplementedError(f"Can map numpy to C name for {name}") def __init__(self, dtype, const=False): self.const = const diff --git a/pystencils/datahandling/parallel_datahandling.py b/pystencils/datahandling/parallel_datahandling.py index 535933300f73977d3ede92e714f2a381be92fa50..4d3fcdf7a68aeaaebbdf5fd2618432b9c0d455cc 100644 --- a/pystencils/datahandling/parallel_datahandling.py +++ b/pystencils/datahandling/parallel_datahandling.py @@ -383,7 +383,7 @@ class ParallelDataHandling(DataHandling): if not os.path.exists(directory): os.mkdir(directory) if os.path.isfile(directory): - raise RuntimeError("Trying to save to {}, but file exists already".format(directory)) + raise RuntimeError(f"Trying to save to {directory}, but file exists already") for field_name, data_name in self._field_name_to_cpu_data_name.items(): self.blocks.writeBlockData(data_name, os.path.join(directory, field_name + ".dat")) diff --git a/pystencils/datahandling/serial_datahandling.py b/pystencils/datahandling/serial_datahandling.py index d4af43f189333a260b9a266b83c21335cd4a1c44..e5244c05a166306347a9b5e948145305f9a870bc 100644 --- a/pystencils/datahandling/serial_datahandling.py +++ b/pystencils/datahandling/serial_datahandling.py @@ -407,7 +407,7 @@ class SerialDataHandling(DataHandling): time_running = time.perf_counter() - self._start_time spacing = 7 - len(str(int(time_running))) - message = "[{: <8}]{}({:.3f} sec) {} ".format(level, spacing * '-', time_running, message) + message = f"[{level: <8}]{spacing * '-'}({time_running:.3f} sec) {message} " print(message, flush=True) def log_on_root(self, *args, level='INFO'): @@ -428,7 +428,7 @@ class SerialDataHandling(DataHandling): file_contents = np.load(file) for arr_name, arr_contents in self.cpu_arrays.items(): if arr_name not in file_contents: - print("Skipping read data {} because there is no data with this name in data handling".format(arr_name)) + print(f"Skipping read data {arr_name} because there is no data with this name in data handling") continue if file_contents[arr_name].shape != arr_contents.shape: print("Skipping read data {} because shapes don't match. " diff --git a/pystencils/display_utils.py b/pystencils/display_utils.py index cb09197bf175b43c4896072693ea11253976691f..32531cdc5e2bba37b46e5708859ed60e8150dea5 100644 --- a/pystencils/display_utils.py +++ b/pystencils/display_utils.py @@ -30,7 +30,7 @@ def highlight_cpp(code: str): from pygments.lexers import CppLexer css = HtmlFormatter().get_style_defs('.highlight') - css_tag = "<style>{css}</style>".format(css=css) + css_tag = f"<style>{css}</style>" display(HTML(css_tag)) return HTML(highlight(code, CppLexer(), HtmlFormatter())) diff --git a/pystencils/fd/derivation.py b/pystencils/fd/derivation.py index e0e7a65ad31236f869ef287344ae52f3e3a7c528..23579f488716c97e98fe7f066266ad2f648ff458 100644 --- a/pystencils/fd/derivation.py +++ b/pystencils/fd/derivation.py @@ -107,7 +107,7 @@ class FiniteDifferenceStencilDerivation: @staticmethod def symbolic_weight(*args): str_args = [str(e) for e in args] - return sp.Symbol("w_({})".format(",".join(str_args))) + return sp.Symbol(f"w_({','.join(str_args)})") def error_term_dict(self, order): error_terms = defaultdict(lambda: 0) diff --git a/pystencils/fd/derivative.py b/pystencils/fd/derivative.py index 31daf4294f4ffa70c766632c4126dd7403690251..0e2890ec558db92a364c6912b19b26cb676f7217 100644 --- a/pystencils/fd/derivative.py +++ b/pystencils/fd/derivative.py @@ -109,7 +109,7 @@ class Diff(sp.Expr): return result def __str__(self): - return "D(%s)" % self.arg + return f"D({self.arg})" def interpolated_access(self, offset, **kwargs): """Represents an interpolated access on a spatially differentiated field diff --git a/pystencils/fd/finitedifferences.py b/pystencils/fd/finitedifferences.py index 317e8e02537159e20a2c9ea75bc7cc308e1cb69e..1a119f71b5060831e1597f1290e20f149c4c6f39 100644 --- a/pystencils/fd/finitedifferences.py +++ b/pystencils/fd/finitedifferences.py @@ -193,7 +193,7 @@ class Advection(sp.Function): return self.scalar.spatial_dimensions def _latex(self, printer): - name_suffix = "_%s" % self.scalar_index if self.scalar_index is not None else "" + name_suffix = f"_{self.scalar_index}" if self.scalar_index is not None else "" if isinstance(self.vector, Field): return r"\nabla \cdot(%s %s)" % (printer.doprint(sp.Symbol(self.vector.name)), printer.doprint(sp.Symbol(self.scalar.name + name_suffix))) @@ -240,7 +240,7 @@ class Diffusion(sp.Function): return self.scalar.spatial_dimensions def _latex(self, printer): - name_suffix = "_%s" % self.scalar_index if self.scalar_index is not None else "" + name_suffix = f"_{self.scalar_index}" if self.scalar_index is not None else "" coeff = self.diffusion_coeff diff_coeff = sp.Symbol(coeff.name) if isinstance(coeff, Field) else coeff return r"div(%s \nabla %s)" % (printer.doprint(diff_coeff), @@ -273,7 +273,7 @@ class Transient(sp.Function): return None if len(self.args) <= 1 else int(self.args[1]) def _latex(self, printer): - name_suffix = "_%s" % self.scalar_index if self.scalar_index is not None else "" + name_suffix = f"_{self.scalar_index}" if self.scalar_index is not None else "" return r"\partial_t %s" % (printer.doprint(sp.Symbol(self.scalar.name + name_suffix)),) diff --git a/pystencils/field.py b/pystencils/field.py index 6b85dead11778bf5aa6a820d4f34e8b547a95df4..9fe59d1f4528d446bf5574e69be5fb787e5bd797 100644 --- a/pystencils/field.py +++ b/pystencils/field.py @@ -583,7 +583,7 @@ class Field(AbstractField): } } if not self.index_shape[0] in stencils[self.spatial_dimensions]: - raise ValueError("No known stencil has {} staggered points".format(self.index_shape[0])) + raise ValueError(f"No known stencil has {self.index_shape[0]} staggered points") return stencils[self.spatial_dimensions][self.index_shape[0]] @property @@ -706,7 +706,7 @@ class Field(AbstractField): offset_name = hashlib.md5(pickle.dumps(offsets_and_index)).hexdigest()[:12] superscript = None - symbol_name = "%s_%s" % (field_name, offset_name) + symbol_name = f"{field_name}_{offset_name}" if superscript is not None: symbol_name += "^" + superscript @@ -871,9 +871,9 @@ class Field(AbstractField): offset_str = ",".join([sp.latex(self._staggered_offset(self.offsets, self.index[0])[i]) for i in range(len(self.offsets))]) if self.is_absolute_access: - offset_str = "\\mathbf{}".format(offset_str) + offset_str = f"\\mathbf{offset_str}" elif self.field.spatial_dimensions > 1: - offset_str = "({})".format(offset_str) + offset_str = f"({offset_str})" if FieldType.is_staggered(self._field): if self.index and self.field.index_dimensions > 1: @@ -894,18 +894,18 @@ class Field(AbstractField): offset_str = ",".join([sp.latex(self._staggered_offset(self.offsets, self.index[0])[i]) for i in range(len(self.offsets))]) if self.is_absolute_access: - offset_str = "[abs]{}".format(offset_str) + offset_str = f"[abs]{offset_str}" if FieldType.is_staggered(self._field): if self.index and self.field.index_dimensions > 1: - return "%s[%s](%s)" % (n, offset_str, self.index[1:] if len(self.index) > 2 else self.index[1]) + return f"{n}[{offset_str}]({self.index[1:] if len(self.index) > 2 else self.index[1]})" else: - return "%s[%s]" % (n, offset_str) + return f"{n}[{offset_str}]" else: if self.index and self.field.index_dimensions > 0: - return "%s[%s](%s)" % (n, offset_str, self.index if len(self.index) > 1 else self.index[0]) + return f"{n}[{offset_str}]({self.index if len(self.index) > 1 else self.index[0]})" else: - return "%s[%s]" % (n, offset_str) + return f"{n}[{offset_str}]" def get_layout_from_strides(strides: Sequence[int], index_dimension_ids: Optional[List[int]] = None): diff --git a/pystencils/gpucuda/indexing.py b/pystencils/gpucuda/indexing.py index eb212119ac8505ac5bf4db3112ef645b8e793f80..ae5db1b984d1ddc6f33ec0437b3f9fdc44ea48a4 100644 --- a/pystencils/gpucuda/indexing.py +++ b/pystencils/gpucuda/indexing.py @@ -305,7 +305,7 @@ def indexing_creator_from_params(gpu_indexing, gpu_indexing_params): elif gpu_indexing == 'line': indexing_creator = LineIndexing else: - raise ValueError("Unknown GPU indexing %s. Valid values are 'block' and 'line'" % (gpu_indexing,)) + raise ValueError(f"Unknown GPU indexing {gpu_indexing}. Valid values are 'block' and 'line'") if gpu_indexing_params: indexing_creator = partial(indexing_creator, **gpu_indexing_params) return indexing_creator diff --git a/pystencils/gpucuda/kernelcreation.py b/pystencils/gpucuda/kernelcreation.py index 33db3ad56da5d5e26f43403cf354c3814b2805e9..52a4dc8bd90e6caa8dd462b0ced27ce33e6c1ae2 100644 --- a/pystencils/gpucuda/kernelcreation.py +++ b/pystencils/gpucuda/kernelcreation.py @@ -131,7 +131,7 @@ def created_indexed_cuda_kernel(assignments, rhs = ind_f[0](name) lhs = TypedSymbol(name, BasicType(data_type.get_element_type(name))) return SympyAssignment(lhs, rhs) - raise ValueError("Index %s not found in any of the passed index fields" % (name,)) + raise ValueError(f"Index {name} not found in any of the passed index fields") coordinate_symbol_assignments = [get_coordinate_symbol_assignment(n) for n in coordinate_names[:spatial_coordinates]] diff --git a/pystencils/integer_set_analysis.py b/pystencils/integer_set_analysis.py index 3560ba6ca1ad3f10ba456564aa74669273ef8dae..82af791caf805877089ba957afcff517669f4b6b 100644 --- a/pystencils/integer_set_analysis.py +++ b/pystencils/integer_set_analysis.py @@ -36,13 +36,12 @@ def isl_iteration_set(node: ast.Node): loop_start_str = remove_brackets(str(loop.start)) loop_stop_str = remove_brackets(str(loop.stop)) ctr_name = loop.loop_counter_name - set_string_description = "{} >= {} and {} < {}".format(ctr_name, loop_start_str, ctr_name, loop_stop_str) + set_string_description = f"{ctr_name} >= {loop_start_str} and {ctr_name} < {loop_stop_str}" conditions.append(remove_brackets(set_string_description)) symbol_names = ','.join(degrees_of_freedom) condition_str = ' and '.join(conditions) - set_description = "{{ [{symbol_names}] : {condition_str} }}".format(symbol_names=symbol_names, - condition_str=condition_str) + set_description = f"{{ [{symbol_names}] : {condition_str} }}" return degrees_of_freedom, isl.BasicSet(set_description) @@ -53,8 +52,7 @@ def simplify_loop_counter_dependent_conditional(conditional): if dofs_in_condition.issubset(dofs_in_loops): symbol_names = ','.join(dofs_in_loops) condition_str = remove_brackets(str(conditional.condition_expr)) - condition_set = isl.BasicSet("{{ [{symbol_names}] : {condition_str} }}".format(symbol_names=symbol_names, - condition_str=condition_str)) + condition_set = isl.BasicSet(f"{{ [{symbol_names}] : {condition_str} }}") if condition_set.is_empty(): conditional.replace_by_false_block() diff --git a/pystencils/interpolation_astnodes.py b/pystencils/interpolation_astnodes.py index 76bd340b7e2c9bd66d9c82f77bc0399208017e52..c230d0115bf858213e3071986abb70ed86d23f96 100644 --- a/pystencils/interpolation_astnodes.py +++ b/pystencils/interpolation_astnodes.py @@ -126,7 +126,7 @@ class Interpolator(object): return InterpolatorAccess(self.symbol, *[sp.S(o) for o in offset]) def __str__(self): - return '%s_interpolator_%s' % (self.field.name, self.reproducible_hash) + return f'{self.field.name}_interpolator_{self.reproducible_hash}' def __repr__(self): return self.__str__() @@ -186,7 +186,7 @@ class InterpolatorAccess(TypedSymbol): return super()._hashable_content() + ((self.symbol, self.field, tuple(self.offsets), self.symbol.interpolator)) def __str__(self): - return '%s_interpolator(%s)' % (self.field.name, ', '.join(str(o) for o in self.offsets)) + return f"{self.field.name}_interpolator({', '.join(str(o) for o in self.offsets)})" def __repr__(self): return self.__str__() @@ -437,7 +437,7 @@ class TextureCachedField(Interpolator): return obj def __str__(self): - return '%s_texture_%s' % (self.field.name, self.reproducible_hash) + return f'{self.field.name}_texture_{self.reproducible_hash}' def __repr__(self): return self.__str__() diff --git a/pystencils/jupyter.py b/pystencils/jupyter.py index f977e87c0b9c1b835eccf6670c4e4ec63eccd086..5e86e0c2cae812a69fd8a38c59639cbbadeaf798 100644 --- a/pystencils/jupyter.py +++ b/pystencils/jupyter.py @@ -44,17 +44,10 @@ def log_progress(sequence, every=None, size=None, name='Items'): for index, record in enumerate(sequence, 1): if index == 1 or index % every == 0: if is_iterator: - label.value = '{name}: {index} / ?'.format( - name=name, - index=index - ) + label.value = f'{name}: {index} / ?' else: progress.value = index - label.value = u'{name}: {index} / {size}'.format( - name=name, - index=index, - size=size - ) + label.value = f'{name}: {index} / {size}' yield record except: progress.bar_style = 'danger' @@ -62,10 +55,7 @@ def log_progress(sequence, every=None, size=None, name='Items'): else: progress.bar_style = 'success' progress.value = index - label.value = "{name}: {index}".format( - name=name, - index=str(index or '?') - ) + label.value = f"{name}: {str(index or '?')}" VIDEO_TAG = """<video controls width="80%"> diff --git a/pystencils/kerncraft_coupling/kerncraft_interface.py b/pystencils/kerncraft_coupling/kerncraft_interface.py index 37a5109de80b0c975a5cb30043316e1c1e8e9e9e..bd1771493434d1166bf899cc8a8188994bbd2101 100644 --- a/pystencils/kerncraft_coupling/kerncraft_interface.py +++ b/pystencils/kerncraft_coupling/kerncraft_interface.py @@ -140,7 +140,7 @@ class PyStencilsKerncraftKernel(KernelCode): """ code = generate_benchmark(self.kernel_ast, likwid=type_ == 'likwid', openmp=openmp) if as_filename: - fp, already_available = self._get_intermediate_file('kernel_{}.c'.format(type_), + fp, already_available = self._get_intermediate_file(f'kernel_{type_}.c', machine_and_compiler_dependent=False) if not already_available: fp.write(code) diff --git a/pystencils/kernelcreation.py b/pystencils/kernelcreation.py index 2c8aabaa530f985f7b645a41a29a9537a655fa07..b158754c8716a2d0bdae495ceda59341f945c8d8 100644 --- a/pystencils/kernelcreation.py +++ b/pystencils/kernelcreation.py @@ -128,7 +128,7 @@ def create_kernel(assignments, ast._backend = 'opencl' return ast else: - raise ValueError("Unknown target %s. Has to be one of 'cpu', 'gpu' or 'llvm' " % (target,)) + raise ValueError(f"Unknown target {target}. Has to be one of 'cpu', 'gpu' or 'llvm' ") if use_auto_for_assignments: for a in ast.atoms(SympyAssignment): @@ -214,7 +214,7 @@ def create_indexed_kernel(assignments, ast._backend = 'opencl' return ast else: - raise ValueError("Unknown target %s. Has to be either 'cpu' or 'gpu'" % (target,)) + raise ValueError(f"Unknown target {target}. Has to be either 'cpu' or 'gpu'") def create_staggered_kernel(assignments, target='cpu', gpu_exclusive_conditions=False, **kwargs): diff --git a/pystencils/kernelparameters.py b/pystencils/kernelparameters.py index 9284a1ee5d14dd97c63f44574e020f1bff24d4e5..3257522e419bf921b13010215e44a51a5290ce80 100644 --- a/pystencils/kernelparameters.py +++ b/pystencils/kernelparameters.py @@ -29,7 +29,7 @@ class FieldStrideSymbol(TypedSymbol): return obj def __new_stage2__(cls, field_name, coordinate): - name = "_stride_{name}_{i}".format(name=field_name, i=coordinate) + name = f"_stride_{field_name}_{coordinate}" obj = super(FieldStrideSymbol, cls).__xnew__(cls, name, STRIDE_DTYPE, positive=True) obj.field_name = field_name obj.coordinate = coordinate @@ -54,7 +54,7 @@ class FieldShapeSymbol(TypedSymbol): def __new_stage2__(cls, field_names, coordinate): names = "_".join([field_name for field_name in field_names]) - name = "_size_{names}_{i}".format(names=names, i=coordinate) + name = f"_size_{names}_{coordinate}" obj = super(FieldShapeSymbol, cls).__xnew__(cls, name, SHAPE_DTYPE, positive=True) obj.field_names = tuple(field_names) obj.coordinate = coordinate @@ -77,7 +77,7 @@ class FieldPointerSymbol(TypedSymbol): return obj def __new_stage2__(cls, field_name, field_dtype, const): - name = "_data_{name}".format(name=field_name) + name = f"_data_{field_name}" dtype = PointerType(get_base_type(field_dtype), const=const, restrict=True) obj = super(FieldPointerSymbol, cls).__xnew__(cls, name, dtype) obj.field_name = field_name diff --git a/pystencils/llvm/llvm.py b/pystencils/llvm/llvm.py index 1d5223e9509f274e002d755fa19a1a56f9ec016e..a0de12689d620abefbd35e168bdac61f44544462 100644 --- a/pystencils/llvm/llvm.py +++ b/pystencils/llvm/llvm.py @@ -97,7 +97,7 @@ class LLVMPrinter(Printer): # look up parameter with name s val = self.func_arg_map.get(s.name) if not val: - raise LookupError("Symbol not found: %s" % s) + raise LookupError(f"Symbol not found: {s}") return val def _print_Pow(self, expr): diff --git a/pystencils/placeholder_function.py b/pystencils/placeholder_function.py index 18a0574b82292ecd9da0bff50f68d86811b472c7..8b8aa6ed0ed39d59f97c960d7efdd73f07cf38ef 100644 --- a/pystencils/placeholder_function.py +++ b/pystencils/placeholder_function.py @@ -34,7 +34,7 @@ def to_placeholder_function(expr, name): """ symbols = list(expr.atoms(sp.Symbol)) symbols.sort(key=lambda e: e.name) - derivative_symbols = [sp.Symbol("_d{}_d{}".format(name, s.name)) for s in symbols] + derivative_symbols = [sp.Symbol(f"_d{name}_d{s.name}") for s in symbols] derivatives = [sp.diff(expr, s) for s in symbols] assignments = [Assignment(sp.Symbol(name), expr)] diff --git a/pystencils/rng.py b/pystencils/rng.py index 85bc7c1b16e3f30bfdf23b6036e2e5849ccfc85a..bbc28bbd2c7d98cf931149d7e5572cda7fa33442 100644 --- a/pystencils/rng.py +++ b/pystencils/rng.py @@ -13,7 +13,7 @@ def _get_rng_template(name, data_type, num_vars): c_type = "double" template = "\n" for i in range(num_vars): - template += "{{result_symbols[{}].dtype}} {{result_symbols[{}].name}};\n".format(i, i) + template += f"{{result_symbols[{i}].dtype}} {{result_symbols[{i}].name}};\n" template += ("{}_{}{}({{parameters}}, " + ", ".join(["{{result_symbols[{}].name}}"] * num_vars) + ");\n") \ .format(name, c_type, num_vars, *tuple(range(num_vars))) return template @@ -36,15 +36,15 @@ class RNGBase(CustomCodeNode): if keys is None: keys = (0,) * self._num_keys if len(keys) != self._num_keys: - raise ValueError("Provided {} keys but need {}".format(len(keys), self._num_keys)) + raise ValueError(f"Provided {len(keys)} keys but need {self._num_keys}") if len(offsets) != 3: - raise ValueError("Provided {} offsets but need {}".format(len(offsets), 3)) + raise ValueError(f"Provided {len(offsets)} offsets but need {3}") self.result_symbols = tuple(TypedSymbol(sp.Dummy().name, self._data_type) for _ in range(self._num_vars)) symbols_read = [s for s in keys if isinstance(s, sp.Symbol)] super().__init__("", symbols_read=symbols_read, symbols_defined=self.result_symbols) self._time_step = time_step self._offsets = offsets - self.headers = ['"{}_rand.h"'.format(self._name)] + self.headers = [f'"{self._name}_rand.h"'] self.keys = tuple(keys) self._args = sp.sympify((dim, time_step, keys)) self._dim = dim diff --git a/pystencils/runhelper/db.py b/pystencils/runhelper/db.py index bc3aa0a9ec799d57165bb797a059dc78f85f08e3..21b75c4ba91a53588db8637651bfda090c4044e6 100644 --- a/pystencils/runhelper/db.py +++ b/pystencils/runhelper/db.py @@ -120,7 +120,7 @@ class Database: Returns: pandas data frame """ - from pandas.io.json import json_normalize + from pandas import json_normalize query_result = self.filter_params(parameter_query) attributes = [e.attributes for e in query_result] diff --git a/pystencils/runhelper/parameterstudy.py b/pystencils/runhelper/parameterstudy.py index 0ad27fd5bdd426b74c515a37d500da29eb805864..f4d8327d335125f7f57a8d622e1fd37855c3d9dd 100644 --- a/pystencils/runhelper/parameterstudy.py +++ b/pystencils/runhelper/parameterstudy.py @@ -215,7 +215,7 @@ class ParameterStudy: def log_message(self, fmt, *args): return - print("Listening to connections on {}:{}. Scenarios to simulate: {}".format(ip, port, len(filtered_runs))) + print(f"Listening to connections on {ip}:{port}. Scenarios to simulate: {len(filtered_runs)}") server = HTTPServer((ip, port), ParameterStudyServer) while len(ParameterStudyServer.currently_running) > 0 or len(ParameterStudyServer.runs) > 0: server.handle_request() @@ -241,7 +241,7 @@ class ParameterStudy: from urllib.error import URLError import time parameter_update = {} if parameter_update is None else parameter_update - url = "http://{}:{}".format(server, port) + url = f"http://{server}:{port}" client_name = client_name.format(hostname=socket.gethostname(), pid=os.getpid()) start_time = time.time() while True: @@ -265,7 +265,7 @@ class ParameterStudy: 'client_name': client_name} urlopen(url + '/result', data=json.dumps(answer).encode()) except URLError: - print("Cannot connect to server {} retrying in 5 seconds...".format(url)) + print(f"Cannot connect to server {url} retrying in 5 seconds...") sleep(5) def run_from_command_line(self, argv: Optional[Sequence[str]] = None) -> None: diff --git a/pystencils/simp/assignment_collection.py b/pystencils/simp/assignment_collection.py index 706008c859bd0cdc9f2f3b892557242a5aa01184..696038dd59f7faad83e74dbeecdfcfb038ea127a 100644 --- a/pystencils/simp/assignment_collection.py +++ b/pystencils/simp/assignment_collection.py @@ -378,10 +378,10 @@ class AssignmentCollection: def __str__(self): result = "Subexpressions:\n" for eq in self.subexpressions: - result += "\t{eq}\n".format(eq=eq) + result += f"\t{eq}\n" result += "Main Assignments:\n" for eq in self.main_assignments: - result += "\t{eq}\n".format(eq=eq) + result += f"\t{eq}\n" return result def __iter__(self): @@ -446,6 +446,6 @@ class SymbolGen: return self def __next__(self): - name = "{}_{}".format(self._symbol, self._ctr) + name = f"{self._symbol}_{self._ctr}" self._ctr += 1 return sp.Symbol(name) diff --git a/pystencils/simp/simplificationstrategy.py b/pystencils/simp/simplificationstrategy.py index 2c70c25c75534f12d6a404b531c218345be8a0af..cc601aa56981124dd75199f333a8c005fbdcb95d 100644 --- a/pystencils/simp/simplificationstrategy.py +++ b/pystencils/simp/simplificationstrategy.py @@ -92,7 +92,7 @@ class SimplificationStrategy: assignment_collection = t(assignment_collection) end_time = timeit.default_timer() op = assignment_collection.operation_count - time_str = "%.2f ms" % ((end_time - start_time) * 1000,) + time_str = f"{(end_time - start_time) * 1000:.2f} ms" total = op['adds'] + op['muls'] + op['divs'] report.add(ReportElement(t.__name__, time_str, op['adds'], op['muls'], op['divs'], total)) return report @@ -129,7 +129,7 @@ class SimplificationStrategy: def _repr_html_(self): def print_assignment_collection(title, c): - text = '<h5 style="padding-bottom:10px">%s</h5> <div style="padding-left:20px;">' % (title, ) + text = f'<h5 style="padding-bottom:10px">{title}</h5> <div style="padding-left:20px;">' if self.restrict_symbols: text += "\n".join(["$$" + sp.latex(e) + '$$' for e in c.new_filtered(self.restrict_symbols).main_assignments]) @@ -151,5 +151,5 @@ class SimplificationStrategy: def __repr__(self): result = "Simplification Strategy:\n" for t in self._rules: - result += " - %s\n" % (t.__name__,) + result += f" - {t.__name__}\n" return result diff --git a/pystencils/transformations.py b/pystencils/transformations.py index 5b44eb3e1b0b5c0622a4369bbcc8c77ebd16e616..b3f9431bbf3035aaabd25f6eb430c738dddaf3a7 100644 --- a/pystencils/transformations.py +++ b/pystencils/transformations.py @@ -137,7 +137,7 @@ def get_common_shape(field_set): fixed_field_names = ",".join([f.name for f in field_set if f.has_fixed_shape]) var_field_names = ",".join([f.name for f in field_set if not f.has_fixed_shape]) msg = "Mixing fixed-shaped and variable-shape fields in a single kernel is not possible\n" - msg += "Variable shaped: %s \nFixed shaped: %s" % (var_field_names, fixed_field_names) + msg += f"Variable shaped: {var_field_names} \nFixed shaped: {fixed_field_names}" raise ValueError(msg) shape_set = set([f.spatial_shape for f in field_set]) @@ -326,7 +326,7 @@ def parse_base_pointer_info(base_pointer_specification, loop_order, spatial_dime index = int(element[len("index"):]) add_new_element(spatial_dimensions + index) else: - raise ValueError("Unknown specification %s" % (element,)) + raise ValueError(f"Unknown specification {element}") result.append(new_group) @@ -902,13 +902,12 @@ class KernelConstraintsCheck: self._field_writes[fai].add(lhs.offsets) if self.check_double_write_condition and len(self._field_writes[fai]) > 1: raise ValueError( - "Field {} is written at two different locations".format( - lhs.field.name)) + f"Field {lhs.field.name} is written at two different locations") elif isinstance(lhs, sp.Symbol): if self.scopes.is_defined_locally(lhs): - raise ValueError("Assignments not in SSA form, multiple assignments to {}".format(lhs.name)) + raise ValueError(f"Assignments not in SSA form, multiple assignments to {lhs.name}") if lhs in self.scopes.free_parameters: - raise ValueError("Symbol {} is written, after it has been read".format(lhs.name)) + raise ValueError(f"Symbol {lhs.name} is written, after it has been read") self.scopes.define_symbol(lhs) def _update_accesses_rhs(self, rhs): @@ -1281,7 +1280,7 @@ def loop_blocking(ast_node: ast.KernelFunction, block_size) -> int: loop_stops[coord] = loop.stop else: assert loop.start == loop_starts[coord] and loop.stop == loop_stops[coord], \ - "Multiple loops over coordinate {} with different loop bounds".format(coord) + f"Multiple loops over coordinate {coord} with different loop bounds" # Create the outer loops that iterate over the blocks outer_loop = None diff --git a/pystencils_tests/test_abs.py b/pystencils_tests/test_abs.py new file mode 100644 index 0000000000000000000000000000000000000000..53917bcc60a8b409490c492b8281d90b44003c25 --- /dev/null +++ b/pystencils_tests/test_abs.py @@ -0,0 +1,19 @@ +import sympy + +import pystencils +from pystencils.data_types import cast_func, create_type + + +def test_abs(): + x, y, z = pystencils.fields('x, y, z: float64[2d]') + + default_int_type = create_type('int64') + + assignments = pystencils.AssignmentCollection({ + x[0, 0]: sympy.Abs(cast_func(y[0, 0], default_int_type)) + }) + + ast = pystencils.create_kernel(assignments, target="gpu") + code = pystencils.get_code_str(ast) + print(code) + assert 'fabs(' not in code diff --git a/pystencils_tests/test_blocking.py b/pystencils_tests/test_blocking.py index 579ba41997cec4990ad4da00ae811cdb0b564bd2..b2b815b1a317d9f3228e9cc780c66336f378f782 100644 --- a/pystencils_tests/test_blocking.py +++ b/pystencils_tests/test_blocking.py @@ -19,7 +19,7 @@ def check_equivalence(assignments, src_arr): with_blocking = ps.create_kernel(assignments, cpu_blocking=(8, 16, 4), cpu_openmp=openmp, cpu_vectorize_info=vectorization).compile() without_blocking = ps.create_kernel(assignments).compile() - print(" openmp {}, vectorization {}".format(openmp, vectorization)) + print(f" openmp {openmp}, vectorization {vectorization}") dst_arr = np.zeros_like(src_arr) ref_arr = np.zeros_like(src_arr) np.copyto(src_arr, np.random.rand(*src_arr.shape)) diff --git a/pystencils_tests/test_buffer_gpu.py b/pystencils_tests/test_buffer_gpu.py index f9ee96e9b19c147d95f006de4221980900375cb1..f63254cd45797f2b2de8b6601fceb23bb0a94d54 100644 --- a/pystencils_tests/test_buffer_gpu.py +++ b/pystencils_tests/test_buffer_gpu.py @@ -39,7 +39,8 @@ def _generate_fields(dt=np.uint8, stencil_directions=1, layout='numpy'): gpu_src_arr = gpuarray.to_gpu(src_arr) gpu_dst_arr = gpuarray.zeros_like(gpu_src_arr) - gpu_buffer_arr = gpuarray.zeros(np.prod(src_arr.shape), dtype=dt) + size = int(np.prod(src_arr.shape)) + gpu_buffer_arr = gpuarray.zeros(size, dtype=dt) fields.append((src_arr, gpu_src_arr, gpu_dst_arr, gpu_buffer_arr)) return fields diff --git a/pystencils_tests/test_interpolation.py b/pystencils_tests/test_interpolation.py index 477765bb31289dbfdc48927e3cc55f10d49f16a0..19201c7c9016be156f2ed73828eb65f1b9d6d229 100644 --- a/pystencils_tests/test_interpolation.py +++ b/pystencils_tests/test_interpolation.py @@ -125,7 +125,7 @@ def test_rotate_interpolation_gpu(dtype, address_mode, use_textures): else: lenna_gpu = gpuarray.to_gpu( np.ascontiguousarray(lenna, dtype)) - x_f, y_f = pystencils.fields('x,y: %s [2d]' % type_map[dtype], ghost_layers=0) + x_f, y_f = pystencils.fields(f'x,y: {type_map[dtype]} [2d]', ghost_layers=0) transformed = scale * \ sympy.rot_axis3(rotation_angle)[:2, :2] * sympy.Matrix((x_, y_)) - sympy.Matrix([2, 2]) @@ -173,7 +173,7 @@ def test_shift_interpolation_gpu(address_mode, dtype, use_textures): lenna_gpu = gpuarray.to_gpu( np.ascontiguousarray(lenna, dtype)) - x_f, y_f = pystencils.fields('x,y: %s [2d]' % type_map[dtype], ghost_layers=0) + x_f, y_f = pystencils.fields(f'x,y: {type_map[dtype]} [2d]', ghost_layers=0) if use_textures: transformed = scale * sympy.rot_axis3(rotation_angle)[:2, :2] * sympy.Matrix((x_, y_)) + shift diff --git a/pystencils_tests/test_kerncraft_coupling.py b/pystencils_tests/test_kerncraft_coupling.py index 058c35c2a284da6d84928505587e6fbf12477843..0040006097bc5f48461105cb1d0462313c18bd1a 100644 --- a/pystencils_tests/test_kerncraft_coupling.py +++ b/pystencils_tests/test_kerncraft_coupling.py @@ -14,7 +14,7 @@ SCRIPT_FOLDER = os.path.dirname(os.path.realpath(__file__)) INPUT_FOLDER = os.path.join(SCRIPT_FOLDER, "kerncraft_inputs") -@pytest.mark.kernkraft +@pytest.mark.kerncraft def test_compilation(): machine_file_path = os.path.join(INPUT_FOLDER, "default_machine_file.yaml") machine = kerncraft.machinemodel.MachineModel(path_to_yaml=machine_file_path) @@ -36,7 +36,7 @@ def test_compilation(): print(mine) -@pytest.mark.kernkraft +@pytest.mark.kerncraft def analysis(kernel, model='ecmdata'): machine_file_path = os.path.join(INPUT_FOLDER, "default_machine_file.yaml") machine = kerncraft.machinemodel.MachineModel(path_to_yaml=machine_file_path) @@ -54,7 +54,7 @@ def analysis(kernel, model='ecmdata'): return model -@pytest.mark.kernkraft +@pytest.mark.kerncraft def test_3d_7pt_iaca(): # Make sure you use the intel compiler size = [20, 200, 200] @@ -82,7 +82,7 @@ def test_3d_7pt_iaca(): # assert reference.results['cl throughput'] == analysis.results['cl throughput'] -@pytest.mark.kernkraft +@pytest.mark.kerncraft def test_2d_5pt(): size = [30, 50, 3] kernel_file_path = os.path.join(INPUT_FOLDER, "2d-5pt.c") @@ -104,7 +104,7 @@ def test_2d_5pt(): assert e1 == e2 -@pytest.mark.kernkraft +@pytest.mark.kerncraft def test_3d_7pt(): size = [30, 50, 50] kernel_file_path = os.path.join(INPUT_FOLDER, "3d-7pt.c") diff --git a/pystencils_tests/test_loop_cutting.py b/pystencils_tests/test_loop_cutting.py index 0291074b87c051bcf381883e474078c663274ac1..daf803cbdab91417671dff53ae18561ed3df6011 100644 --- a/pystencils_tests/test_loop_cutting.py +++ b/pystencils_tests/test_loop_cutting.py @@ -112,7 +112,7 @@ def test_staggered_iteration_manual(): def test_staggered_gpu(): dim = 2 - f = ps.fields("f: double[{dim}D]".format(dim=dim)) + f = ps.fields(f"f: double[{dim}D]") s = ps.fields("s({dim}): double[{dim}D]".format(dim=dim), field_type=FieldType.STAGGERED) expressions = [(f[0, 0] + f[-1, 0]) / 2, (f[0, 0] + f[0, -1]) / 2] diff --git a/pytest.ini b/pytest.ini index 0070425966626449378fcd1ff9eabe468256a112..2795fb9d85e18838ddc963f307d232ef1a6365bf 100644 --- a/pytest.ini +++ b/pytest.ini @@ -4,6 +4,7 @@ norecursedirs = *.egg-info .git .cache .ipynb_checkpoints htmlcov addopts = --doctest-modules --durations=20 --cov-config pytest.ini markers = kerncraft: tests depending on kerncraft + notebook: mark for notebooks [run] branch = True @@ -38,7 +39,7 @@ exclude_lines = if __name__ == .__main__.: skip_covered = True -fail_under = 74 +fail_under = 75 [html] directory = coverage_report