Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F78280318
fenics_engine_base.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Mon, Aug 19, 14:23
Size
21 KB
Mime Type
text/x-python
Expires
Wed, Aug 21, 14:23 (2 d)
Engine
blob
Format
Raw Data
Handle
20017933
Attached To
R6746 RationalROMPy
fenics_engine_base.py
View Options
# Copyright (C) 2018-2020 by the RROMPy authors
#
# This file is part of RROMPy.
#
# RROMPy is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RROMPy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with RROMPy. If not, see <http://www.gnu.org/licenses/>.
#
from
os
import
path
,
mkdir
import
fenics
as
fen
import
numpy
as
np
from
matplotlib
import
pyplot
as
plt
from
.scipy_engine_base
import
ScipyEngineBase
,
checknports
from
rrompy.utilities.base.types
import
(
Np1D
,
strLst
,
FenFunc
,
Tuple
,
List
,
FigHandle
)
from
rrompy.utilities.base.data_structures
import
purgeList
,
getNewFilename
from
rrompy.utilities.base
import
verbosityManager
as
vbMng
from
rrompy.solver.fenics
import
(
L2NormMatrix
,
fenplot
,
interp_project
,
serializeFunctionSpace
)
from
.boundary_conditions
import
BoundaryConditions
from
rrompy.utilities.exception_manager
import
RROMPyException
from
rrompy.utilities.parallel
import
(
SELF
,
masterCore
,
bcast
,
indicesScatter
,
listGather
)
__all__
=
[
'FenicsEngineBase'
,
'FenicsEngineBaseTensorized'
]
def
plottingBaseFen
(
u
,
fig
,
V
,
what
,
nRows
,
subplotidx
,
warping
,
name
,
colorbar
,
fenplotArgs
):
if
'ABS'
in
what
:
uAb
=
fen
.
Function
(
V
)
uAb
.
vector
()
.
set_local
(
np
.
abs
(
u
))
subplotidx
=
subplotidx
+
1
ax
=
fig
.
add_subplot
(
nRows
,
len
(
what
),
subplotidx
)
p
=
fenplot
(
uAb
,
warping
=
warping
,
title
=
"|{}|"
.
format
(
name
),
**
fenplotArgs
)
if
colorbar
:
fig
.
colorbar
(
p
,
ax
=
ax
)
if
'PHASE'
in
what
:
uPh
=
fen
.
Function
(
V
)
uPh
.
vector
()
.
set_local
(
np
.
angle
(
u
))
subplotidx
=
subplotidx
+
1
ax
=
fig
.
add_subplot
(
nRows
,
len
(
what
),
subplotidx
)
p
=
fenplot
(
uPh
,
warping
=
warping
,
title
=
"phase({})"
.
format
(
name
),
**
fenplotArgs
)
if
colorbar
:
fig
.
colorbar
(
p
,
ax
=
ax
)
if
'REAL'
in
what
:
uRe
=
fen
.
Function
(
V
)
uRe
.
vector
()
.
set_local
(
np
.
real
(
u
))
subplotidx
=
subplotidx
+
1
ax
=
fig
.
add_subplot
(
nRows
,
len
(
what
),
subplotidx
)
p
=
fenplot
(
uRe
,
warping
=
warping
,
title
=
"Re({})"
.
format
(
name
),
**
fenplotArgs
)
if
colorbar
:
fig
.
colorbar
(
p
,
ax
=
ax
)
if
'IMAG'
in
what
:
uIm
=
fen
.
Function
(
V
)
uIm
.
vector
()
.
set_local
(
np
.
imag
(
u
))
subplotidx
=
subplotidx
+
1
ax
=
fig
.
add_subplot
(
nRows
,
len
(
what
),
subplotidx
)
p
=
fenplot
(
uIm
,
warping
=
warping
,
title
=
"Im({})"
.
format
(
name
),
**
fenplotArgs
)
if
colorbar
:
fig
.
colorbar
(
p
,
ax
=
ax
)
class
FenicsEngineBase
(
ScipyEngineBase
):
"""Generic solver for parametric fenics problems."""
def
__init__
(
self
,
degree_threshold
:
int
=
np
.
inf
,
verbosity
:
int
=
10
,
timestamp
:
bool
=
True
):
super
()
.
__init__
(
verbosity
=
verbosity
,
timestamp
=
timestamp
)
self
.
BCManager
=
BoundaryConditions
()
self
.
V
=
fen
.
FunctionSpace
(
fen
.
UnitSquareMesh
(
SELF
,
1
,
1
),
"P"
,
1
)
self
.
degree_threshold
=
degree_threshold
@property
def
V
(
self
):
"""Value of V."""
return
self
.
_V
@V.setter
def
V
(
self
,
V
):
if
not
type
(
V
)
.
__name__
==
'FunctionSpace'
:
raise
RROMPyException
(
"V type not recognized."
)
self
.
dsToBeSet
=
True
self
.
_V
=
serializeFunctionSpace
(
V
)
self
.
u
=
fen
.
TrialFunction
(
self
.
_V
)
self
.
v
=
fen
.
TestFunction
(
self
.
_V
)
@property
def
spacedim
(
self
):
return
self
.
V
.
dim
()
def
buildEnergyNormForm
(
self
):
"""
Build sparse matrix (in CSR format) representative of scalar product.
"""
vbMng
(
self
,
"INIT"
,
"Assembling energy matrix."
,
20
)
self
.
_energyNormMatrix
=
L2NormMatrix
(
self
.
V
)
vbMng
(
self
,
"DEL"
,
"Done assembling energy matrix."
,
20
)
def
buildEnergyNormDualForm
(
self
):
"""
Build sparse matrix (in CSR format) representative of dual scalar
product without duality.
"""
self
.
_energyNormDualMatrix
=
self
.
energyNormMatrix
def
liftDirichletData
(
self
)
->
Np1D
:
"""Lift Dirichlet datum."""
if
not
hasattr
(
self
,
"_liftedDirichletDatum"
):
liftRe
=
interp_project
(
self
.
DirichletDatum
[
0
],
self
.
V
)
liftIm
=
interp_project
(
self
.
DirichletDatum
[
1
],
self
.
V
)
self
.
_liftedDirichletDatum
=
(
np
.
array
(
liftRe
.
vector
())
+
1.j
*
np
.
array
(
liftIm
.
vector
()))
return
self
.
_liftedDirichletDatum
def
reduceQuadratureDegree
(
self
,
fun
:
FenFunc
,
name
:
str
):
"""Check whether to reduce compiler parameters to degree threshold."""
if
not
np
.
isinf
(
self
.
degree_threshold
):
from
ufl.algorithms.estimate_degrees
import
(
estimate_total_polynomial_degree
as
ETPD
)
try
:
deg
=
ETPD
(
fun
)
except
:
return
False
if
deg
>
self
.
degree_threshold
:
vbMng
(
self
,
"MAIN"
,
(
"Reducing quadrature degree from {} to {} for "
"{}."
)
.
format
(
deg
,
self
.
degree_threshold
,
name
),
15
)
return
True
return
False
def
iterReduceQuadratureDegree
(
self
,
funsNames
:
List
[
Tuple
[
FenFunc
,
str
]]):
"""
Iterate reduceQuadratureDegree over list and define reduce compiler
parameters.
"""
if
funsNames
is
not
None
:
for
fun
,
name
in
funsNames
:
if
self
.
reduceQuadratureDegree
(
fun
,
name
):
return
{
"quadrature_degree"
:
self
.
degree_threshold
}
return
{}
def
plot
(
self
,
u
:
Np1D
,
warping
:
List
[
callable
]
=
None
,
is_state
:
bool
=
False
,
name
:
str
=
"u"
,
save
:
str
=
None
,
what
:
strLst
=
'all'
,
forceNewFile
:
bool
=
True
,
saveFormat
:
str
=
"eps"
,
saveDPI
:
int
=
100
,
show
:
bool
=
True
,
colorMap
:
str
=
"jet"
,
fenplotArgs
:
dict
=
{},
**
figspecs
)
->
Tuple
[
FigHandle
,
str
]:
"""
Do some nice plots of the complex-valued function with given dofs.
Args:
u: numpy complex array with function dofs.
warping(optional): Domain warping functions.
is_state(optional): whether given u is value before multiplication
by c. Defaults to False.
name(optional): Name to be shown as title of the plots. Defaults to
'u'.
save(optional): Where to save plot(s). Defaults to None, i.e. no
saving.
what(optional): Which plots to do. If list, can contain 'ABS',
'PHASE', 'REAL', 'IMAG'. If str, same plus wildcard 'ALL'.
Defaults to 'ALL'.
forceNewFile(optional): Whether to create new output file.
saveFormat(optional): Format for saved plot(s). Defaults to "eps".
saveDPI(optional): DPI for saved plot(s). Defaults to 100.
show(optional): Whether to show figure. Defaults to True.
colorMap(optional): Pyplot colormap. Defaults to 'jet'.
fenplotArgs(optional): Optional arguments for fenplot.
figspecs(optional key args): Optional arguments for matplotlib
figure creation.
Returns:
Output filename and figure handle.
"""
if
not
is_state
and
not
self
.
isCEye
:
return
super
()
.
plot
(
u
,
warping
,
False
,
name
,
save
,
what
,
forceNewFile
,
saveFormat
,
saveDPI
,
show
,
colorMap
,
fenplotArgs
,
**
figspecs
)
if
isinstance
(
what
,
(
str
,)):
if
what
.
upper
()
==
'ALL'
:
what
=
[
'ABS'
,
'PHASE'
,
'REAL'
,
'IMAG'
]
else
:
what
=
[
what
]
what
=
purgeList
(
what
,
[
'ABS'
,
'PHASE'
,
'REAL'
,
'IMAG'
],
listname
=
self
.
name
()
+
".what"
,
baselevel
=
1
)
if
len
(
what
)
==
0
:
return
out
=
None
if
masterCore
():
if
'figsize'
not
in
figspecs
.
keys
():
figspecs
[
'figsize'
]
=
plt
.
figaspect
(
1.
/
len
(
what
))
fig
=
plt
.
figure
(
**
figspecs
)
plt
.
set_cmap
(
colorMap
)
plottingBaseFen
(
u
,
fig
,
self
.
V
,
what
,
1
,
0
,
warping
,
name
,
self
.
V
.
mesh
()
.
geometric_dimension
()
>
1
,
fenplotArgs
)
plt
.
tight_layout
()
if
save
is
not
None
:
save
=
save
.
strip
()
if
forceNewFile
:
fileOut
=
getNewFilename
(
"{}_fig_"
.
format
(
save
),
saveFormat
)
else
:
fileOut
=
"{}_fig.{}"
.
format
(
save
,
saveFormat
)
fig
.
savefig
(
fileOut
,
format
=
saveFormat
,
dpi
=
saveDPI
)
else
:
fileOut
=
None
if
show
:
plt
.
show
()
out
=
fig
if
fileOut
is
None
else
(
fig
,
fileOut
)
return
bcast
(
out
)
def
plotmesh
(
self
,
warping
:
List
[
callable
]
=
None
,
name
:
str
=
"Mesh"
,
save
:
str
=
None
,
forceNewFile
:
bool
=
True
,
saveFormat
:
str
=
"eps"
,
saveDPI
:
int
=
100
,
show
:
bool
=
True
,
fenplotArgs
:
dict
=
{},
**
figspecs
)
->
Tuple
[
FigHandle
,
str
]:
"""
Do a nice plot of the mesh.
Args:
u: numpy complex array with function dofs.
warping(optional): Domain warping functions.
name(optional): Name to be shown as title of the plots. Defaults to
'u'.
save(optional): Where to save plot(s). Defaults to None, i.e. no
saving.
forceNewFile(optional): Whether to create new output file.
saveFormat(optional): Format for saved plot(s). Defaults to "eps".
saveDPI(optional): DPI for saved plot(s). Defaults to 100.
show(optional): Whether to show figure. Defaults to True.
fenplotArgs(optional): Optional arguments for fenplot.
figspecs(optional key args): Optional arguments for matplotlib
figure creation.
Returns:
Output filename and figure handle.
"""
out
=
None
if
masterCore
():
fig
=
plt
.
figure
(
**
figspecs
)
fenplot
(
self
.
V
.
mesh
(),
warping
=
warping
,
**
fenplotArgs
)
plt
.
tight_layout
()
if
save
is
not
None
:
save
=
save
.
strip
()
if
forceNewFile
:
fileOut
=
getNewFilename
(
"{}_msh_"
.
format
(
save
),
saveFormat
)
else
:
fileOut
=
"{}_msh.{}"
.
format
(
save
,
saveFormat
)
fig
.
savefig
(
fileOut
,
format
=
saveFormat
,
dpi
=
saveDPI
)
else
:
fileOut
=
None
if
show
:
plt
.
show
()
out
=
fig
if
fileOut
is
None
else
(
fig
,
fileOut
)
return
bcast
(
out
)
def
outParaview
(
self
,
u
:
Np1D
,
warping
:
List
[
callable
]
=
None
,
is_state
:
bool
=
False
,
name
:
str
=
"u"
,
filename
:
str
=
"out"
,
time
:
float
=
0.
,
what
:
strLst
=
'all'
,
forceNewFile
:
bool
=
True
,
folder
:
bool
=
False
,
filePW
=
None
)
->
str
:
"""
Output complex-valued function with given dofs to ParaView file.
Args:
u: numpy complex array with function dofs.
warping(optional): Domain warping functions.
is_state(optional): whether given u is value before multiplication
by c. Defaults to False.
name(optional): Base name to be used for data output.
filename(optional): Name of output file.
time(optional): Timestamp.
what(optional): Which plots to do. If list, can contain 'MESH',
'ABS', 'PHASE', 'REAL', 'IMAG'. If str, same plus wildcard
'ALL'. Defaults to 'ALL'.
forceNewFile(optional): Whether to create new output file.
folder(optional): Whether to create an additional folder layer.
filePW(optional): Fenics File entity (for time series).
Returns:
Output filename.
"""
if
not
is_state
and
not
self
.
isCEye
:
raise
RROMPyException
((
"Cannot output to Paraview non-state "
"object."
))
if
isinstance
(
what
,
(
str
,)):
if
what
.
upper
()
==
'ALL'
:
what
=
[
'MESH'
,
'ABS'
,
'PHASE'
,
'REAL'
,
'IMAG'
]
else
:
what
=
[
what
]
what
=
purgeList
(
what
,
[
'MESH'
,
'ABS'
,
'PHASE'
,
'REAL'
,
'IMAG'
],
listname
=
self
.
name
()
+
".what"
,
baselevel
=
1
)
if
len
(
what
)
==
0
:
return
filePW
=
None
if
masterCore
():
if
filePW
is
None
:
if
folder
:
if
not
path
.
exists
(
filename
+
"/"
):
mkdir
(
filename
)
idxpath
=
filename
.
rfind
(
"/"
)
filename
+=
"/"
+
filename
[
idxpath
+
1
:]
if
forceNewFile
:
filePW
=
fen
.
File
(
getNewFilename
(
filename
,
"pvd"
))
else
:
filePW
=
fen
.
File
(
"{}.pvd"
.
format
(
filename
))
if
warping
is
not
None
:
fen
.
ALE
.
move
(
self
.
V
.
mesh
(),
interp_project
(
warping
[
0
],
self
.
V
.
mesh
()))
if
what
==
[
'MESH'
]:
filePW
<<
(
self
.
V
.
mesh
(),
time
)
if
'ABS'
in
what
:
uAb
=
fen
.
Function
(
self
.
V
,
name
=
"{}_ABS"
.
format
(
name
))
uAb
.
vector
()
.
set_local
(
np
.
abs
(
u
))
filePW
<<
(
uAb
,
time
)
if
'PHASE'
in
what
:
uPh
=
fen
.
Function
(
self
.
V
,
name
=
"{}_PHASE"
.
format
(
name
))
uPh
.
vector
()
.
set_local
(
np
.
angle
(
u
))
filePW
<<
(
uPh
,
time
)
if
'REAL'
in
what
:
uRe
=
fen
.
Function
(
self
.
V
,
name
=
"{}_REAL"
.
format
(
name
))
uRe
.
vector
()
.
set_local
(
np
.
real
(
u
))
filePW
<<
(
uRe
,
time
)
if
'IMAG'
in
what
:
uIm
=
fen
.
Function
(
self
.
V
,
name
=
"{}_IMAG"
.
format
(
name
))
uIm
.
vector
()
.
set_local
(
np
.
imag
(
u
))
filePW
<<
(
uIm
,
time
)
if
warping
is
not
None
:
fen
.
ALE
.
move
(
self
.
V
.
mesh
(),
interp_project
(
warping
[
1
],
self
.
V
.
mesh
()))
return
bcast
(
filePW
)
def
outParaviewTimeDomain
(
self
,
u
:
Np1D
,
omega
:
float
,
warping
:
List
[
callable
]
=
None
,
is_state
:
bool
=
False
,
timeFinal
:
float
=
None
,
periodResolution
:
int
=
20
,
name
:
str
=
"u"
,
filename
:
str
=
"out"
,
forceNewFile
:
bool
=
True
,
folder
:
bool
=
False
)
->
str
:
"""
Output complex-valued function with given dofs to ParaView file,
converted to time domain.
Args:
u: numpy complex array with function dofs.
omega: frequency.
warping(optional): Domain warping functions.
is_state(optional): whether given u is value before multiplication
by c. Defaults to False.
timeFinal(optional): final time of simulation.
periodResolution(optional): number of time steps per period.
name(optional): Base name to be used for data output.
filename(optional): Name of output file.
forceNewFile(optional): Whether to create new output file.
folder(optional): Whether to create an additional folder layer.
Returns:
Output filename.
"""
if
not
is_state
and
not
self
.
isCEye
:
raise
RROMPyException
((
"Cannot output to Paraview non-state "
"object."
))
filePW
=
None
if
masterCore
():
if
folder
:
if
not
path
.
exists
(
filename
+
"/"
):
mkdir
(
filename
)
idxpath
=
filename
.
rfind
(
"/"
)
filename
+=
"/"
+
filename
[
idxpath
+
1
:]
if
forceNewFile
:
filePW
=
fen
.
File
(
getNewFilename
(
filename
,
"pvd"
))
else
:
filePW
=
fen
.
File
(
"{}.pvd"
.
format
(
filename
))
t
=
0.
dt
=
2.
*
np
.
pi
/
np
.
abs
(
omega
)
/
periodResolution
if
timeFinal
is
None
:
timeFinal
=
2.
*
np
.
pi
/
np
.
abs
(
omega
)
-
dt
if
warping
is
not
None
:
fen
.
ALE
.
move
(
self
.
V
.
mesh
(),
interp_project
(
warping
[
0
],
self
.
V
.
mesh
()))
for
j
in
range
(
int
(
np
.
ceil
(
timeFinal
/
dt
))
+
1
):
ut
=
fen
.
Function
(
self
.
V
,
name
=
name
)
ut
.
vector
()
.
set_local
(
np
.
real
(
u
)
*
np
.
cos
(
omega
*
t
)
+
np
.
imag
(
u
)
*
np
.
sin
(
omega
*
t
))
filePW
<<
(
ut
,
t
)
t
+=
dt
if
warping
is
not
None
:
fen
.
ALE
.
move
(
self
.
V
.
mesh
(),
interp_project
(
warping
[
1
],
self
.
V
.
mesh
()))
return
bcast
(
filePW
)
class
FenicsEngineBaseTensorized
(
FenicsEngineBase
):
"""The number of tensorized dimensions should be assigned to nports."""
def
plot
(
self
,
u
:
Np1D
,
warping
:
List
[
callable
]
=
None
,
is_state
:
bool
=
False
,
name
:
str
=
"u"
,
save
:
str
=
None
,
what
:
strLst
=
'all'
,
forceNewFile
:
bool
=
True
,
saveFormat
:
str
=
"eps"
,
saveDPI
:
int
=
100
,
show
:
bool
=
True
,
colorMap
:
str
=
"jet"
,
fenplotArgs
:
dict
=
{},
**
figspecs
)
->
Tuple
[
FigHandle
,
str
]:
"""
Do some nice plots of the complex-valued function with given dofs.
Args:
u: numpy complex array with function dofs.
warping(optional): Domain warping functions.
is_state(optional): whether given u is value before multiplication
by c. Defaults to False.
name(optional): Name to be shown as title of the plots. Defaults to
'u'.
save(optional): Where to save plot(s). Defaults to None, i.e. no
saving.
what(optional): Which plots to do. If list, can contain 'ABS',
'PHASE', 'REAL', 'IMAG'. If str, same plus wildcard 'ALL'.
Defaults to 'ALL'.
forceNewFile(optional): Whether to create new output file.
saveFormat(optional): Format for saved plot(s). Defaults to "eps".
saveDPI(optional): DPI for saved plot(s). Defaults to 100.
show(optional): Whether to show figure. Defaults to True.
colorMap(optional): Pyplot colormap. Defaults to 'jet'.
fenplotArgs(optional): Optional arguments for fenplot.
figspecs(optional key args): Optional arguments for matplotlib
figure creation.
Returns:
Output filename and figure handle.
"""
nP
=
checknports
(
self
)
if
not
is_state
and
not
self
.
isCEye
:
return
super
()
.
plot
(
u
.
reshape
(
-
1
,
nP
),
warping
,
False
,
name
,
save
,
what
,
forceNewFile
,
saveFormat
,
saveDPI
,
show
,
colorMap
,
fenplotArgs
,
**
figspecs
)
if
isinstance
(
what
,
(
str
,)):
if
what
.
upper
()
==
'ALL'
:
what
=
[
'ABS'
,
'PHASE'
,
'REAL'
,
'IMAG'
]
else
:
what
=
[
what
]
what
=
purgeList
(
what
,
[
'ABS'
,
'PHASE'
,
'REAL'
,
'IMAG'
],
listname
=
self
.
name
()
+
".what"
,
baselevel
=
1
)
if
len
(
what
)
==
0
:
return
out
=
None
if
masterCore
():
if
'figsize'
not
in
figspecs
.
keys
():
figspecs
[
'figsize'
]
=
plt
.
figaspect
(
1.
/
len
(
what
))
figspecs
[
'figsize'
][
1
]
*=
nP
fig
=
plt
.
figure
(
**
figspecs
)
plt
.
set_cmap
(
colorMap
)
for
i
in
range
(
nP
):
plottingBaseFen
(
u
[
i
::
nP
],
fig
,
self
.
V
,
what
,
nP
,
i
*
len
(
what
),
warping
,
"{}_port{}"
.
format
(
name
,
i
+
1
),
self
.
V
.
mesh
()
.
geometric_dimension
()
>
1
,
fenplotArgs
)
plt
.
tight_layout
()
if
save
is
not
None
:
save
=
save
.
strip
()
if
forceNewFile
:
fileOut
=
getNewFilename
(
"{}_fig_"
.
format
(
save
),
saveFormat
)
else
:
fileOut
=
"{}_fig.{}"
.
format
(
save
,
saveFormat
)
fig
.
savefig
(
fileOut
,
format
=
saveFormat
,
dpi
=
saveDPI
)
else
:
fileOut
=
None
if
show
:
plt
.
show
()
out
=
fig
if
fileOut
is
None
else
(
fig
,
fileOut
)
return
bcast
(
out
)
def
outParaview
(
self
,
u
:
Np1D
,
*
args
,
**
kwargs
)
->
List
[
str
]:
nP
=
checknports
(
self
)
idx
=
indicesScatter
(
nP
)[
0
]
filesOut
=
[]
if
len
(
idx
)
>
0
:
for
j
in
idx
:
filesOut
+=
super
()
.
outParaview
(
u
[
j
::
nP
],
*
args
,
**
kwargs
)
filesOut
=
listGather
(
filesOut
)
if
filesOut
[
0
]
is
None
:
return
None
return
filesOut
def
outParaviewTimeDomain
(
self
,
u
:
Np1D
,
*
args
,
**
kwargs
)
->
List
[
str
]:
nP
=
checknports
(
self
)
idx
=
indicesScatter
(
nP
)[
0
]
filesOut
=
[]
if
len
(
idx
)
>
0
:
for
j
in
idx
:
filesOut
+=
super
()
.
outParaviewTimeDomain
(
u
[
j
::
nP
],
*
args
,
**
kwargs
)
filesOut
=
listGather
(
filesOut
)
if
filesOut
[
0
]
is
None
:
return
None
return
filesOut
Event Timeline
Log In to Comment