Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • inducer/grudge
  • jdsteve2/grudge
  • eshoag2/grudge
  • mattwala/grudge
  • kaushikcfd/grudge
  • fikl2/grudge
6 results
Show changes
Showing
with 0 additions and 3784 deletions
__copyright__ = "Copyright (C) 2007 Andreas Kloeckner"
__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 __future__ import division
from __future__ import absolute_import
from __future__ import print_function
import numpy
import numpy.linalg as la
def main(write_output=True, flux_type_arg="upwind"):
from grudge.tools import mem_checkpoint
from math import sin, cos, pi, sqrt
from math import floor
from grudge.backends import guess_run_context
rcon = guess_run_context()
def f(x):
return sin(pi*x)
def u_analytic(x, el, t):
return f((-numpy.dot(v, x)/norm_v+t*norm_v))
def boundary_tagger(vertices, el, face_nr, all_v):
if numpy.dot(el.face_normals[face_nr], v) < 0:
return ["inflow"]
else:
return ["outflow"]
dim = 2
if dim == 1:
v = numpy.array([1])
if rcon.is_head_rank:
from grudge.mesh.generator import make_uniform_1d_mesh
mesh = make_uniform_1d_mesh(0, 2, 10, periodic=True)
elif dim == 2:
v = numpy.array([2,0])
if rcon.is_head_rank:
from grudge.mesh.generator import make_disk_mesh
mesh = make_disk_mesh(boundary_tagger=boundary_tagger)
elif dim == 3:
v = numpy.array([0,0,1])
if rcon.is_head_rank:
from grudge.mesh.generator import make_cylinder_mesh, make_ball_mesh, make_box_mesh
mesh = make_cylinder_mesh(max_volume=0.04, height=2, boundary_tagger=boundary_tagger,
periodic=False, radial_subdivisions=32)
else:
raise RuntimeError("bad number of dimensions")
norm_v = la.norm(v)
if rcon.is_head_rank:
mesh_data = rcon.distribute_mesh(mesh)
else:
mesh_data = rcon.receive_mesh()
if dim != 1:
mesh_data = mesh_data.reordered_by("cuthill")
discr = rcon.make_discretization(mesh_data, order=4)
vis_discr = discr
from grudge.visualization import VtkVisualizer
if write_output:
vis = VtkVisualizer(vis_discr, rcon, "fld")
# operator setup ----------------------------------------------------------
from grudge.data import \
ConstantGivenFunction, \
TimeConstantGivenFunction, \
TimeDependentGivenFunction
from grudge.models.advection import StrongAdvectionOperator, WeakAdvectionOperator
op = WeakAdvectionOperator(v,
inflow_u=TimeDependentGivenFunction(u_analytic),
flux_type=flux_type_arg)
u = discr.interpolate_volume_function(lambda x, el: u_analytic(x, el, 0))
# timestep setup ----------------------------------------------------------
from grudge.timestep.runge_kutta import LSRK4TimeStepper
stepper = LSRK4TimeStepper()
if rcon.is_head_rank:
print("%d elements" % len(discr.mesh.elements))
# diagnostics setup -------------------------------------------------------
from logpyle import LogManager, \
add_general_quantities, \
add_simulation_quantities, \
add_run_info
if write_output:
log_file_name = "advection.dat"
else:
log_file_name = None
logmgr = LogManager(log_file_name, "w", rcon.communicator)
add_run_info(logmgr)
add_general_quantities(logmgr)
add_simulation_quantities(logmgr)
discr.add_instrumentation(logmgr)
stepper.add_instrumentation(logmgr)
from grudge.log import Integral, LpNorm
u_getter = lambda: u
logmgr.add_quantity(Integral(u_getter, discr, name="int_u"))
logmgr.add_quantity(LpNorm(u_getter, discr, p=1, name="l1_u"))
logmgr.add_quantity(LpNorm(u_getter, discr, name="l2_u"))
logmgr.add_watches(["step.max", "t_sim.max", "l2_u", "t_step.max"])
# timestep loop -----------------------------------------------------------
rhs = op.bind(discr)
try:
from grudge.timestep import times_and_steps
step_it = times_and_steps(
final_time=3, logmgr=logmgr,
max_dt_getter=lambda t: op.estimate_timestep(discr,
stepper=stepper, t=t, fields=u))
for step, t, dt in step_it:
if step % 5 == 0 and write_output:
visf = vis.make_file("fld-%04d" % step)
vis.add_data(visf, [
("u", discr.convert_volume(u, kind="numpy")),
], time=t, step=step)
visf.close()
u = stepper(u, t, dt, rhs)
true_u = discr.interpolate_volume_function(lambda x, el: u_analytic(x, el, t))
print(discr.norm(u-true_u))
assert discr.norm(u-true_u) < 1e-2
finally:
if write_output:
vis.close()
logmgr.close()
discr.close()
if __name__ == "__main__":
main()
# entry points for py.test ----------------------------------------------------
def test_advection():
from pytools.test import mark_test
mark_long = mark_test.long
for flux_type in ["upwind", "central", "lf"]:
yield "advection with %s flux" % flux_type, \
mark_long(main), False, flux_type
import os
import numpy as np
import pyopencl as cl
from grudge import sym, bind, DGDiscretizationWithBoundaries
from grudge.shortcuts import set_up_rk4
def simple_wave_entrypoint(dim=2, num_elems=256, order=4, num_steps=30,
log_filename="grudge.dat"):
cl_ctx = cl.create_some_context()
queue = cl.CommandQueue(cl_ctx)
from mpi4py import MPI
comm = MPI.COMM_WORLD
num_parts = comm.Get_size()
n = int(num_elems ** (1./dim))
from meshmode.distributed import MPIMeshDistributor
mesh_dist = MPIMeshDistributor(comm)
if mesh_dist.is_mananger_rank():
from meshmode.mesh.generation import generate_regular_rect_mesh
mesh = generate_regular_rect_mesh(a=(-0.5,)*dim,
b=(0.5,)*dim,
n=(n,)*dim)
from pymetis import part_graph
_, p = part_graph(num_parts,
xadj=mesh.nodal_adjacency.neighbors_starts.tolist(),
adjncy=mesh.nodal_adjacency.neighbors.tolist())
part_per_element = np.array(p)
local_mesh = mesh_dist.send_mesh_parts(mesh, part_per_element, num_parts)
else:
local_mesh = mesh_dist.receive_mesh_part()
vol_discr = DGDiscretizationWithBoundaries(cl_ctx, local_mesh, order=order,
mpi_communicator=comm)
source_center = np.array([0.1, 0.22, 0.33])[:local_mesh.dim]
source_width = 0.05
source_omega = 3
sym_x = sym.nodes(local_mesh.dim)
sym_source_center_dist = sym_x - source_center
sym_t = sym.ScalarVariable("t")
from grudge.models.wave import StrongWaveOperator
from meshmode.mesh import BTAG_ALL, BTAG_NONE
op = StrongWaveOperator(-0.1, vol_discr.dim,
source_f=(
sym.sin(source_omega*sym_t)
* sym.exp(
-np.dot(sym_source_center_dist, sym_source_center_dist)
/ source_width**2)),
dirichlet_tag=BTAG_NONE,
neumann_tag=BTAG_NONE,
radiation_tag=BTAG_ALL,
flux_type="upwind")
from pytools.obj_array import join_fields
fields = join_fields(vol_discr.zeros(queue),
[vol_discr.zeros(queue) for i in range(vol_discr.dim)])
from logpyle import LogManager, \
add_general_quantities, \
add_run_info, \
IntervalTimer, EventCounter
# NOTE: LogManager hangs when using a file on a shared directory.
logmgr = LogManager(log_filename, "w", comm)
add_run_info(logmgr)
add_general_quantities(logmgr)
log_quantities =\
{"rank_data_swap_timer": IntervalTimer("rank_data_swap_timer",
"Time spent evaluating RankDataSwapAssign"),
"rank_data_swap_counter": EventCounter("rank_data_swap_counter",
"Number of RankDataSwapAssign instructions evaluated"),
"exec_timer": IntervalTimer("exec_timer",
"Total time spent executing instructions"),
"insn_eval_timer": IntervalTimer("insn_eval_timer",
"Time spend evaluating instructions"),
"future_eval_timer": IntervalTimer("future_eval_timer",
"Time spent evaluating futures"),
"busy_wait_timer": IntervalTimer("busy_wait_timer",
"Time wasted doing busy wait")}
for quantity in log_quantities.values():
logmgr.add_quantity(quantity)
bound_op = bind(vol_discr, op.sym_operator())
def rhs(t, w):
val, rhs.profile_data = bound_op(queue, profile_data=rhs.profile_data,
log_quantities=log_quantities,
t=t, w=w)
return val
rhs.profile_data = {}
dt = 0.04
dt_stepper = set_up_rk4("w", dt, fields, rhs)
logmgr.tick_before()
for event in dt_stepper.run(t_end=dt * num_steps):
if isinstance(event, dt_stepper.StateComputed):
logmgr.tick_after()
logmgr.tick_before()
logmgr.tick_after()
def print_profile_data(data):
print("""execute() for rank %d:
\tInstruction Evaluation: %f%%
\tFuture Evaluation: %f%%
\tBusy Wait: %f%%
\tTotal: %f seconds""" %
(comm.Get_rank(),
data['insn_eval_time'] / data['total_time'] * 100,
data['future_eval_time'] / data['total_time'] * 100,
data['busy_wait_time'] / data['total_time'] * 100,
data['total_time']))
print_profile_data(rhs.profile_data)
logmgr.close()
if __name__ == "__main__":
assert "RUN_WITHIN_MPI" in os.environ, "Must run within mpi"
import sys
assert len(sys.argv) == 5, \
"Usage: %s %s num_elems order num_steps logfile" \
% (sys.executable, sys.argv[0])
simple_wave_entrypoint(num_elems=int(sys.argv[1]),
order=int(sys.argv[2]),
num_steps=int(sys.argv[3]),
log_filename=sys.argv[4])
#!/bin/bash
# Weak scaling: We run our code on one computer, then we buy a second computer
# and we can run twice as much code in the same amount of time.
# Strong scaling: We run our code on one computer, then we buy a second computer
# and we can run the same code in half the time.
# Examples:
# ./run_benchmark.sh -t WEAK -n 100 -r 20 -s 1000 -l ~/weak_scaling.dat -o weak_scaling.txt
# ./run_benchmark.sh -t STRONG -n 100 -r 20 -s 1000 -l ~/strong_scaling.dat -o strong_scaling.txt
set -eu
# NOTE: benchmark_mpi.py hangs when logfile is in a shared directory.
USAGE="Usage: $0 -t <WEAK|STRONG> -n num_elems -r order -s num_steps -l logfile -o outfile"
while getopts "t:n:r:s:l:o:" OPT; do
case $OPT in
t)
case $OPTARG in
WEAK)
SCALING_TYPE='WEAK'
;;
STRONG)
SCALING_TYPE='STRONG'
;;
*)
echo $USAGE
exit 1
;;
esac
;;
n)
NUM_ELEMS=$OPTARG
;;
r)
ORDER=$OPTARG
;;
s)
NUM_STEPS=$OPTARG
;;
l)
LOGFILE=$OPTARG
;;
o)
OUTFILE=$OPTARG
;;
*)
echo $USAGE
exit 1
;;
esac
done
# NOTE: We want to make sure we run grudge in the right environment.
SHARED="/home/eshoag2/shared"
source $SHARED/miniconda3/bin/activate inteq
PYTHON=$(which python)
BENCHMARK_MPI="$SHARED/grudge/examples/benchmark_grudge/benchmark_mpi.py"
# Assume HOSTS_LIST is sorted in increasing order starting with one host.
HOSTS_LIST="\
porter \
porter,stout \
porter,stout,koelsch"
ENVIRONMENT_VARS="\
-x RUN_WITHIN_MPI=1 \
-x PYOPENCL_CTX=0 \
-x POCL_AFFINITY=1"
PERF_EVENTS="\
cpu-cycles,\
instructions,\
task-clock"
TEMPDIR=$(mktemp -d)
trap 'rm -rf $TEMPDIR' EXIT HUP INT QUIT TERM
echo "$(date): Testing $SCALING_TYPE scaling" | tee -a $OUTFILE
NUM_HOSTS=1
BASE_NUM_ELEMS=$NUM_ELEMS
for HOSTS in $HOSTS_LIST; do
if [ $SCALING_TYPE = 'WEAK' ]; then
NUM_ELEMS=$(echo $BASE_NUM_ELEMS $NUM_HOSTS | awk '{ print $1 * $2 }')
fi
BENCHMARK_CMD="$PYTHON $BENCHMARK_MPI $NUM_ELEMS $ORDER $NUM_STEPS $LOGFILE.trial$NUM_HOSTS"
# NOTE: mpiexec recently updated so some things might act weird.
MPI_CMD="mpiexec --output-filename $TEMPDIR -H $HOSTS $ENVIRONMENT_VARS $BENCHMARK_CMD"
echo "Executing: $MPI_CMD"
# NOTE: perf does not follow mpi accross different nodes.
# Instead, perf will follow all processes on the porter node.
echo "====================Using $NUM_HOSTS host(s)===================" >> $OUTFILE
START_TIME=$(date +%s)
perf stat --append -o $OUTFILE -e $PERF_EVENTS $MPI_CMD
DURATION=$(($(date +%s) - $START_TIME))
echo "Finished in $DURATION seconds"
echo "===================Output of Python===================" >> $OUTFILE
find $TEMPDIR -type f -exec cat {} \; >> $OUTFILE
echo "======================================================" >> $OUTFILE
rm -rf $TEMPDIR/*
if [ $NUM_HOSTS -eq 1 ]; then
BASE_DURATION=$DURATION
fi
# Efficiency is expected / actual
if [ $SCALING_TYPE = 'STRONG' ]; then
EFFICIENCY=$(echo $DURATION $BASE_DURATION $NUM_HOSTS | awk '{ print $2 / ($3 * $1) * 100"%" }')
elif [ $SCALING_TYPE = 'WEAK' ]; then
EFFICIENCY=$(echo $DURATION $BASE_DURATION | awk '{ print $2 / $1 * 100"%" }')
fi
echo "Efficiency for $SCALING_TYPE scaling is $EFFICIENCY for $NUM_HOSTS host(s)." | tee -a $OUTFILE
((NUM_HOSTS++))
done
__copyright__ = "Copyright (C) 2007 Andreas Kloeckner"
__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 __future__ import division
from __future__ import absolute_import
from __future__ import print_function
import numpy
import numpy.linalg as la
from math import sin, cos, pi, sqrt
from pytools.test import mark_test
class ExactTestCase:
a = 0
b = 150
final_time = 1000
def u0(self, x):
return self.u_exact(x, 0)
def u_exact(self, x, t):
# CAUTION: This gets the shock speed wrong as soon as the pulse
# starts interacting with itself.
def f(x, shock_loc):
if x < (t-40)/4:
return 1/4
else:
if t < 40:
if x < (3*t)/4:
return (x+15)/(t+20)
elif x < (t+80)/4:
return (x-30)/(t-40)
else:
return 1/4
else:
if x < shock_loc:
return (x+15)/(t+20)
else:
return 1/4
from math import sqrt
shock_loc = 30*sqrt(2*t+40)/sqrt(120) + t/4 - 10
shock_win = (shock_loc + 20) // self.b
x += shock_win * 150
x -= 20
return max(f(x, shock_loc), f(x-self.b, shock_loc-self.b))
class OffCenterMigratingTestCase:
a = -pi
b = pi
final_time = 10
def u0(self, x):
return -0.4+sin(x+0.1)
class CenteredStationaryTestCase:
# does funny things to P-P
a = -pi
b = pi
final_time = 10
def u0(self, x):
return -sin(x)
class OffCenterStationaryTestCase:
# does funny things to P-P
a = -pi
b = pi
final_time = 10
def u0(self, x):
return -sin(x+0.3)
def main(write_output=True, flux_type_arg="upwind",
#case = CenteredStationaryTestCase(),
#case = OffCenterStationaryTestCase(),
#case = OffCenterMigratingTestCase(),
case = ExactTestCase(),
):
from grudge.backends import guess_run_context
rcon = guess_run_context()
order = 3
if rcon.is_head_rank:
if True:
from grudge.mesh.generator import make_uniform_1d_mesh
mesh = make_uniform_1d_mesh(case.a, case.b, 20, periodic=True)
else:
from grudge.mesh.generator import make_rect_mesh
print((pi*2)/(11*5*2))
mesh = make_rect_mesh((-pi, -1), (pi, 1),
periodicity=(True, True),
subdivisions=(11,5),
max_area=(pi*2)/(11*5*2)
)
if rcon.is_head_rank:
mesh_data = rcon.distribute_mesh(mesh)
else:
mesh_data = rcon.receive_mesh()
discr = rcon.make_discretization(mesh_data, order=order,
quad_min_degrees={"quad": 3*order})
if write_output:
from grudge.visualization import VtkVisualizer
vis = VtkVisualizer(discr, rcon, "fld")
# operator setup ----------------------------------------------------------
from grudge.second_order import IPDGSecondDerivative
from grudge.models.burgers import BurgersOperator
op = BurgersOperator(mesh.dimensions,
viscosity_scheme=IPDGSecondDerivative())
if rcon.is_head_rank:
print("%d elements" % len(discr.mesh.elements))
# exact solution ----------------------------------------------------------
import pymbolic
var = pymbolic.var
u = discr.interpolate_volume_function(lambda x, el: case.u0(x[0]))
# diagnostics setup -------------------------------------------------------
from logpyle import LogManager, \
add_general_quantities, \
add_simulation_quantities, \
add_run_info
if write_output:
log_file_name = "burgers.dat"
else:
log_file_name = None
logmgr = LogManager(log_file_name, "w", rcon.communicator)
add_run_info(logmgr)
add_general_quantities(logmgr)
add_simulation_quantities(logmgr)
discr.add_instrumentation(logmgr)
from grudge.log import LpNorm
u_getter = lambda: u
logmgr.add_quantity(LpNorm(u_getter, discr, p=1, name="l1_u"))
logmgr.add_watches(["step.max", "t_sim.max", "l1_u", "t_step.max"])
# timestep loop -----------------------------------------------------------
rhs = op.bind(discr)
from grudge.timestep.runge_kutta import ODE45TimeStepper, LSRK4TimeStepper
stepper = ODE45TimeStepper()
stepper.add_instrumentation(logmgr)
try:
from grudge.timestep import times_and_steps
# for visc=0.01
#stab_fac = 0.1 # RK4
#stab_fac = 1.6 # dumka3(3), central
#stab_fac = 3 # dumka3(4), central
#stab_fac = 0.01 # RK4
stab_fac = 0.2 # dumka3(3), central
#stab_fac = 3 # dumka3(4), central
dt = stab_fac*op.estimate_timestep(discr,
stepper=LSRK4TimeStepper(), t=0, fields=u)
step_it = times_and_steps(
final_time=case.final_time, logmgr=logmgr, max_dt_getter=lambda t: dt)
from grudge.symbolic import InverseVandermondeOperator
inv_vdm = InverseVandermondeOperator().bind(discr)
for step, t, dt in step_it:
if step % 3 == 0 and write_output:
if hasattr(case, "u_exact"):
extra_fields = [
("u_exact",
discr.interpolate_volume_function(
lambda x, el: case.u_exact(x[0], t)))]
else:
extra_fields = []
visf = vis.make_file("fld-%04d" % step)
vis.add_data(visf, [
("u", u),
] + extra_fields,
time=t,
step=step)
visf.close()
u = stepper(u, t, dt, rhs)
if isinstance(case, ExactTestCase):
assert discr.norm(u, 1) < 50
finally:
if write_output:
vis.close()
logmgr.save()
if __name__ == "__main__":
main()
# entry points for py.test ----------------------------------------------------
@mark_test.long
def test_stability():
main(write_output=False)
__copyright__ = "Copyright (C) 2008 Andreas Kloeckner"
__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 __future__ import division
from __future__ import absolute_import
from __future__ import print_function
import numpy
def make_boxmesh():
from meshpy.tet import MeshInfo, build
from meshpy.geometry import GeometryBuilder, Marker, make_box
geob = GeometryBuilder()
box_marker = Marker.FIRST_USER_MARKER
extent_small = 0.1*numpy.ones(3, dtype=numpy.float64)
geob.add_geometry(*make_box(-extent_small, extent_small))
# make small "separator box" for region attribute
geob.add_geometry(
*make_box(
-extent_small*4,
numpy.array([4, 0.4, 0.4], dtype=numpy.float64)))
geob.add_geometry(
*make_box(
numpy.array([-1, -1, -1], dtype=numpy.float64),
numpy.array([5, 1, 1], dtype=numpy.float64)))
mesh_info = MeshInfo()
geob.set(mesh_info)
mesh_info.set_holes([(0, 0, 0)])
# region attributes
mesh_info.regions.resize(1)
mesh_info.regions[0] = (
# point in region
list(extent_small*2) + [
# region number
1,
# max volume in region
#0.0001
0.005
])
mesh = build(mesh_info, max_volume=0.02,
volume_constraints=True, attributes=True)
print("%d elements" % len(mesh.elements))
#mesh.write_vtk("box-in-box.vtk")
#print "done writing"
fvi2fm = mesh.face_vertex_indices_to_face_marker
face_marker_to_tag = {
box_marker: "noslip",
Marker.MINUS_X: "inflow",
Marker.PLUS_X: "outflow",
Marker.MINUS_Y: "inflow",
Marker.PLUS_Y: "inflow",
Marker.PLUS_Z: "inflow",
Marker.MINUS_Z: "inflow"
}
def bdry_tagger(fvi, el, fn, all_v):
face_marker = fvi2fm[fvi]
return [face_marker_to_tag[face_marker]]
from grudge.mesh import make_conformal_mesh
return make_conformal_mesh(
mesh.points, mesh.elements, bdry_tagger)
def main():
from grudge.backends import guess_run_context
rcon = guess_run_context(["cuda"])
if rcon.is_head_rank:
mesh = make_boxmesh()
#from grudge.mesh import make_rect_mesh
#mesh = make_rect_mesh(
# boundary_tagger=lambda fvi, el, fn, all_v: ["inflow"])
mesh_data = rcon.distribute_mesh(mesh)
else:
mesh_data = rcon.receive_mesh()
for order in [3]:
from pytools import add_python_path_relative_to_script
add_python_path_relative_to_script("..")
from gas_dynamics_initials import UniformMachFlow
box = UniformMachFlow(angle_of_attack=0)
from grudge.models.gas_dynamics import GasDynamicsOperator
op = GasDynamicsOperator(dimensions=3,
gamma=box.gamma, mu=box.mu,
prandtl=box.prandtl, spec_gas_const=box.spec_gas_const,
bc_inflow=box, bc_outflow=box, bc_noslip=box,
inflow_tag="inflow", outflow_tag="outflow", noslip_tag="noslip")
discr = rcon.make_discretization(mesh_data, order=order,
debug=[
#"cuda_no_plan",
#"cuda_dump_kernels",
#"dump_dataflow_graph",
#"dump_optemplate_stages",
#"dump_dataflow_graph",
#"print_op_code",
"cuda_no_plan_el_local",
],
default_scalar_type=numpy.float32,
tune_for=op.sym_operator())
from grudge.visualization import SiloVisualizer, VtkVisualizer # noqa
#vis = VtkVisualizer(discr, rcon, "shearflow-%d" % order)
vis = SiloVisualizer(discr, rcon)
fields = box.volume_interpolant(0, discr)
navierstokes_ex = op.bind(discr)
max_eigval = [0]
def rhs(t, q):
ode_rhs, speed = navierstokes_ex(t, q)
max_eigval[0] = speed
return ode_rhs
rhs(0, fields)
if rcon.is_head_rank:
print("---------------------------------------------")
print("order %d" % order)
print("---------------------------------------------")
print("#elements=", len(mesh.elements))
from grudge.timestep import RK4TimeStepper
stepper = RK4TimeStepper()
# diagnostics setup ---------------------------------------------------
from logpyle import LogManager, add_general_quantities, \
add_simulation_quantities, add_run_info
logmgr = LogManager("navierstokes-%d.dat" % order, "w", rcon.communicator)
add_run_info(logmgr)
add_general_quantities(logmgr)
add_simulation_quantities(logmgr)
discr.add_instrumentation(logmgr)
stepper.add_instrumentation(logmgr)
logmgr.add_watches(["step.max", "t_sim.max", "t_step.max"])
from logpyle import LogQuantity
class ChangeSinceLastStep(LogQuantity):
"""Records the change of a variable between a time step and the previous
one"""
def __init__(self, name="change"):
LogQuantity.__init__(self, name, "1", "Change since last time step")
self.old_fields = 0
def __call__(self):
result = discr.norm(fields - self.old_fields)
self.old_fields = fields
return result
logmgr.add_quantity(ChangeSinceLastStep())
# timestep loop -------------------------------------------------------
try:
from grudge.timestep import times_and_steps
step_it = times_and_steps(
final_time=200,
#max_steps=500,
logmgr=logmgr,
max_dt_getter=lambda t: op.estimate_timestep(discr,
stepper=stepper, t=t, max_eigenvalue=max_eigval[0]))
for step, t, dt in step_it:
if step % 200 == 0:
#if False:
visf = vis.make_file("box-%d-%06d" % (order, step))
#rhs_fields = rhs(t, fields)
vis.add_data(visf,
[
("rho", discr.convert_volume(
op.rho(fields), kind="numpy")),
("e", discr.convert_volume(
op.e(fields), kind="numpy")),
("rho_u", discr.convert_volume(
op.rho_u(fields), kind="numpy")),
("u", discr.convert_volume(
op.u(fields), kind="numpy")),
# ("rhs_rho", discr.convert_volume(
# op.rho(rhs_fields), kind="numpy")),
# ("rhs_e", discr.convert_volume(
# op.e(rhs_fields), kind="numpy")),
# ("rhs_rho_u", discr.convert_volume(
# op.rho_u(rhs_fields), kind="numpy")),
],
expressions=[
("p", "(0.4)*(e- 0.5*(rho_u*u))"),
],
time=t, step=step
)
visf.close()
fields = stepper(fields, t, dt, rhs)
finally:
vis.close()
logmgr.save()
discr.close()
if __name__ == "__main__":
main()
__copyright__ = "Copyright (C) 2008 Andreas Kloeckner"
__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 __future__ import division
from __future__ import absolute_import
from __future__ import print_function
import numpy
import numpy.linalg as la
class SineWave:
def __init__(self):
self.gamma = 1.4
self.mu = 0
self.prandtl = 0.72
self.spec_gas_const = 287.1
def __call__(self, t, x_vec):
rho = 2 + numpy.sin(x_vec[0] + x_vec[1] + x_vec[2] - 2 * t)
velocity = numpy.array([1, 1, 0])
p = 1
e = p/(self.gamma-1) + rho/2 * numpy.dot(velocity, velocity)
rho_u = rho * velocity[0]
rho_v = rho * velocity[1]
rho_w = rho * velocity[2]
from grudge.tools import join_fields
return join_fields(rho, e, rho_u, rho_v, rho_w)
def properties(self):
return(self.gamma, self.mu, self.prandtl, self.spec_gas_const)
def volume_interpolant(self, t, discr):
return discr.convert_volume(
self(t, discr.nodes.T),
kind=discr.compute_kind)
def boundary_interpolant(self, t, discr, tag):
return discr.convert_boundary(
self(t, discr.get_boundary(tag).nodes.T),
tag=tag, kind=discr.compute_kind)
def main(final_time=1, write_output=False):
from grudge.backends import guess_run_context
rcon = guess_run_context()
from grudge.tools import EOCRecorder, to_obj_array
eoc_rec = EOCRecorder()
if rcon.is_head_rank:
from grudge.mesh import make_box_mesh
mesh = make_box_mesh((0,0,0), (10,10,10), max_volume=0.5)
mesh_data = rcon.distribute_mesh(mesh)
else:
mesh_data = rcon.receive_mesh()
for order in [3, 4, 5]:
discr = rcon.make_discretization(mesh_data, order=order,
default_scalar_type=numpy.float64)
from grudge.visualization import SiloVisualizer, VtkVisualizer
vis = VtkVisualizer(discr, rcon, "sinewave-%d" % order)
#vis = SiloVisualizer(discr, rcon)
sinewave = SineWave()
fields = sinewave.volume_interpolant(0, discr)
gamma, mu, prandtl, spec_gas_const = sinewave.properties()
from grudge.mesh import BTAG_ALL
from grudge.models.gas_dynamics import GasDynamicsOperator
op = GasDynamicsOperator(dimensions=mesh.dimensions, gamma=gamma, mu=mu,
prandtl=prandtl, spec_gas_const=spec_gas_const,
bc_inflow=sinewave, bc_outflow=sinewave, bc_noslip=sinewave,
inflow_tag=BTAG_ALL, source=None)
euler_ex = op.bind(discr)
max_eigval = [0]
def rhs(t, q):
ode_rhs, speed = euler_ex(t, q)
max_eigval[0] = speed
return ode_rhs
rhs(0, fields)
if rcon.is_head_rank:
print("---------------------------------------------")
print("order %d" % order)
print("---------------------------------------------")
print("#elements=", len(mesh.elements))
from grudge.timestep import RK4TimeStepper
stepper = RK4TimeStepper()
# diagnostics setup ---------------------------------------------------
from logpyle import LogManager, add_general_quantities, \
add_simulation_quantities, add_run_info
if write_output:
log_name = ("euler-sinewave-%(order)d-%(els)d.dat"
% {"order":order, "els":len(mesh.elements)})
else:
log_name = False
logmgr = LogManager(log_name, "w", rcon.communicator)
add_run_info(logmgr)
add_general_quantities(logmgr)
add_simulation_quantities(logmgr)
discr.add_instrumentation(logmgr)
stepper.add_instrumentation(logmgr)
logmgr.add_watches(["step.max", "t_sim.max", "t_step.max"])
# timestep loop -------------------------------------------------------
try:
from grudge.timestep import times_and_steps
step_it = times_and_steps(
final_time=final_time, logmgr=logmgr,
max_dt_getter=lambda t: op.estimate_timestep(discr,
stepper=stepper, t=t, max_eigenvalue=max_eigval[0]))
for step, t, dt in step_it:
#if step % 10 == 0:
if write_output:
visf = vis.make_file("sinewave-%d-%04d" % (order, step))
#from pyvisfile.silo import DB_VARTYPE_VECTOR
vis.add_data(visf,
[
("rho", discr.convert_volume(op.rho(fields), kind="numpy")),
("e", discr.convert_volume(op.e(fields), kind="numpy")),
("rho_u", discr.convert_volume(op.rho_u(fields), kind="numpy")),
("u", discr.convert_volume(op.u(fields), kind="numpy")),
#("true_rho", op.rho(true_fields)),
#("true_e", op.e(true_fields)),
#("true_rho_u", op.rho_u(true_fields)),
#("true_u", op.u(true_fields)),
#("rhs_rho", op.rho(rhs_fields)),
#("rhs_e", op.e(rhs_fields)),
#("rhs_rho_u", op.rho_u(rhs_fields)),
],
#expressions=[
#("diff_rho", "rho-true_rho"),
#("diff_e", "e-true_e"),
#("diff_rho_u", "rho_u-true_rho_u", DB_VARTYPE_VECTOR),
#("p", "0.4*(e- 0.5*(rho_u*u))"),
#],
time=t, step=step
)
visf.close()
fields = stepper(fields, t, dt, rhs)
finally:
vis.close()
logmgr.close()
discr.close()
true_fields = sinewave.volume_interpolant(t, discr)
eoc_rec.add_data_point(order, discr.norm(fields-true_fields))
print()
print(eoc_rec.pretty_print("P.Deg.", "L2 Error"))
if __name__ == "__main__":
main()
# entry points for py.test ----------------------------------------------------
from pytools.test import mark_test
@mark_test.long
def test_euler_sine_wave():
main(final_time=0.1, write_output=False)
from __future__ import division
from __future__ import absolute_import
from __future__ import print_function
import numpy
import numpy.linalg as la
class Sod:
def __init__(self, gamma):
self.gamma = gamma
self.prandtl = 0.72
def __call__(self, t, x_vec):
from grudge.tools import heaviside
from grudge.tools import heaviside_a
x_rel = x_vec[0]
y_rel = x_vec[1]
from math import pi
r = numpy.sqrt(x_rel**2+y_rel**2)
r_shift=r-3.0
u = 0.0
v = 0.0
from numpy import sign
rho = heaviside(-r_shift)+.125*heaviside_a(r_shift,1.0)
e = (1.0/(self.gamma-1.0))*(heaviside(-r_shift)+.1*heaviside_a(r_shift,1.0))
p = (self.gamma-1.0)*e
from grudge.tools import join_fields
return join_fields(rho, e, rho*u, rho*v)
def volume_interpolant(self, t, discr):
return discr.convert_volume(
self(t, discr.nodes.T),
kind=discr.compute_kind)
def boundary_interpolant(self, t, discr, tag):
return discr.convert_boundary(
self(t, discr.get_boundary(tag).nodes.T),
tag=tag, kind=discr.compute_kind)
def main():
from grudge.backends import guess_run_context
rcon = guess_run_context()
from grudge.tools import to_obj_array
if rcon.is_head_rank:
from grudge.mesh.generator import make_rect_mesh
mesh = make_rect_mesh((-5,-5), (5,5), max_area=0.01)
mesh_data = rcon.distribute_mesh(mesh)
else:
mesh_data = rcon.receive_mesh()
for order in [1]:
discr = rcon.make_discretization(mesh_data, order=order,
default_scalar_type=numpy.float64)
from grudge.visualization import SiloVisualizer, VtkVisualizer
vis = VtkVisualizer(discr, rcon, "Sod2D-%d" % order)
#vis = SiloVisualizer(discr, rcon)
sod_field = Sod(gamma=1.4)
fields = sod_field.volume_interpolant(0, discr)
from grudge.models.gas_dynamics import GasDynamicsOperator
from grudge.mesh import BTAG_ALL
op = GasDynamicsOperator(dimensions=2, gamma=sod_field.gamma, mu=0.0,
prandtl=sod_field.prandtl,
bc_inflow=sod_field,
bc_outflow=sod_field,
bc_noslip=sod_field,
inflow_tag=BTAG_ALL,
source=None)
euler_ex = op.bind(discr)
max_eigval = [0]
def rhs(t, q):
ode_rhs, speed = euler_ex(t, q)
max_eigval[0] = speed
return ode_rhs
rhs(0, fields)
if rcon.is_head_rank:
print("---------------------------------------------")
print("order %d" % order)
print("---------------------------------------------")
print("#elements=", len(mesh.elements))
# limiter setup ------------------------------------------------------------
from grudge.models.gas_dynamics import SlopeLimiter1NEuler
limiter = SlopeLimiter1NEuler(discr, sod_field.gamma, 2, op)
# integrator setup---------------------------------------------------------
from grudge.timestep import SSPRK3TimeStepper, RK4TimeStepper
stepper = SSPRK3TimeStepper(limiter=limiter)
#stepper = SSPRK3TimeStepper()
#stepper = RK4TimeStepper()
# diagnostics setup ---------------------------------------------------
from logpyle import LogManager, add_general_quantities, \
add_simulation_quantities, add_run_info
logmgr = LogManager("euler-%d.dat" % order, "w", rcon.communicator)
add_run_info(logmgr)
add_general_quantities(logmgr)
add_simulation_quantities(logmgr)
discr.add_instrumentation(logmgr)
stepper.add_instrumentation(logmgr)
logmgr.add_watches(["step.max", "t_sim.max", "t_step.max"])
# filter setup-------------------------------------------------------------
from grudge.discretization import Filter, ExponentialFilterResponseFunction
mode_filter = Filter(discr,
ExponentialFilterResponseFunction(min_amplification=0.9,order=4))
# timestep loop -------------------------------------------------------
try:
from grudge.timestep import times_and_steps
step_it = times_and_steps(
final_time=1.0, logmgr=logmgr,
max_dt_getter=lambda t: op.estimate_timestep(discr,
stepper=stepper, t=t, max_eigenvalue=max_eigval[0]))
for step, t, dt in step_it:
if step % 5 == 0:
#if False:
visf = vis.make_file("vortex-%d-%04d" % (order, step))
#true_fields = vortex.volume_interpolant(t, discr)
#from pyvisfile.silo import DB_VARTYPE_VECTOR
vis.add_data(visf,
[
("rho", discr.convert_volume(op.rho(fields), kind="numpy")),
("e", discr.convert_volume(op.e(fields), kind="numpy")),
("rho_u", discr.convert_volume(op.rho_u(fields), kind="numpy")),
("u", discr.convert_volume(op.u(fields), kind="numpy")),
#("true_rho", op.rho(true_fields)),
#("true_e", op.e(true_fields)),
#("true_rho_u", op.rho_u(true_fields)),
#("true_u", op.u(true_fields)),
#("rhs_rho", op.rho(rhs_fields)),
#("rhs_e", op.e(rhs_fields)),
#("rhs_rho_u", op.rho_u(rhs_fields)),
],
#expressions=[
#("diff_rho", "rho-true_rho"),
#("diff_e", "e-true_e"),
#("diff_rho_u", "rho_u-true_rho_u", DB_VARTYPE_VECTOR),
#("p", "0.4*(e- 0.5*(rho_u*u))"),
#],
time=t, step=step
)
visf.close()
fields = stepper(fields, t, dt, rhs)
# fields = limiter(fields)
# fields = mode_filter(fields)
assert not numpy.isnan(numpy.sum(fields[0]))
finally:
vis.close()
logmgr.close()
discr.close()
# not solution, just to check against when making code changes
true_fields = sod_field.volume_interpolant(t, discr)
print(discr.norm(fields-true_fields))
if __name__ == "__main__":
main()
__copyright__ = "Copyright (C) 2008 Andreas Kloeckner"
__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 __future__ import division
from __future__ import absolute_import
from __future__ import print_function
import numpy
import numpy.linalg as la
def main(write_output=True):
from pytools import add_python_path_relative_to_script
add_python_path_relative_to_script("..")
from grudge.backends import guess_run_context
rcon = guess_run_context()
from grudge.tools import EOCRecorder
eoc_rec = EOCRecorder()
if rcon.is_head_rank:
from grudge.mesh.generator import \
make_rect_mesh, \
make_centered_regular_rect_mesh
refine = 4
mesh = make_centered_regular_rect_mesh((0,-5), (10,5), n=(9,9),
post_refine_factor=refine)
mesh_data = rcon.distribute_mesh(mesh)
else:
mesh_data = rcon.receive_mesh()
# a second mesh to regrid to
if rcon.is_head_rank:
from grudge.mesh.generator import \
make_rect_mesh, \
make_centered_regular_rect_mesh
refine = 4
mesh2 = make_centered_regular_rect_mesh((0,-5), (10,5), n=(8,8),
post_refine_factor=refine)
mesh_data2 = rcon.distribute_mesh(mesh2)
else:
mesh_data2 = rcon.receive_mesh()
for order in [3,4]:
discr = rcon.make_discretization(mesh_data, order=order,
default_scalar_type=numpy.float64,
quad_min_degrees={
"gasdyn_vol": 3*order,
"gasdyn_face": 3*order,
})
discr2 = rcon.make_discretization(mesh_data2, order=order,
default_scalar_type=numpy.float64,
quad_min_degrees={
"gasdyn_vol": 3*order,
"gasdyn_face": 3*order,
})
from grudge.visualization import SiloVisualizer, VtkVisualizer
vis = VtkVisualizer(discr, rcon, "vortex-%d" % order)
#vis = SiloVisualizer(discr, rcon)
from gas_dynamics_initials import Vortex
vortex = Vortex()
fields = vortex.volume_interpolant(0, discr)
from grudge.models.gas_dynamics import GasDynamicsOperator
from grudge.mesh import BTAG_ALL
op = GasDynamicsOperator(dimensions=2, gamma=vortex.gamma, mu=vortex.mu,
prandtl=vortex.prandtl, spec_gas_const=vortex.spec_gas_const,
bc_inflow=vortex, bc_outflow=vortex, bc_noslip=vortex,
inflow_tag=BTAG_ALL, source=None)
euler_ex = op.bind(discr)
max_eigval = [0]
def rhs(t, q):
ode_rhs, speed = euler_ex(t, q)
max_eigval[0] = speed
return ode_rhs
rhs(0, fields)
if rcon.is_head_rank:
print("---------------------------------------------")
print("order %d" % order)
print("---------------------------------------------")
print("#elements for mesh 1 =", len(mesh.elements))
print("#elements for mesh 2 =", len(mesh2.elements))
# limiter ------------------------------------------------------------
from grudge.models.gas_dynamics import SlopeLimiter1NEuler
limiter = SlopeLimiter1NEuler(discr, vortex.gamma, 2, op)
from grudge.timestep import SSPRK3TimeStepper
#stepper = SSPRK3TimeStepper(limiter=limiter)
stepper = SSPRK3TimeStepper()
#from grudge.timestep import RK4TimeStepper
#stepper = RK4TimeStepper()
# diagnostics setup ---------------------------------------------------
from logpyle import LogManager, add_general_quantities, \
add_simulation_quantities, add_run_info
if write_output:
log_file_name = "euler-%d.dat" % order
else:
log_file_name = None
logmgr = LogManager(log_file_name, "w", rcon.communicator)
add_run_info(logmgr)
add_general_quantities(logmgr)
add_simulation_quantities(logmgr)
discr.add_instrumentation(logmgr)
stepper.add_instrumentation(logmgr)
logmgr.add_watches(["step.max", "t_sim.max", "t_step.max"])
# timestep loop -------------------------------------------------------
try:
final_time = 0.2
from grudge.timestep import times_and_steps
step_it = times_and_steps(
final_time=final_time, logmgr=logmgr,
max_dt_getter=lambda t: op.estimate_timestep(discr,
stepper=stepper, t=t, max_eigenvalue=max_eigval[0]))
for step, t, dt in step_it:
if step % 10 == 0 and write_output:
#if False:
visf = vis.make_file("vortex-%d-%04d" % (order, step))
#true_fields = vortex.volume_interpolant(t, discr)
from pyvisfile.silo import DB_VARTYPE_VECTOR
vis.add_data(visf,
[
("rho", discr.convert_volume(op.rho(fields), kind="numpy")),
("e", discr.convert_volume(op.e(fields), kind="numpy")),
("rho_u", discr.convert_volume(op.rho_u(fields), kind="numpy")),
("u", discr.convert_volume(op.u(fields), kind="numpy")),
#("true_rho", discr.convert_volume(op.rho(true_fields), kind="numpy")),
#("true_e", discr.convert_volume(op.e(true_fields), kind="numpy")),
#("true_rho_u", discr.convert_volume(op.rho_u(true_fields), kind="numpy")),
#("true_u", discr.convert_volume(op.u(true_fields), kind="numpy")),
#("rhs_rho", discr.convert_volume(op.rho(rhs_fields), kind="numpy")),
#("rhs_e", discr.convert_volume(op.e(rhs_fields), kind="numpy")),
#("rhs_rho_u", discr.convert_volume(op.rho_u(rhs_fields), kind="numpy")),
],
#expressions=[
#("diff_rho", "rho-true_rho"),
#("diff_e", "e-true_e"),
#("diff_rho_u", "rho_u-true_rho_u", DB_VARTYPE_VECTOR),
#("p", "0.4*(e- 0.5*(rho_u*u))"),
#],
time=t, step=step
)
visf.close()
fields = stepper(fields, t, dt, rhs)
#fields = limiter(fields)
#regrid to discr2 at some arbitrary time
if step == 21:
#get interpolated fields
fields = discr.get_regrid_values(fields, discr2, dtype=None, use_btree=True, thresh=1e-8)
#get new stepper (old one has reference to discr
stepper = SSPRK3TimeStepper()
#new bind
euler_ex = op.bind(discr2)
#new rhs
max_eigval = [0]
def rhs(t, q):
ode_rhs, speed = euler_ex(t, q)
max_eigval[0] = speed
return ode_rhs
rhs(t+dt, fields)
#add logmanager
#discr2.add_instrumentation(logmgr)
#new step_it
step_it = times_and_steps(
final_time=final_time, logmgr=logmgr,
max_dt_getter=lambda t: op.estimate_timestep(discr2,
stepper=stepper, t=t, max_eigenvalue=max_eigval[0]))
#new visualization
vis.close()
vis = VtkVisualizer(discr2, rcon, "vortexNewGrid-%d" % order)
discr=discr2
assert not numpy.isnan(numpy.sum(fields[0]))
true_fields = vortex.volume_interpolant(final_time, discr)
l2_error = discr.norm(fields-true_fields)
l2_error_rho = discr.norm(op.rho(fields)-op.rho(true_fields))
l2_error_e = discr.norm(op.e(fields)-op.e(true_fields))
l2_error_rhou = discr.norm(op.rho_u(fields)-op.rho_u(true_fields))
l2_error_u = discr.norm(op.u(fields)-op.u(true_fields))
eoc_rec.add_data_point(order, l2_error)
print()
print(eoc_rec.pretty_print("P.Deg.", "L2 Error"))
logmgr.set_constant("l2_error", l2_error)
logmgr.set_constant("l2_error_rho", l2_error_rho)
logmgr.set_constant("l2_error_e", l2_error_e)
logmgr.set_constant("l2_error_rhou", l2_error_rhou)
logmgr.set_constant("l2_error_u", l2_error_u)
logmgr.set_constant("refinement", refine)
finally:
if write_output:
vis.close()
logmgr.close()
discr.close()
# after order loop
# assert eoc_rec.estimate_order_of_convergence()[0,1] > 6
if __name__ == "__main__":
main()
__copyright__ = "Copyright (C) 2008 Andreas Kloeckner"
__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 __future__ import division
from __future__ import absolute_import
from __future__ import print_function
import numpy
import numpy.linalg as la
# modifies isentropic vortex solution so that rho->Arho, P->A^gamma rho^gamma
# this will be analytic solution if appropriate source terms are added
# to the RHS. coded for vel_x=1, vel_y=0
class Vortex:
def __init__(self, beta, gamma, center, velocity, densityA):
self.beta = beta
self.gamma = gamma
self.center = numpy.asarray(center)
self.velocity = numpy.asarray(velocity)
self.densityA = densityA
def __call__(self, t, x_vec):
vortex_loc = self.center + t*self.velocity
# coordinates relative to vortex center
x_rel = x_vec[0] - vortex_loc[0]
y_rel = x_vec[1] - vortex_loc[1]
# Y.C. Zhou, G.W. Wei / Journal of Computational Physics 189 (2003) 159
# also JSH/TW Nodal DG Methods, p. 209
from math import pi
r = numpy.sqrt(x_rel**2+y_rel**2)
expterm = self.beta*numpy.exp(1-r**2)
u = self.velocity[0] - expterm*y_rel/(2*pi)
v = self.velocity[1] + expterm*x_rel/(2*pi)
rho = self.densityA*(1-(self.gamma-1)/(16*self.gamma*pi**2)*expterm**2)**(1/(self.gamma-1))
p = rho**self.gamma
e = p/(self.gamma-1) + rho/2*(u**2+v**2)
from grudge.tools import join_fields
return join_fields(rho, e, rho*u, rho*v)
def volume_interpolant(self, t, discr):
return discr.convert_volume(
self(t, discr.nodes.T
.astype(discr.default_scalar_type)),
kind=discr.compute_kind)
def boundary_interpolant(self, t, discr, tag):
return discr.convert_boundary(
self(t, discr.get_boundary(tag).nodes.T
.astype(discr.default_scalar_type)),
tag=tag, kind=discr.compute_kind)
class SourceTerms:
def __init__(self, beta, gamma, center, velocity, densityA):
self.beta = beta
self.gamma = gamma
self.center = numpy.asarray(center)
self.velocity = numpy.asarray(velocity)
self.densityA = densityA
def __call__(self,t,x_vec,q):
vortex_loc = self.center + t*self.velocity
# coordinates relative to vortex center
x_rel = x_vec[0] - vortex_loc[0]
y_rel = x_vec[1] - vortex_loc[1]
# sources written in terms of A=1.0 solution
# (standard isentropic vortex)
from math import pi
r = numpy.sqrt(x_rel**2+y_rel**2)
expterm = self.beta*numpy.exp(1-r**2)
u = self.velocity[0] - expterm*y_rel/(2*pi)
v = self.velocity[1] + expterm*x_rel/(2*pi)
rho = (1-(self.gamma-1)/(16*self.gamma*pi**2)*expterm**2)**(1/(self.gamma-1))
p = rho**self.gamma
#computed necessary derivatives
expterm_t = 2*expterm*x_rel
expterm_x = -2*expterm*x_rel
expterm_y = -2*expterm*y_rel
u_x = -expterm*y_rel/(2*pi)*(-2*x_rel)
v_y = expterm*x_rel/(2*pi)*(-2*y_rel)
#derivatives for rho (A=1)
facG=self.gamma-1
rho_t = (1/facG)*(1-(facG)/(16*self.gamma*pi**2)*expterm**2)**(1/facG-1)* \
(-facG/(16*self.gamma*pi**2)*2*expterm*expterm_t)
rho_x = (1/facG)*(1-(facG)/(16*self.gamma*pi**2)*expterm**2)**(1/facG-1)* \
(-facG/(16*self.gamma*pi**2)*2*expterm*expterm_x)
rho_y = (1/facG)*(1-(facG)/(16*self.gamma*pi**2)*expterm**2)**(1/facG-1)* \
(-facG/(16*self.gamma*pi**2)*2*expterm*expterm_y)
#derivatives for rho (A=1) to the power of gamma
rho_gamma_t = self.gamma*rho**(self.gamma-1)*rho_t
rho_gamma_x = self.gamma*rho**(self.gamma-1)*rho_x
rho_gamma_y = self.gamma*rho**(self.gamma-1)*rho_y
factorA=self.densityA**self.gamma-self.densityA
#construct source terms
source_rho = x_vec[0]-x_vec[0]
source_e = (factorA/(self.gamma-1))*(rho_gamma_t + self.gamma*(u_x*rho**self.gamma+u*rho_gamma_x)+ \
self.gamma*(v_y*rho**self.gamma+v*rho_gamma_y))
source_rhou = factorA*rho_gamma_x
source_rhov = factorA*rho_gamma_y
from grudge.tools import join_fields
return join_fields(source_rho, source_e, source_rhou, source_rhov, x_vec[0]-x_vec[0])
def volume_interpolant(self,t,q,discr):
return discr.convert_volume(
self(t,discr.nodes.T,q),
kind=discr.compute_kind)
def main(write_output=True):
from grudge.backends import guess_run_context
rcon = guess_run_context(
#["cuda"]
)
gamma = 1.4
# at A=1 we have case of isentropic vortex, source terms
# arise for other values
densityA = 2.0
from grudge.tools import EOCRecorder, to_obj_array
eoc_rec = EOCRecorder()
if rcon.is_head_rank:
from grudge.mesh import \
make_rect_mesh, \
make_centered_regular_rect_mesh
refine = 1
mesh = make_centered_regular_rect_mesh((0,-5), (10,5), n=(9,9),
post_refine_factor=refine)
mesh_data = rcon.distribute_mesh(mesh)
else:
mesh_data = rcon.receive_mesh()
for order in [4,5]:
discr = rcon.make_discretization(mesh_data, order=order,
debug=[#"cuda_no_plan",
#"print_op_code"
],
default_scalar_type=numpy.float64)
from grudge.visualization import SiloVisualizer, VtkVisualizer
#vis = VtkVisualizer(discr, rcon, "vortex-%d" % order)
vis = SiloVisualizer(discr, rcon)
vortex = Vortex(beta=5, gamma=gamma,
center=[5,0],
velocity=[1,0], densityA=densityA)
fields = vortex.volume_interpolant(0, discr)
sources=SourceTerms(beta=5, gamma=gamma,
center=[5,0],
velocity=[1,0], densityA=densityA)
from grudge.models.gas_dynamics import (
GasDynamicsOperator, GammaLawEOS)
from grudge.mesh import BTAG_ALL
op = GasDynamicsOperator(dimensions=2,
mu=0.0, prandtl=0.72, spec_gas_const=287.1,
equation_of_state=GammaLawEOS(vortex.gamma),
bc_inflow=vortex, bc_outflow=vortex, bc_noslip=vortex,
inflow_tag=BTAG_ALL, source=sources)
euler_ex = op.bind(discr)
max_eigval = [0]
def rhs(t, q):
ode_rhs, speed = euler_ex(t, q)
max_eigval[0] = speed
return ode_rhs
rhs(0, fields)
if rcon.is_head_rank:
print("---------------------------------------------")
print("order %d" % order)
print("---------------------------------------------")
print("#elements=", len(mesh.elements))
# limiter setup -------------------------------------------------------
from grudge.models.gas_dynamics import SlopeLimiter1NEuler
limiter = SlopeLimiter1NEuler(discr, gamma, 2, op)
# time stepper --------------------------------------------------------
from grudge.timestep import SSPRK3TimeStepper, RK4TimeStepper
#stepper = SSPRK3TimeStepper(limiter=limiter)
#stepper = SSPRK3TimeStepper()
stepper = RK4TimeStepper()
# diagnostics setup ---------------------------------------------------
from logpyle import LogManager, add_general_quantities, \
add_simulation_quantities, add_run_info
if write_output:
log_file_name = "euler-%d.dat" % order
else:
log_file_name = None
logmgr = LogManager(log_file_name, "w", rcon.communicator)
add_run_info(logmgr)
add_general_quantities(logmgr)
add_simulation_quantities(logmgr)
discr.add_instrumentation(logmgr)
stepper.add_instrumentation(logmgr)
logmgr.add_watches(["step.max", "t_sim.max", "t_step.max"])
# timestep loop -------------------------------------------------------
t = 0
#fields = limiter(fields)
try:
from grudge.timestep import times_and_steps
step_it = times_and_steps(
final_time=.1,
#max_steps=500,
logmgr=logmgr,
max_dt_getter=lambda t: 0.4*op.estimate_timestep(discr,
stepper=stepper, t=t, max_eigenvalue=max_eigval[0]))
for step, t, dt in step_it:
if step % 1 == 0 and write_output:
#if False:
visf = vis.make_file("vortex-%d-%04d" % (order, step))
true_fields = vortex.volume_interpolant(t, discr)
#rhs_fields = rhs(t, fields)
from pyvisfile.silo import DB_VARTYPE_VECTOR
vis.add_data(visf,
[
("rho", discr.convert_volume(op.rho(fields), kind="numpy")),
("e", discr.convert_volume(op.e(fields), kind="numpy")),
("rho_u", discr.convert_volume(op.rho_u(fields), kind="numpy")),
("u", discr.convert_volume(op.u(fields), kind="numpy")),
#("true_rho", discr.convert_volume(op.rho(true_fields), kind="numpy")),
#("true_e", discr.convert_volume(op.e(true_fields), kind="numpy")),
#("true_rho_u", discr.convert_volume(op.rho_u(true_fields), kind="numpy")),
#("true_u", discr.convert_volume(op.u(true_fields), kind="numpy")),
#("rhs_rho", discr.convert_volume(op.rho(rhs_fields), kind="numpy")),
#("rhs_e", discr.convert_volume(op.e(rhs_fields), kind="numpy")),
#("rhs_rho_u", discr.convert_volume(op.rho_u(rhs_fields), kind="numpy")),
],
expressions=[
#("diff_rho", "rho-true_rho"),
#("diff_e", "e-true_e"),
#("diff_rho_u", "rho_u-true_rho_u", DB_VARTYPE_VECTOR),
("p", "0.4*(e- 0.5*(rho_u*u))"),
],
time=t, step=step
)
visf.close()
fields = stepper(fields, t, dt, rhs)
true_fields = vortex.volume_interpolant(t, discr)
l2_error = discr.norm(fields-true_fields)
l2_error_rho = discr.norm(op.rho(fields)-op.rho(true_fields))
l2_error_e = discr.norm(op.e(fields)-op.e(true_fields))
l2_error_rhou = discr.norm(op.rho_u(fields)-op.rho_u(true_fields))
l2_error_u = discr.norm(op.u(fields)-op.u(true_fields))
eoc_rec.add_data_point(order, l2_error_rho)
print()
print(eoc_rec.pretty_print("P.Deg.", "L2 Error"))
logmgr.set_constant("l2_error", l2_error)
logmgr.set_constant("l2_error_rho", l2_error_rho)
logmgr.set_constant("l2_error_e", l2_error_e)
logmgr.set_constant("l2_error_rhou", l2_error_rhou)
logmgr.set_constant("l2_error_u", l2_error_u)
logmgr.set_constant("refinement", refine)
finally:
if write_output:
vis.close()
logmgr.close()
discr.close()
# after order loop
#assert eoc_rec.estimate_order_of_convergence()[0,1] > 6
if __name__ == "__main__":
main()
# entry points for py.test ----------------------------------------------------
from pytools.test import mark_test
@mark_test.long
def test_euler_vortex():
main(write_output=False)
__copyright__ = "Copyright (C) 2008 Andreas Kloeckner"
__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 __future__ import division
from __future__ import absolute_import
from __future__ import print_function
import numpy
def main(write_output=True):
from pytools import add_python_path_relative_to_script
add_python_path_relative_to_script("..")
from grudge.backends import guess_run_context
rcon = guess_run_context()
from grudge.tools import EOCRecorder
eoc_rec = EOCRecorder()
if rcon.is_head_rank:
from grudge.mesh.generator import \
make_rect_mesh, \
make_centered_regular_rect_mesh
refine = 4
mesh = make_centered_regular_rect_mesh((0,-5), (10,5), n=(9,9),
post_refine_factor=refine)
mesh_data = rcon.distribute_mesh(mesh)
else:
mesh_data = rcon.receive_mesh()
for order in [3, 4, 5]:
from gas_dynamics_initials import Vortex
flow = Vortex()
from grudge.models.gas_dynamics import (
GasDynamicsOperator, PolytropeEOS, GammaLawEOS)
from grudge.mesh import BTAG_ALL
# works equally well for GammaLawEOS
op = GasDynamicsOperator(dimensions=2, mu=flow.mu,
prandtl=flow.prandtl, spec_gas_const=flow.spec_gas_const,
equation_of_state=PolytropeEOS(flow.gamma),
bc_inflow=flow, bc_outflow=flow, bc_noslip=flow,
inflow_tag=BTAG_ALL, source=None)
discr = rcon.make_discretization(mesh_data, order=order,
default_scalar_type=numpy.float64,
quad_min_degrees={
"gasdyn_vol": 3*order,
"gasdyn_face": 3*order,
},
tune_for=op.sym_operator(),
debug=["cuda_no_plan"])
from grudge.visualization import SiloVisualizer, VtkVisualizer
vis = VtkVisualizer(discr, rcon, "vortex-%d" % order)
#vis = SiloVisualizer(discr, rcon)
fields = flow.volume_interpolant(0, discr)
euler_ex = op.bind(discr)
max_eigval = [0]
def rhs(t, q):
ode_rhs, speed = euler_ex(t, q)
max_eigval[0] = speed
return ode_rhs
rhs(0, fields)
if rcon.is_head_rank:
print("---------------------------------------------")
print("order %d" % order)
print("---------------------------------------------")
print("#elements=", len(mesh.elements))
# limiter ------------------------------------------------------------
from grudge.models.gas_dynamics import SlopeLimiter1NEuler
limiter = SlopeLimiter1NEuler(discr, flow.gamma, 2, op)
from grudge.timestep.runge_kutta import SSP3TimeStepper
#stepper = SSP3TimeStepper(limiter=limiter)
stepper = SSP3TimeStepper(
vector_primitive_factory=discr.get_vector_primitive_factory())
#from grudge.timestep import RK4TimeStepper
#stepper = RK4TimeStepper()
# diagnostics setup ---------------------------------------------------
from logpyle import LogManager, add_general_quantities, \
add_simulation_quantities, add_run_info
if write_output:
log_file_name = "euler-%d.dat" % order
else:
log_file_name = None
logmgr = LogManager(log_file_name, "w", rcon.communicator)
add_run_info(logmgr)
add_general_quantities(logmgr)
add_simulation_quantities(logmgr)
discr.add_instrumentation(logmgr)
stepper.add_instrumentation(logmgr)
logmgr.add_watches(["step.max", "t_sim.max", "t_step.max"])
# timestep loop -------------------------------------------------------
try:
final_time = flow.final_time
from grudge.timestep import times_and_steps
step_it = times_and_steps(
final_time=final_time, logmgr=logmgr,
max_dt_getter=lambda t: op.estimate_timestep(discr,
stepper=stepper, t=t, max_eigenvalue=max_eigval[0]))
print("run until t=%g" % final_time)
for step, t, dt in step_it:
if step % 10 == 0 and write_output:
#if False:
visf = vis.make_file("vortex-%d-%04d" % (order, step))
#true_fields = vortex.volume_interpolant(t, discr)
from pyvisfile.silo import DB_VARTYPE_VECTOR
vis.add_data(visf,
[
("rho", discr.convert_volume(op.rho(fields), kind="numpy")),
("e", discr.convert_volume(op.e(fields), kind="numpy")),
("rho_u", discr.convert_volume(op.rho_u(fields), kind="numpy")),
("u", discr.convert_volume(op.u(fields), kind="numpy")),
#("true_rho", discr.convert_volume(op.rho(true_fields), kind="numpy")),
#("true_e", discr.convert_volume(op.e(true_fields), kind="numpy")),
#("true_rho_u", discr.convert_volume(op.rho_u(true_fields), kind="numpy")),
#("true_u", discr.convert_volume(op.u(true_fields), kind="numpy")),
#("rhs_rho", discr.convert_volume(op.rho(rhs_fields), kind="numpy")),
#("rhs_e", discr.convert_volume(op.e(rhs_fields), kind="numpy")),
#("rhs_rho_u", discr.convert_volume(op.rho_u(rhs_fields), kind="numpy")),
],
#expressions=[
#("diff_rho", "rho-true_rho"),
#("diff_e", "e-true_e"),
#("diff_rho_u", "rho_u-true_rho_u", DB_VARTYPE_VECTOR),
#("p", "0.4*(e- 0.5*(rho_u*u))"),
#],
time=t, step=step
)
visf.close()
fields = stepper(fields, t, dt, rhs)
#fields = limiter(fields)
assert not numpy.isnan(numpy.sum(fields[0]))
true_fields = flow.volume_interpolant(final_time, discr)
l2_error = discr.norm(fields-true_fields)
l2_error_rho = discr.norm(op.rho(fields)-op.rho(true_fields))
l2_error_e = discr.norm(op.e(fields)-op.e(true_fields))
l2_error_rhou = discr.norm(op.rho_u(fields)-op.rho_u(true_fields))
l2_error_u = discr.norm(op.u(fields)-op.u(true_fields))
eoc_rec.add_data_point(order, l2_error)
print()
print(eoc_rec.pretty_print("P.Deg.", "L2 Error"))
logmgr.set_constant("l2_error", l2_error)
logmgr.set_constant("l2_error_rho", l2_error_rho)
logmgr.set_constant("l2_error_e", l2_error_e)
logmgr.set_constant("l2_error_rhou", l2_error_rhou)
logmgr.set_constant("l2_error_u", l2_error_u)
logmgr.set_constant("refinement", refine)
finally:
if write_output:
vis.close()
logmgr.close()
discr.close()
# after order loop
assert eoc_rec.estimate_order_of_convergence()[0,1] > 6
if __name__ == "__main__":
main()
# entry points for py.test ----------------------------------------------------
from pytools.test import mark_test
@mark_test.long
def test_euler_vortex():
main(write_output=False)
__copyright__ = "Copyright (C) 2008 Andreas Kloeckner"
__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 __future__ import division
from __future__ import absolute_import
import numpy
import numpy.linalg as la
from six.moves import range
class UniformMachFlow:
def __init__(self, mach=0.1, p=1, rho=1, reynolds=100,
gamma=1.4, prandtl=0.72, char_length=1, spec_gas_const=287.1,
angle_of_attack=None, direction=None, gaussian_pulse_at=None,
pulse_magnitude=0.1):
"""
:param direction: is a vector indicating the direction of the
flow. Only one of angle_of_attack and direction may be
specified. Only the direction, not the magnitude, of
direction is taken into account.
:param angle_of_attack: if not None, specifies the angle of
the flow along the Y axis, where the flow is
directed along the X axis.
"""
if angle_of_attack is not None and direction is not None:
raise ValueError("Only one of angle_of_attack and "
"direction may be specified.")
if angle_of_attack is None and direction is None:
angle_of_attack = 0
if direction is not None:
self.direction = direction/la.norm(direction)
else:
self.direction = None
self.mach = mach
self.p = p
self.rho = rho
self.gamma = gamma
self.prandtl = prandtl
self.reynolds = reynolds
self.length = char_length
self.spec_gas_const = spec_gas_const
self.angle_of_attack = angle_of_attack
self.gaussian_pulse_at = gaussian_pulse_at
self.pulse_magnitude = pulse_magnitude
self.c = (self.gamma * p / rho)**0.5
u = self.velocity = mach * self.c
self.e = p / (self.gamma - 1) + rho / 2 * u**2
if numpy.isinf(self.reynolds):
self.mu = 0
else:
self.mu = u * self.length * rho / self.reynolds
def direction_vector(self, dimensions):
# this must be done here because dimensions is not known above
if self.direction is None:
assert self.angle_of_attack is not None
direction = numpy.zeros(dimensions, dtype=numpy.float64)
direction[0] = numpy.cos(
self.angle_of_attack / 180. * numpy.pi)
direction[1] = numpy.sin(
self.angle_of_attack / 180. * numpy.pi)
return direction
else:
return self.direction
def __call__(self, t, x_vec):
ones = numpy.ones_like(x_vec[0])
rho_field = ones*self.rho
if self.gaussian_pulse_at is not None:
rel_to_pulse = [x_vec[i] - self.gaussian_pulse_at[i]
for i in range(len(x_vec))]
rho_field += self.pulse_magnitude * self.rho * numpy.exp(
- sum(rtp_i**2 for rtp_i in rel_to_pulse)/2)
direction = self.direction_vector(x_vec.shape[0])
from grudge.tools import make_obj_array
u_field = make_obj_array([ones*self.velocity*dir_i
for dir_i in direction])
from grudge.tools import join_fields
return join_fields(rho_field, self.e*ones, self.rho*u_field)
def volume_interpolant(self, t, discr):
return discr.convert_volume(
self(t, discr.nodes.T),
kind=discr.compute_kind,
dtype=discr.default_scalar_type)
def boundary_interpolant(self, t, discr, tag):
return discr.convert_boundary(
self(t, discr.get_boundary(tag).nodes.T),
tag=tag, kind=discr.compute_kind,
dtype=discr.default_scalar_type)
class Vortex:
def __init__(self):
self.beta = 5
self.gamma = 1.4
self.center = numpy.array([5, 0])
self.velocity = numpy.array([1, 0])
self.mu = 0
self.prandtl = 0.72
self.spec_gas_const = 287.1
def __call__(self, t, x_vec):
vortex_loc = self.center + t*self.velocity
# coordinates relative to vortex center
x_rel = x_vec[0] - vortex_loc[0]
y_rel = x_vec[1] - vortex_loc[1]
# Y.C. Zhou, G.W. Wei / Journal of Computational Physics 189 (2003) 159
# also JSH/TW Nodal DG Methods, p. 209
from math import pi
r = numpy.sqrt(x_rel**2+y_rel**2)
expterm = self.beta*numpy.exp(1-r**2)
u = self.velocity[0] - expterm*y_rel/(2*pi)
v = self.velocity[1] + expterm*x_rel/(2*pi)
rho = (1-(self.gamma-1)/(16*self.gamma*pi**2)*expterm**2)**(1/(self.gamma-1))
p = rho**self.gamma
e = p/(self.gamma-1) + rho/2*(u**2+v**2)
from grudge.tools import join_fields
return join_fields(rho, e, rho*u, rho*v)
def volume_interpolant(self, t, discr):
return discr.convert_volume(
self(t, discr.nodes.T
.astype(discr.default_scalar_type)),
kind=discr.compute_kind)
def boundary_interpolant(self, t, discr, tag):
return discr.convert_boundary(
self(t, discr.get_boundary(tag).nodes.T
.astype(discr.default_scalar_type)),
tag=tag, kind=discr.compute_kind)
class Vortex:
def __init__(self):
self.beta = 5
self.gamma = 1.4
self.center = numpy.array([5, 0])
self.velocity = numpy.array([1, 0])
self.final_time = 0.5
self.mu = 0
self.prandtl = 0.72
self.spec_gas_const = 287.1
def __call__(self, t, x_vec):
vortex_loc = self.center + t*self.velocity
# coordinates relative to vortex center
x_rel = x_vec[0] - vortex_loc[0]
y_rel = x_vec[1] - vortex_loc[1]
# Y.C. Zhou, G.W. Wei / Journal of Computational Physics 189 (2003) 159
# also JSH/TW Nodal DG Methods, p. 209
from math import pi
r = numpy.sqrt(x_rel**2+y_rel**2)
expterm = self.beta*numpy.exp(1-r**2)
u = self.velocity[0] - expterm*y_rel/(2*pi)
v = self.velocity[1] + expterm*x_rel/(2*pi)
rho = (1-(self.gamma-1)/(16*self.gamma*pi**2)*expterm**2)**(1/(self.gamma-1))
p = rho**self.gamma
e = p/(self.gamma-1) + rho/2*(u**2+v**2)
from grudge.tools import join_fields
return join_fields(rho, e, rho*u, rho*v)
def volume_interpolant(self, t, discr):
return discr.convert_volume(
self(t, discr.nodes.T
.astype(discr.default_scalar_type)),
kind=discr.compute_kind)
def boundary_interpolant(self, t, discr, tag):
return discr.convert_boundary(
self(t, discr.get_boundary(tag).nodes.T
.astype(discr.default_scalar_type)),
tag=tag, kind=discr.compute_kind)
__copyright__ = "Copyright (C) 2011 Andreas Kloeckner"
__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 __future__ import division
from __future__ import absolute_import
from __future__ import print_function
import numpy as np
import numpy.linalg as la
from six.moves import range
def main(write_output=True, dtype=np.float32):
from grudge.backends import guess_run_context
rcon = guess_run_context()
from grudge.mesh.generator import make_rect_mesh
if rcon.is_head_rank:
h_fac = 1
mesh = make_rect_mesh(a=(0,0),b=(1,1), max_area=h_fac**2*1e-4,
periodicity=(True,True),
subdivisions=(int(70/h_fac), int(70/h_fac)))
from grudge.models.gas_dynamics.lbm import \
D2Q9LBMMethod, LatticeBoltzmannOperator
op = LatticeBoltzmannOperator(
D2Q9LBMMethod(), lbm_delta_t=0.001, nu=1e-4)
if rcon.is_head_rank:
print("%d elements" % len(mesh.elements))
mesh_data = rcon.distribute_mesh(mesh)
else:
mesh_data = rcon.receive_mesh()
discr = rcon.make_discretization(mesh_data, order=3,
default_scalar_type=dtype,
debug=["cuda_no_plan"])
from grudge.timestep.runge_kutta import LSRK4TimeStepper
stepper = LSRK4TimeStepper(dtype=dtype,
#vector_primitive_factory=discr.get_vector_primitive_factory()
)
from grudge.visualization import VtkVisualizer
if write_output:
vis = VtkVisualizer(discr, rcon, "fld")
from grudge.data import CompiledExpressionData
def ic_expr(t, x, fields):
from grudge.symbolic import FunctionSymbol
from pymbolic.primitives import IfPositive
from pytools.obj_array import make_obj_array
tanh = FunctionSymbol("tanh")
sin = FunctionSymbol("sin")
rho = 1
u0 = 0.05
w = 0.05
delta = 0.05
from grudge.symbolic.primitives import make_common_subexpression as cse
u = cse(make_obj_array([
IfPositive(x[1]-1/2,
u0*tanh(4*(3/4-x[1])/w),
u0*tanh(4*(x[1]-1/4)/w)),
u0*delta*sin(2*np.pi*(x[0]+1/4))]),
"u")
return make_obj_array([
op.method.f_equilibrium(rho, alpha, u)
for alpha in range(len(op.method))
])
# timestep loop -----------------------------------------------------------
stream_rhs = op.bind_rhs(discr)
collision_update = op.bind(discr, op.collision_update)
get_rho = op.bind(discr, op.rho)
get_rho_u = op.bind(discr, op.rho_u)
f_bar = CompiledExpressionData(ic_expr).volume_interpolant(0, discr)
from grudge.discretization import ExponentialFilterResponseFunction
from grudge.symbolic.operators import FilterOperator
mode_filter = FilterOperator(
ExponentialFilterResponseFunction(min_amplification=0.9, order=4))\
.bind(discr)
final_time = 1000
try:
lbm_dt = op.lbm_delta_t
dg_dt = op.estimate_timestep(discr, stepper=stepper)
print(dg_dt)
dg_steps_per_lbm_step = int(np.ceil(lbm_dt / dg_dt))
dg_dt = lbm_dt / dg_steps_per_lbm_step
lbm_steps = int(final_time // op.lbm_delta_t)
for step in range(lbm_steps):
t = step*lbm_dt
if step % 100 == 0 and write_output:
visf = vis.make_file("fld-%04d" % step)
rho = get_rho(f_bar)
rho_u = get_rho_u(f_bar)
vis.add_data(visf,
[ ("fbar%d" %i,
discr.convert_volume(f_bar_i, "numpy")) for i, f_bar_i in enumerate(f_bar)]+
[
("rho", discr.convert_volume(rho, "numpy")),
("rho_u", discr.convert_volume(rho_u, "numpy")),
],
time=t,
step=step)
visf.close()
print("step=%d, t=%f" % (step, t))
f_bar = collision_update(f_bar)
for substep in range(dg_steps_per_lbm_step):
f_bar = stepper(f_bar, t + substep*dg_dt, dg_dt, stream_rhs)
#f_bar = mode_filter(f_bar)
finally:
if write_output:
vis.close()
discr.close()
if __name__ == "__main__":
main(True)
__copyright__ = "Copyright (C) 2008 Andreas Kloeckner"
__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 __future__ import division
from __future__ import absolute_import
from __future__ import print_function
import numpy
import numpy.linalg as la
from six.moves import range
def make_nacamesh():
def round_trip_connect(seq):
result = []
for i in range(len(seq)):
result.append((i, (i+1)%len(seq)))
return result
pt_back = numpy.array([1,0])
#def max_area(pt):
#max_area_front = 1e-2*la.norm(pt)**2 + 1e-5
#max_area_back = 1e-2*la.norm(pt-pt_back)**2 + 1e-4
#return min(max_area_front, max_area_back)
def max_area(pt):
x = pt[0]
if x < 0:
return 1e-2*la.norm(pt)**2 + 1e-5
elif x > 1:
return 1e-2*la.norm(pt-pt_back)**2 + 1e-5
else:
return 1e-2*pt[1]**2 + 1e-5
def needs_refinement(vertices, area):
barycenter = sum(numpy.array(v) for v in vertices)/3
return bool(area > max_area(barycenter))
from meshpy.naca import get_naca_points
points = get_naca_points(naca_digits="2412", number_of_points=80)
from meshpy.geometry import GeometryBuilder, Marker
from meshpy.triangle import write_gnuplot_mesh
profile_marker = Marker.FIRST_USER_MARKER
builder = GeometryBuilder()
builder.add_geometry(points=points,
facets=round_trip_connect(points),
facet_markers=profile_marker)
builder.wrap_in_box(4, (10, 8))
from meshpy.triangle import MeshInfo, build
mi = MeshInfo()
builder.set(mi)
mi.set_holes([builder.center()])
mesh = build(mi, refinement_func=needs_refinement,
#allow_boundary_steiner=False,
generate_faces=True)
write_gnuplot_mesh("mesh.dat", mesh)
print("%d elements" % len(mesh.elements))
fvi2fm = mesh.face_vertex_indices_to_face_marker
face_marker_to_tag = {
profile_marker: "noslip",
Marker.MINUS_X: "inflow",
Marker.PLUS_X: "outflow",
Marker.MINUS_Y: "inflow",
Marker.PLUS_Y: "inflow"
#Marker.MINUS_Y: "minus_y",
#Marker.PLUS_Y: "plus_y"
}
def bdry_tagger(fvi, el, fn, all_v):
face_marker = fvi2fm[fvi]
return [face_marker_to_tag[face_marker]]
from grudge.mesh import make_conformal_mesh_ext
vertices = numpy.asarray(mesh.points, order="C")
from grudge.mesh.element import Triangle
return make_conformal_mesh_ext(
vertices,
[Triangle(i, el_idx, vertices)
for i, el_idx in enumerate(mesh.elements)],
bdry_tagger,
#periodicity=[None, ("minus_y", "plus_y")]
)
def main():
from grudge.backends import guess_run_context
rcon = guess_run_context()
if rcon.is_head_rank:
mesh = make_nacamesh()
mesh_data = rcon.distribute_mesh(mesh)
else:
mesh_data = rcon.receive_mesh()
from pytools import add_python_path_relative_to_script
add_python_path_relative_to_script("..")
for order in [4]:
from gas_dynamics_initials import UniformMachFlow
uniform_flow = UniformMachFlow()
from grudge.models.gas_dynamics import GasDynamicsOperator, GammaLawEOS
op = GasDynamicsOperator(dimensions=2,
equation_of_state=GammaLawEOS(uniform_flow.gamma),
prandtl=uniform_flow.prandtl,
spec_gas_const=uniform_flow.spec_gas_const, mu=uniform_flow.mu,
bc_inflow=uniform_flow, bc_outflow=uniform_flow, bc_noslip=uniform_flow,
inflow_tag="inflow", outflow_tag="outflow", noslip_tag="noslip")
discr = rcon.make_discretization(mesh_data, order=order,
debug=[
"cuda_no_plan",
#"cuda_dump_kernels",
#"dump_optemplate_stages",
#"dump_dataflow_graph",
#"print_op_code"
],
default_scalar_type=numpy.float32,
tune_for=op.sym_operator())
from grudge.visualization import SiloVisualizer, VtkVisualizer
#vis = VtkVisualizer(discr, rcon, "shearflow-%d" % order)
vis = SiloVisualizer(discr, rcon)
fields = uniform_flow.volume_interpolant(0, discr)
navierstokes_ex = op.bind(discr)
max_eigval = [0]
def rhs(t, q):
ode_rhs, speed = navierstokes_ex(t, q)
max_eigval[0] = speed
return ode_rhs
rhs(0, fields)
if rcon.is_head_rank:
print("---------------------------------------------")
print("order %d" % order)
print("---------------------------------------------")
print("#elements=", len(mesh.elements))
from grudge.timestep.runge_kutta import \
ODE23TimeStepper, LSRK4TimeStepper
stepper = ODE23TimeStepper(dtype=discr.default_scalar_type,
rtol=1e-6,
vector_primitive_factory=discr.get_vector_primitive_factory())
#stepper = LSRK4TimeStepper(dtype=discr.default_scalar_type)
# diagnostics setup ---------------------------------------------------
from logpyle import LogManager, add_general_quantities, \
add_simulation_quantities, add_run_info
logmgr = LogManager("cns-naca-%d.dat" % order, "w", rcon.communicator)
add_run_info(logmgr)
add_general_quantities(logmgr)
add_simulation_quantities(logmgr)
discr.add_instrumentation(logmgr)
stepper.add_instrumentation(logmgr)
from logpyle import LogQuantity
class ChangeSinceLastStep(LogQuantity):
"""Records the change of a variable between a time step and the previous
one"""
def __init__(self, name="change"):
LogQuantity.__init__(self, name, "1", "Change since last time step")
self.old_fields = 0
def __call__(self):
result = discr.norm(fields - self.old_fields)
self.old_fields = fields
return result
#logmgr.add_quantity(ChangeSinceLastStep())
# filter setup-------------------------------------------------------------
from grudge.discretization import Filter, ExponentialFilterResponseFunction
mode_filter = Filter(discr,
ExponentialFilterResponseFunction(min_amplification=0.9,order=4))
# timestep loop -------------------------------------------------------
logmgr.add_watches(["step.max", "t_sim.max", "t_step.max"])
try:
from grudge.timestep import times_and_steps
step_it = times_and_steps(
final_time=200,
#max_steps=500,
logmgr=logmgr,
max_dt_getter=lambda t: next_dt,
taken_dt_getter=lambda: taken_dt)
model_stepper = LSRK4TimeStepper()
next_dt = op.estimate_timestep(discr,
stepper=model_stepper, t=0,
max_eigenvalue=max_eigval[0])
for step, t, dt in step_it:
if step % 10 == 0:
visf = vis.make_file("naca-%d-%06d" % (order, step))
from pyvisfile.silo import DB_VARTYPE_VECTOR
vis.add_data(visf,
[
("rho", discr.convert_volume(op.rho(fields), kind="numpy")),
("e", discr.convert_volume(op.e(fields), kind="numpy")),
("rho_u", discr.convert_volume(op.rho_u(fields), kind="numpy")),
("u", discr.convert_volume(op.u(fields), kind="numpy")),
#("true_rho", op.rho(true_fields)),
#("true_e", op.e(true_fields)),
#("true_rho_u", op.rho_u(true_fields)),
#("true_u", op.u(true_fields)),
#("rhs_rho", discr.convert_volume(op.rho(rhs_fields), kind="numpy")),
#("rhs_e", discr.convert_volume(op.e(rhs_fields), kind="numpy")),
#("rhs_rho_u", discr.convert_volume(op.rho_u(rhs_fields), kind="numpy")),
],
expressions=[
#("diff_rho", "rho-true_rho"),
#("diff_e", "e-true_e"),
#("diff_rho_u", "rho_u-true_rho_u", DB_VARTYPE_VECTOR),
("p", "(0.4)*(e- 0.5*(rho_u*u))"),
],
time=t, step=step
)
visf.close()
fields, t, taken_dt, next_dt = stepper(fields, t, dt, rhs)
fields = mode_filter(fields)
finally:
vis.close()
logmgr.save()
discr.close()
if __name__ == "__main__":
main()
__copyright__ = "Copyright (C) 2008 Andreas Kloeckner"
__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 __future__ import division
from __future__ import absolute_import
from __future__ import print_function
import numpy
import numpy.linalg as la
class SteadyShearFlow:
def __init__(self):
self.gamma = 1.5
self.mu = 0.01
self.prandtl = 0.72
self.spec_gas_const = 287.1
def __call__(self, t, x_vec):
# JSH/TW Nodal DG Methods, p.326
rho = numpy.ones_like(x_vec[0])
rho_u = x_vec[1] * x_vec[1]
rho_v = numpy.zeros_like(x_vec[0])
e = (2 * self.mu * x_vec[0] + 10) / (self.gamma - 1) + x_vec[1]**4 / 2
from grudge.tools import join_fields
return join_fields(rho, e, rho_u, rho_v)
def properties(self):
return(self.gamma, self.mu, self.prandtl, self.spec_gas_const)
def volume_interpolant(self, t, discr):
return discr.convert_volume(
self(t, discr.nodes.T
.astype(discr.default_scalar_type)),
kind=discr.compute_kind)
def boundary_interpolant(self, t, discr, tag):
result = discr.convert_boundary(
self(t, discr.get_boundary(tag).nodes.T
.astype(discr.default_scalar_type)),
tag=tag, kind=discr.compute_kind)
return result
def main():
from grudge.backends import guess_run_context
rcon = guess_run_context(
#["cuda"]
)
from grudge.tools import EOCRecorder, to_obj_array
eoc_rec = EOCRecorder()
def boundary_tagger(vertices, el, face_nr, all_v):
return ["inflow"]
if rcon.is_head_rank:
from grudge.mesh import make_rect_mesh, \
make_centered_regular_rect_mesh
#mesh = make_rect_mesh((0,0), (10,1), max_area=0.01)
refine = 1
mesh = make_centered_regular_rect_mesh((0,0), (10,1), n=(20,4),
#periodicity=(True, False),
post_refine_factor=refine,
boundary_tagger=boundary_tagger)
mesh_data = rcon.distribute_mesh(mesh)
else:
mesh_data = rcon.receive_mesh()
for order in [3]:
discr = rcon.make_discretization(mesh_data, order=order,
default_scalar_type=numpy.float64)
from grudge.visualization import SiloVisualizer, VtkVisualizer
#vis = VtkVisualizer(discr, rcon, "shearflow-%d" % order)
vis = SiloVisualizer(discr, rcon)
shearflow = SteadyShearFlow()
fields = shearflow.volume_interpolant(0, discr)
gamma, mu, prandtl, spec_gas_const = shearflow.properties()
from grudge.models.gas_dynamics import GasDynamicsOperator
op = GasDynamicsOperator(dimensions=2, gamma=gamma, mu=mu,
prandtl=prandtl, spec_gas_const=spec_gas_const,
bc_inflow=shearflow, bc_outflow=shearflow, bc_noslip=shearflow,
inflow_tag="inflow", outflow_tag="outflow", noslip_tag="noslip")
navierstokes_ex = op.bind(discr)
max_eigval = [0]
def rhs(t, q):
ode_rhs, speed = navierstokes_ex(t, q)
max_eigval[0] = speed
return ode_rhs
# needed to get first estimate of maximum eigenvalue
rhs(0, fields)
if rcon.is_head_rank:
print("---------------------------------------------")
print("order %d" % order)
print("---------------------------------------------")
print("#elements=", len(mesh.elements))
from grudge.timestep import RK4TimeStepper
stepper = RK4TimeStepper()
# diagnostics setup ---------------------------------------------------
from logpyle import LogManager, add_general_quantities, \
add_simulation_quantities, add_run_info
logmgr = LogManager("navierstokes-cpu-%d-%d.dat" % (order, refine),
"w", rcon.communicator)
add_run_info(logmgr)
add_general_quantities(logmgr)
add_simulation_quantities(logmgr)
discr.add_instrumentation(logmgr)
stepper.add_instrumentation(logmgr)
logmgr.add_watches(["step.max", "t_sim.max", "t_step.max"])
# timestep loop -------------------------------------------------------
try:
from grudge.timestep import times_and_steps
step_it = times_and_steps(
final_time=0.3,
#max_steps=500,
logmgr=logmgr,
max_dt_getter=lambda t: op.estimate_timestep(discr,
stepper=stepper, t=t, max_eigenvalue=max_eigval[0]))
for step, t, dt in step_it:
if step % 10 == 0:
#if False:
visf = vis.make_file("shearflow-%d-%04d" % (order, step))
#true_fields = shearflow.volume_interpolant(t, discr)
from pyvisfile.silo import DB_VARTYPE_VECTOR
vis.add_data(visf,
[
("rho", discr.convert_volume(op.rho(fields), kind="numpy")),
("e", discr.convert_volume(op.e(fields), kind="numpy")),
("rho_u", discr.convert_volume(op.rho_u(fields), kind="numpy")),
("u", discr.convert_volume(op.u(fields), kind="numpy")),
#("true_rho", discr.convert_volume(op.rho(true_fields), kind="numpy")),
#("true_e", discr.convert_volume(op.e(true_fields), kind="numpy")),
#("true_rho_u", discr.convert_volume(op.rho_u(true_fields), kind="numpy")),
#("true_u", discr.convert_volume(op.u(true_fields), kind="numpy")),
],
expressions=[
#("diff_rho", "rho-true_rho"),
#("diff_e", "e-true_e"),
#("diff_rho_u", "rho_u-true_rho_u", DB_VARTYPE_VECTOR),
("p", "0.4*(e- 0.5*(rho_u*u))"),
],
time=t, step=step
)
visf.close()
fields = stepper(fields, t, dt, rhs)
true_fields = shearflow.volume_interpolant(t, discr)
l2_error = discr.norm(op.u(fields)-op.u(true_fields))
eoc_rec.add_data_point(order, l2_error)
print()
print(eoc_rec.pretty_print("P.Deg.", "L2 Error"))
logmgr.set_constant("l2_error", l2_error)
finally:
vis.close()
logmgr.save()
discr.close()
if __name__ == "__main__":
main()
__copyright__ = "Copyright (C) 2008 Andreas Kloeckner"
__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 __future__ import division
from __future__ import absolute_import
from __future__ import print_function
import numpy
import numpy.linalg as la
from six.moves import range
def make_squaremesh():
def round_trip_connect(seq):
result = []
for i in range(len(seq)):
result.append((i, (i+1)%len(seq)))
return result
def needs_refinement(vertices, area):
x = sum(numpy.array(v) for v in vertices)/3
max_area_volume = 0.7e-2 + 0.03*(0.05*x[1]**2 + 0.3*min(x[0]+1,0)**2)
max_area_corners = 1e-3 + 0.001*max(
la.norm(x-corner)**4 for corner in obstacle_corners)
return bool(area > 2.5*min(max_area_volume, max_area_corners))
from meshpy.geometry import make_box
points, facets, _, _ = make_box((-0.5,-0.5), (0.5,0.5))
obstacle_corners = points[:]
from meshpy.geometry import GeometryBuilder, Marker
profile_marker = Marker.FIRST_USER_MARKER
builder = GeometryBuilder()
builder.add_geometry(points=points, facets=facets,
facet_markers=profile_marker)
points, facets, _, facet_markers = make_box((-16, -22), (25, 22))
builder.add_geometry(points=points, facets=facets,
facet_markers=facet_markers)
from meshpy.triangle import MeshInfo, build
mi = MeshInfo()
builder.set(mi)
mi.set_holes([(0,0)])
mesh = build(mi, refinement_func=needs_refinement,
allow_boundary_steiner=True,
generate_faces=True)
print("%d elements" % len(mesh.elements))
from meshpy.triangle import write_gnuplot_mesh
write_gnuplot_mesh("mesh.dat", mesh)
fvi2fm = mesh.face_vertex_indices_to_face_marker
face_marker_to_tag = {
profile_marker: "noslip",
Marker.MINUS_X: "inflow",
Marker.PLUS_X: "outflow",
Marker.MINUS_Y: "inflow",
Marker.PLUS_Y: "inflow"
}
def bdry_tagger(fvi, el, fn, all_v):
face_marker = fvi2fm[fvi]
return [face_marker_to_tag[face_marker]]
from grudge.mesh import make_conformal_mesh_ext
vertices = numpy.asarray(mesh.points, dtype=float, order="C")
from grudge.mesh.element import Triangle
return make_conformal_mesh_ext(
vertices,
[Triangle(i, el_idx, vertices)
for i, el_idx in enumerate(mesh.elements)],
bdry_tagger)
def main():
import logging
logging.basicConfig(level=logging.INFO)
from grudge.backends import guess_run_context
rcon = guess_run_context()
if rcon.is_head_rank:
if True:
mesh = make_squaremesh()
else:
from grudge.mesh import make_rect_mesh
mesh = make_rect_mesh(
boundary_tagger=lambda fvi, el, fn, all_v: ["inflow"],
max_area=0.1)
mesh_data = rcon.distribute_mesh(mesh)
else:
mesh_data = rcon.receive_mesh()
from pytools import add_python_path_relative_to_script
add_python_path_relative_to_script(".")
for order in [3]:
from gas_dynamics_initials import UniformMachFlow
square = UniformMachFlow(gaussian_pulse_at=numpy.array([-2, 2]),
pulse_magnitude=0.003)
from grudge.models.gas_dynamics import (
GasDynamicsOperator,
GammaLawEOS)
op = GasDynamicsOperator(dimensions=2,
equation_of_state=GammaLawEOS(square.gamma), mu=square.mu,
prandtl=square.prandtl, spec_gas_const=square.spec_gas_const,
bc_inflow=square, bc_outflow=square, bc_noslip=square,
inflow_tag="inflow", outflow_tag="outflow", noslip_tag="noslip")
discr = rcon.make_discretization(mesh_data, order=order,
debug=["cuda_no_plan",
"cuda_dump_kernels",
#"dump_dataflow_graph",
#"dump_optemplate_stages",
#"dump_dataflow_graph",
#"dump_op_code"
#"cuda_no_plan_el_local"
],
default_scalar_type=numpy.float64,
tune_for=op.sym_operator(),
quad_min_degrees={
"gasdyn_vol": 3*order,
"gasdyn_face": 3*order,
}
)
from grudge.visualization import SiloVisualizer, VtkVisualizer
#vis = VtkVisualizer(discr, rcon, "shearflow-%d" % order)
vis = SiloVisualizer(discr, rcon)
from grudge.timestep.runge_kutta import (
LSRK4TimeStepper, ODE23TimeStepper, ODE45TimeStepper)
from grudge.timestep.dumka3 import Dumka3TimeStepper
#stepper = LSRK4TimeStepper(dtype=discr.default_scalar_type,
#vector_primitive_factory=discr.get_vector_primitive_factory())
stepper = ODE23TimeStepper(dtype=discr.default_scalar_type,
rtol=1e-6,
vector_primitive_factory=discr.get_vector_primitive_factory())
# Dumka works kind of poorly
#stepper = Dumka3TimeStepper(dtype=discr.default_scalar_type,
#rtol=1e-7, pol_index=2,
#vector_primitive_factory=discr.get_vector_primitive_factory())
#from grudge.timestep.dumka3 import Dumka3TimeStepper
#stepper = Dumka3TimeStepper(3, rtol=1e-7)
# diagnostics setup ---------------------------------------------------
from logpyle import LogManager, add_general_quantities, \
add_simulation_quantities, add_run_info
logmgr = LogManager("cns-square-sp-%d.dat" % order, "w", rcon.communicator)
add_run_info(logmgr)
add_general_quantities(logmgr)
discr.add_instrumentation(logmgr)
stepper.add_instrumentation(logmgr)
from logpyle import LogQuantity
class ChangeSinceLastStep(LogQuantity):
"""Records the change of a variable between a time step and the previous
one"""
def __init__(self, name="change"):
LogQuantity.__init__(self, name, "1", "Change since last time step")
self.old_fields = 0
def __call__(self):
result = discr.norm(fields - self.old_fields)
self.old_fields = fields
return result
#logmgr.add_quantity(ChangeSinceLastStep())
add_simulation_quantities(logmgr)
logmgr.add_watches(["step.max", "t_sim.max", "t_step.max"])
# filter setup ------------------------------------------------------------
from grudge.discretization import Filter, ExponentialFilterResponseFunction
mode_filter = Filter(discr,
ExponentialFilterResponseFunction(min_amplification=0.95, order=6))
# timestep loop -------------------------------------------------------
fields = square.volume_interpolant(0, discr)
navierstokes_ex = op.bind(discr)
max_eigval = [0]
def rhs(t, q):
ode_rhs, speed = navierstokes_ex(t, q)
max_eigval[0] = speed
return ode_rhs
rhs(0, fields)
if rcon.is_head_rank:
print("---------------------------------------------")
print("order %d" % order)
print("---------------------------------------------")
print("#elements=", len(mesh.elements))
try:
from grudge.timestep import times_and_steps
step_it = times_and_steps(
final_time=1000,
#max_steps=500,
logmgr=logmgr,
max_dt_getter=lambda t: next_dt,
taken_dt_getter=lambda: taken_dt)
model_stepper = LSRK4TimeStepper()
next_dt = op.estimate_timestep(discr,
stepper=model_stepper, t=0,
max_eigenvalue=max_eigval[0])
for step, t, dt in step_it:
#if (step % 10000 == 0): #and step < 950000) or (step % 500 == 0 and step > 950000):
#if False:
if step % 5 == 0:
visf = vis.make_file("square-%d-%06d" % (order, step))
#from pyvisfile.silo import DB_VARTYPE_VECTOR
vis.add_data(visf,
[
("rho", discr.convert_volume(op.rho(fields), kind="numpy")),
("e", discr.convert_volume(op.e(fields), kind="numpy")),
("rho_u", discr.convert_volume(op.rho_u(fields), kind="numpy")),
("u", discr.convert_volume(op.u(fields), kind="numpy")),
],
expressions=[
("p", "(0.4)*(e- 0.5*(rho_u*u))"),
],
time=t, step=step
)
visf.close()
if stepper.adaptive:
fields, t, taken_dt, next_dt = stepper(fields, t, dt, rhs)
else:
taken_dt = dt
fields = stepper(fields, t, dt, rhs)
dt = op.estimate_timestep(discr,
stepper=model_stepper, t=0,
max_eigenvalue=max_eigval[0])
#fields = mode_filter(fields)
finally:
vis.close()
logmgr.save()
discr.close()
if __name__ == "__main__":
main()
__copyright__ = "Copyright (C) 2008 Andreas Kloeckner"
__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 __future__ import division
from __future__ import absolute_import
from __future__ import print_function
import numpy
import numpy.linalg as la
from six.moves import zip
def make_wingmesh():
import numpy
from math import pi, cos, sin
from meshpy.tet import MeshInfo, build
from meshpy.geometry import GeometryBuilder, Marker, \
generate_extrusion, make_box
geob = GeometryBuilder()
profile_marker = Marker.FIRST_USER_MARKER
wing_length = 2
wing_subdiv = 5
rz_points = [
(0, -wing_length*1.05),
(0.7, -wing_length*1.05),
] + [
(r, x) for x, r in zip(
numpy.linspace(-wing_length, 0, wing_subdiv, endpoint=False),
numpy.linspace(0.8, 1, wing_subdiv, endpoint=False))
] + [(1,0)] + [
(r, x) for x, r in zip(
numpy.linspace(wing_length, 0, wing_subdiv, endpoint=False),
numpy.linspace(0.8, 1, wing_subdiv, endpoint=False))
][::-1] + [
(0.7, wing_length*1.05),
(0, wing_length*1.05)
]
from meshpy.naca import get_naca_points
geob.add_geometry(*generate_extrusion(
rz_points=rz_points,
base_shape=get_naca_points("0012", number_of_points=20),
ring_markers=(wing_subdiv*2+4)*[profile_marker]))
def deform_wing(p):
x, y, z = p
return numpy.array([
x + 0.8*abs(z/wing_length)** 1.2,
y + 0.1*abs(z/wing_length)**2,
z])
geob.apply_transform(deform_wing)
points, facets, facet_markers = make_box(
numpy.array([-1.5,-1,-wing_length-1], dtype=numpy.float64),
numpy.array([3,1,wing_length+1], dtype=numpy.float64))
geob.add_geometry(points, facets, facet_markers=facet_markers)
mesh_info = MeshInfo()
geob.set(mesh_info)
mesh_info.set_holes([(0.5,0,0)])
mesh = build(mesh_info)
print("%d elements" % len(mesh.elements))
fvi2fm = mesh.face_vertex_indices_to_face_marker
face_marker_to_tag = {
profile_marker: "noslip",
Marker.MINUS_X: "inflow",
Marker.PLUS_X: "outflow",
Marker.MINUS_Y: "inflow",
Marker.PLUS_Y: "inflow",
Marker.PLUS_Z: "inflow",
Marker.MINUS_Z: "inflow"
}
def bdry_tagger(fvi, el, fn, all_v):
face_marker = fvi2fm[fvi]
return [face_marker_to_tag[face_marker]]
from grudge.mesh import make_conformal_mesh
return make_conformal_mesh(mesh.points, mesh.elements, bdry_tagger)
def main():
from grudge.backends import guess_run_context
rcon = guess_run_context( ["cuda", "mpi"])
if rcon.is_head_rank:
mesh = make_wingmesh()
#from grudge.mesh import make_rect_mesh
#mesh = make_rect_mesh(
# boundary_tagger=lambda fvi, el, fn, all_v: ["inflow"])
mesh_data = rcon.distribute_mesh(mesh)
else:
mesh_data = rcon.receive_mesh()
for order in [3]:
from pytools import add_python_path_relative_to_script
add_python_path_relative_to_script("..")
from gas_dynamics_initials import UniformMachFlow
wing = UniformMachFlow(angle_of_attack=0)
from grudge.models.gas_dynamics import GasDynamicsOperator
op = GasDynamicsOperator(dimensions=3,
gamma=wing.gamma, mu=wing.mu,
prandtl=wing.prandtl, spec_gas_const=wing.spec_gas_const,
bc_inflow=wing, bc_outflow=wing, bc_noslip=wing,
inflow_tag="inflow", outflow_tag="outflow", noslip_tag="noslip")
discr = rcon.make_discretization(mesh_data, order=order,
debug=["cuda_no_plan",
#"cuda_dump_kernels",
#"dump_dataflow_graph",
#"dump_optemplate_stages",
#"dump_dataflow_graph",
#"print_op_code"
"cuda_no_metis",
],
default_scalar_type=numpy.float64,
tune_for=op.sym_operator())
from grudge.visualization import SiloVisualizer, VtkVisualizer
#vis = VtkVisualizer(discr, rcon, "shearflow-%d" % order)
vis = SiloVisualizer(discr, rcon)
fields = wing.volume_interpolant(0, discr)
navierstokes_ex = op.bind(discr)
max_eigval = [0]
def rhs(t, q):
ode_rhs, speed = navierstokes_ex(t, q)
max_eigval[0] = speed
return ode_rhs
rhs(0, fields)
if rcon.is_head_rank:
print("---------------------------------------------")
print("order %d" % order)
print("---------------------------------------------")
print("#elements=", len(mesh.elements))
from grudge.timestep import RK4TimeStepper
stepper = RK4TimeStepper()
# diagnostics setup ---------------------------------------------------
from logpyle import LogManager, add_general_quantities, \
add_simulation_quantities, add_run_info
logmgr = LogManager("navierstokes-%d.dat" % order, "w", rcon.communicator)
add_run_info(logmgr)
add_general_quantities(logmgr)
add_simulation_quantities(logmgr)
discr.add_instrumentation(logmgr)
stepper.add_instrumentation(logmgr)
logmgr.add_watches(["step.max", "t_sim.max", "t_step.max"])
# timestep loop -------------------------------------------------------
try:
from grudge.timestep import times_and_steps
step_it = times_and_steps(
final_time=200,
#max_steps=500,
logmgr=logmgr,
max_dt_getter=lambda t: 0.6 * op.estimate_timestep(discr,
stepper=stepper, t=t, max_eigenvalue=max_eigval[0]))
for step, t, dt in step_it:
if step % 200 == 0:
#if False:
visf = vis.make_file("wing-%d-%06d" % (order, step))
#rhs_fields = rhs(t, fields)
from pyvisfile.silo import DB_VARTYPE_VECTOR
from grudge.discretization import ones_on_boundary
vis.add_data(visf,
[
("rho", discr.convert_volume(op.rho(fields), kind="numpy")),
("e", discr.convert_volume(op.e(fields), kind="numpy")),
("rho_u", discr.convert_volume(op.rho_u(fields), kind="numpy")),
("u", discr.convert_volume(op.u(fields), kind="numpy")),
#("rhs_rho", discr.convert_volume(op.rho(rhs_fields), kind="numpy")),
#("rhs_e", discr.convert_volume(op.e(rhs_fields), kind="numpy")),
#("rhs_rho_u", discr.convert_volume(op.rho_u(rhs_fields), kind="numpy")),
],
expressions=[
("p", "(0.4)*(e- 0.5*(rho_u*u))"),
],
time=t, step=step
)
visf.close()
fields = stepper(fields, t, dt, rhs)
t += dt
finally:
vis.close()
logmgr.save()
discr.close()
if __name__ == "__main__":
main()
from __future__ import absolute_import
from __future__ import print_function
__copyright__ = "Copyright (C) 2007 Andreas Kloeckner"
__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.
"""
import numpy
import numpy.linalg as la
def main(write_output=True) :
from math import sin, cos, pi, exp, sqrt
from grudge.data import TimeConstantGivenFunction, \
ConstantGivenFunction
from grudge.backends import guess_run_context
rcon = guess_run_context()
dim = 2
def boundary_tagger(fvi, el, fn, all_v):
if el.face_normals[fn][0] > 0:
return ["dirichlet"]
else:
return ["neumann"]
if dim == 2:
if rcon.is_head_rank:
from grudge.mesh.generator import make_disk_mesh
mesh = make_disk_mesh(r=0.5, boundary_tagger=boundary_tagger)
elif dim == 3:
if rcon.is_head_rank:
from grudge.mesh.generator import make_ball_mesh
mesh = make_ball_mesh(max_volume=0.001)
else:
raise RuntimeError("bad number of dimensions")
if rcon.is_head_rank:
print("%d elements" % len(mesh.elements))
mesh_data = rcon.distribute_mesh(mesh)
else:
mesh_data = rcon.receive_mesh()
discr = rcon.make_discretization(mesh_data, order=3,
debug=["cuda_no_plan"],
default_scalar_type=numpy.float64)
if write_output:
from grudge.visualization import VtkVisualizer
vis = VtkVisualizer(discr, rcon, "fld")
def u0(x, el):
if la.norm(x) < 0.2:
return 1
else:
return 0
def coeff(x, el):
if x[0] < 0:
return 0.25
else:
return 1
def dirichlet_bc(t, x):
return 0
def neumann_bc(t, x):
return 2
from grudge.models.diffusion import DiffusionOperator
op = DiffusionOperator(discr.dimensions,
#coeff=coeff,
dirichlet_tag="dirichlet",
dirichlet_bc=TimeConstantGivenFunction(ConstantGivenFunction(0)),
neumann_tag="neumann",
neumann_bc=TimeConstantGivenFunction(ConstantGivenFunction(1))
)
u = discr.interpolate_volume_function(u0)
# diagnostics setup -------------------------------------------------------
from logpyle import LogManager, \
add_general_quantities, \
add_simulation_quantities, \
add_run_info
if write_output:
log_file_name = "heat.dat"
else:
log_file_name = None
logmgr = LogManager(log_file_name, "w", rcon.communicator)
add_run_info(logmgr)
add_general_quantities(logmgr)
add_simulation_quantities(logmgr)
discr.add_instrumentation(logmgr)
from grudge.log import LpNorm
u_getter = lambda: u
logmgr.add_quantity(LpNorm(u_getter, discr, 1, name="l1_u"))
logmgr.add_quantity(LpNorm(u_getter, discr, name="l2_u"))
logmgr.add_watches(["step.max", "t_sim.max", "l2_u", "t_step.max"])
# timestep loop -----------------------------------------------------------
from grudge.timestep.runge_kutta import LSRK4TimeStepper, ODE45TimeStepper
from grudge.timestep.dumka3 import Dumka3TimeStepper
#stepper = LSRK4TimeStepper()
stepper = Dumka3TimeStepper(3, rtol=1e-6, rcon=rcon,
vector_primitive_factory=discr.get_vector_primitive_factory(),
dtype=discr.default_scalar_type)
#stepper = ODE45TimeStepper(rtol=1e-6, rcon=rcon,
#vector_primitive_factory=discr.get_vector_primitive_factory(),
#dtype=discr.default_scalar_type)
stepper.add_instrumentation(logmgr)
rhs = op.bind(discr)
try:
next_dt = op.estimate_timestep(discr,
stepper=LSRK4TimeStepper(), t=0, fields=u)
from grudge.timestep import times_and_steps
step_it = times_and_steps(
final_time=0.1, logmgr=logmgr,
max_dt_getter=lambda t: next_dt,
taken_dt_getter=lambda: taken_dt)
for step, t, dt in step_it:
if step % 10 == 0 and write_output:
visf = vis.make_file("fld-%04d" % step)
vis.add_data(visf, [
("u", discr.convert_volume(u, kind="numpy")),
], time=t, step=step)
visf.close()
u, t, taken_dt, next_dt = stepper(u, t, next_dt, rhs)
#u = stepper(u, t, dt, rhs)
assert discr.norm(u) < 1
finally:
if write_output:
vis.close()
logmgr.close()
discr.close()
if __name__ == "__main__":
main()
# entry points for py.test ----------------------------------------------------
from pytools.test import mark_test
@mark_test.long
def test_heat():
main(write_output=False)
bessel_zeros.py
2d_cavity
from __future__ import absolute_import
from six.moves import range
def main():
import scipy.special
maxnu = 10
n_zeros = 20
zeros = []
for n in range(0,maxnu+1):
zeros.append(list(scipy.special.jn_zeros(n, n_zeros)))
outf = open("bessel_zeros.py", "w").write("bessel_zeros = %s" % zeros)
if __name__ == "__main__":
main()
/*
From Robert E. Collin, Field Theory of Guided Waves, p. 413, chaper 6
Find the cut-off frequency of a rectangular waveguide partially filled with a dielectric slab,
in order to find the resonant frequency of an inhomogeneous 2D cavity.
Take (5a), the transcendental equation for h and l, and substitute for their definitions in terms of gamma
Then solve for the condition that gamma is 0, for the mode with m=0.
t - width of dielectric section
d - width of air section
kappa - relative permittivity
k_0 - free space wavenumber
gamma - waveguide wavenumber
l - transverse wavenumber in dielectric
h - transverse wavenumber in air
*/
trans_eq : h*tan(l*t) + l*tan(h*d);
l_gamma : sqrt(gamma^2 - (m*pi/b)^2 + kappa*k_0^2);
h_gamma : sqrt(gamma^2 - (m*pi/b)^2 + k_0^2);
l_simp : l_gamma, gamma=0, m=0;
h_simp : h_gamma, gamma=0, m=0;
subst(h_gamma, h, trans_eq)$
subst(l_gamma, l, %)$
subst(0, m, %)$
trans_eq2 : subst(0, gamma, %);
c : 2.99792458e8$
plot2d([trans_eq2], [f,0.1e9,1.4e9], [y, -1000, 1000]), t = 50e-3, d=100e-3, kappa=2, k_0 = 2*%pi*f/c$
f_sol : find_root(trans_eq2, f, 0.8e9, 1e9), t = 50e-3, d = 100e-3, kappa = 2, k_0 = 2*%pi*f/c;
h_simp: float(2*%pi*f_sol/c);
sqrt(kappa)*2*%pi*f_sol/c, kappa=2$
l_simp: float(%);
%pi*a/(a-d-sqrt(kappa)), a=150e-3, d=100e-3, kappa=2;
float(%);