Skip to content
Snippets Groups Projects
Commit b77b460a authored by René Heß's avatar René Heß
Browse files

Merge branch 'feature/better-manufactured-solution-testing' into 'master'

Full test suite passes.

This fixes #29 

To achieve this goal, I did:
* switch to l2error comparison for all manufactured solution examples
* implement mixed expressions to allow that for systems
* fix `stokes_stress_symdiff`

The following issues remain, but the tests are deactivated until an upstream problem is fixed:
* `heatquation{_dg}_explicit` fails, new issue is #30.
* `poisson_dg_matrix_free` needs a suiting solver, depends on #31 kind of.

I also improved error handling: No more exceptions, instead non-zero error code. That way you get vtk output for failing tests (the previous behaviour was potentially harmful, as you could look at old solutions in debugging!!!).

See merge request !23
parents ad6aef2c 1a38d3a5
No related branches found
No related tags found
No related merge requests found
Showing
with 363 additions and 140 deletions
......@@ -18,9 +18,10 @@ int main(int argc, char** argv)
std::cout<<"I am rank "<<helper.rank()<<" of "<<helper.size()
<<" processes!"<<std::endl;
driver(argc, argv);
return 0;
if (driver(argc, argv))
return 1;
else
return 0;
}
catch (Dune::Exception &e){
std::cerr << "Dune reported error: " << e << std::endl;
......
......@@ -236,9 +236,9 @@ class UFL2LoopyVisitor(ModifiedTerminalTracker, UFL2PymbolicMapper, GeometryMapp
# Check if this is a parameter function
else:
# We expect all coefficients to be of type Expression or VectorExpression!
from dune.perftool.ufl.execution import Expression, VectorExpression
assert isinstance(o, (Expression, VectorExpression))
# We expect all coefficients to be of type Expression!
from dune.perftool.ufl.execution import Expression
assert isinstance(o, Expression)
# Determine the name of the parameter function
from dune.perftool.generation import get_global_context_value
......
......@@ -423,9 +423,9 @@ def define_intersection_lambda(expression, name):
if expression is None:
return "auto {} = [&](const auto& x){{ return 0; }};".format(name)
if expression.is_global:
return "auto {} = [&](const auto& x){{ {} }};".format(name, expression.c_expr)
return "auto {} = [&](const auto& x){{ {} }};".format(name, expression.c_expr[0])
else:
return "auto {} = [&](const auto& is, const auto& x){{ {} }};".format(name, expression.c_expr)
return "auto {} = [&](const auto& is, const auto& x){{ {} }};".format(name, expression.c_expr[0])
@symbol
......@@ -741,9 +741,9 @@ def define_boundary_lambda(boundary, name):
if boundary is None:
return "auto {} = [&](const auto& x){{ return 0.0; }};".format(name)
if boundary.is_global:
return "auto {} = [&](const auto& x){{ {} }};".format(name, boundary.c_expr)
return "auto {} = [&](const auto& x){{ {} }};".format(name, boundary.c_expr[0])
else:
return "auto {} = [&](const auto& e, const auto& x){{ {} }};".format(name, boundary.c_expr)
return "auto {} = [&](const auto& e, const auto& x){{ {} }};".format(name, boundary.c_expr[0])
@symbol
......@@ -777,41 +777,61 @@ def define_compositegfs_parameterfunction(name, *children):
', '.join(children))
def expression_splitter(expr, length):
if expr is None:
return (None,) * length
else:
from dune.perftool.ufl.execution import split_expression
return split_expression(expr)
@symbol
def name_boundary_function(expr):
def _name_boundary_function(element, boundary, name=None):
from ufl import MixedElement, VectorElement, TensorElement
if isinstance(expr, (VectorElement, TensorElement)):
element, (_, boundary) = get_constraints_metadata(expr)
if isinstance(element, (VectorElement, TensorElement)):
from dune.perftool.generation import get_global_context_value
name = get_global_context_value("data").object_names.get(id(boundary), "zero")
define_boundary_function(boundary, name)
return name
if isinstance(expr, MixedElement):
children = tuple(name_boundary_function(el) for el in expr.sub_elements())
basename = get_global_context_value("data").object_names.get(id(boundary), "veczero")
children = tuple(_name_boundary_function(el, exp, basename + '_' + str(i)) for el, exp, i in zip(element.sub_elements(), expression_splitter(boundary, element.num_sub_elements()), range(element.num_sub_elements())))
define_compositegfs_parameterfunction(basename, *children)
return basename
if isinstance(element, MixedElement):
children = tuple(name_boundary_function(el) for el in element.sub_elements())
name = '_'.join(children)
define_compositegfs_parameterfunction(name, *children)
return name
# This is a scalar leaf of the ansatz function tree
element, (_, boundary) = get_constraints_metadata(expr)
from dune.perftool.generation import get_global_context_value
name = get_global_context_value("data").object_names.get(id(boundary), "zero")
if name is None:
name = get_global_context_value("data").object_names.get(id(boundary), "zero")
define_boundary_function(boundary, name)
return name
def name_boundary_function(expr):
# This is a scalar leaf of the ansatz function tree
element, (_, boundary) = get_constraints_metadata(expr)
return _name_boundary_function(element, boundary)
@symbol
def name_solution_function(expr):
# Get expression representing solution
def name_solution_function(tree_path=()):
from dune.perftool.generation import get_global_context_value
expr = get_global_context_value("data").object_by_name[get_option("exact_solution_expression")]
from dune.perftool.ufl.execution import split_expression
for i in tree_path:
expr = split_expression(expr)[int(i)]
from dune.perftool.generation import get_global_context_value
solution_expression_name = get_option("exact_solution_expression")
solution_expression = get_global_context_value("data").object_by_name[solution_expression_name]
try:
name = get_global_context_value("data").object_names[id(expr)]
except KeyError:
from dune.perftool.generation.cache import _GlobalCounter
name = 'generic_{}'.format(_GlobalCounter().get())
# Create function just like it is done for boundary_function
name = "solution_function"
define_boundary_function(solution_expression, name)
define_boundary_function(expr, name)
return name
......@@ -833,7 +853,7 @@ def interpolate_solution_expression(name):
formdata = _driver_data['formdata']
define_vector(name, formdata)
element = _driver_data['form'].coefficients()[0].ufl_element()
sol = name_solution_function(element)
sol = name_solution_function()
gfs = name_gfs(element)
return "Dune::PDELab::interpolate({}, {}, {});".format(sol,
gfs,
......@@ -1156,6 +1176,7 @@ def name_vtkfile():
def compare_dofs():
v = name_vector(_driver_data['formdata'])
solution = name_vector_from_solution_expression()
fail = name_test_fail_variable()
return ["",
"// Maximum norm of difference between dof vectors of the",
"// numerical solution and the interpolation of the exact solution",
......@@ -1166,44 +1187,161 @@ def compare_dofs():
" maxerror = std::abs(native({})[i]-native({})[i]);".format(v, solution),
"std::cout << std::endl << \"Maxerror: \" << maxerror << std::endl;",
"if (maxerror>{})".format(get_option("compare_dofs")),
" throw;"]
" {} = true;".format(fail)]
@symbol
def type_discrete_grid_function(gfs):
return "DGF_{}".format(gfs.upper())
@preamble
def define_discrete_grid_function(gfs, vector_name, dgf_name):
return ["typedef Dune::PDELab::DiscreteGridFunction<decltype({}),decltype({})> DGF;".format(gfs, vector_name),
"DGF {}({},{});".format(dgf_name, gfs, vector_name)]
dgf_type = type_discrete_grid_function(gfs)
return ["typedef Dune::PDELab::DiscreteGridFunction<decltype({}),decltype({})> {};".format(gfs, vector_name, dgf_type),
"{} {}({},{});".format(dgf_type, dgf_name, gfs, vector_name)]
@symbol
def name_discrete_grid_function(gfs, vector_name):
dgf_name = vector_name + "_dgf"
dgf_name = gfs + "_dgf"
define_discrete_grid_function(gfs, vector_name, dgf_name)
return dgf_name
@symbol
def type_subgfs(element, tree_path):
include_file('dune/pdelab/gridfunctionspace/subspace.hh', filetag='driver')
gfs = type_gfs(element)
return "Dune::PDELab::GridFunctionSubSpace<{}, Dune::TypeTree::TreePath<{}> >".format(gfs, ', '.join(tree_path))
@preamble
def compare_L2_squared():
def define_subgfs(name, element, tree_path):
t = type_subgfs(element, tree_path)
gfs = name_gfs(element)
return '{} {}({});'.format(t, name, gfs)
@symbol
def name_subgfs(element, tree_path):
gfs = name_gfs(element)
if len(tree_path) == 0:
return gfs
else:
name = "subgfs_{}_{}".format(gfs, '_'.join(tree_path))
define_subgfs(name, element, tree_path)
return name
@preamble
def typedef_difference_squared_adapter(name, tree_path):
element = _driver_data['form'].coefficients()[0].ufl_element()
formdata = _driver_data['formdata']
v = name_vector(formdata)
gfs = name_gfs(element)
vdgf = name_discrete_grid_function(gfs, v)
solution_function = name_solution_function(element)
solution_function = name_solution_function(tree_path)
gfs = name_subgfs(element, tree_path)
vector = name_vector(formdata)
dgf = name_discrete_grid_function(gfs, vector)
return 'typedef DifferenceSquaredAdapter<decltype({}), decltype({})> {};'.format(solution_function, dgf, name)
@symbol
def type_difference_squared_adapter(tree_path):
t = 'DifferenceSquared_{}'.format('_'.join(tree_path))
typedef_difference_squared_adapter(t, tree_path)
return t
@preamble
def define_difference_squared_adapter(name, tree_path):
element = _driver_data['form'].coefficients()[0].ufl_element()
formdata = _driver_data['formdata']
t = type_difference_squared_adapter(tree_path)
solution_function = name_solution_function(tree_path)
gfs = name_subgfs(element, tree_path)
vector = name_vector(formdata)
dgf = name_discrete_grid_function(gfs, vector)
return '{} {}({}, {});'.format(t, name, solution_function, dgf)
def name_difference_squared_adapter(tree_path):
name = 'differencesquared_{}'.format('_'.join(tree_path))
define_difference_squared_adapter(name, tree_path)
return name
@preamble
def _accumulate_L2_squared(tree_path):
dsa = name_difference_squared_adapter(tree_path)
t_dsa = type_difference_squared_adapter(tree_path)
accum_error = name_accumulated_L2_error()
include_file("dune/pdelab/gridfunctionspace/gridfunctionadapter.hh", filetag="driver")
include_file("dune/pdelab/common/functionutilities.hh", filetag="driver")
return ["",
"// L2 error squared of difference between numerical",
"// solution and the interpolation of exact solution",
"typedef DifferenceSquaredAdapter<decltype({}),decltype({})> DifferenceSquared;".format(solution_function, vdgf),
"DifferenceSquared differencesquared({},{});".format(solution_function, vdgf),
"typename DifferenceSquared::Traits::RangeType l2errorsquared(0.0);",
"Dune::PDELab::integrateGridFunction(differencesquared,l2errorsquared,10);",
"std::cout << \"l2errorsquared: \" << l2errorsquared << std::endl;",
"if (l2errorsquared>{})".format(get_option("compare_l2errorsquared")),
" throw;"]
return ["{",
" // L2 error squared of difference between numerical",
" // solution and the interpolation of exact solution",
" // only subgfs with treepath: {}".format(', '.join(tree_path)),
" typename {}::Traits::RangeType err(0.0);".format(t_dsa),
" Dune::PDELab::integrateGridFunction({}, err, 10);".format(dsa),
" {} += err;".format(accum_error),
" std::cout << \"Accumlated L2 Error for tree path {}: \" << err << std::endl;".format(tree_path),
"}"]
def accumulate_L2_squared(tree_path=()):
element = _driver_data['form'].coefficients()[0].ufl_element()
from ufl.functionview import select_subelement
from ufl.classes import MultiIndex, FixedIndex
element = select_subelement(element, MultiIndex(tuple(FixedIndex(int(i)) for i in tree_path)))
from ufl import MixedElement
if isinstance(element, MixedElement):
for i, subel in enumerate(element.sub_elements()):
accumulate_L2_squared(tree_path + (str(i),))
else:
_accumulate_L2_squared(tree_path)
@preamble
def define_accumulated_L2_error(name):
return "double {}(0.0);".format(name)
@symbol
def name_accumulated_L2_error():
name = 'l2error'
define_accumulated_L2_error(name)
return name
@preamble
def compare_L2_squared():
accumulate_L2_squared()
accum_error = name_accumulated_L2_error()
fail = name_test_fail_variable()
return ["std::cout << \"l2errorsquared: \" << {} << std::endl;".format(accum_error),
"if ({}>{})".format(accum_error, get_option("compare_l2errorsquared")),
" {} = true;".format(fail)]
@preamble
def define_test_fail_variable(name):
return 'bool {}(false);'.format(name)
@symbol
def name_test_fail_variable():
name = "testfail"
define_test_fail_variable(name)
return name
@preamble
......@@ -1289,10 +1427,6 @@ def vtkoutput():
print_matrix()
if get_option("exact_solution_expression"):
from ufl import MixedElement, VectorElement, TensorElement
if isinstance(_driver_data['form'].coefficients()[0].ufl_element(), (MixedElement, VectorElement, TensorElement)):
raise NotImplementedError("Comparing to exact solution is olny implemented for scalar elements.")
if get_option("compare_dofs"):
compare_dofs()
if get_option("compare_l2errorsquared"):
......@@ -1424,16 +1558,18 @@ def solve_instationary():
print_residual()
print_matrix()
if get_option("exact_solution_expression"):
from ufl import MixedElement, VectorElement, TensorElement
if isinstance(_driver_data['form'].coefficients()[0].ufl_element(), (MixedElement, VectorElement, TensorElement)):
raise NotImplementedError("Comparing to exact solution is olny implemented for scalar elements.")
if get_option("compare_dofs"):
compare_dofs()
if get_option("compare_l2errorsquared"):
compare_L2_squared()
@preamble
def return_statement():
fail = name_test_fail_variable()
return "return {};".format(fail)
def generate_driver(formdatas, data):
# The driver module uses a global dictionary for storing necessary data
set_driver_data(formdatas, data)
......@@ -1445,9 +1581,11 @@ def generate_driver(formdatas, data):
else:
solve_instationary()
return_statement()
from dune.perftool.generation import retrieve_cache_items
from cgen import FunctionDeclaration, FunctionBody, Block, Value
driver_signature = FunctionDeclaration(Value('void', 'driver'), [Value('int', 'argc'), Value('char**', 'argv')])
driver_signature = FunctionDeclaration(Value('bool', 'driver'), [Value('int', 'argc'), Value('char**', 'argv')])
driver_body = Block(contents=[i for i in retrieve_cache_items("preamble", make_generable=True)])
driver = FunctionBody(driver_signature, driver_body)
......
......@@ -69,8 +69,22 @@ def define_set_time_method():
return result
def component_to_tree_path(element, component):
subel = element.extract_subelement_component(component)
def _flatten(x):
if isinstance(x, tuple):
return '_'.join(_flatten(i) for i in x if i != ())
else:
return str(x)
return _flatten(subel)
@class_member("parameterclass", access=AccessModifier.PUBLIC)
def define_parameter_function_class_member(name, expr, t, cell):
def define_parameter_function_class_member(name, expr, baset, shape, cell):
t = construct_nested_fieldvector(baset, shape)
geot = "E" if cell else "I"
geo = geot.lower()
result = ["template<typename {}, typename X>".format(geot),
......@@ -78,12 +92,32 @@ def define_parameter_function_class_member(name, expr, t, cell):
"{",
]
if expr.is_global:
result.append(" auto x = {}.geometry().global(local);".format(geo))
# In the case of a non-scalar parameter function, recurse into leafs
if expr.element.value_shape():
# Check that this is a VectorElement, as I have no idea how a parameter function
# over a non-vector mixed element should be well-defined in PDELab.
from ufl import VectorElement
assert isinstance(expr.element, VectorElement)
result.append(" {} result(0.0);".format(t))
from dune.perftool.ufl.execution import split_expression
for i, subexpr in enumerate(split_expression(expr)):
child_name = "{}_{}".format(name, component_to_tree_path(expr.element, i))
result.append(" result[{}] = {}({}, local);".format(i, child_name, geo))
define_parameter_function_class_member(child_name, subexpr, baset, shape[1:], cell)
result.append(" return result;")
else:
result.append(" auto x = local;")
# Evaluate a scalar parameter function
if expr.is_global:
result.append(" auto x = {}.geometry().global(local);".format(geo))
else:
result.append(" auto x = local;")
result.append(" " + expr.c_expr[0])
result.append(" " + expr.c_expr)
result.append("}")
return result
......@@ -175,8 +209,7 @@ def construct_nested_fieldvector(t, shape):
def cell_parameter_function(name, expr, restriction, cellwise_constant, t='double'):
shape = expr.ufl_element().value_shape()
shape_impl = ('fv',) * len(shape)
t = construct_nested_fieldvector(t, shape)
define_parameter_function_class_member(name, expr, t, True)
define_parameter_function_class_member(name, expr, t, shape, True)
if cellwise_constant:
from dune.perftool.generation.loopy import default_declaration
default_declaration(name, shape, shape_impl)
......@@ -190,8 +223,7 @@ def cell_parameter_function(name, expr, restriction, cellwise_constant, t='doubl
def intersection_parameter_function(name, expr, cellwise_constant, t='double'):
shape = expr.ufl_element().value_shape()
shape_impl = ('fv',) * len(shape)
t = construct_nested_fieldvector(t, shape)
define_parameter_function_class_member(name, expr, t, False)
define_parameter_function_class_member(name, expr, t, shape, False)
if cellwise_constant:
from dune.perftool.generation.loopy import default_declaration
default_declaration(name, shape, shape_impl)
......
......@@ -38,7 +38,10 @@ class Coefficient(ufl.Coefficient):
ufl.Coefficient.__init__(self, element, count)
split = ufl.split_functions.split2
def split(obj):
if isinstance(obj, Expression):
return split_expression(obj)
return ufl.split_functions.split2(obj)
def Coefficients(element):
......@@ -54,42 +57,66 @@ def TrialFunctions(element):
class Expression(Coefficient):
def __init__(self, expr, is_global=True, on_intersection=False, cell_type="triangle", cellwise_constant=False):
assert isinstance(expr, str)
self.c_expr = expr
self.is_global = is_global
self.on_intersection = on_intersection
# Avoid ufl complaining about not matching dimension/cells
if cellwise_constant:
_dg = FiniteElement("DG", cell_type, 0)
else:
_dg = FiniteElement("DG", cell_type, 1)
def __init__(self, cppcode=None, element=None, cell="triangle", degree=None, is_global=True, on_intersection=False, cellwise_constant=False):
assert cppcode
# Initialize a coefficient with a dummy finite element map.
Coefficient.__init__(self, _dg)
if isinstance(cppcode, str):
cppcode = (cppcode,)
# TODO the subdomain_data code needs a uflid, not idea how to get it here
# The standard way through class decorator fails here...
def ufl_id(self):
return 0
def wrap_return(e):
if "return" not in e:
return "return {};".format(e)
else:
return e
cppcode = tuple(wrap_return(e) for e in cppcode)
class VectorExpression(Coefficient):
def __init__(self, expr, is_global=True, on_intersection=False, cell_type="triangle", cellwise_constant=False):
assert isinstance(expr, str)
self.c_expr = expr
if cellwise_constant:
if element:
assert element.degree() == 0
elif degree is not None:
assert degree == 0
else:
element = FiniteElement("DG", cell, 0)
if degree is None:
degree = 1
if element is None:
if len(cppcode) == 1:
element = FiniteElement("DG", cell, degree)
else:
element = VectorElement("DG", cell, degree, len(cppcode))
def element_length(elem):
if isinstance(elem, ufl.FiniteElement):
return 1
else:
return elem.value_shape()[0]
assert element_length(element) == len(cppcode)
self.c_expr = cppcode
self.is_global = is_global
self.on_intersection = on_intersection
# Avoid ufl complaining about not matching dimension/cells
if cellwise_constant:
_dgvec = VectorElement("DG", cell_type, 0)
else:
_dgvec = VectorElement("DG", cell_type, 1)
self.element = element
# Initialize a coefficient with a dummy finite element map.
Coefficient.__init__(self, _dgvec)
Coefficient.__init__(self, element)
def __mul__(self, other):
# Allow the combination of Expressions
if isinstance(other, Expression):
def get_sub(elem):
if isinstance(elem, MixedElement) and not isinstance(elem, (VectorElement, TensorElement)):
return elem.sub_elements()
else:
return [elem]
newelem = MixedElement(*(get_sub(self.element) + get_sub(other.element)))
return Expression(cppcode=self.c_expr + other.c_expr, element=newelem)
else:
return Coefficient.__mul__(self, other)
# TODO the subdomain_data code needs a uflid, not idea how to get it here
# The standard way through class decorator fails here...
......@@ -97,6 +124,19 @@ class VectorExpression(Coefficient):
return 0
def split_expression(expr):
assert isinstance(expr, Expression)
def element_slice(expression, sub):
offset = sum(subel.value_size() for subel in expression.element.sub_elements()[:sub])
return expression.c_expr[offset:offset + expr.element.sub_elements()[sub].value_size()]
return tuple(Expression(cppcode=element_slice(expr, i),
element=expr.element.sub_elements()[i])
for i in range(expr.element.num_sub_elements())
)
class FiniteElement(ufl.FiniteElement):
def __init__(self, *args, **kwargs):
if ('dirichlet_constraints' in kwargs) or ('dirichlet_expression' in kwargs):
......
......@@ -15,3 +15,6 @@ extension = vtu
explicit_time_stepping = 0, 1 | expand scheme
exact_solution_expression = g
compare_l2errorsquared = 1e-7
# Disable explicit tests for now
{__exec_suffix} == explicit | exclude
......@@ -15,3 +15,6 @@ extension = vtu
explicit_time_stepping = 0, 1 | expand scheme
exact_solution_expression = g
compare_l2errorsquared = 1e-5
# Disable explicit tests for now
{__exec_suffix} == explicit | exclude
cell_type = "interval"
cell = "interval"
f = Expression("return -2.0*x.size();", cell_type=cell_type)
g = Expression("return x.two_norm2();", cell_type=cell_type)
f = Expression("return -2.0*x.size();", cell=cell)
g = Expression("return x.two_norm2();", cell=cell)
V = FiniteElement("CG", cell_type, 1, dirichlet_expression=g)
V = FiniteElement("CG", cell, 1, dirichlet_expression=g)
u = TrialFunction(V)
v = TestFunction(V)
......
cell_type = "interval"
cell = "interval"
f = Expression("return -2.0*x.size();", cell_type=cell_type)
g = Expression("return x.two_norm2();", on_intersection=True, cell_type=cell_type)
f = Expression("return -2.0*x.size();", cell=cell)
g = Expression("return x.two_norm2();", on_intersection=True, cell=cell)
V = FiniteElement("DG", cell_type, 1)
V = FiniteElement("DG", cell, 1)
u = TrialFunction(V)
v = TestFunction(V)
n = FacetNormal(cell_type)('+')
n = FacetNormal(cell)('+')
gamma = 1.0
theta = 1.0
......
cell_type = "quadrilateral"
cell = "quadrilateral"
f = Expression("return -2.0*x.size();", cell_type=cell_type)
g = Expression("return x.two_norm2();", cell_type=cell_type)
f = Expression("return -2.0*x.size();", cell=cell)
g = Expression("return x.two_norm2();", cell=cell)
V = FiniteElement("CG", cell_type, 1, dirichlet_expression=g)
V = FiniteElement("CG", cell, 1, dirichlet_expression=g)
u = TrialFunction(V)
v = TestFunction(V)
......
cell_type = "quadrilateral"
cell = "quadrilateral"
f = Expression("return -2.0*x.size();", cell_type=cell_type)
g = Expression("return x.two_norm2();", on_intersection=True, cell_type=cell_type)
f = Expression("return -2.0*x.size();", cell=cell)
g = Expression("return x.two_norm2();", on_intersection=True, cell=cell)
V = FiniteElement("DG", cell_type, 1)
V = FiniteElement("DG", cell, 1)
u = TrialFunction(V)
v = TestFunction(V)
n = FacetNormal(cell_type)('+')
n = FacetNormal(cell)('+')
gamma = 1.0
theta = 1.0
......
cell_type = "hexahedron"
cell = "hexahedron"
f = Expression("return -2.0*x.size();", cell_type=cell_type)
g = Expression("return x.two_norm2();", cell_type=cell_type)
f = Expression("return -2.0*x.size();", cell=cell)
g = Expression("return x.two_norm2();", cell=cell)
V = FiniteElement("CG", cell_type, 1, dirichlet_expression=g)
V = FiniteElement("CG", cell, 1, dirichlet_expression=g)
u = TrialFunction(V)
v = TestFunction(V)
......
cell_type = "tetrahedron"
cell = "tetrahedron"
f = Expression("return -2.0*x.size();", cell_type=cell_type)
g = Expression("return x.two_norm2();", cell_type=cell_type)
f = Expression("return -2.0*x.size();", cell=cell)
g = Expression("return x.two_norm2();", cell=cell)
V = FiniteElement("CG", "tetrahedron", 1, dirichlet_expression=g)
u = TrialFunction(V)
......
cell_type = "hexahedron"
cell = "hexahedron"
f = Expression("return -2.0*x.size();", cell_type=cell_type)
g = Expression("return x.two_norm2();", on_intersection=True, cell_type=cell_type)
f = Expression("return -2.0*x.size();", cell=cell)
g = Expression("return x.two_norm2();", on_intersection=True, cell=cell)
V = FiniteElement("DG", cell_type, 1)
V = FiniteElement("DG", cell, 1)
u = TrialFunction(V)
v = TestFunction(V)
n = FacetNormal(cell_type)('+')
n = FacetNormal(cell)('+')
gamma = 1.0
theta = 1.0
......
cell_type = "tetrahedron"
cell = "tetrahedron"
f = Expression("return -2.0*x.size();", cell_type=cell_type)
g = Expression("return x.two_norm2();", on_intersection=True, cell_type=cell_type)
f = Expression("return -2.0*x.size();", cell=cell)
g = Expression("return x.two_norm2();", on_intersection=True, cell=cell)
V = FiniteElement("DG", cell_type, 1)
V = FiniteElement("DG", cell, 1)
u = TrialFunction(V)
v = TestFunction(V)
n = FacetNormal(cell_type)('+')
n = FacetNormal(cell)('+')
gamma = 1.0
theta = 1.0
......
......@@ -5,17 +5,14 @@ dune_symlink_to_source_files(FILES hagenpoiseuille_ref.vtu
dune_add_formcompiler_system_test(UFLFILE stokes.ufl
BASENAME stokes
INIFILE stokes.mini
SCRIPT dune_vtkcompare.py
)
dune_add_formcompiler_system_test(UFLFILE stokes_dg.ufl
BASENAME stokes_dg
INIFILE stokes_dg.mini
SCRIPT dune_vtkcompare.py
)
dune_add_formcompiler_system_test(UFLFILE stokes_stress.ufl
BASENAME stokes_stress
INIFILE stokes_stress.mini
SCRIPT dune_vtkcompare.py
)
......@@ -14,3 +14,5 @@ extension = vtu
[formcompiler]
numerical_jacobian = 0, 1 | expand num
exact_solution_expression = g
compare_l2errorsquared = 1e-6
v_bctype = Expression("if (x[0] < 1. - 1e-8) return 1; else return 0;", on_intersection=True)
v_dirichlet = Expression("Dune::FieldVector<double, 2> y(0.0); y[0] = 4*x[1]*(1.-x[1]); return y;")
g_v = Expression(("4*x[1]*(1.-x[1])", "0.0"))
g_p = Expression("8*(1.-x[0])")
g = g_v * g_p
cell = triangle
P2 = VectorElement("Lagrange", cell, 2, dirichlet_constraints=v_bctype, dirichlet_expression=v_dirichlet)
P2 = VectorElement("Lagrange", cell, 2, dirichlet_constraints=v_bctype, dirichlet_expression=g_v)
P1 = FiniteElement("Lagrange", cell, 1)
TH = P2 * P1
......
......@@ -16,3 +16,5 @@ zeroThreshold.data_1 = 1e-6
[formcompiler]
numerical_jacobian = 0, 1 | expand num
exact_solution_expression = g
compare_l2errorsquared = 1e-5
g = VectorExpression("Dune::FieldVector<double, 2> y(0.0); y[0]=4*x[1]*(1.-x[1]); return y;", on_intersection=True)
g_v = Expression(("4*x[1]*(1.-x[1])", "0.0"), on_intersection=True)
g_p = Expression("8*(1.-x[0])")
g = g_v * g_p
bctype = Expression("if (x[0] < 1. - 1e-8) return 1; else return 0;", on_intersection=True)
cell = triangle
......@@ -19,15 +21,15 @@ r = inner(grad(u), grad(v))*dx \
+ inner(avg(grad(u))*n, jump(v))*dS \
- eps * inner(avg(grad(v))*n, jump(u))*dS \
- inner(grad(u)*n, v)*ds \
+ eps * inner(grad(v)*n, u-g)*ds \
+ eps * inner(grad(v)*n, u-g_v)*ds \
+ sigma * inner(jump(u), jump(v))*dS \
+ sigma * inner(u-g, v)*ds \
+ sigma * inner(u-g_v, v)*ds \
- p*div(v)*dx \
- avg(p)*inner(jump(v), n)*dS \
+ p*inner(v, n)*ds \
- q*div(u)*dx \
- avg(q)*inner(jump(u), n)*dS \
+ q*inner(u, n)*ds \
- q*inner(g, n)*ds
- q*inner(g_v, n)*ds
forms = [r]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment