From ecaf17d9dc926cfa39b536163086c0193ea6f276 Mon Sep 17 00:00:00 2001 From: Thomas Gibson <gibsonthomas1120@hotmail.com> Date: Fri, 14 May 2021 11:22:57 -0500 Subject: [PATCH] Convert constant-coefficient advection model --- grudge/models/advection.py | 173 +++++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 67 deletions(-) diff --git a/grudge/models/advection.py b/grudge/models/advection.py index 980425e5..a6a3175f 100644 --- a/grudge/models/advection.py +++ b/grudge/models/advection.py @@ -1,6 +1,9 @@ """Operators modeling advective phenomena.""" -__copyright__ = "Copyright (C) 2009-2017 Andreas Kloeckner, Bogdan Enache" +__copyright__ = """ +Copyright (C) 2009-2017 Andreas Kloeckner, Bogdan Enache +Copyright (C) 2021 University of Illinois Board of Trustees +""" __license__ = """ Permission is hereby granted, free of charge, to any person obtaining a copy @@ -25,29 +28,36 @@ THE SOFTWARE. import numpy as np import numpy.linalg as la +import grudge.op as op +import types from grudge.models import HyperbolicOperator +from grudge.symbolic.primitives import TracePair + +from meshmode.dof_array import thaw + from grudge import sym # {{{ fluxes -def advection_weak_flux(flux_type, u, velocity): - normal = sym.normal(u.dd, len(velocity)) - v_dot_n = sym.cse(velocity.dot(normal), "v_dot_normal") +def advection_weak_flux(dcoll, flux_type, u_tpair, velocity): + r"""Compute the numerical flux for the advection operator + $(v \cdot \nabla)u$. + """ + actx = u_tpair.int.array_context + dd = u_tpair.dd + normal = thaw(actx, op.normal(dcoll, dd)) + v_dot_n = np.dot(velocity, normal) flux_type = flux_type.lower() if flux_type == "central": - return u.avg * v_dot_n + return u_tpair.avg * v_dot_n elif flux_type == "lf": - norm_v = sym.sqrt((velocity**2).sum()) - return u.avg * v_dot_n + 0.5 * norm_v * (u.int - u.ext) + norm_v = np.sqrt(sum(velocity**2)) + return u_tpair.avg * v_dot_n + 0.5 * norm_v * (u_tpair.int - u_tpair.ext) elif flux_type == "upwind": - u_upwind = sym.If( - sym.Comparison(v_dot_n, ">", 0), - u.int, # outflow - u.ext # inflow - ) + u_upwind = actx.np.where(v_dot_n > 0, u_tpair.int, u_tpair.ext) return u_upwind * v_dot_n else: raise ValueError(f"flux '{flux_type}' is not implemented") @@ -58,84 +68,113 @@ def advection_weak_flux(flux_type, u, velocity): # {{{ constant-coefficient advection class AdvectionOperatorBase(HyperbolicOperator): - flux_types = [ - "central", - "upwind", - "lf" - ] - - def __init__(self, v, inflow_u, flux_type="central"): - self.ambient_dim = len(v) - self.v = v - self.inflow_u = inflow_u - self.flux_type = flux_type + flux_types = ["central", "upwind", "lf"] + def __init__(self, dcoll, v, inflow_u, flux_type="central"): if flux_type not in self.flux_types: raise ValueError(f"unknown flux type: '{flux_type}'") - def weak_flux(self, u): - return advection_weak_flux(self.flux_type, u, self.v) + if not isinstance(inflow_u, types.LambdaType): + raise ValueError( + "inflow_u must be a lambda function of time `t`" + ) - def max_eigenvalue(self, t=None, fields=None, discr=None): - return la.norm(self.v) + self.dcoll = dcoll + self.v = v + self.inflow_u = inflow_u + self.flux_type = flux_type + + def weak_flux(self, u_tpair): + return advection_weak_flux(self.dcoll, self.flux_type, u_tpair, self.v) class StrongAdvectionOperator(AdvectionOperatorBase): - def flux(self, u): - normal = sym.normal(u.dd, self.ambient_dim) - v_dot_normal = sym.cse(self.v.dot(normal), "v_dot_normal") + def flux(self, u_tpair): + actx = u_tpair.int.array_context + dd = u_tpair.dd + normal = thaw(actx, op.normal(self.dcoll, dd)) + v_dot_normal = np.dot(self.v, normal) - return u.int * v_dot_normal - self.weak_flux(u) + return u_tpair.int * v_dot_normal - self.weak_flux(u_tpair) - def sym_operator(self): + def operator(self, t, u): from meshmode.mesh import BTAG_ALL - u = sym.var("u") + dcoll = self.dcoll + inflow_u = self.inflow_u(t) - def flux(pair): - return sym.project(pair.dd, "all_faces")( - self.flux(pair)) + def flux(tpair): + return op.project(dcoll, tpair.dd, "all_faces", self.flux(tpair)) return ( - - self.v.dot(sym.nabla(self.ambient_dim)*u) - + sym.InverseMassOperator()( - sym.FaceMassOperator()( - flux(sym.int_tpair(u)) - + flux(sym.bv_tpair(BTAG_ALL, u, self.inflow_u)) - - # FIXME: Add back support for inflow/outflow tags - #+ flux(sym.bv_tpair(self.inflow_tag, u, bc_in)) - #+ flux(sym.bv_tpair(self.outflow_tag, u, bc_out)) - ))) + -self.v.dot(op.local_grad(dcoll, u)) + + op.inverse_mass( + dcoll, + op.face_mass( + dcoll, + flux(op.interior_trace_pair(dcoll, u)) + + flux(TracePair(BTAG_ALL, + interior=op.project( + dcoll, "vol", BTAG_ALL, u + ), + exterior=inflow_u)) + + # FIXME: Add support for inflow/outflow tags + # + flux(TracePair(self.inflow_tag, + # interior=op.project( + # dcoll, "vol", self.inflow_tag, u + # ), + # exterior=bc_in)) + # + flux(TracePair(self.outflow_tag, + # interior=op.project( + # dcoll, "vol", self.outflow_tag, u + # ), + # exterior=bc_out)) + ) + ) + ) class WeakAdvectionOperator(AdvectionOperatorBase): - def flux(self, u): - return self.weak_flux(u) + def flux(self, u_tpair): + return self.weak_flux(u_tpair) - def sym_operator(self): + def operator(self, t, u): from meshmode.mesh import BTAG_ALL - u = sym.var("u") - - def flux(pair): - return sym.project(pair.dd, "all_faces")( - self.flux(pair)) + dcoll = self.dcoll + inflow_u = self.inflow_u(t) - bc_in = self.inflow_u - # bc_out = sym.project(DD_VOLUME, self.outflow_tag)(u) + def flux(tpair): + return op.project(dcoll, tpair.dd, "all_faces", self.flux(tpair)) - return sym.InverseMassOperator()( - np.dot( - self.v, sym.stiffness_t(self.ambient_dim)*u) - - sym.FaceMassOperator()( - flux(sym.int_tpair(u)) - + flux(sym.bv_tpair(BTAG_ALL, u, bc_in)) - - # FIXME: Add back support for inflow/outflow tags - #+ flux(sym.bv_tpair(self.inflow_tag, u, bc_in)) - #+ flux(sym.bv_tpair(self.outflow_tag, u, bc_out)) - )) + return ( + op.inverse_mass( + dcoll, + np.dot(self.v, op.weak_local_grad(dcoll, u)) + - op.face_mass( + dcoll, + flux(op.interior_trace_pair(dcoll, u)) + + flux(TracePair(BTAG_ALL, + interior=op.project( + dcoll, "vol", BTAG_ALL, u + ), + exterior=inflow_u)) + + # FIXME: Add support for inflow/outflow tags + # + flux(TracePair(self.inflow_tag, + # interior=op.project( + # dcoll, "vol", self.inflow_tag, u + # ), + # exterior=bc_in)) + # + flux(TracePair(self.outflow_tag, + # interior=op.project( + # dcoll, "vol", self.outflow_tag, u + # ), + # exterior=bc_out)) + ) + ) + ) # }}} -- GitLab