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
a3556a10
Commit
a3556a10
authored
May 24, 2017
by
Martin Bauer
Browse files
Automatic Chapman Enskog Analysis of moment-based methods
parent
9d35ef5d
Changes
14
Expand all
Hide whitespace changes
Inline
Side-by-side
chapman_enskog/ChapmanEnskog-MultiDim.ipynb
0 → 100644
View file @
a3556a10
This diff is collapsed.
Click to expand it.
chapman_enskog/ChapmanEnskog.ipynb
0 → 100644
View file @
a3556a10
{
"cells": [
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import sympy as sp\n",
"\n",
"# Using operator and kets from quantum module to represent differential operators and pdfs\n",
"from sympy.physics.quantum import Ket as Func\n",
"from sympy.physics.quantum import Operator\n",
"# Disable Ket notation |f> for functions\n",
"Func.lbracket_latex =''\n",
"Func.rbracket_latex = ''\n",
"\n",
"sp.init_printing()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Chapman Enskog analysis\n",
"\n",
"Particle distribution function $f$:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"c = sp.Symbol(\"c_x\")\n",
"dt = sp.Symbol(\"Delta_t\")\n",
"t = sp.symbols(\"t\")\n",
"f = Func(\"f\")\n",
"C = Func(\"C\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Differential operators (defined simply as non-commutative symbols here)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"Dx = Operator(\"\\partial_x\") \n",
"Dt = Operator(\"\\partial_t\")"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAASYAAAAvBAMAAAC8knqVAAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAZjJ2me8QRFSJqyLN\n3buI9fnTAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEq0lEQVRYCc1WTYhbVRT+kiYvefmZGVGKoNCI\nuivMoIPSuvChVVBoGQQRQWgWunHEyaZQBTHgpi7U6BRhGMWgS4tm0Y3IOKkUBI0QUanVhaMbQRdO\n7TAiFcd7z7nn/mRehYbIvLt479zvnvPd773cvO8AMuJjD0qYmfsqzmRGiwj5AbM9ibNyv4D1Vla0\nKB0zrOW1ZnY05S+zlq+zIwmF4/SC4iRDmk4e6Gg1N2RIEpLitpJT6pQamVFVauf+UmIOnnq1mRlN\nBUAfqOM7O5mRhJMAH6hxJf0PrtQF6ECNKwmTd6VyG8htjS1IFU7elSpajj5Qn+pgnDF5VzqlZRxI\nEOkPwphj0q7U1TqKV1AejilIlU3Ylcrnj6hxdKt69HxjXFGTdqX6Do9mrW0kVU2bwNPcodU0qQLf\npBfTXMknCRmvX+n9B2POX5yWySdBxSqebQUATwSuqKo0V5Jeg7IDxrgX/ZJCqL4ovNH73uIJib+Q\nQN9zfeQXfIBjC0f9dFcyvQZnB4w3A7czHFwt4zMefDjiF5VLPBAFJeiSA8pzHDt42Xell2ym6TVo\nHjI+AEzP2DxIiWWMzRY65f6YE+s9V8DRNw4QTRph+Cm3CLsBTK/Ba7sY64krEk0aIcZowS0+fwfH\naw7SUf5G/OMQq8nCtZZbdZpMr8FLI4y3tKc3XI3VZBk/c4sSzetg+c4Gz/PnFt/Y4lBfRZODg++A\n3cD0GlwYMh7c/9Fswgv6KiWO8bRblOgnFay1a32en2hgyrTrGhBNDlZn0w3ZIOw1AsbSI8Dv3pGR\nEseo/gSj4zsFPI5Km/Cq0lP/06UYTQbWDhl8/mUDdE2vQR4aMK4rPT96v7cp8Rhfgflk8m1TbfIY\nULDWV1FRccFoigeDL58YDNR+DJND5nUNjbcGg28Hg891LL0Ge2jA+GETeJTy1cWVeIyzsuruiqG4\nIdPpPrDUkZn97RimV+Q0qSx5T9Jr8EsMGP8GIt1qyzAlHmOKJvWmSUU8f+u7WEqAe5sUEon57Qhe\nJIcsDYVd3UWT6TWMh/qM0RawbxvL9x1ucJ0p8Rhf8AhNqE6k/qa176r0L2BpDrgICmlZNBFMDpl6\nxrs6WfUa7KE+Y6QPaGdf80y9RYTyGLwR5aec8dPqPHXxZKNRmwGmuqhsgEKiMJoYJocsdJibruah\npdcAe2jA+CvwAfI4J1WmxGN8SJbcXb+6levm1NvqAdWvFo+oufVn+d8RTA5Za7hSeWjba7CHBoxr\n+88mquKKVBlNvBHlm3737LGfJQfWCWbRUIf6daUMFOoMo4lhcsjgI2020Jk02ENDxpd1e5PfzJsU\nKaGNdH51SCtRF++0TA5yCUXVzbfRYcwLjU8zTg6pPNiNRRdSxB66m3E9HsYmNSjR+fEcrVSa7iME\n/EZY9N5zh5pc54UMmKt2yKhvJqk346G7GJ++e/nNtAKdb3qV4hCVP2xO0IFZ9CrBVO8qCz58TYz8\nAKht+5rCTtXnTomp903BA+haGL3et27tJGDb08mL5jzvqYiRzb8fmWdgWkgyIGJEwvzIPAPTcoKP\nMyAjkHAbcE8A7P2kenHl4eHeywgU1FTnmyFN/wL4tmTZeQ4GZwAAAABJRU5ErkJggg==\n",
"text/latex": [
"$$\\frac{\\Delta_{t}^{2}}{2} \\left(c_{x} \\partial_x + \\partial_t\\right)^{2} + \\Delta_{t} \\left(c_{x} \\partial_x + \\partial_t\\right)$$"
],
"text/plain": [
" 2 2 \n",
"Δₜ ⋅(cₓ⋅\\partialₓ + \\partialₜ) \n",
"─────────────────────────────── + Δₜ⋅(cₓ⋅\\partialₓ + \\partialₜ)\n",
" 2 "
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"taylorOrder = 2\n",
"taylorOperator = sum(dt**k * (Dt + c* Dx)**k / sp.functions.factorial(k)\n",
" for k in range(1, taylorOrder+1))\n",
"taylorOperator"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As right-hand-side we use the abstract collision operator $C$, which corresponds to (4.5)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/latex": [
"$$\\left(\\frac{\\Delta_{t}^{2}}{2} \\left(c_{x} \\partial_x + \\partial_t\\right)^{2} + \\Delta_{t} \\left(c_{x} \\partial_x + \\partial_t\\right)\\right) {f} - {C}$$"
],
"text/plain": [
"⎛ 2 2 ⎞ \n",
"⎜Δₜ ⋅(cₓ⋅\\partialₓ + \\partialₜ) ⎟ \n",
"⎜─────────────────────────────── + Δₜ⋅(cₓ⋅\\partialₓ + \\partialₜ)⎟⋅❘f⟩ - ❘C⟩\n",
"⎝ 2 ⎠ "
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"eq_4_5 = (taylorOperator * f) - C\n",
"eq_4_5"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Following the same steps as in the book, getting rid of second derivative, and discarding $\\Delta_t^3$ we get to (4.7)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"eq_4_7 = eq_4_5 - (dt/2)* (Dt + c*Dx) * eq_4_5\n",
"eq_4_7 = eq_4_7.expand().subs(dt**3, 0)\n",
"eq_4_7"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Chapman Enskog Ansatz\n",
"\n",
"Open Question:\n",
" why is not everything expanded equally (derivatives start at 1, spatial terminates one earlier...)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"eps = sp.Symbol(\"epsilon\")\n",
"\n",
"ceSymbolsF = [Func(\"f{}\".format(i)) for i in range(3)]\n",
"ceSymbolsDt = [Operator(\"\\partial_t^{{ ({}) }}\".format(i)) for i in range(1,3)]\n",
"ceSymbolsDx = [Operator(\"\\partial_x^{{ ({}) }}\".format(i)) for i in range(1,2)]\n",
"\n",
"ceF = sum(eps**k * s for k, s in enumerate(ceSymbolsF, start=0))\n",
"ceDt = sum(eps**k * s for k, s in enumerate(ceSymbolsDt, start=1))\n",
"ceDx = sum(eps**k * s for k, s in enumerate(ceSymbolsDx, start=1))\n",
"\n",
"ceSubstitutions = {\n",
" Dt : ceDt,\n",
" Dx : ceDx,\n",
" f: ceF\n",
"}\n",
"ceSubstitutions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Inserting the SRT/BGK collision operator"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"srtC = -dt / sp.Symbol(\"tau\") * ( ceF - ceSymbolsF[0])\n",
"srtC"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"eq_4_7_ce = eq_4_7.subs(ceSubstitutions).subs(C, srtC).expand().collect(eps)\n",
"eq_4_7_ce"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"eq_4_9_a = (eq_4_7_ce.coeff(eps) / dt).expand()\n",
"eq_4_9_a"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"eq_4_9_b = (eq_4_7_ce.coeff(eps**2) / dt).expand()\n",
"eq_4_9_b"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Computing moments"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import operator\n",
"from functools import reduce\n",
"def prod(factors):\n",
" return reduce(operator.mul, factors, 1)\n",
"\n",
"def getMomentSymbol(idx, order):\n",
" momentOrderStr = ['alpha', 'beta', 'gamma', 'delta']\n",
" momentOrderStr = \"_\".join(momentOrderStr[:order-1] + ['x'])\n",
" return sp.Symbol(\"Pi^(%d)_%s\" % (idx, momentOrderStr), commutative=False)\n",
"\n",
"def takeMoments(eqn, order):\n",
" markerTerms = sp.symbols(\"c_alpha c_beta c_gamma c_delta\")\n",
" velocityTermSet = set(markerTerms)\n",
" velocityTermSet.add(c)\n",
" factor = prod(markerTerms[:order])\n",
" eqn = (eqn*factor).expand()\n",
" result = 0\n",
" for fac in eqn.args:\n",
" occuringFs = list(fac.atoms(Func))\n",
" assert len(occuringFs) < 2\n",
" if len(occuringFs) == 0:\n",
" result += fac\n",
" continue\n",
" fIdx = ceSymbolsF.index(occuringFs[0])\n",
" \n",
" occuringCs = fac.atoms(sp.Symbol).intersection(velocityTermSet)\n",
" facWithoutCs = sp.cancel(fac / prod(occuringCs) / occuringFs[0])\n",
" assert not facWithoutCs.atoms(sp.Symbol).intersection(velocityTermSet), \"Non-linear velocity term\"\n",
" \n",
" # TODO handle multiple non-marker terms\n",
" moment = getMomentSymbol(fIdx, len(occuringCs))\n",
" #momentOrderStr = ['alpha', 'beta', 'gamma', 'delta']\n",
" #momentOrderStr = \"_\".join(momentOrderStr[:len(occuringCs)])\n",
" #moment = sp.Symbol(\"Pi^(%d)_%s\" % (fIdx, momentOrderStr), commutative=False)\n",
" result += facWithoutCs * moment\n",
" \n",
" return result"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rho = Func(\"rho\")\n",
"u_x = Func(\"u_x\")\n",
"momentReplacements = {\n",
" getMomentSymbol(0, 0): rho,\n",
" getMomentSymbol(0, 1): rho * u_x,\n",
" \n",
" getMomentSymbol(1, 0): 0, # According to eq 4.4\n",
" getMomentSymbol(1, 1): 0,\n",
" getMomentSymbol(2, 0): 0,\n",
" getMomentSymbol(2, 1): 0,\n",
"}\n",
"momentReplacements"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Moments\n",
"\n",
"Moments of $\\epsilon$-sorted equations\n",
"\n",
"$O(\\epsilon)$"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"eq_4_10_a = takeMoments(eq_4_9_a, 0).subs(momentReplacements)\n",
"eq_4_10_a"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"eq_4_10_b = takeMoments(eq_4_9_a, 1).subs(momentReplacements)\n",
"eq_4_10_b"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"eq_4_10_c = takeMoments(eq_4_9_a, 2).subs(momentReplacements)\n",
"eq_4_10_c"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$O(\\epsilon^2)$"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"eq_4_12_a = takeMoments(eq_4_9_b, 0).subs(momentReplacements)\n",
"eq_4_12_a"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"eq_4_12_b = takeMoments(eq_4_9_b, 1).subs(momentReplacements)\n",
"eq_4_12_b"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Recombination"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"(eps * eq_4_10_a + eps**2 * eq_4_12_a).expand()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"(eps * eq_4_10_b + eps**2 * eq_4_12_b).expand()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"stressTensorSubs = -"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from lbmpy.maxwellian_equilibrium import getMomentsOfDiscreteMaxwellianEquilibrium\n",
"from lbmpy.stencils import getStencil\n",
"from lbmpy.moments import momentsOfOrder\n",
"stencil = getStencil(\"D3Q19\")\n",
"dim = len(stencil[0])\n",
"moments = tuple(momentsOfOrder(2, dim=dim))\n",
"print(moments)\n",
"u = Func(\"u_x\"), Func(\"u_y\"), Func(\"u_z\")\n",
"rho = Func(\"rho\")\n",
"pi_ab = getMomentsOfDiscreteMaxwellianEquilibrium(stencil, moments,c_s_sq=sp.Rational(1,3), order=2, u=u, rho=rho)\n",
"pi_ab"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from lbmpy.maxwellian_equilibrium import getMomentsOfContinuousMaxwellianEquilibrium\n",
"pi_ab2 = getMomentsOfContinuousMaxwellianEquilibrium(moments, dim, c_s_sq=sp.Rational(1,3), order=2)\n",
"pi_ab2"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sp.solve(eq_4_10_c, getMomentSymbol(1, 2))[0]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from lbmpy.chapman_enskog import *\n",
"productRule((ceSymbolsDt[0] * pi_ab[1]).expand())"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"dtSubsDict = {\n",
" ceSymbolsDt[0] * rho: -ceSymbolsDx[0]*(rho*u[0]),\n",
" productRule((ceSymbolsDt[0] * (rho * u[1])).expand()) : sp.Symbol(\"bla\")\n",
"}\n",
"dtSubsDict"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"-ceSymbolsDx[0]*(rho*u[0])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
%% Cell type:code id: tags:
```
python
import
sympy
as
sp
# Using operator and kets from quantum module to represent differential operators and pdfs
from
sympy.physics.quantum
import
Ket
as
Func
from
sympy.physics.quantum
import
Operator
# Disable Ket notation |f> for functions
Func
.
lbracket_latex
=
''
Func
.
rbracket_latex
=
''
sp
.
init_printing
()
```
%% Cell type:markdown id: tags:
# Chapman Enskog analysis
Particle distribution function $f$:
%% Cell type:code id: tags:
```
python
c
=
sp
.
Symbol
(
"c_x"
)
dt
=
sp
.
Symbol
(
"Delta_t"
)
t
=
sp
.
symbols
(
"t"
)
f
=
Func
(
"f"
)
C
=
Func
(
"C"
)
```
%% Cell type:markdown id: tags:
Differential operators (defined simply as non-commutative symbols here)
%% Cell type:code id: tags:
```
python
Dx
=
Operator
(
"\partial_x"
)
Dt
=
Operator
(
"\partial_t"
)
```
%% Cell type:code id: tags:
```
python
taylorOrder
=
2
taylorOperator
=
sum
(
dt
**
k
*
(
Dt
+
c
*
Dx
)
**
k
/
sp
.
functions
.
factorial
(
k
)
for
k
in
range
(
1
,
taylorOrder
+
1
))
taylorOperator
```
%% Output
$$\frac{\Delta_{t}^{2}}{2} \left(c_{x} \partial_x + \partial_t\right)^{2} + \Delta_{t} \left(c_{x} \partial_x + \partial_t\right)$$
2 2
Δₜ ⋅(cₓ⋅\partialₓ + \partialₜ)
─────────────────────────────── + Δₜ⋅(cₓ⋅\partialₓ + \partialₜ)
2
%% Cell type:markdown id: tags:
As right-hand-side we use the abstract collision operator $C$, which corresponds to (4.5)
%% Cell type:code id: tags:
```
python
eq_4_5
=
(
taylorOperator
*
f
)
-
C
eq_4_5
```
%% Output
$$\left(\frac{\Delta_{t}^{2}}{2} \left(c_{x} \partial_x + \partial_t\right)^{2} + \Delta_{t} \left(c_{x} \partial_x + \partial_t\right)\right) {f} - {C}$$
⎛ 2 2 ⎞
⎜Δₜ ⋅(cₓ⋅\partialₓ + \partialₜ) ⎟
⎜─────────────────────────────── + Δₜ⋅(cₓ⋅\partialₓ + \partialₜ)⎟⋅❘f⟩ - ❘C⟩
⎝ 2 ⎠
%% Cell type:markdown id: tags:
Following the same steps as in the book, getting rid of second derivative, and discarding $
\D
elta_t^3$ we get to (4.7)
%% Cell type:code id: tags:
```
python
eq_4_7
=
eq_4_5
-
(
dt
/
2
)
*
(
Dt
+
c
*
Dx
)
*
eq_4_5
eq_4_7
=
eq_4_7
.
expand
().
subs
(
dt
**
3
,
0
)
eq_4_7
```
%% Cell type:markdown id: tags:
### Chapman Enskog Ansatz
Open Question:
why is not everything expanded equally (derivatives start at 1, spatial terminates one earlier...)
%% Cell type:code id: tags:
```
python
eps
=
sp
.
Symbol
(
"epsilon"
)
ceSymbolsF
=
[
Func
(
"f{}"
.
format
(
i
))
for
i
in
range
(
3
)]
ceSymbolsDt
=
[
Operator
(
"\partial_t^{{ ({}) }}"
.
format
(
i
))
for
i
in
range
(
1
,
3
)]
ceSymbolsDx
=
[
Operator
(
"\partial_x^{{ ({}) }}"
.
format
(
i
))
for
i
in
range
(
1
,
2
)]
ceF
=
sum
(
eps
**
k
*
s
for
k
,
s
in
enumerate
(
ceSymbolsF
,
start
=
0
))
ceDt
=
sum
(
eps
**
k
*
s
for
k
,
s
in
enumerate
(
ceSymbolsDt
,
start
=
1
))
ceDx
=
sum
(
eps
**
k
*
s
for
k
,
s
in
enumerate
(
ceSymbolsDx
,
start
=
1
))
ceSubstitutions
=
{
Dt
:
ceDt
,
Dx
:
ceDx
,
f
:
ceF
}
ceSubstitutions
```
%% Cell type:markdown id: tags:
Inserting the SRT/BGK collision operator
%% Cell type:code id: tags:
```
python
srtC
=
-
dt
/
sp
.
Symbol
(
"tau"
)
*
(
ceF
-
ceSymbolsF
[
0
])
srtC
```
%% Cell type:code id: tags:
```
python
eq_4_7_ce
=
eq_4_7
.
subs
(
ceSubstitutions
).
subs
(
C
,
srtC
).
expand
().
collect
(
eps
)
eq_4_7_ce
```
%% Cell type:code id: tags:
```
python
eq_4_9_a
=
(
eq_4_7_ce
.
coeff
(
eps
)
/
dt
).
expand
()
eq_4_9_a
```
%% Cell type:code id: tags:
```
python
eq_4_9_b
=
(
eq_4_7_ce
.
coeff
(
eps
**
2
)
/
dt
).
expand
()
eq_4_9_b
```
%% Cell type:markdown id: tags:
Computing moments
%% Cell type:code id: tags:
```
python
import
operator
from
functools
import
reduce
def
prod
(
factors
):
return
reduce
(
operator
.
mul
,
factors
,
1
)
def
getMomentSymbol
(
idx
,
order
):