Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Summarize changes to support CEESD prediction #1

Open
wants to merge 134 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
134 commits
Select commit Hold shift + click to select a range
ef79f35
Support new find_distributed_partition
matthiasdiener Jan 10, 2023
439a41f
pylint
matthiasdiener Jan 10, 2023
6f64d77
flake8
matthiasdiener Jan 10, 2023
6f52ae5
only catch one type of TypeError
matthiasdiener Jan 19, 2023
bc2d41b
flake8
matthiasdiener Jan 19, 2023
dec4fce
set up connections between volumes
majosm Sep 21, 2022
a9690f9
add inter-volume communication
majosm Sep 21, 2022
c536905
add fixme
majosm Nov 3, 2022
d5576fb
check for heterogeneous inter-volume data
majosm Nov 3, 2022
1a38e2d
tag communication by destination volume
majosm Nov 3, 2022
50e2d42
add filter_part_boundaries
majosm Apr 3, 2023
343529c
Merge remote-tracking branch 'origin/support-new-find_partition' into…
majosm Apr 3, 2023
dc8d8dc
Entropy stable DG and flux-differencing
thomasgibson Apr 14, 2023
203878b
Merge remote-tracking branch 'inducer/flux-diff-update' into grudge-esdg
MTCam Apr 14, 2023
7c532c6
Update for multi-volume cases.
MTCam Apr 26, 2023
ffa5592
Update for multivol
MTCam Apr 26, 2023
248043c
tag axes in reshape in _apply_elementwise_reduction
majosm May 25, 2023
8894445
set up connections between volumes
majosm Sep 21, 2022
deb2e46
add inter-volume communication
majosm Sep 21, 2022
d16767a
add fixme
majosm Nov 3, 2022
a3810ce
check for heterogeneous inter-volume data
majosm Nov 3, 2022
bfad1f7
tag communication by destination volume
majosm Nov 3, 2022
c112288
add filter_part_boundaries
majosm Apr 3, 2023
7f73999
Merge branch 'elementwise-reduction-axes' into production
majosm May 25, 2023
142cdd8
Merge with upstream changes
MTCam Jun 16, 2023
bfe2d4b
Add Numpy actx
MTCam Jun 27, 2023
b12f624
Merge branch 'main' into production-mrgup
MTCam Jun 27, 2023
76fd6cf
Merge branch 'production-mrgup' into production-esdg-mrgup
MTCam Jun 27, 2023
b1be58a
Update _reference_derivative_matrices to recognize TensorProductEleme…
a-alveyblanc Aug 1, 2023
8fa3321
Stub in tensor product gradient computation in _gradient_kernel
a-alveyblanc Aug 1, 2023
3778edf
First version of grad routine
a-alveyblanc Aug 1, 2023
45e859e
Initial working version of tensor product gradient operator application
a-alveyblanc Aug 1, 2023
22ffacd
Add 3 dimensional test and order 3 test for 2D and 3D
a-alveyblanc Aug 1, 2023
d0bd17e
Add arg names to geometric factor application, refine some comments
a-alveyblanc Aug 1, 2023
ef667bb
Divergence operator version 0.0
a-alveyblanc Aug 2, 2023
eed2516
Prototype of divergence kernel. Needs work, but it passes currently i…
a-alveyblanc Aug 4, 2023
1e40a11
Remove random import included by CoC autocomplete
a-alveyblanc Aug 4, 2023
f2b0275
Generate einsum specification dynamically instead of using if-else
a-alveyblanc Aug 5, 2023
036681c
Rename vandermonde and vandermonde derivative matrices
a-alveyblanc Aug 5, 2023
7ad9017
Give einsums a single source of truth. Still only valid for dim <= 3
a-alveyblanc Aug 7, 2023
c645dbe
Move TP array context to array_context.py, other minor changes
a-alveyblanc Aug 10, 2023
dcd7ca0
Update tensor product grad test to match the other grad test case
a-alveyblanc Aug 10, 2023
683cdd8
Update tensor product divergence test to match original test case.
a-alveyblanc Aug 10, 2023
f93e112
Merge branch 'main' into production-pilot
MTCam Aug 14, 2023
1563950
Divergence kernel functioning again
a-alveyblanc Aug 14, 2023
e1380fe
Update some comments, begin weak form matrices work
a-alveyblanc Aug 21, 2023
33a54e4
TMP: Use outside actx in TP grad
inducer Sep 6, 2023
e446bb7
Add TP transform cartoon
inducer Sep 6, 2023
a98b95c
Merge branch 'main' into production-pilot
MTCam Sep 12, 2023
264192c
Temporary changes to get tensor product gradient working again
a-alveyblanc Sep 12, 2023
ba03b3f
Tensor product array context related changes
a-alveyblanc Sep 13, 2023
8263333
Update example
a-alveyblanc Sep 14, 2023
6b50028
Add code for printing generated differentiation code
a-alveyblanc Sep 14, 2023
5d36bfb
Update strong tp diff example
a-alveyblanc Sep 18, 2023
2857036
Merge branch 'main' into production-pilot
MTCam Sep 18, 2023
92991a3
Version 0.1 of weak gradient computation
a-alveyblanc Sep 30, 2023
49116ab
Weak form divergence version 0.1
a-alveyblanc Sep 30, 2023
d87c19f
Move TP array contexts. Add acoustic pulse TP example
a-alveyblanc Oct 1, 2023
aec8bdb
Merge branch 'inducer:main' into tensor-product-differentiation-opera…
a-alveyblanc Oct 8, 2023
cb0dfcf
Merge branch 'main' into production-pilot
MTCam Oct 10, 2023
c14f08d
Merge branch 'inducer:main' into tensor-product-differentiation-opera…
a-alveyblanc Oct 17, 2023
7a5326b
Merge remote-tracking branch 'addison/tensor-product-differentiation-…
MTCam Oct 24, 2023
c294df7
Add baseline MPI version of TP actx
a-alveyblanc Oct 25, 2023
d97b338
Merge branch 'main' into production-pilot
MTCam Oct 26, 2023
a9dbb5a
Initial lazy array context for TP elements
a-alveyblanc Oct 26, 2023
bb4e2ed
Merge branch 'production' into production-addison
MTCam Oct 26, 2023
7beb2e8
Fix up some array context business. Make lazy TPMPIArrayContext a sub…
a-alveyblanc Nov 3, 2023
b39ef37
Merge remote-tracking branch 'inducer/main' into coupled-volumes
majosm Nov 14, 2023
ebcde7c
Merge branch 'coupled-volumes' into production-pilot
majosm Nov 14, 2023
2353cb2
Merge branch 'main' into production-pilot
MTCam Nov 29, 2023
fb42a02
Add fixed up einsums for TP
a-alveyblanc Dec 21, 2023
06463ef
Minor changes
a-alveyblanc Dec 21, 2023
1256d22
Merge branch 'production' into tpe-merge-production
MTCam Dec 21, 2023
43543ec
Restore some op changes
MTCam Dec 21, 2023
fbb9369
Remove stale requirement
MTCam Dec 21, 2023
511358b
Update dt_geometric_factors to support tensor product elements.
MTCam Feb 1, 2024
7967767
Add tpe to dt util testing
MTCam Feb 5, 2024
a4dd3f0
Add TPE to dt estimate tests
MTCam Feb 5, 2024
4341099
Update TP operators, TP operator tests, and add support for TP in bas…
a-alveyblanc Feb 11, 2024
999904f
Remove no longer used TP actx classes
a-alveyblanc Feb 11, 2024
79ae993
Add in MPINumpyArrayContext
a-alveyblanc Feb 11, 2024
d0ca536
Clean up TP arraycontext imports
a-alveyblanc Feb 11, 2024
cb44738
Add back simplicial test in test_op
a-alveyblanc Feb 11, 2024
d9fea00
Change how geometric factors are applied
a-alveyblanc Feb 12, 2024
74fea52
Skip 1d dt test for tpe, debugging print.
MTCam Feb 12, 2024
afb4a0d
Update dt_utils test.
MTCam Feb 12, 2024
bb82f72
Tag axes for normal to fix fallbacks for 1d cases.
MTCam Feb 20, 2024
cdd2632
make array context fallbacks optional (disabled by default)
majosm Feb 26, 2024
5599def
Use vol/max(face_area) for geometric_factor of TPE
MTCam Feb 28, 2024
de15213
Makes lazy work, eager still gives old result
MTCam Feb 28, 2024
41aba76
Fix up max face area snippet for non-lazy actx.
MTCam Feb 29, 2024
7ef92bc
Bring back missing scale factor for face areas.
MTCam Feb 29, 2024
e315767
Correct misfac
MTCam Mar 2, 2024
a5a58ea
Tweak more
MTCam Mar 2, 2024
40dd0ce
Merge branch 'main' into production-pilot
MTCam Mar 6, 2024
2dca87c
Merge branch 'main' into production-pilot
MTCam Mar 7, 2024
1ca5487
Merge branch 'main' into production-pilot
MTCam Apr 10, 2024
2a76426
Merge branch 'main' into production-pilot
MTCam Apr 27, 2024
e7af8e8
Update dt tpe
MTCam May 1, 2024
4c72f9c
Update TPE tests - esp for wave rk4 estimate
MTCam May 1, 2024
eebbd89
Merge branch 'main' into production-pilot
matthiasdiener May 28, 2024
ea03612
Merge to main
MTCam Jun 11, 2024
5d03d5a
Merge branch 'main' into production-pilot
MTCam Jun 11, 2024
811b3c0
Add TPE option, reorder term calc in euler to expose issue with face …
MTCam Jun 13, 2024
5b563de
Use geoderiv_connection only for Simplices
MTCam Jun 17, 2024
6df78a7
Allow generation of TPE mesh type
MTCam Jun 17, 2024
00b6ca4
Extend some tests to hit TPEs
MTCam Jun 17, 2024
4bb5f45
Merge branch 'add-tpe-to-acoustic-pulse' into production-pilot
MTCam Jun 18, 2024
95d6834
Disable tpe div for now
MTCam Jun 19, 2024
85c0eec
Add missing params to mesh data
MTCam Jun 19, 2024
d50f7e4
Re-enable tpe div
MTCam Jun 19, 2024
82924d8
add working op for tpe
MTCam Jun 20, 2024
e2db31a
Remove tpe op calls from differentiation operators.
MTCam Jun 22, 2024
c4f2d3a
Update wadg to use quadrature discretization
MTCam Jul 16, 2024
4410722
Merge with main.
MTCam Jul 19, 2024
c94a386
update the update to working condition
MTCam Jul 19, 2024
7c8eaec
Merge branch 'update-wadg' into update-wadg-rebase
MTCam Jul 19, 2024
a6c5168
Dont overintegration WADG for simplices
MTCam Jul 20, 2024
aaa67d9
Disable rate-of-convergence test for TPE
MTCam Jul 24, 2024
d78f0a8
Merge branch 'main' into production-pilot
MTCam Jul 24, 2024
26862d2
Combine a few stages in wadg
MTCam Jul 25, 2024
1e553b1
Update wadg to match main version.
MTCam Jul 26, 2024
be3f127
Merge branch 'main' into production-pilot-up2date
MTCam Aug 29, 2024
7ad2cbe
Merge branch 'main' into production-pilot
MTCam Sep 9, 2024
8f586e3
Update esdg to use modepy for diff_mats instead of meshmode.
MTCam Sep 9, 2024
f297017
Add test to demonstrate simplex integral fails with overintegration
MTCam Sep 25, 2024
3502174
Fix up linting issues
MTCam Sep 25, 2024
2e54482
Replace integral calls to mass_matrix with direct use of quadrature w…
MTCam Sep 27, 2024
0fa70b2
add ProcessLogger for find_distributed_partition
matthiasdiener Sep 27, 2024
e7749e7
Adding some quadrature tests.
MTCam Oct 1, 2024
f17c7bd
Merge branch 'main' into production-pilot
MTCam Oct 13, 2024
13ff89c
Merge branch 'main' into production-pilot
MTCam Nov 5, 2024
109da04
Remove TPE-specific routines
MTCam Nov 11, 2024
d32c9fe
Merge branch 'main' into production-pilot
MTCam Nov 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/operators.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Discontinuous Galerkin operators

.. automodule:: grudge.op
.. automodule:: grudge.trace_pair
.. automodule:: grudge.flux_differencing


Transferring data between discretizations
Expand Down
76 changes: 66 additions & 10 deletions examples/euler/acoustic_pulse.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,22 @@

import pyopencl as cl
import pyopencl.tools as cl_tools

from grudge.array_context import (
PyOpenCLArrayContext,
PytatoPyOpenCLArrayContext
)
from grudge.models.euler import (
ConservedEulerField,
EulerOperator,
EntropyStableEulerOperator,
InviscidWallBC
)
from meshmode.mesh import TensorProductElementGroup
from grudge.shortcuts import rk4_step

from arraycontext import ArrayContext

from meshmode.mesh import BTAG_ALL
from pytools.obj_array import make_obj_array

Expand Down Expand Up @@ -105,8 +120,24 @@ def run_acoustic_pulse(actx,
order=3,
final_time=1,
resolution=16,
esdg=False,
overintegration=False,
visualize=False):
visualize=False,
tpe=False):

logger.info(
"""
Acoustic pulse parameters:\n
order: %s\n
final_time: %s\n
resolution: %s\n
entropy stable: %s\n
overintegration: %s\n
visualize: %s
""",
order, final_time, resolution, esdg,
overintegration, visualize
)

# eos-related parameters
gamma = 1.4
Expand All @@ -118,10 +149,12 @@ def run_acoustic_pulse(actx,
dim = 2
box_ll = -0.5
box_ur = 0.5
group_cls = TensorProductElementGroup if tpe else None
mesh = generate_regular_rect_mesh(
a=(box_ll,)*dim,
b=(box_ur,)*dim,
nelements_per_axis=(resolution,)*dim)
nelements_per_axis=(resolution,)*dim,
group_cls=group_cls)

from meshmode.discretization.poly_element import (
QuadratureSimplexGroupFactory,
Expand All @@ -130,8 +163,19 @@ def run_acoustic_pulse(actx,

from grudge.discretization import make_discretization_collection
from grudge.dof_desc import DISCR_TAG_BASE, DISCR_TAG_QUAD
from meshmode.discretization.poly_element import (
InterpolatoryEdgeClusteredGroupFactory,
QuadratureGroupFactory)

if esdg:
case = "esdg-pulse"
operator_cls = EntropyStableEulerOperator
else:
case = "pulse"
operator_cls = EulerOperator

exp_name = f"fld-{case}-N{order}-K{resolution}"

exp_name = f"fld-acoustic-pulse-N{order}-K{resolution}"
if overintegration:
exp_name += "-overintegrated"
quad_tag = DISCR_TAG_QUAD
Expand All @@ -141,17 +185,16 @@ def run_acoustic_pulse(actx,
dcoll = make_discretization_collection(
actx, mesh,
discr_tag_to_group_factory={
DISCR_TAG_BASE: default_simplex_group_factory(
base_dim=mesh.dim, order=order),
DISCR_TAG_QUAD: QuadratureSimplexGroupFactory(2*order)
DISCR_TAG_BASE: InterpolatoryEdgeClusteredGroupFactory(order),
DISCR_TAG_QUAD: QuadratureGroupFactory(2*order)
}
)

# }}}

# {{{ Euler operator

euler_operator = EulerOperator(
euler_operator = operator_cls(
dcoll,
bdry_conditions={BTAG_ALL: InviscidWallBC()},
flux_type="lf",
Expand Down Expand Up @@ -208,7 +251,8 @@ def rhs(t, q):


def main(ctx_factory, order=3, final_time=1, resolution=16,
overintegration=False, visualize=False, lazy=False):
overintegration=False, visualize=False, lazy=False,
esdg=False, tpe=False):
cl_ctx = ctx_factory()
queue = cl.CommandQueue(cl_ctx)

Expand All @@ -224,13 +268,20 @@ def main(ctx_factory, order=3, final_time=1, resolution=16,
force_device_scalars=True,
)

if not actx.supports_nonscalar_broadcasting and esdg is True:
raise RuntimeError(
"Cannot use ESDG with an array context that cannot perform "
"nonscalar broadcasting. Run with --lazy instead."
)

run_acoustic_pulse(
actx,
order=order,
resolution=resolution,
esdg=esdg,
overintegration=overintegration,
final_time=final_time,
visualize=visualize
visualize=visualize, tpe=tpe
)


Expand All @@ -241,19 +292,24 @@ def main(ctx_factory, order=3, final_time=1, resolution=16,
parser.add_argument("--order", default=3, type=int)
parser.add_argument("--tfinal", default=0.1, type=float)
parser.add_argument("--resolution", default=16, type=int)
parser.add_argument("--esdg", action="store_true",
help="use entropy stable dg")
parser.add_argument("--oi", action="store_true",
help="use overintegration")
parser.add_argument("--visualize", action="store_true",
help="write out vtk output")
parser.add_argument("--lazy", action="store_true",
help="switch to a lazy computation mode")
parser.add_argument("--tpe", action="store_true",
help="use tensor product elements")
args = parser.parse_args()

logging.basicConfig(level=logging.INFO)
main(cl.create_some_context,
order=args.order,
final_time=args.tfinal,
resolution=args.resolution,
esdg=args.esdg,
overintegration=args.oi,
visualize=args.visualize,
lazy=args.lazy)
lazy=args.lazy, tpe=args.tpe)
227 changes: 227 additions & 0 deletions examples/euler/sod.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
__copyright__ = """
Copyright (C) 2021 University of Illinois Board of Trustees
"""

__license__ = """
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""


from grudge.dof_desc import BoundaryDomainTag
import pyopencl as cl
import pyopencl.tools as cl_tools

from arraycontext import thaw, freeze
from grudge.array_context import PytatoPyOpenCLArrayContext
from grudge.models.euler import (
EntropyStableEulerOperator,
ConservedEulerField,
PrescribedBC,
conservative_to_primitive_vars,
)
from grudge.shortcuts import rk4_step

from pytools.obj_array import make_obj_array

import grudge.op as op

import logging
logger = logging.getLogger(__name__)


def sod_shock_initial_condition(nodes, t=0):
gamma = 1.4
dim = len(nodes)
gmn1 = 1.0 / (gamma - 1.0)
x = nodes[0]
actx = x.array_context
zeros = 0*x

_x0 = 0.5
_rhoin = 1.0
_rhoout = 0.125
_pin = 1.0
_pout = 0.1
rhoin = zeros + _rhoin
rhoout = zeros + _rhoout
energyin = zeros + gmn1 * _pin
energyout = zeros + gmn1 * _pout

x0 = zeros + _x0
sigma = 1e-13
weight = 0.5 * (1.0 - actx.np.tanh(1.0/sigma * (x - x0)))

mass = rhoout + (rhoin - rhoout)*weight
energy = energyout + (energyin - energyout)*weight
momentum = make_obj_array([zeros for _ in range(dim)])

return ConservedEulerField(mass=mass, energy=energy, momentum=momentum)


def run_sod_shock_tube(
actx, order=4, resolution=32, final_time=0.2, visualize=False):

logger.info(
"""
Sod 1-D parameters:\n
order: %s\n
final_time: %s\n
resolution: %s\n
visualize: %s
""",
order, final_time, resolution, visualize
)

# eos-related parameters
gamma = 1.4

# {{{ discretization

from meshmode.mesh.generation import generate_regular_rect_mesh

dim = 1
box_ll = 0.0
box_ur = 1.0
mesh = generate_regular_rect_mesh(
a=(box_ll,)*dim,
b=(box_ur,)*dim,
nelements_per_axis=(resolution,)*dim,
boundary_tag_to_face={
"prescribed": ["+x", "-x"],
}
)

from grudge import DiscretizationCollection
from grudge.dof_desc import \
DISCR_TAG_BASE, DISCR_TAG_QUAD
from meshmode.discretization.poly_element import \
(default_simplex_group_factory,
QuadratureSimplexGroupFactory)

exp_name = f"fld-sod-1d-N{order}-K{resolution}"
quad_tag = DISCR_TAG_QUAD

dcoll = DiscretizationCollection(
actx, mesh,
discr_tag_to_group_factory={
DISCR_TAG_BASE: default_simplex_group_factory(dim, order),
DISCR_TAG_QUAD: QuadratureSimplexGroupFactory(order + 2)
}
)

# }}}

# {{{ Euler operator

dd_prescribed = BoundaryDomainTag("prescribed")
bcs = {
dd_prescribed: PrescribedBC(prescribed_state=sod_shock_initial_condition)
}

euler_operator = EntropyStableEulerOperator(
dcoll,
bdry_conditions=bcs,
flux_type="lf",
gamma=gamma,
quadrature_tag=quad_tag
)

def rhs(t, q):
return euler_operator.operator(t, q)

compiled_rhs = actx.compile(rhs)

fields = sod_shock_initial_condition(thaw(dcoll.nodes(), actx))

from grudge.dt_utils import h_min_from_volume

cfl = 0.01
cn = 0.5*(order + 1)**2
dt = cfl * actx.to_numpy(h_min_from_volume(dcoll)) / cn

logger.info("Timestep size: %g", dt)

# }}}

from grudge.shortcuts import make_visualizer

vis = make_visualizer(dcoll)

# {{{ time stepping

step = 0
t = 0.0
while t < final_time:
if step % 10 == 0:
norm_q = actx.to_numpy(op.norm(dcoll, fields, 2))
logger.info("[%04d] t = %.5f |q| = %.5e", step, t, norm_q)
if visualize:
rho, velocity, pressure = \
conservative_to_primitive_vars(fields, gamma=gamma)
vis.write_vtk_file(
f"{exp_name}-{step:04d}.vtu",
[
("rho", rho),
("energy", fields.energy),
("momentum", fields.momentum),
("velocity", velocity),
("pressure", pressure)
]
)
assert norm_q < 10000

fields = thaw(freeze(fields, actx), actx)
fields = rk4_step(fields, t, dt, compiled_rhs)
t += dt
step += 1

# }}}


def main(ctx_factory, order=4, final_time=0.2, resolution=32, visualize=False):
cl_ctx = ctx_factory()
queue = cl.CommandQueue(cl_ctx)
actx = PytatoPyOpenCLArrayContext(
queue,
allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)),
)

run_sod_shock_tube(
actx, order=order,
resolution=resolution,
final_time=final_time,
visualize=visualize)


if __name__ == "__main__":
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--order", default=4, type=int)
parser.add_argument("--tfinal", default=0.2, type=float)
parser.add_argument("--resolution", default=32, type=int)
parser.add_argument("--visualize", action="store_true")
args = parser.parse_args()

logging.basicConfig(level=logging.INFO)
main(cl.create_some_context,
order=args.order,
final_time=args.tfinal,
resolution=args.resolution,
visualize=args.visualize)
Loading
Loading