Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Markus Holzer
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
Supports
Markdown
0%
Try again
or
attach a new 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