diff --git a/creationfunctions.py b/creationfunctions.py index 14db3a2282ff9c17a0c55806432ab83ec06d957a..3a28cedfc9cf7c9888bc30b76346e246bfeeb8eb 100644 --- a/creationfunctions.py +++ b/creationfunctions.py @@ -3,6 +3,7 @@ Factory functions for standard LBM methods """ import sympy as sp from copy import copy +from functools import partial from lbmpy.methods.creationfunctions import createKBCTypeTRT, createRawMRT, createThreeRelaxationRateMRT from lbmpy.methods.entropic import addIterativeEntropyCondition, addEntropyCondition @@ -13,7 +14,7 @@ from lbmpy.simplificationfactory import createSimplificationStrategy from lbmpy.updatekernels import createStreamPullKernel, createPdfArray -def _getParams(params, optParams): +def updateWithDefaultParameters(params, optParams): defaultMethodDescription = { 'stencil': 'D2Q9', 'method': 'srt', # can be srt, trt or mrt @@ -43,6 +44,10 @@ def _getParams(params, optParams): 'target': 'cpu', 'openMP': True, 'pdfArr': None, + 'doublePrecision': True, + + 'gpuIndexing': 'block', + 'gpuIndexingParams': {}, } unknownParams = [k for k in params.keys() if k not in defaultMethodDescription] unknownOptParams = [k for k in optParams.keys() if k not in defaultOptimizationDescription] @@ -59,7 +64,7 @@ def _getParams(params, optParams): def createLatticeBoltzmannFunction(ast=None, optimizationParams={}, **kwargs): - params, optParams = _getParams(kwargs, optimizationParams) + params, optParams = updateWithDefaultParameters(kwargs, optimizationParams) if ast is None: params['optimizationParams'] = optParams @@ -86,7 +91,7 @@ def createLatticeBoltzmannFunction(ast=None, optimizationParams={}, **kwargs): def createLatticeBoltzmannAst(updateRule=None, optimizationParams={}, **kwargs): - params, optParams = _getParams(kwargs, optimizationParams) + params, optParams = updateWithDefaultParameters(kwargs, optimizationParams) if updateRule is None: params['optimizationParams'] = optimizationParams @@ -95,14 +100,21 @@ def createLatticeBoltzmannAst(updateRule=None, optimizationParams={}, **kwargs): if optParams['target'] == 'cpu': from pystencils.cpu import createKernel if 'splitGroups' in updateRule.simplificationHints: - print("splitting!") splitGroups = updateRule.simplificationHints['splitGroups'] else: splitGroups = () - res = createKernel(updateRule.allEquations, splitGroups=splitGroups) + res = createKernel(updateRule.allEquations, splitGroups=splitGroups, + typeForSymbol='double' if optParams['doublePrecision'] else 'float') elif optParams['target'] == 'gpu': from pystencils.gpucuda import createCUDAKernel - res = createCUDAKernel(updateRule.allEquations) + from pystencils.gpucuda.indexing import LineIndexing, BlockIndexing + assert optParams['gpuIndexing'] in ('line', 'block') + indexingCreator = LineIndexing if optParams['gpuIndexing'] == 'line' else BlockIndexing + if optParams['gpuIndexingParams']: + indexingCreator = partial(indexingCreator, **optParams['gpuIndexingParams']) + res = createCUDAKernel(updateRule.allEquations, + typeForSymbol='double' if optParams['doublePrecision'] else 'float', + indexingCreator=indexingCreator) else: return ValueError("'target' has to be either 'cpu' or 'gpu'") @@ -112,7 +124,7 @@ def createLatticeBoltzmannAst(updateRule=None, optimizationParams={}, **kwargs): def createLatticeBoltzmannUpdateRule(lbMethod=None, optimizationParams={}, **kwargs): - params, optParams = _getParams(kwargs, optimizationParams) + params, optParams = updateWithDefaultParameters(kwargs, optimizationParams) stencil = getStencil(params['stencil']) if lbMethod is None: @@ -154,7 +166,7 @@ def createLatticeBoltzmannUpdateRule(lbMethod=None, optimizationParams={}, **kwa def createLatticeBoltzmannMethod(**params): - params, _ = _getParams(params, {}) + params, _ = updateWithDefaultParameters(params, {}) stencil = getStencil(params['stencil']) dim = len(stencil[0]) diff --git a/macroscopic_value_kernels.py b/macroscopic_value_kernels.py index 86ac145c5fe12f843812263f2a02b8e6614a3a2f..b9a4dff74e89ad7d58c03f0066b74726cdfe4a82 100644 --- a/macroscopic_value_kernels.py +++ b/macroscopic_value_kernels.py @@ -1,5 +1,5 @@ from copy import deepcopy -from pystencils.field import Field, getLayoutFromNumpyArray +from pystencils.field import Field, getLayoutOfArray from lbmpy.simplificationfactory import createSimplificationStrategy @@ -42,9 +42,9 @@ def compileMacroscopicValuesGetter(lbMethod, outputQuantities, pdfArr=None, fiel outputFieldShape = pdfArr.shape[:-1] if indDims > 0: outputFieldShape += (numberOfElements,) - fieldLayout = getLayoutFromNumpyArray(pdfArr) + fieldLayout = getLayoutOfArray(pdfArr) else: - fieldLayout = getLayoutFromNumpyArray(pdfArr, indexDimensionIds=[len(pdfField.shape) - 1]) + fieldLayout = getLayoutOfArray(pdfArr, indexDimensionIds=[len(pdfField.shape) - 1]) outputField = Field.createFixedSize(outputQuantity, outputFieldShape, indDims, pdfArr.dtype, fieldLayout) outputMapping[outputQuantity] = [outputField(i) for i in range(numberOfElements)] diff --git a/methods/abstractlbmethod.py b/methods/abstractlbmethod.py index ed32c2c36cd2b9cbf6f8f39d99da194fff2f544c..8f35614d32b07828723e23d79b59dc014418f3ea 100644 --- a/methods/abstractlbmethod.py +++ b/methods/abstractlbmethod.py @@ -12,6 +12,7 @@ class LbmCollisionRule(EquationCollection): super(LbmCollisionRule, self).__init__(*args, **kwargs) self.method = lbmMethod + class AbstractLbMethod(abc.ABCMeta('ABC', (object,), {})): """ Abstract base class for all LBM methods diff --git a/serialscenario.py b/serialscenario.py index e5247e5dd9c881bbdf3364291cfdb6c91c8d9407..aa4af97ad6e03c5dbe8aad53d85105d02ebad403 100644 --- a/serialscenario.py +++ b/serialscenario.py @@ -1,28 +1,28 @@ from functools import partial import numpy as np from pystencils import Field +from pystencils.field import getLayoutOfArray, createNumpyArrayWithLayout from pystencils.slicing import sliceFromDirection, addGhostLayers, getPeriodicBoundaryFunctor -from lbmpy.creationfunctions import createLatticeBoltzmannFunction +from lbmpy.creationfunctions import createLatticeBoltzmannFunction, updateWithDefaultParameters from lbmpy.macroscopic_value_kernels import compileMacroscopicValuesGetter, compileMacroscopicValuesSetter from lbmpy.boundaries import BoundaryHandling, noSlip, ubb, fixedDensity from lbmpy.stencils import getStencil +from lbmpy.updatekernels import createPdfArray def createScenario(domainSize, boundarySetupFunction, methodParameters, optimizationParams, lbmKernel=None, initialVelocity=None, preUpdateFunctions=[], kernelParams={}): - if 'target' not in optimizationParams: - optimizationParams['target'] = 'cpu' - ghostLayers = 1 domainSizeWithGhostLayer = tuple([s + 2 * ghostLayers for s in domainSize]) D = len(domainSize) - if 'stencil' not in methodParameters: methodParameters['stencil'] = 'D2Q9' if D == 2 else 'D3Q27' + methodParameters, optimizationParams = updateWithDefaultParameters(methodParameters, optimizationParams) + Q = len(getStencil(methodParameters['stencil'])) - pdfArrays = [np.zeros(domainSizeWithGhostLayer + (Q,)), - np.zeros(domainSizeWithGhostLayer + (Q,))] + pdfArrays = [createPdfArray(domainSize, Q, layout=optimizationParams['fieldLayout']), + createPdfArray(domainSize, Q, layout=optimizationParams['fieldLayout'])] # Create kernel if lbmKernel is None: @@ -43,8 +43,10 @@ def createScenario(domainSize, boundarySetupFunction, methodParameters, optimiza boundaryHandling = None # Macroscopic value input/output - densityArr = [np.zeros(domainSizeWithGhostLayer)] - velocityArr = [np.zeros(domainSizeWithGhostLayer + (D,))] + pdfArrLayout = getLayoutOfArray(pdfArrays[0]) + pdfArrLayoutNoIdx = getLayoutOfArray(pdfArrays[0], indexDimensionIds=[D]) + densityArr = [createNumpyArrayWithLayout(domainSizeWithGhostLayer, layout=pdfArrLayoutNoIdx)] + velocityArr = [createNumpyArrayWithLayout(list(domainSizeWithGhostLayer) + [D], layout=pdfArrLayout)] getMacroscopic = compileMacroscopicValuesGetter(method, ['density', 'velocity'], pdfArr=pdfArrays[0], target='cpu') if initialVelocity is None: diff --git a/updatekernels.py b/updatekernels.py index 08a282478e412cc0e1402846bb71449b5ec56bcf..585c20a4a900ab1ccaa813599b2137506be21048 100644 --- a/updatekernels.py +++ b/updatekernels.py @@ -1,6 +1,7 @@ import numpy as np import sympy as sp from pystencils import Field +from pystencils.field import createNumpyArrayWithLayout from pystencils.sympyextensions import fastSubs from lbmpy.fieldaccess import StreamPullTwoFieldsAccessor @@ -73,6 +74,7 @@ def createStreamPullKernel(collisionRule, numpyField=None, srcFieldName="src", d # ---------------------------------- Pdf array creation for various layouts -------------------------------------------- + def createPdfArray(size, numDirections, ghostLayers=1, layout='fzyx'): """ Creates an empty numpy array for a pdf field with the specified memory layout. @@ -88,17 +90,14 @@ def createPdfArray(size, numDirections, ghostLayers=1, layout='fzyx'): (72, 360, 8) """ sizeWithGl = [s + 2 * ghostLayers for s in size] + dim = len(size) if layout == "fzyx" or layout == 'f' or layout == 'reverseNumpy': - return np.empty(sizeWithGl + [numDirections], order='f') + layout = tuple(reversed(range(dim+1))) elif layout == 'c' or layout == 'numpy': - return np.empty(sizeWithGl + [numDirections], order='c') + layout = tuple(range(dim+1)) elif layout == 'zyxf': - res = np.empty(list(reversed(sizeWithGl)) + [numDirections], order='c') - res = res.swapaxes(0, 1) - if len(size) == 3: - res = res.swapaxes(1, 2) - res = res.swapaxes(0, 1) - return res + layout = tuple(reversed(range(dim))) + (dim,) + return createNumpyArrayWithLayout(sizeWithGl + [numDirections], layout) # ------------------------------------------- Add output fields to kernel ----------------------------------------------