Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
pycodegen
lbmpy
Commits
fd57b765
Commit
fd57b765
authored
Jan 25, 2017
by
Martin Bauer
Browse files
new lbm module: macroscopic values & bugfixes
parent
f5ad4934
Changes
8
Hide whitespace changes
Inline
Side-by-side
boundaries/boundaryconditions.py
View file @
fd57b765
...
...
@@ -5,19 +5,19 @@ from pystencils.sympyextensions import getSymmetricPart
from
lbmpy.boundaries.boundaryhandling
import
offsetFromDir
,
weightOfDirection
,
invDir
def
noSlip
(
pdfField
,
direction
,
lb
m
Method
):
def
noSlip
(
pdfField
,
direction
,
lbMethod
):
"""No-Slip, simple bounce back boundary condition, enforcing zero velocity at obstacle"""
neighbor
=
offsetFromDir
(
direction
,
lb
m
Method
.
dim
)
neighbor
=
offsetFromDir
(
direction
,
lbMethod
.
dim
)
inverseDir
=
invDir
(
direction
)
return
[
sp
.
Eq
(
pdfField
[
neighbor
](
inverseDir
),
pdfField
(
direction
))]
def
ubb
(
pdfField
,
direction
,
lb
m
Method
,
velocity
):
def
ubb
(
pdfField
,
direction
,
lbMethod
,
velocity
):
"""Velocity bounce back boundary condition, enforcing specified velocity at obstacle"""
assert
len
(
velocity
)
==
lb
m
Method
.
dim
,
\
"Dimension of velocity (%d) does not match dimension of LB method (%d)"
%
(
len
(
velocity
,
lb
m
Method
.
dim
)
)
neighbor
=
offsetFromDir
(
direction
,
lb
m
Method
.
dim
)
assert
len
(
velocity
)
==
lbMethod
.
dim
,
\
"Dimension of velocity (%d) does not match dimension of LB method (%d)"
%
(
len
(
velocity
)
,
lbMethod
.
dim
)
neighbor
=
offsetFromDir
(
direction
,
lbMethod
.
dim
)
inverseDir
=
invDir
(
direction
)
velTerm
=
6
*
sum
([
d_i
*
v_i
for
d_i
,
v_i
in
zip
(
neighbor
,
velocity
)])
*
weightOfDirection
(
direction
)
...
...
@@ -25,21 +25,21 @@ def ubb(pdfField, direction, lbmMethod, velocity):
pdfField
(
direction
)
-
velTerm
)]
def
fixedDensity
(
pdfField
,
direction
,
lb
m
Method
,
density
):
def
fixedDensity
(
pdfField
,
direction
,
lbMethod
,
density
):
"""Boundary condition that fixes the density/pressure at the obstacle"""
def
removeAsymmetricPartOfMainEquations
(
eqColl
,
dofs
):
newMainEquations
=
[
sp
.
Eq
(
e
.
lhs
,
getSymmetricPart
(
e
.
rhs
,
dofs
))
for
e
in
eqColl
.
mainEquations
]
return
eqColl
.
copy
(
newMainEquations
)
neighbor
=
offsetFromDir
(
direction
,
lb
m
Method
.
dim
)
neighbor
=
offsetFromDir
(
direction
,
lbMethod
.
dim
)
inverseDir
=
invDir
(
direction
)
symmetricEq
=
removeAsymmetricPartOfMainEquations
(
lb
m
Method
.
getEquilibrium
())
simplification
=
createSimplificationStrategy
(
lb
m
Method
)
symmetricEq
=
removeAsymmetricPartOfMainEquations
(
lbMethod
.
getEquilibrium
())
simplification
=
createSimplificationStrategy
(
lbMethod
)
symmetricEq
=
simplification
(
symmetricEq
)
densitySymbol
=
lb
m
Method
.
conservedQuantityComputation
.
definedSymbols
()[
'density'
]
densitySymbol
=
lbMethod
.
conservedQuantityComputation
.
definedSymbols
()[
'density'
]
conditions
=
[(
eq_i
.
rhs
,
sp
.
Equality
(
direction
,
i
))
for
i
,
eq_i
in
enumerate
(
symmetricEq
.
mainEquations
)]
+
[(
0
,
True
)]
...
...
boundaries/boundaryhandling.py
View file @
fd57b765
...
...
@@ -12,13 +12,13 @@ WEIGHTS_SYMBOL = TypedSymbol("weights", "double")
class
BoundaryHandling
:
def
__init__
(
self
,
symbolicPdfField
,
domainShape
,
l
atticeModel
,
ghostLayers
=
1
,
target
=
'cpu'
):
def
__init__
(
self
,
symbolicPdfField
,
domainShape
,
l
bMethod
,
ghostLayers
=
1
,
target
=
'cpu'
):
self
.
_symbolicPdfField
=
symbolicPdfField
self
.
_shapeWithGhostLayers
=
[
d
+
2
*
ghostLayers
for
d
in
domainShape
]
self
.
_fluidFlag
=
2
**
3
1
self
.
_fluidFlag
=
2
**
3
0
self
.
flagField
=
np
.
full
(
self
.
_shapeWithGhostLayers
,
self
.
_fluidFlag
,
dtype
=
np
.
int32
)
self
.
_ghostLayers
=
ghostLayers
self
.
_l
atticeModel
=
latticeModel
self
.
_l
bMethod
=
lbMethod
self
.
_boundaryFunctions
=
[]
self
.
_nameToIndex
=
{}
self
.
_boundarySweeps
=
[]
...
...
@@ -30,8 +30,10 @@ class BoundaryHandling:
if
name
is
None
:
name
=
boundaryFunction
.
__name__
self
.
_nameToIndex
[
name
]
=
len
(
self
.
_boundaryFunctions
)
newIdx
=
len
(
self
.
_boundaryFunctions
)
self
.
_nameToIndex
[
name
]
=
newIdx
self
.
_boundaryFunctions
.
append
(
boundaryFunction
)
return
2
**
newIdx
def
invalidateIndexCache
(
self
):
self
.
_boundarySweeps
=
[]
...
...
@@ -68,9 +70,9 @@ class BoundaryHandling:
def
prepare
(
self
):
self
.
invalidateIndexCache
()
for
boundaryIdx
,
boundaryFunc
in
enumerate
(
self
.
_boundaryFunctions
):
idxField
=
createBoundaryIndexList
(
self
.
flagField
,
self
.
_l
atticeModel
.
stencil
,
idxField
=
createBoundaryIndexList
(
self
.
flagField
,
self
.
_l
bMethod
.
stencil
,
2
**
boundaryIdx
,
self
.
_fluidFlag
,
self
.
_ghostLayers
)
ast
=
generateBoundaryHandling
(
self
.
_symbolicPdfField
,
idxField
,
self
.
_l
atticeModel
,
boundaryFunc
)
ast
=
generateBoundaryHandling
(
self
.
_symbolicPdfField
,
idxField
,
self
.
_l
bMethod
,
boundaryFunc
)
if
self
.
_target
==
'cpu'
:
from
pystencils.cpu
import
makePythonFunction
as
makePythonCpuFunction
...
...
@@ -131,8 +133,8 @@ class LbmMethodInfo(CustomCppCode):
super
(
LbmMethodInfo
,
self
).
__init__
(
code
,
symbolsRead
=
set
(),
symbolsDefined
=
symbolsDefined
)
def
generateBoundaryHandling
(
pdfField
,
indexArr
,
l
atticeModel
,
boundaryFunctor
):
dim
=
l
atticeModel
.
dim
def
generateBoundaryHandling
(
pdfField
,
indexArr
,
l
bMethod
,
boundaryFunctor
):
dim
=
l
bMethod
.
dim
cellLoopBody
=
Block
([])
cellLoop
=
LoopOverCoordinate
(
cellLoopBody
,
coordinateToLoopOver
=
0
,
start
=
0
,
stop
=
indexArr
.
shape
[
0
])
...
...
@@ -145,7 +147,7 @@ def generateBoundaryHandling(pdfField, indexArr, latticeModel, boundaryFunctor):
dirSymbol
=
TypedSymbol
(
"dir"
,
"int"
)
cellLoopBody
.
append
(
SympyAssignment
(
dirSymbol
,
indexField
[
0
](
dim
)))
boundaryEqList
=
boundaryFunctor
(
pdfField
,
dirSymbol
,
l
atticeModel
)
boundaryEqList
=
boundaryFunctor
(
pdfField
,
dirSymbol
,
l
bMethod
)
if
type
(
boundaryEqList
)
is
tuple
:
boundaryEqList
,
additionalNodes
=
boundaryEqList
else
:
...
...
@@ -168,7 +170,7 @@ def generateBoundaryHandling(pdfField, indexArr, latticeModel, boundaryFunctor):
for
node
in
additionalNodes
:
loop
.
body
.
append
(
node
)
functionBody
.
insertFront
(
LbmMethodInfo
(
l
atticeModel
))
functionBody
.
insertFront
(
LbmMethodInfo
(
l
bMethod
))
fixedCoordinateMapping
=
{
f
.
name
:
coordinateSymbols
[:
dim
]
for
f
in
fieldsAccessed
}
resolveFieldAccesses
(
ast
,
set
([
'indexField'
]),
fieldToFixedCoordinates
=
fixedCoordinateMapping
)
...
...
boundaries/createindexlist.py
View file @
fd57b765
...
...
@@ -30,10 +30,11 @@ def createBoundaryIndexList(flagField, stencil, boundaryMask, fluidMask, nrOfGho
if
cythonFuncsAvailable
:
stencil
=
np
.
array
(
stencil
,
dtype
=
np
.
int32
)
if
len
(
flagField
.
shape
)
==
2
:
return
np
.
array
(
createBoundaryIndexList2D
(
flagField
,
nrOfGhostLayers
,
boundaryMask
,
fluidMask
,
stencil
)
)
idxList
=
createBoundaryIndexList2D
(
flagField
,
nrOfGhostLayers
,
boundaryMask
,
fluidMask
,
stencil
)
elif
len
(
flagField
.
shape
)
==
3
:
return
np
.
array
(
createBoundaryIndexList3D
(
flagField
,
nrOfGhostLayers
,
boundaryMask
,
fluidMask
,
stencil
)
)
idxList
=
createBoundaryIndexList3D
(
flagField
,
nrOfGhostLayers
,
boundaryMask
,
fluidMask
,
stencil
)
else
:
raise
ValueError
(
"Flag field has to be a 2 or 3 dimensional numpy array"
)
return
np
.
array
(
idxList
,
dtype
=
np
.
int32
)
else
:
return
_createBoundaryIndexListPython
(
flagField
,
nrOfGhostLayers
,
boundaryMask
,
fluidMask
,
stencil
)
boundaries/createindexlistcython.pyx
View file @
fd57b765
...
...
@@ -4,6 +4,7 @@ ctypedef fused IntegerType:
short
int
long
long
long
unsigned
short
unsigned
int
unsigned
long
...
...
creationfunctions.py
View file @
fd57b765
...
...
@@ -47,10 +47,12 @@ def _getParams(params, optParams):
return
paramsResult
,
optParamsResult
def
createLatticeBoltzmannFunction
(
optimizationParams
=
{},
**
kwargs
):
def
createLatticeBoltzmannFunction
(
ast
=
None
,
optimizationParams
=
{},
**
kwargs
):
params
,
optParams
=
_getParams
(
kwargs
,
optimizationParams
)
ast
=
createLatticeBoltzmannKernel
(
**
params
,
optimizationParams
=
optParams
)
if
ast
is
None
:
ast
=
createLatticeBoltzmannAst
(
**
params
,
optimizationParams
=
optParams
)
if
params
[
'target'
]
==
'cpu'
:
from
pystencils.cpu
import
makePythonFunction
as
makePythonCpuFunction
,
addOpenMP
if
'openMP'
in
optParams
:
...
...
@@ -58,18 +60,22 @@ def createLatticeBoltzmannFunction(optimizationParams={}, **kwargs):
addOpenMP
(
ast
)
elif
isinstance
(
optParams
[
'openMP'
],
int
):
addOpenMP
(
ast
,
numThreads
=
optParams
[
'openMP'
])
re
turn
makePythonCpuFunction
(
ast
)
re
s
=
makePythonCpuFunction
(
ast
)
elif
params
[
'target'
]
==
'gpu'
:
from
pystencils.gpucuda
import
makePythonFunction
as
makePythonGpuFunction
re
turn
makePythonGpuFunction
(
ast
)
re
s
=
makePythonGpuFunction
(
ast
)
else
:
return
ValueError
(
"'target' has to be either 'cpu' or 'gpu'"
)
res
.
method
=
ast
.
method
return
res
def
createLatticeBoltzmann
Kernel
(
optimizationParams
=
{},
**
kwargs
):
def
createLatticeBoltzmann
Ast
(
updateRule
=
None
,
optimizationParams
=
{},
**
kwargs
):
params
,
optParams
=
_getParams
(
kwargs
,
optimizationParams
)
updateRule
=
createLatticeBoltzmannUpdateRule
(
**
params
,
optimizationParams
=
optimizationParams
)
if
updateRule
is
None
:
updateRule
=
createLatticeBoltzmannUpdateRule
(
**
params
,
optimizationParams
=
optimizationParams
)
if
params
[
'target'
]
==
'cpu'
:
from
pystencils.cpu
import
createKernel
...
...
@@ -77,26 +83,31 @@ def createLatticeBoltzmannKernel(optimizationParams={}, **kwargs):
splitGroups
=
updateRule
.
simplificationHints
[
'splitGroups'
]
else
:
splitGroups
=
()
re
turn
createKernel
(
updateRule
.
allEquations
,
splitGroups
=
splitGroups
)
re
s
=
createKernel
(
updateRule
.
allEquations
,
splitGroups
=
splitGroups
)
elif
params
[
'target'
]
==
'gpu'
:
from
pystencils.gpucuda
import
createCUDAKernel
re
turn
createCUDAKernel
(
updateRule
.
allEquations
)
re
s
=
createCUDAKernel
(
updateRule
.
allEquations
)
else
:
return
ValueError
(
"'target' has to be either 'cpu' or 'gpu'"
)
res
.
method
=
updateRule
.
method
return
res
def
createLatticeBoltzmannUpdateRule
(
optimizationParams
=
{},
**
kwargs
):
def
createLatticeBoltzmannUpdateRule
(
lbMethod
=
None
,
optimizationParams
=
{},
**
kwargs
):
params
,
optParams
=
_getParams
(
kwargs
,
optimizationParams
)
stencil
=
getStencil
(
params
[
'stencil'
])
method
=
createLatticeBoltzmannCollisionRule
(
**
params
)
if
lbMethod
is
None
:
lbMethod
=
createLatticeBoltzmannMethod
(
**
params
)
splitInnerLoop
=
'split'
in
optParams
and
optParams
[
'split'
]
dirCSE
=
'doCseInOpposingDirections'
doCseInOpposingDirections
=
False
if
dirCSE
not
in
optParams
else
optParams
[
dirCSE
]
doOverallCse
=
False
if
'doOverallCse'
not
in
optParams
else
optParams
[
'doOverallCse'
]
simplification
=
createSimplificationStrategy
(
m
ethod
,
doCseInOpposingDirections
,
doOverallCse
,
splitInnerLoop
)
collisionRule
=
simplification
(
m
ethod
.
getCollisionRule
())
simplification
=
createSimplificationStrategy
(
lbM
ethod
,
doCseInOpposingDirections
,
doOverallCse
,
splitInnerLoop
)
collisionRule
=
simplification
(
lbM
ethod
.
getCollisionRule
())
if
'fieldSize'
in
optParams
and
optParams
[
'fieldSize'
]:
npField
=
createPdfArray
(
optParams
[
'fieldSize'
],
len
(
stencil
),
layout
=
optParams
[
'fieldLayout'
])
...
...
@@ -111,7 +122,7 @@ def createLatticeBoltzmannUpdateRule(optimizationParams={}, **kwargs):
return
updateRule
def
createLatticeBoltzmann
CollisionRule
(
**
params
):
def
createLatticeBoltzmann
Method
(
**
params
):
params
,
_
=
_getParams
(
params
,
{})
stencil
=
getStencil
(
params
[
'stencil'
])
...
...
macroscopicValueKernels.py
View file @
fd57b765
import
sympy
as
sp
from
lbmpy.simplificationfactory
import
createSimplificationStrategy
from
copy
import
deepcopy
from
pystencils.field
import
Field
from
lbmpy.simplificationfactory
import
createSimplificationStrategy
def
compileMacroscopicValuesGetter
(
lbMethod
,
outputQuantities
,
pdfArr
=
None
,
fieldLayout
=
'numpy'
,
target
=
'cpu'
):
...
...
@@ -75,6 +75,9 @@ def compileMacroscopicValuesSetter(lbMethod, quantitiesToSet, pdfArr=None, field
:param lbMethod: instance of :class:`lbmpy.methods.AbstractLbMethod`
:param quantitiesToSet: map from conserved quantity name to fixed value or numpy array
:param pdfArr: optional numpy array for pdf field - used to get optimal loop structure for kernel
:param fieldLayout: layout of the pdf field if pdfArr was not given
:param target: 'cpu' or 'gpu'
:return: function taking pdf array as single argument and which sets the field to the given values
"""
if
pdfArr
is
not
None
:
pdfField
=
Field
.
createFromNumpyArray
(
'pdfs'
,
pdfArr
,
indexDimensions
=
1
)
...
...
@@ -82,22 +85,28 @@ def compileMacroscopicValuesSetter(lbMethod, quantitiesToSet, pdfArr=None, field
pdfField
=
Field
.
createGeneric
(
'pdfs'
,
lbMethod
.
dim
,
indexDimensions
=
1
,
layout
=
fieldLayout
)
fixedKernelParameters
=
{}
cqc
=
lbMethod
.
conservedQuantityComputation
valueMap
=
{}
atLeastOneFieldInput
=
False
for
quantityName
,
value
in
quantitiesToSet
.
items
():
if
hasattr
(
value
,
'shape'
):
fixedKernelParameters
[
quantityName
]
=
value
value
=
Field
.
createFromNumpyArray
(
quantityName
,
value
)
atLeastOneFieldInput
=
True
numComponents
=
cqc
.
conservedQuantities
[
quantityName
]
field
=
Field
.
createFromNumpyArray
(
quantityName
,
value
,
indexDimensions
=
0
if
numComponents
<=
1
else
1
)
if
numComponents
==
1
:
value
=
field
(
0
)
else
:
value
=
[
field
(
i
)
for
i
in
range
(
numComponents
)]
valueMap
[
quantityName
]
=
value
cqc
=
lbMethod
.
conservedQuantityComputation
cqEquations
=
cqc
.
equilibriumInputEquationsFromInitValues
(
**
valueMap
)
eq
=
lbMethod
.
getEquilibrium
(
conservedQuantityEquations
=
cqEquations
)
if
atLeastOneFieldInput
:
simplification
=
createSimplificationStrategy
(
eq
)
simplification
=
createSimplificationStrategy
(
lbMethod
)
eq
=
simplification
(
eq
)
else
:
eq
=
eq
.
insertSubexpressions
()
...
...
@@ -123,32 +132,37 @@ def compileMacroscopicValuesSetter(lbMethod, quantitiesToSet, pdfArr=None, field
return
setter
def
compileAdvancedVelocitySetter
(
collisionRule
,
velocityArray
,
pdfArr
=
None
):
def
compileAdvancedVelocitySetter
(
lbMethod
,
velocityArray
,
velocityRelaxationRate
=
1.3
,
pdfArr
=
None
):
"""
Advanced initialization of velocity field through iteration procedure according to
Mei, Luo, Lallemand and Humieres: Consistent initial conditions for LBM simulations, 2005
Important: this procedure only works if a non-zero relaxation rate was used for the velocity moments!
:param collisionRule: unsimplified collision rule
:param lbMethod:
:param velocityArray: array with velocity field
:param
pdfArr: optional array, to compile kernel with fixed layout and shape
:return: function, that has to be called multiple times, with a pdf field (src/dst) until convergenc
e
similar to the normal streamCollide step, also with boundary handling
:param
velocityRelaxationRate: relaxation rate for the velocity moments - determines convergence behaviour
of the initialization schem
e
:return: collision rule
"""
velocityField
=
Field
.
createFromNumpyArray
(
'vel'
,
velocityArray
,
indexDimensions
=
1
)
velocityField
=
Field
.
createFromNumpyArray
(
'velInput'
,
velocityArray
,
indexDimensions
=
1
)
cqc
=
lbMethod
.
conservedQuantityComputation
densitySymbol
=
cqc
.
definedSymbols
(
order
=
0
)[
1
]
velocitySymbols
=
cqc
.
definedSymbols
(
order
=
1
)[
1
]
# density is computed from pdfs
eqInputFromPdfs
=
cqc
.
equilibriumInputEquationsFromPdfs
(
lbMethod
.
preCollisionPdfSymbols
)
eqInputFromPdfs
=
eqInputFromPdfs
.
extract
([
densitySymbol
])
# velocity is read from input field
velSymbols
=
[
velocityField
(
i
)
for
i
in
range
(
lbMethod
.
dim
)]
eqInputFromField
=
cqc
.
equilibriumInputEquationsFromInitValues
(
velocity
=
velSymbols
)
eqInputFromField
=
eqInputFromField
.
extract
(
velocitySymbols
)
# then both are merged together
eqInput
=
eqInputFromPdfs
.
merge
(
eqInputFromField
)
# create normal LBM kernel and replace velocity by expressions of velocity field
from
lbmpy_old.simplifications
import
sympyCSE
latticeModel
=
collisionRule
.
latticeModel
collisionRule
=
sympyCSE
(
collisionRule
)
collisionRule
=
streamPullWithSourceAndDestinationFields
(
collisionRule
,
pdfArr
)
# set first order relaxation rate
lbMethod
=
deepcopy
(
lbMethod
)
lbMethod
.
setFirstMomentRelaxationRate
(
velocityRelaxationRate
)
re
placements
=
{
u_i
:
sp
.
Eq
(
u_i
,
velocityField
(
i
))
for
i
,
u_i
in
enumerate
(
latticeModel
.
symbolicVelocity
)}
re
turn
lbMethod
.
getCollisionRule
(
eqInput
)
newSubExpressions
=
[
replacements
[
eq
.
lhs
]
if
eq
.
lhs
in
replacements
else
eq
for
eq
in
collisionRule
.
subexpressions
]
newCollisionRule
=
LbmCollisionRule
(
collisionRule
.
updateEquations
,
newSubExpressions
,
latticeModel
,
collisionRule
.
updateEquationDirections
)
kernelAst
=
createKernel
(
newCollisionRule
.
equations
)
return
makePythonFunction
(
kernelAst
,
{
'vel'
:
velocityArray
})
methods/momentbased.py
View file @
fd57b765
...
...
@@ -35,23 +35,14 @@ class MomentBasedLbMethod(AbstractLbMethod):
assert
isinstance
(
conservedQuantityComputation
,
AbstractConservedQuantityComputation
)
moments
=
[]
relaxationRates
=
[]
equilibriumMoments
=
[]
for
moment
,
relaxInfo
in
momentToRelaxationInfoDict
.
items
():
moments
.
append
(
moment
)
relaxationRates
.
append
(
relaxInfo
.
relaxationRate
)
equilibriumMoments
.
append
(
relaxInfo
.
equilibriumValue
)
self
.
_forceModel
=
forceModel
self
.
_moments
=
moments
self
.
_momentToRelaxationInfoDict
=
momentToRelaxationInfoDict
self
.
_momentMatrix
=
momentMatrix
(
moments
,
self
.
stencil
)
self
.
_relaxationRates
=
sp
.
Matrix
(
relaxationRates
)
self
.
_equilibriumMoments
=
sp
.
Matrix
(
equilibriumMoments
)
self
.
_momentToRelaxationInfoDict
=
OrderedDict
(
momentToRelaxationInfoDict
.
items
())
self
.
_conservedQuantityComputation
=
conservedQuantityComputation
symbolsInEquilibriumMoments
=
self
.
_equilibriumMoments
.
atoms
(
sp
.
Symbol
)
equilibriumMoments
=
[]
for
moment
,
relaxInfo
in
momentToRelaxationInfoDict
.
items
():
equilibriumMoments
.
append
(
relaxInfo
.
equilibriumValue
)
symbolsInEquilibriumMoments
=
sp
.
Matrix
(
equilibriumMoments
).
atoms
(
sp
.
Symbol
)
conservedQuantities
=
set
()
for
v
in
self
.
_conservedQuantityComputation
.
definedSymbols
().
values
():
if
isinstance
(
v
,
collections
.
Sequence
):
...
...
@@ -65,6 +56,14 @@ class MomentBasedLbMethod(AbstractLbMethod):
self
.
_weights
=
None
def
setFirstMomentRelaxationRate
(
self
,
relaxationRate
):
for
e
in
MOMENT_SYMBOLS
[:
self
.
dim
]:
assert
e
in
self
.
_momentToRelaxationInfoDict
,
"First moments are not relaxed separately by this method"
for
e
in
MOMENT_SYMBOLS
[:
self
.
dim
]:
prevEntry
=
self
.
_momentToRelaxationInfoDict
[
e
]
newEntry
=
RelaxationInfo
(
prevEntry
[
0
],
relaxationRate
)
self
.
_momentToRelaxationInfoDict
[
e
]
=
newEntry
def
_repr_html_
(
self
):
table
=
"""
<table style="border:none; width: 100%">
...
...
@@ -77,7 +76,7 @@ class MomentBasedLbMethod(AbstractLbMethod):
</table>
"""
content
=
""
for
rr
,
moment
,
eqValue
in
zip
(
self
.
_relaxationRates
,
self
.
_moments
,
self
.
_equilibriumMoments
):
for
moment
,
(
eqValue
,
rr
)
in
self
.
_momentToRelaxationInfoDict
.
items
(
):
vals
=
{
'rr'
:
sp
.
latex
(
rr
),
'moment'
:
sp
.
latex
(
moment
),
...
...
@@ -93,7 +92,15 @@ class MomentBasedLbMethod(AbstractLbMethod):
@
property
def
moments
(
self
):
return
self
.
_moments
return
tuple
(
self
.
_momentToRelaxationInfoDict
.
keys
())
@
property
def
momentEquilibriumValues
(
self
):
return
tuple
([
e
.
equilibriumValue
for
e
in
self
.
_momentToRelaxationInfoDict
.
values
()])
@
property
def
relaxationRates
(
self
):
return
tuple
([
e
.
relaxationRate
for
e
in
self
.
_momentToRelaxationInfoDict
.
values
()])
@
property
def
zerothOrderEquilibriumMomentSymbol
(
self
,
):
...
...
@@ -144,13 +151,13 @@ class MomentBasedLbMethod(AbstractLbMethod):
"Can not determine their relaxation rate automatically"
)
def
getEquilibrium
(
self
,
conservedQuantityEquations
=
None
):
D
=
sp
.
eye
(
len
(
self
.
_
relaxationRates
))
D
=
sp
.
eye
(
len
(
self
.
relaxationRates
))
return
self
.
_getCollisionRuleWithRelaxationMatrix
(
D
,
conservedQuantityEquations
=
conservedQuantityEquations
)
def
getCollisionRule
(
self
):
D
=
sp
.
diag
(
*
self
.
_
relaxationRates
)
def
getCollisionRule
(
self
,
conservedQuantityEquations
=
None
):
D
=
sp
.
diag
(
*
self
.
relaxationRates
)
relaxationRateSubExpressions
,
D
=
self
.
_generateRelaxationMatrix
(
D
)
eqColl
=
self
.
_getCollisionRuleWithRelaxationMatrix
(
D
,
relaxationRateSubExpressions
)
eqColl
=
self
.
_getCollisionRuleWithRelaxationMatrix
(
D
,
relaxationRateSubExpressions
,
conservedQuantityEquations
)
if
self
.
_forceModel
is
not
None
:
forceModelTerms
=
self
.
_forceModel
(
self
)
newEqs
=
[
sp
.
Eq
(
eq
.
lhs
,
eq
.
rhs
+
fmt
)
for
eq
,
fmt
in
zip
(
eqColl
.
mainEquations
,
forceModelTerms
)]
...
...
@@ -163,8 +170,8 @@ class MomentBasedLbMethod(AbstractLbMethod):
def
_getCollisionRuleWithRelaxationMatrix
(
self
,
D
,
additionalSubexpressions
=
[],
conservedQuantityEquations
=
None
):
f
=
sp
.
Matrix
(
self
.
preCollisionPdfSymbols
)
M
=
self
.
_
moment
Matrix
m_eq
=
s
elf
.
_e
quilibrium
Moments
M
=
momentMatrix
(
self
.
moment
s
,
self
.
stencil
)
m_eq
=
s
p
.
Matrix
(
self
.
momentE
quilibrium
Values
)
collisionRule
=
f
+
M
.
inv
()
*
D
*
(
m_eq
-
M
*
f
)
collisionEqs
=
[
sp
.
Eq
(
lhs
,
rhs
)
for
lhs
,
rhs
in
zip
(
self
.
postCollisionPdfSymbols
,
collisionRule
)]
...
...
@@ -316,7 +323,7 @@ def createSRT(stencil, relaxationRate, compressible=False, forceModel=None, equi
:return: :class:`lbmpy.methods.MomentBasedLbmMethod` instance
"""
moments
=
getDefaultMomentSetForStencil
(
stencil
)
rrDict
=
{
m
:
relaxationRate
for
m
in
moments
}
rrDict
=
OrderedDict
([(
m
,
relaxationRate
)
for
m
in
moments
])
return
createWithDiscreteMaxwellianEqMoments
(
stencil
,
rrDict
,
compressible
,
forceModel
,
equilibriumAccuracyOrder
)
...
...
@@ -332,7 +339,7 @@ def createTRT(stencil, relaxationRateEvenMoments, relaxationRateOddMoments, comp
If unsure how to choose the odd relaxation rate, use the function :func:`lbmpy.methods.createTRTWithMagicNumber`.
"""
moments
=
getDefaultMomentSetForStencil
(
stencil
)
rrDict
=
{
m
:
relaxationRateEvenMoments
if
isEven
(
m
)
else
relaxationRateOddMoments
for
m
in
moments
}
rrDict
=
OrderedDict
([(
m
,
relaxationRateEvenMoments
if
isEven
(
m
)
else
relaxationRateOddMoments
)
for
m
in
moments
])
return
createWithDiscreteMaxwellianEqMoments
(
stencil
,
rrDict
,
compressible
,
forceModel
,
equilibriumAccuracyOrder
)
...
...
updatekernels.py
View file @
fd57b765
...
...
@@ -57,7 +57,8 @@ def createStreamPullKernel(collisionRule, numpyField=None, srcFieldName="src", d
"""
dim
=
collisionRule
.
method
.
dim
if
numpyField
is
not
None
:
assert
len
(
numpyField
.
shape
)
==
dim
+
1
assert
len
(
numpyField
.
shape
)
==
dim
+
1
,
"Field dimension mismatch: dimension is %s, should be %d"
%
\
(
len
(
numpyField
.
shape
),
dim
+
1
)
if
numpyField
is
None
:
src
=
Field
.
createGeneric
(
srcFieldName
,
dim
,
indexDimensions
=
1
,
layout
=
genericLayout
,
dtype
=
genericFieldType
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment