Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions tests/regression/test_upwind_flux.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
"""
This code does the following.

First, obtains an upwind DG0 approximation to div(u*D).
Then, tries to find a BDM1 flux F such that div F is
equal to this upwind approximation.

we have

\int_e phi D_1 dx = -\int_e grad phi . u D dx
+ \int_{\partial e} phi u.n \tilde{D} ds

where \tilde{D} is the value of D on the upwind face. For
DG0, grad phi = 0.

Then, if we define F such that

\int_f phi F.n ds = \int_f phi u.n \tilde{D} ds

then

\int_e phi div(F) ds = \int_{\partial e} phi u.n \tilde{D} ds
as required.
"""
from firedrake import *
import pytest


def run_test():
mesh = UnitIcosahedralSphereMesh(refinement_level=2)
global_normal = Expression(("x[0]/sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2])",
"x[1]/sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2])",
"x[2]/sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2])"))
mesh.init_cell_orientations(global_normal)

# Define function spaces and basis functions
V_dg = FunctionSpace(mesh, "DG", 0)
M = FunctionSpace(mesh, "RT", 1)

# advecting velocity
u0 = Expression(('-x[1]', 'x[0]', '0'))
u = Function(M).project(u0)

# Mesh-related functions
n = FacetNormal(mesh)

# ( dot(v, n) + |dot(v, n)| )/2.0
un = 0.5*(dot(u, n) + abs(dot(u, n)))

# D advection equation
phi = TestFunction(V_dg)
D = TrialFunction(V_dg)
a_mass = phi*D*dx
a_int = dot(grad(phi), -u*D)*dx
a_flux = (dot(jump(phi), un('+')*D('+') - un('-')*D('-')))*dS

arhs = (a_int + a_flux)

D1 = Function(V_dg)

D0 = Expression("exp(-pow(x[2],2) - pow(x[1],2))")
D = Function(V_dg).interpolate(D0)

D1problem = LinearVariationalProblem(a_mass, action(arhs, D), D1)
D1solver = LinearVariationalSolver(D1problem)
D1solver.solve()

# Surface Flux equation
V1 = FunctionSpace(mesh, "RT", 1)
w = TestFunction(V1)
Ft = TrialFunction(V1)
Fs = Function(V1)

aFs = (inner(w('+'), n('+'))*inner(Ft('+'), n('+')) +
inner(w('-'), n('-'))*inner(Ft('-'), n('-')))*dS
LFs = 2.0*(inner(w('+'), n('+'))*un('+')*D('+')
+ inner(w('-'), n('-'))*un('-')*D('-'))*dS

Fsproblem = LinearVariationalProblem(aFs, LFs, Fs)
Fssolver = LinearVariationalSolver(Fsproblem,
solver_parameters={'ksp_type': 'preonly'})
Fssolver.solve()

divFs = Function(V_dg)

solve(a_mass == phi*div(Fs)*dx, divFs)

assert errornorm(divFs, D1, degree_rise=0) < 1e-12


def test_upwind_flux():
run_test()


@pytest.mark.xfail(reason="No support for interior facet integrals in MPI")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this now supposed to work?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exterior facets ought to work, interior needs a little more work. I need to test Michael's latest change. Maybe next week?

@pytest.mark.parallel
def test_upwind_flux_parallel():
run_test()