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
Commits on Source (3)
"""Minimal example of a grudge driver."""
from __future__ import division, print_function
__copyright__ = "Copyright (C) 2015 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 as np
import pyopencl as cl
from grudge.shortcuts import set_up_rk4
from grudge import sym, bind, Discretization
def main(write_output=True, order=4):
cl_ctx = cl.create_some_context()
queue = cl.CommandQueue(cl_ctx)
dims = 2
from meshmode.mesh.generation import generate_regular_rect_mesh
mesh = generate_regular_rect_mesh(
a=(-0.5,)*dims,
b=(0.5,)*dims,
n=(8,)*dims)
discr = Discretization(cl_ctx, mesh, order=order)
source_center = np.array([0.1, 0.22, 0.33])[:mesh.dim]
source_width = 0.05
source_omega = 3
sym_x = sym.nodes(mesh.dim)
sym_source_center_dist = sym_x - source_center
sym_t = sym.ScalarVariable("t")
c = sym.If(sym.Comparison(
np.dot(sym_x, sym_x), "<", 0.2),
-0.1, -0.2)
#c = np.dot(sym_x,sym_x)
from grudge.models.wave import VariableCoefficientWeakWaveOperator
from meshmode.mesh import BTAG_ALL, BTAG_NONE
op = VariableCoefficientWeakWaveOperator(c,
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="central")
queue = cl.CommandQueue(discr.cl_context)
from pytools.obj_array import join_fields
fields = join_fields(discr.zeros(queue),
[discr.zeros(queue) for i in range(discr.dim)])
# FIXME
#dt = op.estimate_rk4_timestep(discr, fields=fields)
op.check_bc_coverage(mesh)
# print(sym.pretty(op.sym_operator()))
bound_op = bind(discr, op.sym_operator())
print(bound_op)
# 1/0
def rhs(t, w):
return bound_op(queue, t=t, w=w)
if mesh.dim == 2:
dt = 0.04
elif mesh.dim == 3:
dt = 0.02
dt_stepper = set_up_rk4("w", dt, fields, rhs)
final_t = 10
nsteps = int(final_t/dt)
print("dt=%g nsteps=%d" % (dt, nsteps))
from grudge.shortcuts import make_visualizer
vis = make_visualizer(discr, vis_order=order)
step = 0
norm = bind(discr, sym.norm(2, sym.var("u")))
from time import time
t_last_step = time()
for event in dt_stepper.run(t_end=final_t):
if isinstance(event, dt_stepper.StateComputed):
assert event.component_id == "w"
step += 1
print(step, event.t, norm(queue, u=event.state_component[0]),
time()-t_last_step)
if step % 10 == 0:
vis.write_vtk_file("fld-%04d.vtu" % step,
[
("u", event.state_component[0]),
("v", event.state_component[1:]),
])
t_last_step = time()
if __name__ == "__main__":
main()
"""Minimal example of a grudge driver."""
from __future__ import division, print_function
__copyright__ = "Copyright (C) 2015 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 as np
import pyopencl as cl
from grudge.shortcuts import set_up_rk4
from grudge import sym, bind, Discretization
def main(write_output=True, order=4):
cl_ctx = cl.create_some_context()
queue = cl.CommandQueue(cl_ctx)
dims = 2
from meshmode.mesh.generation import generate_regular_rect_mesh
mesh = generate_regular_rect_mesh(
a=(-0.5,)*dims,
b=(0.5,)*dims,
n=(8,)*dims)
discr = Discretization(cl_ctx, mesh, order=order)
source_center = np.array([0.1, 0.22, 0.33])[:mesh.dim]
source_width = 0.05
source_omega = 3
sym_x = sym.nodes(mesh.dim)
sym_source_center_dist = sym_x - source_center
sym_t = sym.ScalarVariable("t")
from grudge.models.wave import WeakWaveOperator
from meshmode.mesh import BTAG_ALL, BTAG_NONE
op = WeakWaveOperator(-0.1, 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")
queue = cl.CommandQueue(discr.cl_context)
from pytools.obj_array import join_fields
fields = join_fields(discr.zeros(queue),
[discr.zeros(queue) for i in range(discr.dim)])
# FIXME
#dt = op.estimate_rk4_timestep(discr, fields=fields)
op.check_bc_coverage(mesh)
# print(sym.pretty(op.sym_operator()))
bound_op = bind(discr, op.sym_operator())
print(bound_op)
# 1/0
def rhs(t, w):
return bound_op(queue, t=t, w=w)
if mesh.dim == 2:
dt = 0.04
elif mesh.dim == 3:
dt = 0.02
dt_stepper = set_up_rk4("w", dt, fields, rhs)
final_t = 10
nsteps = int(final_t/dt)
print("dt=%g nsteps=%d" % (dt, nsteps))
from grudge.shortcuts import make_visualizer
vis = make_visualizer(discr, vis_order=order)
step = 0
norm = bind(discr, sym.norm(2, sym.var("u")))
from time import time
t_last_step = time()
for event in dt_stepper.run(t_end=final_t):
if isinstance(event, dt_stepper.StateComputed):
assert event.component_id == "w"
step += 1
print(step, event.t, norm(queue, u=event.state_component[0]),
time()-t_last_step)
if step % 10 == 0:
vis.write_vtk_file("fld-%04d.vtu" % step,
[
("u", event.state_component[0]),
("v", event.state_component[1:]),
])
t_last_step = time()
if __name__ == "__main__":
main()
...@@ -119,6 +119,17 @@ class ExecutionMapper(mappers.Evaluator, ...@@ -119,6 +119,17 @@ class ExecutionMapper(mappers.Evaluator,
then = self.rec(expr.then) then = self.rec(expr.then)
else_ = self.rec(expr.else_) else_ = self.rec(expr.else_)
if (type(then) is not pyopencl.array.Array):
fill_val = then
then = cl.array.empty(self.queue,bool_crit.shape, dtype=np.float32) #what type should this be lol?
then.fill(fill_val)
if (type(else_) is not pyopencl.array.Array):
fill_val = else_
else_ = cl.array.empty(self.queue,bool_crit.shape, dtype=np.float32)
else_.fill(fill_val)
result = cl.array.empty_like(then, queue=self.queue, result = cl.array.empty_like(then, queue=self.queue,
allocator=self.bound_op.allocator) allocator=self.bound_op.allocator)
cl.array.if_positive(bool_crit, then, else_, out=result, cl.array.if_positive(bool_crit, then, else_, out=result,
......
...@@ -180,187 +180,325 @@ class StrongWaveOperator(HyperbolicOperator): ...@@ -180,187 +180,325 @@ class StrongWaveOperator(HyperbolicOperator):
def max_eigenvalue(self, t, fields=None, discr=None): def max_eigenvalue(self, t, fields=None, discr=None):
return abs(self.c) return abs(self.c)
# }}} class WeakWaveOperator(HyperbolicOperator):
"""This operator discretizes the wave equation
:math:`\\partial_t^2 u = c^2 \\Delta u`.
# {{{ variable-velocity
class VariableVelocityStrongWaveOperator(HyperbolicOperator):
r"""This operator discretizes the wave equation
:math:`\partial_t^2 u = c^2 \Delta u`.
To be precise, we discretize the hyperbolic system To be precise, we discretize the hyperbolic system
.. math:: .. math::
\partial_t u - c \nabla \cdot v = 0 \partial_t u - c \\nabla \\cdot v = 0
\partial_t v - c \\nabla u = 0
The sign of :math:`v` determines whether we discretize the forward or the
backward wave equation.
\partial_t v - c \nabla u = 0 :math:`c` is assumed to be constant across all space.
""" """
def __init__( def __init__(self, c, ambient_dim, source_f=0,
self, c, ambient_dim, source=0,
flux_type="upwind", flux_type="upwind",
dirichlet_tag=BTAG_ALL, dirichlet_tag=BTAG_ALL,
dirichlet_bc_f=0,
neumann_tag=BTAG_NONE, neumann_tag=BTAG_NONE,
radiation_tag=BTAG_NONE, radiation_tag=BTAG_NONE):
time_sign=1,
diffusion_coeff=None,
diffusion_scheme=CentralSecondDerivative()
):
"""*c* and *source* are optemplate expressions.
"""
assert isinstance(ambient_dim, int) assert isinstance(ambient_dim, int)
self.c = c self.c = c
self.time_sign = time_sign
self.ambient_dim = ambient_dim self.ambient_dim = ambient_dim
self.source = source self.source_f = source_f
if self.c > 0:
self.sign = 1
else:
self.sign = -1
self.dirichlet_tag = dirichlet_tag self.dirichlet_tag = dirichlet_tag
self.neumann_tag = neumann_tag self.neumann_tag = neumann_tag
self.radiation_tag = radiation_tag self.radiation_tag = radiation_tag
self.flux_type = flux_type self.dirichlet_bc_f = dirichlet_bc_f
self.diffusion_coeff = diffusion_coeff self.flux_type = flux_type
self.diffusion_scheme = diffusion_scheme
# {{{ flux ---------------------------------------------------------------- def flux(self, w):
def flux(self, w, c_vol):
u = w[0] u = w[0]
v = w[1:] v = w[1:]
normal = sym.normal(w.tag, self.ambient_dim) normal = sym.normal(w.dd, self.ambient_dim)
c = sym.RestrictToBoundary(w.tag)(c_vol) flux_weak = join_fields(
np.dot(v.avg, normal),
u.avg * normal)
flux = self.time_sign*1/2*join_fields(
c.ext * np.dot(v.ext, normal)
- c.int * np.dot(v.int, normal),
normal*(c.ext*u.ext - c.int*u.int))
if self.flux_type == "central": if self.flux_type == "central":
pass return -self.c*flux_weak
elif self.flux_type == "upwind": elif self.flux_type == "upwind":
flux += join_fields( return -self.c*(flux_weak + self.sign*join_fields(
c.ext*u.ext - c.int*u.int, 0.5*(u.int-u.ext),
c.ext*normal*np.dot(normal, v.ext) 0.5*(normal * np.dot(normal, v.int-v.ext))))
- c.int*normal*np.dot(normal, v.int) # see doc/notes/grudge-notes.tm
) # THis is terrible
#flux_weak -= self.sign*join_fields(
#0.5*(u.int-u.ext),
#0.5*(normal * np.dot(normal, v.int-v.ext)))
#else:
#raise ValueError("invalid flux type '%s'" % self.flux_type)
#flux_strong = join_fields(
#np.dot(v.int, normal),
#u.int * normal) - flux_weak
#return self.c*flux_strong
def sym_operator(self):
d = self.ambient_dim
w = sym.make_sym_array("w", d+1)
u = w[0]
v = w[1:]
# boundary conditions -------------------------------------------------
# dirichlet BCs -------------------------------------------------------
dir_u = sym.cse(sym.interp("vol", self.dirichlet_tag)(u))
dir_v = sym.cse(sym.interp("vol", self.dirichlet_tag)(v))
if self.dirichlet_bc_f:
# FIXME
from warnings import warn
warn("Inhomogeneous Dirichlet conditions on the wave equation "
"are still having issues.")
dir_g = sym.Field("dir_bc_u")
dir_bc = join_fields(2*dir_g - dir_u, dir_v)
else: else:
raise ValueError("invalid flux type '%s'" % self.flux_type) dir_bc = join_fields(-dir_u, dir_v)
dir_bc = sym.cse(dir_bc, "dir_bc")
# neumann BCs ---------------------------------------------------------
neu_u = sym.cse(sym.interp("vol", self.neumann_tag)(u))
neu_v = sym.cse(sym.interp("vol", self.neumann_tag)(v))
neu_bc = sym.cse(join_fields(neu_u, -neu_v), "neu_bc")
# radiation BCs -------------------------------------------------------
rad_normal = sym.normal(self.radiation_tag, d)
rad_u = sym.cse(sym.interp("vol", self.radiation_tag)(u))
rad_v = sym.cse(sym.interp("vol", self.radiation_tag)(v))
return flux rad_bc = sym.cse(join_fields(
0.5*(rad_u - self.sign*np.dot(rad_normal, rad_v)),
0.5*rad_normal*(np.dot(rad_normal, rad_v) - self.sign*rad_u)
), "rad_bc")
# }}} # entire operator -----------------------------------------------------
nabla = sym.nabla(d)
def bind_characteristic_velocity(self, discr): def flux(pair):
from grudge.symbolic.operators import ElementwiseMaxOperator return sym.interp(pair.dd, "all_faces")(self.flux(pair))
#result = (
#- join_fields(
#-self.c*np.dot(nabla, v),
#-self.c*(nabla*u)
#)
#+
#sym.InverseMassOperator()(
#sym.FaceMassOperator()(
#flux(sym.int_tpair(w))
#+ flux(sym.bv_tpair(self.dirichlet_tag, w, dir_bc))
#+ flux(sym.bv_tpair(self.neumann_tag, w, neu_bc))
#+ flux(sym.bv_tpair(self.radiation_tag, w, rad_bc))
#)))
result = sym.InverseMassOperator()(
join_fields(
-self.c*np.dot(sym.stiffness_t(self.ambient_dim), v),
-self.c*(sym.stiffness_t(self.ambient_dim)*u)
)
compiled = discr.compile(ElementwiseMaxOperator()(self.c))
def do(t, w, **extra_context): - sym.FaceMassOperator()( flux(sym.int_tpair(w))
return compiled(t=t, w=w, **extra_context) + flux(sym.bv_tpair(self.dirichlet_tag, w, dir_bc))
+ flux(sym.bv_tpair(self.neumann_tag, w, neu_bc))
+ flux(sym.bv_tpair(self.radiation_tag, w, rad_bc))
return do ) )
def sym_operator(self, with_sensor=False): result[0] += self.source_f
d = self.ambient_dim
w = sym.make_sym_array("w", d+1) return result
u = w[0]
v = w[1:] def check_bc_coverage(self, mesh):
from meshmode.mesh import check_bc_coverage
check_bc_coverage(mesh, [
self.dirichlet_tag,
self.neumann_tag,
self.radiation_tag])
def max_eigenvalue(self, t, fields=None, discr=None):
return abs(self.c)
flux_w = join_fields(self.c, w)
# {{{ boundary conditions # }}}
# Dirichlet
dir_c = sym.RestrictToBoundary(self.dirichlet_tag) * self.c
dir_u = sym.RestrictToBoundary(self.dirichlet_tag) * u
dir_v = sym.RestrictToBoundary(self.dirichlet_tag) * v
dir_bc = join_fields(dir_c, -dir_u, dir_v) # {{{ variable-velocity
# Neumann class VariableCoefficientWeakWaveOperator(HyperbolicOperator):
neu_c = sym.RestrictToBoundary(self.neumann_tag) * self.c """This operator discretizes the wave equation
neu_u = sym.RestrictToBoundary(self.neumann_tag) * u :math:`\\partial_t^2 u = c^2 \\Delta u`.
neu_v = sym.RestrictToBoundary(self.neumann_tag) * v
neu_bc = join_fields(neu_c, neu_u, -neu_v) To be precise, we discretize the hyperbolic system
# Radiation .. math::
rad_normal = sym.make_normal(self.radiation_tag, d)
rad_c = sym.RestrictToBoundary(self.radiation_tag) * self.c \partial_t u - c \\nabla \\cdot v = 0
rad_u = sym.RestrictToBoundary(self.radiation_tag) * u
rad_v = sym.RestrictToBoundary(self.radiation_tag) * v
rad_bc = join_fields( \partial_t v - c \\nabla u = 0
rad_c,
0.5*(rad_u - self.time_sign*np.dot(rad_normal, rad_v)),
0.5*rad_normal*(np.dot(rad_normal, rad_v) - self.time_sign*rad_u)
)
# }}} The sign of :math:`v` determines whether we discretize the forward or the
backward wave equation.
# {{{ diffusion ------------------------------------------------------- :math:`c` is assumed to be constant across all space.
from pytools.obj_array import with_object_array_or_scalar """
def make_diffusion(arg): def __init__(self, c, ambient_dim, source_f=0,
if with_sensor or ( flux_type="upwind",
self.diffusion_coeff is not None and self.diffusion_coeff != 0): dirichlet_tag=BTAG_ALL,
if self.diffusion_coeff is None: dirichlet_bc_f=0,
diffusion_coeff = 0 neumann_tag=BTAG_NONE,
else: radiation_tag=BTAG_NONE):
diffusion_coeff = self.diffusion_coeff assert isinstance(ambient_dim, int)
if with_sensor: self.c = c
diffusion_coeff += sym.Field("sensor") self.ambient_dim = ambient_dim
self.source_f = source_f
from grudge.second_order import SecondDerivativeTarget self.sign = sym.If(sym.Comparison(
self.c, ">", 0),
1, -1)
# strong_form here allows the reuse the value of grad u. self.dirichlet_tag = dirichlet_tag
grad_tgt = SecondDerivativeTarget( self.neumann_tag = neumann_tag
self.ambient_dim, strong_form=True, self.radiation_tag = radiation_tag
operand=arg)
self.diffusion_scheme.grad(grad_tgt, bc_getter=None, self.dirichlet_bc_f = dirichlet_bc_f
dirichlet_tags=[], neumann_tags=[])
self.flux_type = flux_type
def flux(self, w):
u = w[0]
v = w[1:]
normal = sym.normal(w.dd, self.ambient_dim)
surf_c = sym.interp("vol", u.dd)(self.c)
flux_weak = join_fields(
np.dot(v.avg, normal),
u.avg * normal)
return -surf_c*flux_weak
if self.flux_type == "central":
return -surf_c*flux_weak
#elif self.flux_type == "upwind":
# see doc/notes/grudge-notes.tm
#flux_weak -= self.sign*join_fields(
#0.5*(u.int-u.ext),
#0.5*(normal * np.dot(normal, v.int-v.ext)))
#else:
#raise ValueError("invalid flux type '%s'" % self.flux_type)
#flux_strong = join_fields(
#np.dot(v.int, normal),
#u.int * normal) - flux_weak
div_tgt = SecondDerivativeTarget( #return self.c*flux_strong
self.ambient_dim, strong_form=False,
operand=diffusion_coeff*grad_tgt.minv_all)
self.diffusion_scheme.div(div_tgt, def sym_operator(self):
bc_getter=None, d = self.ambient_dim
dirichlet_tags=[], neumann_tags=[])
return div_tgt.minv_all w = sym.make_sym_array("w", d+1)
else: u = w[0]
return 0 v = w[1:]
# }}} # boundary conditions -------------------------------------------------
# dirichlet BCs -------------------------------------------------------
dir_u = sym.cse(sym.interp("vol", self.dirichlet_tag)(u))
dir_v = sym.cse(sym.interp("vol", self.dirichlet_tag)(v))
if self.dirichlet_bc_f:
# FIXME
from warnings import warn
warn("Inhomogeneous Dirichlet conditions on the wave equation "
"are still having issues.")
dir_g = sym.Field("dir_bc_u")
dir_bc = join_fields(2*dir_g - dir_u, dir_v)
else:
dir_bc = join_fields(-dir_u, dir_v)
dir_bc = sym.cse(dir_bc, "dir_bc")
# neumann BCs ---------------------------------------------------------
neu_u = sym.cse(sym.interp("vol", self.neumann_tag)(u))
neu_v = sym.cse(sym.interp("vol", self.neumann_tag)(v))
neu_bc = sym.cse(join_fields(neu_u, -neu_v), "neu_bc")
# radiation BCs -------------------------------------------------------
rad_normal = sym.normal(self.radiation_tag, d)
rad_u = sym.cse(sym.interp("vol", self.radiation_tag)(u))
rad_v = sym.cse(sym.interp("vol", self.radiation_tag)(v))
rad_bc = sym.cse(join_fields(
0.5*(rad_u - sym.interp("vol",self.radiation_tag)(self.sign)*np.dot(rad_normal, rad_v)),
0.5*rad_normal*(np.dot(rad_normal, rad_v) -sym.interp("vol",self.radiation_tag)(self.sign)*rad_u)
), "rad_bc")
# entire operator ----------------------------------------------------- # entire operator -----------------------------------------------------
nabla = sym.nabla(d) nabla = sym.nabla(d)
flux_op = sym.get_flux_operator(self.flux())
return ( def flux(pair):
- join_fields( return sym.interp(pair.dd, "all_faces")(self.flux(pair))
- self.time_sign*self.c*np.dot(nabla, v) - make_diffusion(u)
+ self.source,
#result = sym.InverseMassOperator()(
#join_fields(
#-self.c*np.dot(sym.stiffness_t(self.ambient_dim), v),
#-self.c*(sym.stiffness_t(self.ambient_dim)*u)
#)
#- sym.FaceMassOperator()( flux(sym.int_tpair(w))
#+ flux(sym.bv_tpair(self.dirichlet_tag, w, dir_bc))
#+ flux(sym.bv_tpair(self.neumann_tag, w, neu_bc))
#+ flux(sym.bv_tpair(self.radiation_tag, w, rad_bc))
-self.time_sign*self.c*(nabla*u) - with_object_array_or_scalar( #)# )
make_diffusion, v)
result = sym.InverseMassOperator()(
join_fields(
-self.c*np.dot(sym.stiffness_t(self.ambient_dim), v),
-self.c*(sym.stiffness_t(self.ambient_dim)*u)
) )
+
sym.InverseMassOperator() * (
flux_op(flux_w) - sym.FaceMassOperator()( flux(sym.int_tpair(w))
+ flux_op(sym.BoundaryPair(flux_w, dir_bc, self.dirichlet_tag)) + flux(sym.bv_tpair(self.dirichlet_tag, w, dir_bc))
+ flux_op(sym.BoundaryPair(flux_w, neu_bc, self.neumann_tag)) + flux(sym.bv_tpair(self.neumann_tag, w, neu_bc))
+ flux_op(sym.BoundaryPair(flux_w, rad_bc, self.radiation_tag)) + flux(sym.bv_tpair(self.radiation_tag, w, rad_bc))
))
) )
result[0] += self.source_f
return result
def check_bc_coverage(self, mesh): def check_bc_coverage(self, mesh):
from meshmode.mesh import check_bc_coverage from meshmode.mesh import check_bc_coverage
...@@ -369,9 +507,9 @@ class VariableVelocityStrongWaveOperator(HyperbolicOperator): ...@@ -369,9 +507,9 @@ class VariableVelocityStrongWaveOperator(HyperbolicOperator):
self.neumann_tag, self.neumann_tag,
self.radiation_tag]) self.radiation_tag])
def max_eigenvalue_expr(self): def max_eigenvalue(self, t, fields=None, discr=None):
import grudge.symbolic as sym return abs(self.c)
return sym.NodalMax()(sym.CFunction("fabs")(self.c))
# }}} # }}}
......